diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..6e2dcf4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,43 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: appleboy + +--- + +## Describe the bug + +A clear and concise description of what the bug is. If applicable, add screenshots to help explain your problem. + +## Yaml Config + +Please post your Yaml configuration file along with the output results. + +```yaml +name: remote ssh command +on: [push] +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: executing remote ssh commands using password + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script: whoami +``` + +## Related environment + +Please provide the following information: + +1. Your hosting provider information, such as DigitalOcean, Linode, AWS, or GCP. +2. The version information of your host's SSH service. +3. The information from your host's SSH configuration file. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efa88cd..e4a92da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,151 +1,502 @@ -name: remote ssh command +name: testing main branch + on: [push] -env: - FOO: "BAR" - BAR: "FOO" - jobs: - - build: - name: Build + default-user-name-password: runs-on: ubuntu-latest steps: - - name: checkout - uses: actions/checkout@v1 + - name: Checkout code + uses: actions/checkout@v4 - - name: executing remote ssh commands using password - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - port: ${{ secrets.PORT }} - script: whoami + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 - - name: executing remote ssh commands using ssh key - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.KEY }} - port: ${{ secrets.PORT }} - script: whoami + - name: ssh by username and password + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + port: 2222 + script: whoami - - name: multiple command - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.KEY }} - port: ${{ secrets.PORT }} - script: | - whoami - ls -al + check-ssh-key: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 - # - name: stop script if command error - # if: always() - # uses: ./ - # with: - # host: ${{ secrets.HOST }} - # username: ${{ secrets.USERNAME }} - # key: ${{ secrets.KEY }} - # port: ${{ secrets.PORT }} - # script_stop: true - # script: | - # mkdir abc/def - # ls -al + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_rsa.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_rsa.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_rsa >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_rsa + echo "============================" - - name: pass environment - uses: ./ - env: - FOO: "BAR" - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.KEY }} - port: ${{ secrets.PORT }} - envs: FOO - script: | - echo "I am $FOO, thanks" - echo "I am $BAR, thanks" + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 - - name: pass multiple environment - uses: ./ - env: - FOO: "BAR" - BAR: "FOO" - SHA: ${{ github.sha }} - PORT: ${{ secrets.PORT }} - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.KEY }} - port: ${{ secrets.PORT }} - envs: FOO,BAR,SHA,PORT - script: | - echo "I am $FOO, thanks" - echo "I am $BAR, thanks" - echo "sha: $SHA" - echo "port: $PORT" + - name: ssh by private key + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: whoami - - name: ssh key passphrase - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.SSH2 }} - port: ${{ secrets.PORT }} - passphrase: ${{ secrets.PASSPHRASE }} - script: | - whoami - ls -al + - name: wrong password but correct key + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: "abcdef" + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: whoami - - name: use insecure cipher - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - port: ${{ secrets.PORT }} - script: | + - name: correct password but wrong key + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + key: password + port: 2222 + script: whoami + + - name: stop script if command error + uses: ./ + continue-on-error: true + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + key: password + port: 2222 + script_stop: true + sync: true + debug: true + script: | + mkdir abc/def + ls -al + + support-key-passphrase: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_passphrase.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_passphrase + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: ssh key passphrase + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + passphrase: 1234 + script: | + whoami + ls -al + + - name: missing ssh key passphrase + uses: ./ + continue-on-error: true + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + # https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271 + - name: Multiline SSH commands interpreted as single lines + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + passphrase: 1234 + script_stop: true + script: | ls \ -lah - use_insecure_cipher: true + use_insecure_cipher: true - # https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271 - - name: Multiline SSH commands interpreted as single lines - uses: ./ - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - port: ${{ secrets.PORT }} - script_stop: true - script: | - ls \ - -lah - use_insecure_cipher: true + multiple-server: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 - # https://github.com/appleboy/ssh-action/issues/85 - - name: Deployment to multiple hosts with different ports - uses: ./ - with: - host: "${{ secrets.HOST }}:${{ secrets.PORT }}" - username: ${{ secrets.USERNAME }} - password: ${{ secrets.PASSWORD }} - port: 1024 - script_stop: true - script: | - ls \ - -lah - use_insecure_cipher: true + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_passphrase.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_passphrase + echo "============================" - - name: SSH ED25519 Private Key - uses: ./ - with: - host: ${{ secrets.TUNNEL_HOST }} - username: ${{ secrets.TUNNEL_USERNAME }} - key: ${{ secrets.ID_ED25519 }} - port: ${{ secrets.TUNNEL_PORT }} - script: whoami + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server-01 \ + --hostname=openssh-server-01 \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server-01 sh -c "hostname -i" > ip01.txt + echo "REMOTE_HOST_01<> $GITHUB_ENV + cat ip01.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip01.txt + echo "======================================" + + docker run -d \ + --name=openssh-server-02 \ + --hostname=openssh-server-02 \ + -p 2223:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server-02 sh -c "hostname -i" > ip02.txt + echo "REMOTE_HOST_02<> $GITHUB_ENV + cat ip02.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip02.txt + echo "======================================" + + sleep 2 + + # https://github.com/appleboy/ssh-action/issues/85 + - name: Deployment to multiple hosts with different ports + uses: ./ + with: + host: "${{ env.REMOTE_HOST_01 }}:2222,${{ env.REMOTE_HOST_02 }}:2222" + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + passphrase: 1234 + script_stop: true + script: | + whoami + + support-ed25519-key: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_ed25519.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_ed25519 + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: testing id_ed25519 key + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + testing-with-env: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_ed25519.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_ed25519 + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=true \ + -e PASSWORD_ACCESS=true \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: testing id_ed25519 key + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + - name: pass environment + uses: ./ + env: + FOO: "BAR" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO + script: | + echo "I am $FOO, thanks" + echo "I am $BAR, thanks" + + - name: pass multiple environment + uses: ./ + env: + FOO: "BAR" + BAR: "FOO" + SHA: ${{ github.sha }} + PORT: ${{ secrets.PORT }} + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO,BAR,SHA,PORT + script: | + echo "I am $FOO, thanks" + echo "I am $BAR, thanks" + echo "sha: $SHA" + echo "port: $PORT" + + - name: custom envs format + uses: ./ + env: + FOO: "BAR" + AAA: "BBB" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO,BAR,AAA + envs_format: export TEST_{NAME}={VALUE} + script: | + echo "I am $TEST_FOO, thanks" + echo "I am $TEST_BAR, thanks" + echo "I am $BAR, thanks" + echo "I am $TEST_AAA, thanks" + + - name: pass all ENV variables to script + uses: ./ + env: + INPUT_FOO: "BAR" + INPUT_AAA: "BBB" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + allenvs: true + script: | + echo "I am $INPUT_FOO, thanks" + echo "I am $INPUT_AAA, thanks" + echo "$GITHUB_BASE_REF" + echo "$GITHUB_REF" + + - name: switch to root user + uses: ./ + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script_stop: true + request_pty: true + command_timeout: 30s + script: | + whoami && echo 'hello world' && touch todo.txt + sudo whoami + + testing06: + name: testing ipv6 + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v4 + + - name: Set up WARP + uses: fscarmen/warp-on-actions@v1.1 + with: + stack: dual + + - name: testing ipv6 for command + run: | + curl -m 9 --ipv6 --verbose https://google.com + + - name: testing ipv6 + uses: ./ + with: + host: 2402:1f00:8000:800::2628 + username: ubuntu + password: ${{ secrets.OVH_PASSWORD }} + protocol: tcp6 + port: 22 + command_timeout: 30s + script: | + whoami diff --git a/.github/workflows/ssh-server.yml b/.github/workflows/ssh-server.yml new file mode 100644 index 0000000..86ab7dc --- /dev/null +++ b/.github/workflows/ssh-server.yml @@ -0,0 +1,474 @@ +name: testing stable version + +on: [push] + +jobs: + default-user-name-password: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: ssh by username and password + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + port: 2222 + script: whoami + + check-ssh-key: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_rsa.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_rsa.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_rsa >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_rsa + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: ssh by private key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: whoami + + - name: wrong password but correct key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: "abcdef" + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: whoami + + - name: correct password but wrong key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + key: password + port: 2222 + script: whoami + + - name: stop script if command error + uses: appleboy/ssh-action@v1.0.3 + continue-on-error: true + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + password: password + key: password + port: 2222 + script_stop: true + sync: true + debug: true + script: | + mkdir abc/def + ls -al + + support-key-passphrase: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_passphrase.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_passphrase + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: ssh key passphrase + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + passphrase: 1234 + script: | + whoami + ls -al + + - name: missing ssh key passphrase + uses: appleboy/ssh-action@v1.0.3 + continue-on-error: true + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + # https://github.com/appleboy/ssh-action/issues/75#issuecomment-668314271 + - name: Multiline SSH commands interpreted as single lines + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + passphrase: 1234 + script_stop: true + script: | + ls \ + -lah + use_insecure_cipher: true + + multiple-server: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_passphrase.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_passphrase >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_passphrase + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server-01 \ + --hostname=openssh-server-01 \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server-01 sh -c "hostname -i" > ip01.txt + echo "REMOTE_HOST_01<> $GITHUB_ENV + cat ip01.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip01.txt + echo "======================================" + + docker run -d \ + --name=openssh-server-02 \ + --hostname=openssh-server-02 \ + -p 2223:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server-02 sh -c "hostname -i" > ip02.txt + echo "REMOTE_HOST_02<> $GITHUB_ENV + cat ip02.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip02.txt + echo "======================================" + + sleep 2 + + # https://github.com/appleboy/ssh-action/issues/85 + - name: Deployment to multiple hosts with different ports + uses: appleboy/ssh-action@v1.0.3 + with: + host: "${{ env.REMOTE_HOST_01 }}:2222,${{ env.REMOTE_HOST_02 }}:2222" + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + passphrase: 1234 + script_stop: true + script: | + whoami + + support-ed25519-key: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_ed25519.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_ed25519 + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=false \ + -e PASSWORD_ACCESS=true \ + -e USER_PASSWORD=password \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: testing id_ed25519 key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + testing-with-env: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: add public key to env + run: | + echo "PUBLIC_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519.pub >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= public key =========" + cat testdata/.ssh/id_ed25519.pub + echo "============================" + echo "PRIVATE_KEY<> $GITHUB_ENV + cat testdata/.ssh/id_ed25519 >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= private key =========" + cat testdata/.ssh/id_ed25519 + echo "============================" + + - name: create new ssh server + run: | + docker run -d \ + --name=openssh-server \ + --hostname=openssh-server \ + -p 2222:2222 \ + -e PUBLIC_KEY="${{ env.PUBLIC_KEY }}" \ + -e SUDO_ACCESS=true \ + -e PASSWORD_ACCESS=true \ + -e USER_NAME=linuxserver.io \ + --restart unless-stopped \ + lscr.io/linuxserver/openssh-server:latest + docker exec openssh-server sh -c "hostname -i" > ip.txt + echo "REMOTE_HOST<> $GITHUB_ENV + cat ip.txt >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + echo "======= container ip address =========" + cat ip.txt + echo "======================================" + sleep 2 + + - name: testing id_ed25519 key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script: | + whoami + ls -al + + - name: pass environment + uses: appleboy/ssh-action@v1.0.3 + env: + FOO: "BAR" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO + script: | + echo "I am $FOO, thanks" + echo "I am $BAR, thanks" + + - name: pass multiple environment + uses: appleboy/ssh-action@v1.0.3 + env: + FOO: "BAR" + BAR: "FOO" + SHA: ${{ github.sha }} + PORT: ${{ secrets.PORT }} + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO,BAR,SHA,PORT + script: | + echo "I am $FOO, thanks" + echo "I am $BAR, thanks" + echo "sha: $SHA" + echo "port: $PORT" + + - name: custom envs format + uses: appleboy/ssh-action@v1.0.3 + env: + FOO: "BAR" + AAA: "BBB" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + envs: FOO,BAR,AAA + envs_format: export TEST_{NAME}={VALUE} + script: | + echo "I am $TEST_FOO, thanks" + echo "I am $TEST_BAR, thanks" + echo "I am $BAR, thanks" + echo "I am $TEST_AAA, thanks" + + - name: pass all ENV variables to script + uses: appleboy/ssh-action@v1.0.3 + env: + INPUT_FOO: "BAR" + INPUT_AAA: "BBB" + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + allenvs: true + script: | + echo "I am $INPUT_FOO, thanks" + echo "I am $INPUT_AAA, thanks" + echo "$GITHUB_BASE_REF" + echo "$GITHUB_REF" + + - name: switch to root user + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ env.REMOTE_HOST }} + username: linuxserver.io + key: ${{ env.PRIVATE_KEY }} + port: 2222 + script_stop: true + request_pty: true + command_timeout: 30s + script: | + whoami && echo 'hello world' && touch todo.txt + sudo whoami diff --git a/Dockerfile b/Dockerfile index 416b5df..d84c375 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -FROM appleboy/drone-ssh:1.6.4-linux-amd64 +FROM ghcr.io/appleboy/drone-ssh:1.7.4 -COPY entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] +COPY entrypoint.sh /bin/entrypoint.sh + +ENTRYPOINT ["/bin/entrypoint.sh"] diff --git a/README.md b/README.md index 01e0173..7055cf5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # 🚀 SSH for GitHub Actions +[繁體中文](./README.zh-tw.md) + [GitHub Action](https://github.com/features/actions) for executing remote ssh commands. ![ssh workflow](./images/ssh-workflow.png) @@ -8,41 +10,46 @@ **Important**: Only support **Linux** [docker](https://www.docker.com/) container. +This thing is built using [Golang](https://go.dev) and [drone-ssh](https://github.com/appleboy/drone-ssh). 🚀 + ## Input variables See [action.yml](./action.yml) for more detailed information. -* `host` - ssh host -* `port` - ssh port, default is `22` -* `username` - ssh username -* `password` - ssh password -* `passphrase` - the passphrase is usually to encrypt the private key -* `sync` - synchronous execution if multiple hosts, default is false -* `timeout` - timeout for ssh to remote host, default is `30s` -* `command_timeout` - timeout for ssh command, default is `10m` -* `key` - content of ssh private key. ex raw content of ~/.ssh/id_rsa, rembemer include the BEGIN and END lines -* `key_path` - path of ssh private key -* `fingerprint` - fingerprint SHA256 of the host public key, default is to skip verification -* `script` - execute commands -* `script_stop` - stop script after first failure -* `envs` - pass environment variable to shell script -* `debug` - enable debug mode -* `use_insecure_cipher` - include more ciphers with use_insecure_cipher (see [#56](https://github.com/appleboy/ssh-action/issues/56)) -* `cipher` - the allowed cipher algorithms. If unspecified then a sensible - -SSH Proxy Setting: - -* `proxy_host` - proxy host -* `proxy_port` - proxy port, default is `22` -* `proxy_username` - proxy username -* `proxy_password` - proxy password -* `proxy_passphrase` - the passphrase is usually to encrypt the private key -* `proxy_timeout` - timeout for ssh to proxy host, default is `30s` -* `proxy_key` - content of ssh proxy private key. -* `proxy_key_path` - path of ssh proxy private key -* `proxy_fingerprint` - fingerprint SHA256 of the proxy host public key, default is to skip verification -* `proxy_use_insecure_cipher` - include more ciphers with use_insecure_cipher (see [#56](https://github.com/appleboy/ssh-action/issues/56)) -* `proxy_cipher` - the allowed cipher algorithms. If unspecified then a sensible +| Input Parameter | Description | Default Value | +|---------------------------|------------------------------------------------------------------------------------------|---------------| +| host | SSH host address | | +| port | SSH port number | 22 | +| passphrase | SSH key passphrase | | +| username | SSH username | | +| password | SSH password | | +| protocol | SSH protocol version (tcp, tcp4, tcp6) | tcp | +| sync | Enable synchronous execution if multiple hosts | false | +| use_insecure_cipher | Include more ciphers with use_insecure_cipher | false | +| cipher | Allowed cipher algorithms. If unspecified, a sensible default | | +| timeout | Timeout duration for SSH to host | 30s | +| command_timeout | Timeout duration for SSH command | 10m | +| key | Content of SSH private key. e.g., raw content of ~/.ssh/id_rsa | | +| key_path | Path of SSH private key | | +| fingerprint | SHA256 fingerprint of the host public key | | +| proxy_host | SSH proxy host | | +| proxy_port | SSH proxy port | 22 | +| proxy_username | SSH proxy username | | +| proxy_password | SSH proxy password | | +| proxy_passphrase | SSH proxy key passphrase | | +| proxy_timeout | Timeout for SSH to proxy host | 30s | +| proxy_key | Content of SSH proxy private key | | +| proxy_key_path | Path of SSH proxy private key | | +| proxy_fingerprint | SHA256 fingerprint of the proxy host public key | | +| proxy_cipher | Allowed cipher algorithms for the proxy | | +| proxy_use_insecure_cipher | Include more ciphers with use_insecure_cipher for the proxy | false | +| script | Execute commands | | +| script_stop | Stop script after first failure | false | +| envs | Pass environment variables to shell script | | +| envs_format | Flexible configuration of environment value transfer | | +| debug | Enable debug mode | false | +| allenvs | pass the environment variables with prefix value of `GITHUB_` and `INPUT_` to the script | false | +| request_pty | Request a pseudo-terminal from the server | false | ## Usage @@ -58,7 +65,7 @@ jobs: runs-on: ubuntu-latest steps: - name: executing remote ssh commands using password - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -85,76 +92,46 @@ Make sure to follow the below steps while creating SSH Keys and using them. The best practice is create the SSH Keys on local machine not remote machine. Login with username specified in Github Secrets. Generate a RSA Key-Pair: -
-rsa -

+### Generate rsa key ```bash ssh-keygen -t rsa -b 4096 -C "your_email@example.com" ``` -

-
- -
-ed25519 -

+### Generate ed25519 key ```bash ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ``` -

-
- Add newly generated key into Authorized keys. Read more about authorized keys [here](https://www.ssh.com/ssh/authorized_keys/). -
-rsa -

+### Add rsa key into Authorized keys ```bash cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' ``` -

-
- -
-ed25519 -

+### Add ed25519 key into Authorized keys ```bash cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys' ``` -

-
- Copy Private Key content and paste in Github Secrets. -
-rsa -

+### Copy rsa Private key ```bash clip < ~/.ssh/id_rsa ``` -

-
- -
-ed25519 -

+### Copy ed25519 Private key ```bash clip < ~/.ssh/id_ed25519 ``` -

-
- See the detail information about [SSH login without password](http://www.linuxproblem.org/art_9.html). **A note** from one of our readers: Depending on your version of SSH you might also have to do the following changes: @@ -171,8 +148,7 @@ If you are currently using OpenSSH and are getting the following error: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey] ``` -Make sure that your key algorithm of choice is supported. On Ubuntu 20.04 or later you must explicitly allow the use of the ssh-rsa algorithm. Add the following line to your OpenSSH daemon file (which is either `/etc/ssh/sshd_config` or a drop-in file under -`/etc/ssh/sshd_config.d/`): +Make sure that your key algorithm of choice is supported. On Ubuntu 20.04 or later you must explicitly allow the use of the ssh-rsa algorithm. Add the following line to your OpenSSH daemon file (which is either `/etc/ssh/sshd_config` or a drop-in file under `/etc/ssh/sshd_config.d/`): ```bash CASignatureAlgorithms +ssh-rsa @@ -190,7 +166,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```yaml - name: executing remote ssh commands using password - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -203,7 +179,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```yaml - name: executing remote ssh commands using ssh key - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -216,7 +192,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```yaml - name: multiple command - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -233,7 +209,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```diff - name: multiple host - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: - host: "foo.com" + host: "foo.com,bar.com" @@ -245,11 +221,13 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ls -al ``` +The default value of `port` is `22`. + #### Multiple hosts with different port ```diff - name: multiple host - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: - host: "foo.com" + host: "foo.com:1234,bar.com:5678" @@ -264,7 +242,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```diff - name: multiple host - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: "foo.com,bar.com" + sync: true @@ -280,7 +258,7 @@ ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" ```diff - name: pass environment - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 + env: + FOO: "BAR" + BAR: "FOO" @@ -305,7 +283,7 @@ _Inside `env` object, you need to pass every environment variable as a string, p ```diff - name: stop script if command error - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -358,7 +336,7 @@ Host FooServer ```diff - name: ssh proxy command - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -381,7 +359,7 @@ It is not uncommon for files to leak from backups or decommissioned hardware, an ```diff - name: ssh key passphrase - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -407,7 +385,7 @@ Now you can adjust you config: ```diff - name: ssh key passphrase - uses: appleboy/ssh-action@master + uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} @@ -419,6 +397,29 @@ Now you can adjust you config: ls -al ``` +## Q&A + +### Command not found (npm or other command) + +See the [issue comment](https://github.com/appleboy/ssh-action/issues/31#issuecomment-1006565847) about interactive vs non interactive shell. Thanks @kocyigityunus for the solution. + +Basically, if you are running a command in a non interactive shell, like ssh-action, on many linux distros, + +`/etc/bash.bashrc` file has a specific command that returns only, so some of the files didn't run and some specific commands doesn't add to path, + +```sh +# /etc/bash.bashrc +# System-wide .bashrc file for interactive bash(1) shells. + +# To enable the settings / commands in this file for login shells as well, +# this file has to be sourced in /etc/profile. + +# If not running interactively, don't do anything +[ -z "$PS1" ] && return` +``` + +just comment out the line that returns early and everything should work fine, or you can use the real paths of the commands that you would like to use. + ## Contributing We would love for you to contribute to `appleboy/ssh-action`, pull requests are welcome! diff --git a/README.zh-tw.md b/README.zh-tw.md new file mode 100644 index 0000000..9c37b34 --- /dev/null +++ b/README.zh-tw.md @@ -0,0 +1,393 @@ +# 🚀 用於 GitHub Actions 的 SSH + +[GitHub Action](https://github.com/features/actions) for executing remote ssh commands. + +![ssh workflow](./images/ssh-workflow.png) + +[![Actions Status](https://github.com/appleboy/ssh-action/workflows/remote%20ssh%20command/badge.svg)](https://github.com/appleboy/ssh-action/actions) + +**注意**: 只支援在 **Linux** [docker](https://www.docker.com/) 容器上執行。 + +## 輸入變數 + +更詳細的資訊,請參閱 [action.yml](./action.yml)。 + +* `host` - SSH 主機 +* `port` - SSH 連接埠,預設為 `22` +* `username` - SSH 使用者名稱 +* `password` - SSH 密碼 +* `passphrase` - 通常用於加密私鑰的 passphrase +* `sync` - 同步執行多個主機上的命令,預設為 false +* `timeout` - SSH 連接到遠端主機的超時時間,預設為 `30s` +* `command_timeout` - SSH 命令超時時間,預設為 10m +* `key` - SSH 私鑰的內容,例如 ~/.ssh/id_rsa 的原始內容,請記得包含 BEGIN 和 END 行 +* `key_path` - SSH 私鑰的路徑 +* `fingerprint` - 主機公鑰的 SHA256 指紋,預設為略過驗證 +* `script` - 執行命令 +* `script_stop` - 當出現第一個錯誤時停止執行命令 +* `envs` - 傳遞環境變數到 shell script +* `debug` - 啟用偵錯模式 +* `use_insecure_cipher` - 使用不安全的密碼(ciphers)進行加密,參見 [#56](https://github.com/appleboy/ssh-action/issues/56) +* `cipher` - 允許使用的密碼(ciphers)演算法。如果未指定,則使用適當的演算法 + +SSH 代理設置: + +* `proxy_host` - 代理主機 +* `proxy_port` - 代理端口,預設為 `22` +* `proxy_username` - 代理使用者名稱 +* `proxy_password` - 代理密碼 +* `proxy_passphrase` - 密碼通常用於加密私有金鑰 +* `proxy_timeout` - SSH 連線至代理主機的逾時時間,預設為 `30s` +* `proxy_key` - SSH 代理私有金鑰內容 +* `proxy_key_path` - SSH 代理私有金鑰路徑 +* `proxy_fingerprint` - 代理主機公鑰的 SHA256 指紋,預設為跳過驗證 +* `proxy_use_insecure_cipher` - 使用不安全的加密方式,請參閱 [#56](https://github.com/appleboy/ssh-action/issues/56) +* `proxy_cipher` - 允許的加密算法。如果未指定,則使用合理的算法 + +## 使用方式 + +執行遠端 SSH 命令 + +```yaml +name: remote ssh command +on: [push] +jobs: + + build: + name: Build + runs-on: ubuntu-latest + steps: + - name: executing remote ssh commands using password + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script: whoami +``` + +畫面輸出 + +```sh +======CMD====== +whoami +======END====== +out: *** +============================================== +✅ Successfully executed commands to all host. +============================================== +``` + +### 設置 SSH 金鑰 + +請在創建 SSH 金鑰並使用 SSH 金鑰時遵循以下步驟。最佳做法是在本地機器上創建 SSH 金鑰而不是遠端機器上。請使用 Github Secrets 中指定的用戶名登錄。生成 RSA 金鑰: + +### 生成 RSA 金鑰 + +```bash +ssh-keygen -t rsa -b 4096 -C "your_email@example.com" +``` + +### 生成 ed25519 金鑰 + +```bash +ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" +``` + +將新生成的金鑰添加到已授權的金鑰中。詳細了解已授權的金鑰請點擊[此處](https://www.ssh.com/ssh/authorized_keys/). + +### 將 RSA 金鑰添加到已授權金鑰中 + +```bash +cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys' +``` + +### 將 ed25519 金鑰添加到已授權金鑰中 + +```bash +cat .ssh/id_ed25519.pub | ssh b@B 'cat >> .ssh/authorized_keys' +``` + +複製私鑰內容,然後將其粘貼到 Github Secrets 中。 + +### 複製 rsa 私鑰內容 + +```bash +clip < ~/.ssh/id_rsa +``` + +### 複製 ed25519 私鑰內容 + +```bash +clip < ~/.ssh/id_ed25519 +``` + +有關無需密碼登錄 SSH 的詳細信息,請[參見該網站](http://www.linuxproblem.org/art_9.html)。 + +**來自讀者的注意事項**: 根據您的 SSH 版本,您可能還需要進行以下更改: + +* 將公鑰放在 `.ssh/authorized_keys2` 中 +* 將 `.ssh` 的權限更改為700 +* 將 `.ssh/authorized_keys2` 的權限更改為640 + +### 如果你使用的是 OpenSSH + +如果您正在使用 OpenSSH,並出現以下錯誤: + +```bash +ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey] +``` + +請確保您所選擇的密鑰演算法得到支援。在 Ubuntu 20.04 或更高版本上,您必須明確允許使用 SSH-RSA 演算法。請在 OpenSSH 守護進程文件中添加以下行(它可以是 `/etc/ssh/sshd_config` 或 `/etc/ssh/sshd_config.d/` 中的一個附著文件): + +```bash +CASignatureAlgorithms +ssh-rsa +``` + +或者,`Ed25519` 密鑰在 OpenSSH 中默認被接受。如果需要,您可以使用它來替代 RSA。 + +```bash +ssh-keygen -t ed25519 -a 200 -C "your_email@example.com" +``` + +### Example + +#### 使用密碼執行遠端 SSH 命令 + +```yaml +- name: executing remote ssh commands using password + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + password: ${{ secrets.PASSWORD }} + port: ${{ secrets.PORT }} + script: whoami +``` + +#### 使用私鑰 + +```yaml +- name: executing remote ssh commands using ssh key + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} + script: whoami +``` + +#### 多個命令 + +```yaml +- name: multiple command + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} + script: | + whoami + ls -al +``` + +![result](./images/output-result.png) + +#### 多台主機 + +```diff + - name: multiple host + uses: appleboy/ssh-action@v1.0.3 + with: +- host: "foo.com" ++ host: "foo.com,bar.com" + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} + script: | + whoami + ls -al +``` + +#### 多個不同端口的主機 + +```diff + - name: multiple host + uses: appleboy/ssh-action@v1.0.3 + with: +- host: "foo.com" ++ host: "foo.com:1234,bar.com:5678" + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + script: | + whoami + ls -al +``` + +#### 在多個主機上同步執行 + +```diff + - name: multiple host + uses: appleboy/ssh-action@v1.0.3 + with: + host: "foo.com,bar.com" ++ sync: true + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} + script: | + whoami + ls -al +``` + +#### 將環境變量傳遞到 Shell 腳本 + +```diff + - name: pass environment + uses: appleboy/ssh-action@v1.0.3 ++ env: ++ FOO: "BAR" ++ BAR: "FOO" ++ SHA: ${{ github.sha }} + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} ++ envs: FOO,BAR,SHA + script: | + echo "I am $FOO" + echo "I am $BAR" + echo "sha: $SHA" +``` + +_在 `env` 對象中,您需要將每個環境變量作為字符串傳遞,傳遞 `Integer` 數據類型或任何其他類型可能會產生意外結果。_ + +#### 在第一次失敗後停止腳本 + +> ex: missing `abc` folder + +```diff + - name: stop script if command error + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} ++ script_stop: true + script: | + mkdir abc/def + ls -al +``` + +畫面輸出: + +```sh +======CMD====== +mkdir abc/def +ls -al + +======END====== +2019/11/21 01:16:21 Process exited with status 1 +err: mkdir: cannot create directory ‘abc/def’: No such file or directory +##[error]Docker run failed with exit code 1 +``` + +#### 如何使用 `ProxyCommand` 連接遠程服務器? + +```bash ++--------+ +----------+ +-----------+ +| Laptop | <--> | Jumphost | <--> | FooServer | ++--------+ +----------+ +-----------+ +``` + +在您的 `~/.ssh/config` 文件中,您會看到以下內容。 + +```bash +Host Jumphost + HostName Jumphost + User ubuntu + Port 22 + IdentityFile ~/.ssh/keys/jump_host.pem + +Host FooServer + HostName FooServer + User ubuntu + Port 22 + ProxyCommand ssh -q -W %h:%p Jumphost +``` + +#### 如何將其轉換為 GitHubActions 的 YAML 格式? + +```diff + - name: ssh proxy command + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} ++ proxy_host: ${{ secrets.PROXY_HOST }} ++ proxy_username: ${{ secrets.PROXY_USERNAME }} ++ proxy_key: ${{ secrets.PROXY_KEY }} ++ proxy_port: ${{ secrets.PROXY_PORT }} + script: | + mkdir abc/def + ls -al +``` + +#### 如何保護私鑰? + +密碼短語通常用於加密私鑰。這使得攻擊者無法單獨使用密鑰文件。文件泄露可能來自備份或停用的硬件,黑客通常可以從受攻擊系統中洩露文件。因此,保護私鑰非常重要。 + +```diff + - name: ssh key passphrase + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} ++ passphrase: ${{ secrets.PASSPHRASE }} + script: | + whoami + ls -al +``` + +#### 使用主機指紋驗證 + +設置 SSH 主機指紋驗證可以幫助防止中間人攻擊。在設置之前,運行以下命令以獲取 SSH 主機指紋。請記得將 `ed25519` 替換為您的適當金鑰類型(`rsa`、 `dsa`等),而 `example.com` 則替換為您的主機。 + +現代 OpenSSH 版本中,需要提取的_默認金鑰_類型是 `rsa`(從版本 5.1 開始)、`ecdsa`(從版本 6.0 開始)和 `ed25519`(從版本 6.7 開始)。 + +```sh +ssh example.com ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key.pub | cut -d ' ' -f2 +``` + +現在您可以調整您的配置: + +```diff + - name: ssh key passphrase + uses: appleboy/ssh-action@v1.0.3 + with: + host: ${{ secrets.HOST }} + username: ${{ secrets.USERNAME }} + key: ${{ secrets.KEY }} + port: ${{ secrets.PORT }} ++ fingerprint: ${{ secrets.FINGERPRINT }} + script: | + whoami + ls -al +``` + +## 貢獻 + +我們非常希望您為 `appleboy/ssh-action` 做出貢獻,歡迎提交請求! + +## 授權方式 + +本項目中的腳本和文檔采用 [MIT](LICENSE) 許可證 發布。 diff --git a/action.yml b/action.yml index 65891e8..4a16472 100644 --- a/action.yml +++ b/action.yml @@ -1,77 +1,124 @@ -name: 'SSH Remote Commands' -description: 'Executing remote ssh commands' -author: 'Bo-Yi Wu' +name: "SSH Remote Commands" +description: "Executing remote ssh commands" +author: "Bo-Yi Wu" inputs: host: - description: 'ssh host' + description: "SSH host address." port: - description: 'ssh port' - default: 22 + description: "SSH port number." + default: "22" passphrase: - description: 'ssh key passphrase' + description: "Passphrase for the SSH key." username: - description: 'ssh username' + description: "SSH username." password: - description: 'ssh password' + description: "SSH password." + protocol: + description: 'The IP protocol to use. Valid values are "tcp". "tcp4" or "tcp6". Default to tcp.' + default: "tcp" sync: - description: 'synchronous execution if multiple hosts' - default: false + description: "Enable synchronous execution if multiple hosts are involved." use_insecure_cipher: - description: 'include more ciphers with use_insecure_cipher' - default: false + description: "Include more ciphers by using insecure ciphers." cipher: - description: 'the allowed cipher algorithms. If unspecified then a sensible' + description: "Allowed cipher algorithms. If unspecified, a sensible default is used." timeout: - description: 'timeout for ssh to host' + description: "Timeout duration for establishing SSH connection to the host." default: "30s" command_timeout: - description: 'timeout for ssh command' + description: "Timeout duration for SSH commands execution." default: "10m" key: - description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa' + description: "Content of the SSH private key. For example, the raw content of ~/.ssh/id_rsa." key_path: - description: 'path of ssh private key' + description: "Path to the SSH private key file." fingerprint: - description: 'sha256 fingerprint of the host public key' + description: "SHA256 fingerprint of the host public key." proxy_host: - description: 'ssh proxy host' + description: "SSH proxy host address." proxy_port: - description: 'ssh proxy port' - default: 22 + description: "SSH proxy port number." + default: "22" proxy_username: - description: 'ssh proxy username' + description: "SSH proxy username." proxy_password: - description: 'ssh proxy password' + description: "SSH proxy password." proxy_passphrase: - description: 'ssh proxy key passphrase' + description: "SSH proxy key passphrase." proxy_timeout: - description: 'timeout for ssh to proxy host' + description: "Timeout duration for establishing SSH connection to the proxy host." default: "30s" proxy_key: - description: 'content of ssh proxy private key. ex raw content of ~/.ssh/id_rsa' + description: "Content of the SSH proxy private key. For example, the raw content of ~/.ssh/id_rsa." proxy_key_path: - description: 'path of ssh proxy private key' + description: "Path to the SSH proxy private key file." proxy_fingerprint: - description: 'sha256 fingerprint of the proxy host public key' + description: "SHA256 fingerprint of the proxy host public key." proxy_cipher: - description: 'the allowed cipher algorithms. If unspecified then a sensible' + description: "Allowed cipher algorithms for the proxy. If unspecified, a sensible default is used." proxy_use_insecure_cipher: - description: 'include more ciphers with use_insecure_cipher' - default: false + description: "Include more ciphers for the proxy by using insecure ciphers." script: - description: 'execute commands' + description: "Commands to be executed." script_stop: - description: 'stop script after first failure' - default: false + description: "Stop the script after the first failure." envs: - description: 'pass environment variable to shell script' + description: "Environment variables to be passed to the shell script." + envs_format: + description: "Flexible configuration for environment value transfer." debug: - description: 'enable debug mode' - default: false + description: "Enable debug mode." + allenvs: + description: "pass all environment variable to shell script." + request_pty: + description: "Request a pseudo-terminal from the server." + runs: - using: 'docker' - image: 'Dockerfile' + using: "composite" + steps: + - name: Set GitHub Path + run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH + shell: bash + env: + GITHUB_ACTION_PATH: ${{ github.action_path }} + - name: Run entrypoint.sh + run: entrypoint.sh + shell: bash + env: + GITHUB_ACTION_PATH: ${{ github.action_path }} + INPUT_HOST: ${{ inputs.host }} + INPUT_PORT: ${{ inputs.port }} + INPUT_PROTOCOL: ${{ inputs.protocol }} + INPUT_USERNAME: ${{ inputs.username }} + INPUT_PASSWORD: ${{ inputs.password }} + INPUT_PASSPHRASE: ${{ inputs.passphrase }} + INPUT_KEY: ${{ inputs.key }} + INPUT_KEY_PATH: ${{ inputs.key_path }} + INPUT_FINGERPRINT: ${{ inputs.fingerprint }} + INPUT_PROXY_HOST: ${{ inputs.proxy_host }} + INPUT_PROXY_PORT: ${{ inputs.proxy_port }} + INPUT_PROXY_USERNAME: ${{ inputs.proxy_username }} + INPUT_PROXY_PASSWORD: ${{ inputs.proxy_password }} + INPUT_PROXY_PASSPHRASE: ${{ inputs.proxy_passphrase }} + INPUT_PROXY_KEY: ${{ inputs.proxy_key }} + INPUT_PROXY_KEY_PATH: ${{ inputs.proxy_key_path }} + INPUT_PROXY_FINGERPRINT: ${{ inputs.proxy_fingerprint }} + INPUT_TIMEOUT: ${{ inputs.timeout }} + INPUT_PROXY_TIMEOUT: ${{ inputs.proxy_timeout }} + INPUT_COMMAND_TIMEOUT: ${{ inputs.command_timeout }} + INPUT_SCRIPT: ${{ inputs.script }} + INPUT_SCRIPT_STOP: ${{ inputs.script_stop }} + INPUT_ENVS: ${{ inputs.envs }} + INPUT_ENVS_FORMAT: ${{ inputs.envs_format }} + INPUT_DEBUG: ${{ inputs.debug }} + INPUT_ALL_ENVS: ${{ inputs.allenvs }} + INPUT_REQUEST_PTY: ${{ inputs.request_pty }} + INPUT_USE_INSECURE_CIPHER: ${{ inputs.use_insecure_cipher }} + INPUT_CIPHER: ${{ inputs.cipher }} + INPUT_PROXY_USE_INSECURE_CIPHER: ${{ inputs.proxy_use_insecure_cipher }} + INPUT_PROXY_CIPHER: ${{ inputs.proxy_cipher }} + INPUT_SYNC: ${{ inputs.sync }} branding: - icon: 'terminal' - color: 'gray-dark' + icon: "terminal" + color: "gray-dark" diff --git a/entrypoint.sh b/entrypoint.sh index f880594..f50d56e 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,7 +1,66 @@ -#!/bin/sh +#!/usr/bin/env bash -set -eu +set -o errexit +set -o nounset +set -o pipefail export GITHUB="true" -sh -c "/bin/drone-ssh $*" +GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}" +DRONE_SSH_RELEASE_URL="${DRONE_SSH_RELEASE_URL:-https://github.com/appleboy/drone-ssh/releases/download}" +DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.7.4}" + +function detect_client_info() { + if [ -n "${SSH_CLIENT_OS-}" ]; then + CLIENT_PLATFORM="${SSH_CLIENT_OS}" + else + local kernel + kernel="$(uname -s)" + case "${kernel}" in + Darwin) + CLIENT_PLATFORM="darwin" + ;; + Linux) + CLIENT_PLATFORM="linux" + ;; + Windows) + CLIENT_PLATFORM="windows" + ;; + *) + echo "Unknown, unsupported platform: ${kernel}." >&2 + echo "Supported platforms: Linux, Darwin and Windows." >&2 + echo "Bailing out." >&2 + exit 2 + esac + fi + + if [ -n "${SSH_CLIENT_ARCH-}" ]; then + CLIENT_ARCH="${SSH_CLIENT_ARCH}" + else + local machine + machine="$(uname -m)" + case "${machine}" in + x86_64*|i?86_64*|amd64*) + CLIENT_ARCH="amd64" + ;; + aarch64*|arm64*) + CLIENT_ARCH="arm64" + ;; + *) + echo "Unknown, unsupported architecture (${machine})." >&2 + echo "Supported architectures x86_64, i686, arm64." >&2 + echo "Bailing out." >&2 + exit 3 + ;; + esac + fi +} + +detect_client_info +DOWNLOAD_URL_PREFIX="${DRONE_SSH_RELEASE_URL}/v${DRONE_SSH_VERSION}" +CLIENT_BINARY="drone-ssh-${DRONE_SSH_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}" +TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}" +echo "Will download ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}" +curl -fL --retry 3 --keepalive-time 2 "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o ${TARGET} +chmod +x ${TARGET} +sh -c "${TARGET} $*" diff --git a/testdata/.ssh/id_ed25519 b/testdata/.ssh/id_ed25519 new file mode 100644 index 0000000..9dc32bb --- /dev/null +++ b/testdata/.ssh/id_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDoi7FltQCqpWporKh61nJUPIeazUYdzdstncoeU5XS2AAAAKBF5e2SReXt +kgAAAAtzc2gtZWQyNTUxOQAAACDoi7FltQCqpWporKh61nJUPIeazUYdzdstncoeU5XS2A +AAAEBrsLG1vSg08yaQgYM46KQW93Lz2ZikS1tTMH35gfHhpOiLsWW1AKqlamisqHrWclQ8 +h5rNRh3N2y2dyh5TldLYAAAAFnlvdXJfZW1haWxAZXhhbXBsZS5jb20BAgMEBQYH +-----END OPENSSH PRIVATE KEY----- diff --git a/testdata/.ssh/id_ed25519.pub b/testdata/.ssh/id_ed25519.pub new file mode 100644 index 0000000..14f2085 --- /dev/null +++ b/testdata/.ssh/id_ed25519.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOiLsWW1AKqlamisqHrWclQ8h5rNRh3N2y2dyh5TldLY your_email@example.com diff --git a/testdata/.ssh/id_passphrase b/testdata/.ssh/id_passphrase new file mode 100644 index 0000000..089d425 --- /dev/null +++ b/testdata/.ssh/id_passphrase @@ -0,0 +1,39 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +h55pSap77CEhEhE5FPZKuH9f7/E= +-----END OPENSSH PRIVATE KEY----- diff --git a/testdata/.ssh/id_passphrase.pub b/testdata/.ssh/id_passphrase.pub new file mode 100644 index 0000000..1d84832 --- /dev/null +++ b/testdata/.ssh/id_passphrase.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCuWKQh09Vlv3IRu/+oK18ws72VQS7PCXJaIEp1L+7HqC/6+plizaVgd9SjAg0UJSqvp+WfpU5I53hevE0Ip3s71Tsoeu1azWoi2Mbq3ycZ5ysh4htZZklKBkYsyW+2EdITPcmhA8rF+KiDRyuvk7fDo08G3YWgbCScY6VkLA06ReThCehAY54WNvgbx7lyvCWj1qYG0XjM7mTQHr3QN0JHJNdFaG3MCi1rTG2hK/owOlzcesIbzfM1VMIQG5HT4vNg/ULP0BTZ7pGtdvWlvR/660KQwc1tBxLqxI1dYoCgiS/gMyPxhOtNKTvhR/NR7e2sp/StkXURIxTHhj0KjKbnpXTQ2IndnesHAG9kDJ7c31SXastWpbXWhCIdRZk+KQsnmwobZlw3w1vfx2Dm7M2ZCcCgG/ArUPjY44nGOWO5Nz98QHyz3IocsKJXrGVo/3YpNNu72jkw7UGVMqh1dAe3ZMaCAC5pAAa0HKvkid7jdXawL2b//+vsAPSHdnEjP58= mtk10671@NB22040567 diff --git a/testdata/.ssh/id_rsa b/testdata/.ssh/id_rsa new file mode 100644 index 0000000..6270f55 --- /dev/null +++ b/testdata/.ssh/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA4e2D/qPN08pzTac+a8ZmlP1ziJOXk45CynMPtva0rtK/RB26 +VbfAF0hIJji7ltvnYnqCU9oFfvEM33cTn7T96+od8ib/Vz25YU8ZbstqtIskPuwC +bv3K0mAHgsviJyRD7yM+QKTbBQEgbGuW6gtbMKhiYfiIB4Dyj7AdS/fk3v26wDgz +7SHI5OBqu9bv1KhxQYdFEnU3PAtAqeccgzNpbH3eYLyGzuUxEIJlhpZ/uU2G9ppj +/cSrONVPiI8Ahi4RrlZjmP5l57/sq1ClGulyLpFcMw68kP5FikyqHpHJHRBNgU57 +1y0Ph33SjBbs0haCIAcmreWEhGe+/OXnJe6VUQIDAQABAoIBAH97emORIm9DaVSD +7mD6DqA7c5m5Tmpgd6eszU08YC/Vkz9oVuBPUwDQNIX8tT0m0KVs42VVPIyoj874 +bgZMJoucC1G8V5Bur9AMxhkShx9g9A7dNXJTmsKilRpk2TOk7wBdLp9jZoKoZBdJ +jlp6FfaazQjjKD6zsCsMATwAoRCBpBNsmT6QDN0n0bIgY0tE6YGQaDdka0dAv68G +R0VZrcJ9voT6+f+rgJLoojn2DAu6iXaM99Gv8FK91YCymbQlXXgrk6CyS0IHexN7 +V7a3k767KnRbrkqd3o6JyNun/CrUjQwHs1IQH34tvkWScbseRaFehcAm6mLT93RP +muauvMECgYEA9AXGtfDMse0FhvDPZx4mx8x+vcfsLvDHcDLkf/lbyPpu97C27b/z +ia07bu5TAXesUZrWZtKA5KeRE5doQSdTOv1N28BEr8ZwzDJwfn0DPUYUOxsN2iIy +MheO5A45Ko7bjKJVkZ61Mb1UxtqCTF9mqu9R3PBdJGthWOd+HUvF460CgYEA7QRf +Z8+vpGA+eSuu29e0xgRKnRzed5zXYpcI4aERc3JzBgO4Z0er9G8l66OWVGdMfpe6 +CBajC5ToIiT8zqoYxXwqJgN+glir4gJe3mm8J703QfArZiQrdk0NTi5bY7+vLLG/ +knTrtpdsKih6r3kjhuPPaAsIwmMxIydFvATKjLUCgYEAh/y4EihRSk5WKC8GxeZt +oiZ58vT4z+fqnMIfyJmD5up48JuQNcokw/LADj/ODiFM7GUnWkGxBrvDA3H67WQm +49bJjs8E+BfUQFdTjYnJRlpJZ+7Zt1gbNQMf5ENw5CCchTDqEq6pN0DVf8PBnSIF +KvkXW9KvdV5J76uCAn15mDkCgYA1y8dHzbjlCz9Cy2pt1aDfTPwOew33gi7U3skS +RTerx29aDyAcuQTLfyrROBkX4TZYiWGdEl5Bc7PYhCKpWawzrsH2TNa7CRtCOh2E +R+V/84+GNNf04ALJYCXD9/ugQVKmR1XfDRCvKeFQFE38Y/dvV2etCswbKt5tRy2p +xkCe/QKBgQCkLqafD4S20YHf6WTp3jp/4H/qEy2X2a8gdVVBi1uKkGDXr0n+AoVU +ib4KbP5ovZlrjL++akMQ7V2fHzuQIFWnCkDA5c2ZAqzlM+ZN+HRG7gWur7Bt4XH1 +7XC9wlRna4b3Ln8ew3q1ZcBjXwD4ppbTlmwAfQIaZTGJUgQbdsO9YA== +-----END RSA PRIVATE KEY----- diff --git a/testdata/.ssh/id_rsa.pub b/testdata/.ssh/id_rsa.pub new file mode 100644 index 0000000..2983f04 --- /dev/null +++ b/testdata/.ssh/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDh7YP+o83TynNNpz5rxmaU/XOIk5eTjkLKcw+29rSu0r9EHbpVt8AXSEgmOLuW2+dieoJT2gV+8QzfdxOftP3r6h3yJv9XPblhTxluy2q0iyQ+7AJu/crSYAeCy+InJEPvIz5ApNsFASBsa5bqC1swqGJh+IgHgPKPsB1L9+Te/brAODPtIcjk4Gq71u/UqHFBh0USdTc8C0Cp5xyDM2lsfd5gvIbO5TEQgmWGln+5TYb2mmP9xKs41U+IjwCGLhGuVmOY/mXnv+yrUKUa6XIukVwzDryQ/kWKTKoekckdEE2BTnvXLQ+HfdKMFuzSFoIgByat5YSEZ7785ecl7pVR drone-scp@localhost diff --git a/testdata/.ssh/test b/testdata/.ssh/test new file mode 100644 index 0000000..89cc6ec --- /dev/null +++ b/testdata/.ssh/test @@ -0,0 +1,50 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +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 +l4njcaMpg4tpQMHtCBOicGyV0= +-----END OPENSSH PRIVATE KEY----- diff --git a/testdata/.ssh/test.pub b/testdata/.ssh/test.pub new file mode 100644 index 0000000..559daf2 --- /dev/null +++ b/testdata/.ssh/test.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDz6aZ1jY2onnuj2YNHJ/HhfvIu0B973v/+pFFOavnTUOhEEKEy3TASu+s9CkHrYZAtRc+QYIkNZI31mhHBhotdeP/7GoO2UirkFtrzyQKPNJxEcv0RBoG9ssN8jex0PyK6DHIYYFnIWadVBEEOh/H+rK7j7u2/big3oTzYBuFrCwmYFcz5na99MzFeAUhazF44gVBma+zO+1quGeqF51UDIg1SMGvX8I7LNEqrKEBaIUQJKFQcxlOWlRLQsjJCymrOujsXsRrXHAQWcnxDcNevv2ZMOUl0ybvv9yH0BiGbRBd1Hy8/QPILbAQaqu0oQE7fubN8Q8lqb3Jg0loID4x/5GPhSY8WAXpuLcXTOrb93SnCw1JsAgJDNqpuuRFy3BSZ7wBOr1jfeIoo7xk14OHiUjJ0uXDL9cLMkcw6ElWz81mrD2VCkXUz+qFyjJ+G7aGWRtctZoOzKln4yfNfUmwW8/8ra3QnmrMZ2xW2Ylw3ZhO+tLi7jINHYFb54bAdLVPUU1ctIuJns2qkWnjJCxxMiynIqCif20/OU1n8CTJuOWiURmRdmvKOH4PE3JxC2Qnk/3tV3Cf8hp1CH5VjBZ9AjGj5MDMHXyu34VY2WvYo5QyzfS3ySPoT8kCO0G0xpvjwCMHOK+G2RP4kqb/KKZguiKdgintBXuskTlJmD7kcMQ== deploy@easyssh