Support multiple SSH keys (#14)
* Support concatenation of multiple private keys in the given secret * Add a changelog
This commit is contained in:
parent
ea39f521c5
commit
6cf6299d23
5 changed files with 73 additions and 17 deletions
20
.github/workflows/demo.yml
vendored
20
.github/workflows/demo.yml
vendored
|
@ -1,7 +1,21 @@
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
load_key_demo:
|
single_key_demo:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, macOS-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Setup key
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
ssh-private-key: |
|
||||||
|
${{ secrets.DEMO_KEY }}
|
||||||
|
${{ secrets.DEMO_KEY_2 }}
|
||||||
|
|
||||||
|
multiple_keys_demo:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macOS-latest]
|
os: [ubuntu-latest, macOS-latest]
|
||||||
|
@ -12,8 +26,6 @@ jobs:
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
ssh-private-key: ${{ secrets.DEMO_KEY }}
|
ssh-private-key: ${{ secrets.DEMO_KEY }}
|
||||||
- run: |
|
|
||||||
ssh-add -l
|
|
||||||
echo SSH_AUTH_SOCK is at $SSH_AUTH_SOCK
|
|
||||||
|
|
||||||
|
|
||||||
|
|
14
CHANGELOG.md
Normal file
14
CHANGELOG.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* Multiple SSH keys can now be provided (#14, closes #7). Thanks to
|
||||||
|
@webknjaz and @bradmartin for support and tests.
|
||||||
|
|
42
README.md
42
README.md
|
@ -15,10 +15,10 @@ GitHub Actions only have access to the repository they run for. So, in order to
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
1. Create an SSH key with sufficient access privileges. For security reasons, don't use your personal SSH key but set up a dedicated one for use in GitHub Actions. See below for a few hints if you are unsure about this step.
|
1. Create an SSH key with sufficient access privileges. For security reasons, don't use your personal SSH key but set up a dedicated one for use in GitHub Actions. See below for a few hints if you are unsure about this step.
|
||||||
2. In your repository, go to the *Settings > Secrets* menu and create a new secret called `SSH_PRIVATE_KEY`. Put the *unencrypted private* SSH key in `PEM` format into the contents field. <br>
|
2. Make sure you don't have a passphrase set on the private key.
|
||||||
This key should start with `-----BEGIN RSA PRIVATE KEY-----`, consist of many lines and ends with `-----END RSA PRIVATE KEY-----`.
|
3. In your repository, go to the *Settings > Secrets* menu and create a new secret. In this example, we'll call it `SSH_PRIVATE_KEY`. Put the contents of the *private* SSH key file into the contents field. <br>
|
||||||
You can just copy the key as-is from the private key file.
|
This key should start with `-----BEGIN ... PRIVATE KEY-----`, consist of many lines and ends with `-----END ... PRIVATE KEY-----`.
|
||||||
3. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v1` line.
|
4. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v1` line.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# .github/workflows/my-workflow.yml
|
# .github/workflows/my-workflow.yml
|
||||||
|
@ -34,7 +34,28 @@ jobs:
|
||||||
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||||
- ... other steps
|
- ... other steps
|
||||||
```
|
```
|
||||||
4. If, for some reason, you need to change the location of the SSH agent socket, you can use the `ssh-auth-sock` input to provide a path.
|
5. If, for some reason, you need to change the location of the SSH agent socket, you can use the `ssh-auth-sock` input to provide a path.
|
||||||
|
|
||||||
|
### Using multiple keys
|
||||||
|
|
||||||
|
There are cases where you might need to use multiple keys. For example, "deployment keys" might be limited to a single repository each.
|
||||||
|
|
||||||
|
In that case, you can set-up the different keys as multiple secrets and pass them all to the action like so:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# ... contens as before
|
||||||
|
- uses: webfactory/ssh-agent@v0.1.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: |
|
||||||
|
${{ secrets.FIRST_KEY }}
|
||||||
|
${{ secrets.NEXT_KEY }}
|
||||||
|
${{ secrets.ANOTHER_KEY }}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `ssh-agent` will load all of the keys and try each one in order when establishing SSH connections.
|
||||||
|
|
||||||
|
There's one **caveat**, though: SSH servers may abort the connection attempt after a number of mismatching keys have been presented. So if, for example, you have
|
||||||
|
six different keys loaded into the `ssh-agent`, but the server aborts after five unknown keys, the last key (which might be the right one) will never even be tried.
|
||||||
|
|
||||||
## Known issues and limitations
|
## Known issues and limitations
|
||||||
|
|
||||||
|
@ -72,11 +93,12 @@ As a side note, using `ssh-keyscan` without proper key verification is susceptib
|
||||||
|
|
||||||
## Creating SSH keys
|
## Creating SSH keys
|
||||||
|
|
||||||
In order to create a new SSH key, run `ssh-keygen -t rsa -b 4096 -m pem -f path/to/keyfile`. This will prompt you for a key passphrase and save the key in `path/to/keyfile`.
|
In order to create a new SSH key, run `ssh-keygen -t ed25519 -a 100 -f path/to/keyfile`, as suggested in [this blog post](https://stribika.github.io/2015/01/04/secure-secure-shell.html).
|
||||||
|
If you need to work with some older server software and need RSA keys, tr `ssh-keygen -t rsa -b 4096 -o -f path/to/keyfile` instead.
|
||||||
|
|
||||||
Having a passphrase is a good thing, since it will keep the key encrypted on your disk. When configuring the secret `SSH_PRIVATE_KEY` value in your repository, however, you will need the private key *unencrypted*.
|
Both commands will prompt you for a key passphrase and save the key in `path/to/keyfile`.
|
||||||
|
In general, having a passphrase is a good thing, since it will keep the key encrypted on your disk. When using the key with this action, however, you need to make sure you don't
|
||||||
To show the private key unencrypted, run `openssl rsa -in path/to/key -outform pem`.
|
specify a passphrase: The key must be usable without reading the passphrase from input. Since the key itself is stored using GitHub's "Secret" feature, it should be fairly safe anyway.
|
||||||
|
|
||||||
## Authorizing a key
|
## Authorizing a key
|
||||||
|
|
||||||
|
@ -93,7 +115,7 @@ As a note to my future self, in order to work on this repo:
|
||||||
* Clone it
|
* Clone it
|
||||||
* Run `npm install` to fetch dependencies
|
* Run `npm install` to fetch dependencies
|
||||||
* _hack hack hack_
|
* _hack hack hack_
|
||||||
* `node index.js` (inputs are passed through `INPUT_` env vars, but how to set `ssh-private-key`?)
|
* `node index.js`. Inputs are passed through `INPUT_` env vars with their names uppercased. Use `env "INPUT_SSH-PRIVATE-KEY=\`cat file\`" node index.js` for this action.
|
||||||
* Run `./node_modules/.bin/ncc build index.js` to update `dist/index.js`, which is the file actually run
|
* Run `./node_modules/.bin/ncc build index.js` to update `dist/index.js`, which is the file actually run
|
||||||
* Read https://help.github.com/en/articles/creating-a-javascript-action if unsure.
|
* Read https://help.github.com/en/articles/creating-a-javascript-action if unsure.
|
||||||
* Maybe update the README example when publishing a new version.
|
* Maybe update the README example when publishing a new version.
|
||||||
|
|
6
dist/index.js
vendored
6
dist/index.js
vendored
|
@ -72,7 +72,11 @@ try {
|
||||||
core.exportVariable('SSH_AUTH_SOCK', authSock);
|
core.exportVariable('SSH_AUTH_SOCK', authSock);
|
||||||
|
|
||||||
console.log("Adding private key to agent");
|
console.log("Adding private key to agent");
|
||||||
child_process.execSync('ssh-add -', { input: core.getInput('ssh-private-key') });
|
core.getInput('ssh-private-key').split(/(?=-----BEGIN)/).forEach(function(key) {
|
||||||
|
child_process.execSync('ssh-add -', { input: key.trim() + "\n" });
|
||||||
|
});
|
||||||
|
console.log("Keys added:");
|
||||||
|
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
6
index.js
6
index.js
|
@ -17,7 +17,11 @@ try {
|
||||||
core.exportVariable('SSH_AUTH_SOCK', authSock);
|
core.exportVariable('SSH_AUTH_SOCK', authSock);
|
||||||
|
|
||||||
console.log("Adding private key to agent");
|
console.log("Adding private key to agent");
|
||||||
child_process.execSync('ssh-add -', { input: core.getInput('ssh-private-key') });
|
core.getInput('ssh-private-key').split(/(?=-----BEGIN)/).forEach(function(key) {
|
||||||
|
child_process.execSync('ssh-add -', { input: key.trim() + "\n" });
|
||||||
|
});
|
||||||
|
console.log("Keys added:");
|
||||||
|
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue