Compare commits
33 Commits
Author | SHA1 | Date | |
---|---|---|---|
1d1b21ca96 | |||
9fb11fb1f5 | |||
fd39ef0f18 | |||
ffff33f8fe | |||
8bd4933b73 | |||
bf84735fa9 | |||
d09b6e0211 | |||
3ac4675689 | |||
269a4479eb | |||
a2f91cbad1 | |||
e2cbea5f00 | |||
5711a203b3 | |||
b315fb5f98 | |||
682eb0ddda | |||
03b440e441 | |||
1cb5cd31c9 | |||
c9eebc1cde | |||
6b00175bad | |||
a912e225ec | |||
ad6643f705 | |||
26dd2b3a38 | |||
122f35dca5 | |||
03b5d10ad6 | |||
fcfb760891 | |||
fd81fae289 | |||
242a8e2e57 | |||
cfe9c45db6 | |||
73767290ca | |||
e5c07fceef | |||
d690bdebf8 | |||
f478af9b34 | |||
d520c19f4f | |||
0dee98b334 |
82
.github/workflows/ci.yml
vendored
82
.github/workflows/ci.yml
vendored
@ -6,8 +6,11 @@ jobs:
|
|||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: checkout
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
- name: executing remote ssh commands using password
|
- name: executing remote ssh commands using password
|
||||||
uses: appleboy/ssh-action@master
|
uses: ./
|
||||||
with:
|
with:
|
||||||
host: ${{ secrets.HOST }}
|
host: ${{ secrets.HOST }}
|
||||||
username: ${{ secrets.USERNAME }}
|
username: ${{ secrets.USERNAME }}
|
||||||
@ -16,7 +19,7 @@ jobs:
|
|||||||
script: whoami
|
script: whoami
|
||||||
|
|
||||||
- name: executing remote ssh commands using ssh key
|
- name: executing remote ssh commands using ssh key
|
||||||
uses: appleboy/ssh-action@master
|
uses: ./
|
||||||
with:
|
with:
|
||||||
host: ${{ secrets.HOST }}
|
host: ${{ secrets.HOST }}
|
||||||
username: ${{ secrets.USERNAME }}
|
username: ${{ secrets.USERNAME }}
|
||||||
@ -25,7 +28,7 @@ jobs:
|
|||||||
script: whoami
|
script: whoami
|
||||||
|
|
||||||
- name: multiple command
|
- name: multiple command
|
||||||
uses: appleboy/ssh-action@master
|
uses: ./
|
||||||
with:
|
with:
|
||||||
host: ${{ secrets.HOST }}
|
host: ${{ secrets.HOST }}
|
||||||
username: ${{ secrets.USERNAME }}
|
username: ${{ secrets.USERNAME }}
|
||||||
@ -36,7 +39,7 @@ jobs:
|
|||||||
ls -al
|
ls -al
|
||||||
|
|
||||||
# - name: stop script if command error
|
# - name: stop script if command error
|
||||||
# uses: appleboy/ssh-action@master
|
# uses: ./
|
||||||
# with:
|
# with:
|
||||||
# host: ${{ secrets.HOST }}
|
# host: ${{ secrets.HOST }}
|
||||||
# username: ${{ secrets.USERNAME }}
|
# username: ${{ secrets.USERNAME }}
|
||||||
@ -48,7 +51,7 @@ jobs:
|
|||||||
# ls -al
|
# ls -al
|
||||||
|
|
||||||
- name: pass environment
|
- name: pass environment
|
||||||
uses: appleboy/ssh-action@master
|
uses: ./
|
||||||
env:
|
env:
|
||||||
FOO: "BAR"
|
FOO: "BAR"
|
||||||
with:
|
with:
|
||||||
@ -60,3 +63,72 @@ jobs:
|
|||||||
script: |
|
script: |
|
||||||
echo "I am $FOO, thanks"
|
echo "I am $FOO, thanks"
|
||||||
echo "I am $BAR, thanks"
|
echo "I am $BAR, thanks"
|
||||||
|
|
||||||
|
- name: pass multiple environment
|
||||||
|
uses: ./
|
||||||
|
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, thanks"
|
||||||
|
echo "I am $BAR, thanks"
|
||||||
|
echo "sha: $SHA"
|
||||||
|
|
||||||
|
- 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: use insecure cipher
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.HOST }}
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
password: ${{ secrets.PASSWORD }}
|
||||||
|
port: ${{ secrets.PORT }}
|
||||||
|
script: |
|
||||||
|
ls \
|
||||||
|
-lah
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM appleboy/drone-ssh:1.5.4-linux-amd64
|
FROM appleboy/drone-ssh:1.6.3-linux-amd64
|
||||||
|
|
||||||
ADD entrypoint.sh /entrypoint.sh
|
ADD entrypoint.sh /entrypoint.sh
|
||||||
RUN chmod +x /entrypoint.sh
|
RUN chmod +x /entrypoint.sh
|
||||||
|
146
README.md
146
README.md
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
[](https://github.com/appleboy/ssh-action/actions)
|
[](https://github.com/appleboy/ssh-action/actions)
|
||||||
|
|
||||||
|
**Important**: Only support **Linux** [docker](https://www.docker.com/) container.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Executing remote ssh commands.
|
Executing remote ssh commands.
|
||||||
@ -45,18 +47,61 @@ out: ***
|
|||||||
|
|
||||||
See [action.yml](./action.yml) for more detailed information.
|
See [action.yml](./action.yml) for more detailed information.
|
||||||
|
|
||||||
* host - remote host
|
* host - ssh host
|
||||||
* port - remote port, default is `22`
|
* port - ssh port, default is `22`
|
||||||
* username - ssh username
|
* username - ssh username
|
||||||
* password - ssh password
|
* 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`
|
* timeout - timeout for ssh to remote host, default is `30s`
|
||||||
* command_timeout - timeout for ssh command, default is `10m`
|
* command_timeout - timeout for ssh command, default is `10m`
|
||||||
* key - content of ssh private key. ex raw content of ~/.ssh/id_rsa
|
* key - content of ssh private key. ex raw content of ~/.ssh/id_rsa
|
||||||
* key_path - path of ssh private key
|
* key_path - path of ssh private key
|
||||||
|
* fingerprint - fingerprint SHA256 of the host public key, default is to skip verification
|
||||||
* script - execute commands
|
* script - execute commands
|
||||||
* script_stop - stop script after first failure
|
* script_stop - stop script after first failure
|
||||||
* envs - pass environment variable to shell script
|
* envs - pass environment variable to shell script
|
||||||
* debug - enable debug mode
|
* 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
|
||||||
|
|
||||||
|
### Setting up SSH Key
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t rsa -b 4096 -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/).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat .ssh/id_rsa.pub | ssh b@B 'cat >> .ssh/authorized_keys'
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy Private Key content and paste in Github Secrets.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clip < ~/.ssh/id_rsa
|
||||||
|
```
|
||||||
|
|
||||||
|
See the detail information about [SSH login without password](http://www.linuxproblem.org/art_9.html)
|
||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
@ -119,6 +164,37 @@ Multiple Hosts
|
|||||||
ls -al
|
ls -al
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Multiple Hosts with differebt port
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- name: multiple host
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
- host: "foo.com"
|
||||||
|
+ host: "foo.com:1234,bar.com:5678"
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
key: ${{ secrets.KEY }}
|
||||||
|
script: |
|
||||||
|
whoami
|
||||||
|
ls -al
|
||||||
|
```
|
||||||
|
|
||||||
|
Synchronous execution on multiple hosts
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- name: multiple host
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: "foo.com,bar.com"
|
||||||
|
+ sync: true
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
key: ${{ secrets.KEY }}
|
||||||
|
port: ${{ secrets.PORT }}
|
||||||
|
script: |
|
||||||
|
whoami
|
||||||
|
ls -al
|
||||||
|
```
|
||||||
|
|
||||||
Pass environment variable to shell script
|
Pass environment variable to shell script
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
@ -126,17 +202,22 @@ Pass environment variable to shell script
|
|||||||
uses: appleboy/ssh-action@master
|
uses: appleboy/ssh-action@master
|
||||||
+ env:
|
+ env:
|
||||||
+ FOO: "BAR"
|
+ FOO: "BAR"
|
||||||
|
+ BAR: "FOO"
|
||||||
|
+ SHA: ${{ github.sha }}
|
||||||
with:
|
with:
|
||||||
host: ${{ secrets.HOST }}
|
host: ${{ secrets.HOST }}
|
||||||
username: ${{ secrets.USERNAME }}
|
username: ${{ secrets.USERNAME }}
|
||||||
key: ${{ secrets.KEY }}
|
key: ${{ secrets.KEY }}
|
||||||
port: ${{ secrets.PORT }}
|
port: ${{ secrets.PORT }}
|
||||||
+ envs: FOO
|
+ envs: FOO,BAR
|
||||||
script: |
|
script: |
|
||||||
echo "I am $FOO"
|
echo "I am $FOO"
|
||||||
echo "I am $BAR"
|
echo "I am $BAR"
|
||||||
|
echo "sha: $SHA"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
_Inside `env` object, you need to pass every environment variable as a string, passing `Integer` data type or any other may output unexpected results._
|
||||||
|
|
||||||
Stop script after first failure. ex: missing `abc` folder
|
Stop script after first failure. ex: missing `abc` folder
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
@ -165,3 +246,62 @@ ls -al
|
|||||||
err: mkdir: cannot create directory ‘abc/def’: No such file or directory
|
err: mkdir: cannot create directory ‘abc/def’: No such file or directory
|
||||||
##[error]Docker run failed with exit code 1
|
##[error]Docker run failed with exit code 1
|
||||||
```
|
```
|
||||||
|
|
||||||
|
How to connect remote server using `ProxyCommand`?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
+--------+ +----------+ +-----------+
|
||||||
|
| Laptop | <--> | Jumphost | <--> | FooServer |
|
||||||
|
+--------+ +----------+ +-----------+
|
||||||
|
```
|
||||||
|
|
||||||
|
in your `~/.ssh/config`, you will see the following.
|
||||||
|
|
||||||
|
```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
|
||||||
|
```
|
||||||
|
|
||||||
|
How to convert to YAML format of GitHubActions.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- name: ssh proxy command
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
Protecting a Private Key. The purpose of the passphrase is usually to encrypt the private key. This makes the key file by itself useless to an attacker. It is not uncommon for files to leak from backups or decommissioned hardware, and hackers commonly exfiltrate files from compromised systems.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- name: ssh key passphrase
|
||||||
|
uses: appleboy/ssh-action@master
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.HOST }}
|
||||||
|
username: ${{ secrets.USERNAME }}
|
||||||
|
key: ${{ secrets.KEY }}
|
||||||
|
port: ${{ secrets.PORT }}
|
||||||
|
+ passphrase: ${{ secrets.PASSPHRASE }}
|
||||||
|
script: |
|
||||||
|
whoami
|
||||||
|
ls -al
|
||||||
|
```
|
||||||
|
43
action.yml
43
action.yml
@ -3,16 +3,26 @@ description: 'Executing remote ssh commands'
|
|||||||
author: 'Bo-Yi Wu'
|
author: 'Bo-Yi Wu'
|
||||||
inputs:
|
inputs:
|
||||||
host:
|
host:
|
||||||
description: 'ssh remote host'
|
description: 'ssh host'
|
||||||
port:
|
port:
|
||||||
description: 'ssh remote port'
|
description: 'ssh port'
|
||||||
default: 22
|
default: 22
|
||||||
|
passphrase:
|
||||||
|
description: 'ssh key passphrase'
|
||||||
username:
|
username:
|
||||||
description: 'ssh username'
|
description: 'ssh username'
|
||||||
password:
|
password:
|
||||||
description: 'ssh password'
|
description: 'ssh password'
|
||||||
|
sync:
|
||||||
|
description: 'synchronous execution if multiple hosts'
|
||||||
|
default: false
|
||||||
|
use_insecure_cipher:
|
||||||
|
description: 'include more ciphers with use_insecure_cipher'
|
||||||
|
default: false
|
||||||
|
cipher:
|
||||||
|
description: 'the allowed cipher algorithms. If unspecified then a sensible'
|
||||||
timeout:
|
timeout:
|
||||||
description: 'timeout for ssh to remote host'
|
description: 'timeout for ssh to host'
|
||||||
default: "30s"
|
default: "30s"
|
||||||
command_timeout:
|
command_timeout:
|
||||||
description: 'timeout for ssh command'
|
description: 'timeout for ssh command'
|
||||||
@ -21,6 +31,33 @@ inputs:
|
|||||||
description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa'
|
description: 'content of ssh private key. ex raw content of ~/.ssh/id_rsa'
|
||||||
key_path:
|
key_path:
|
||||||
description: 'path of ssh private key'
|
description: 'path of ssh private key'
|
||||||
|
fingerprint:
|
||||||
|
description: 'sha256 fingerprint of the host public key'
|
||||||
|
proxy_host:
|
||||||
|
description: 'ssh proxy host'
|
||||||
|
proxy_port:
|
||||||
|
description: 'ssh proxy port'
|
||||||
|
default: 22
|
||||||
|
proxy_username:
|
||||||
|
description: 'ssh proxy username'
|
||||||
|
proxy_password:
|
||||||
|
description: 'ssh proxy password'
|
||||||
|
proxy_passphrase:
|
||||||
|
description: 'ssh proxy key passphrase'
|
||||||
|
proxy_timeout:
|
||||||
|
description: 'timeout for ssh to proxy host'
|
||||||
|
default: "30s"
|
||||||
|
proxy_key:
|
||||||
|
description: 'content of ssh proxy private key. ex raw content of ~/.ssh/id_rsa'
|
||||||
|
proxy_key_path:
|
||||||
|
description: 'path of ssh proxy private key'
|
||||||
|
proxy_fingerprint:
|
||||||
|
description: 'sha256 fingerprint of the proxy host public key'
|
||||||
|
proxy_cipher:
|
||||||
|
description: 'the allowed cipher algorithms. If unspecified then a sensible'
|
||||||
|
proxy_use_insecure_cipher:
|
||||||
|
description: 'include more ciphers with use_insecure_cipher'
|
||||||
|
default: false
|
||||||
script:
|
script:
|
||||||
description: 'execute commands'
|
description: 'execute commands'
|
||||||
script_stop:
|
script_stop:
|
||||||
|
Reference in New Issue
Block a user