Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace ssh-private-key with ssh-private-keys and expected input is json with {name: key} entries. #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 28 additions & 43 deletions .github/workflows/demo.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,31 @@
on: [ push, pull_request ]

jobs:
deployment_keys_demo:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, macOS-latest, windows-latest ]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Setup key
uses: ./
with:
ssh-private-key: |
${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
- run: |
git clone https://github.com/mpdude/test-1.git test-1-http
git clone [email protected]:mpdude/test-1.git test-1-git
git clone ssh://[email protected]/mpdude/test-1.git test-1-git-ssh
git clone https://github.com/mpdude/test-2.git test-2-http
git clone [email protected]:mpdude/test-2.git test-2-git
git clone ssh://[email protected]/mpdude/test-2.git test-2-git-ssh

docker_demo:
runs-on: ubuntu-latest
container:
image: ubuntu:latest
steps:
- uses: actions/checkout@v3
- run: apt update && apt install -y openssh-client git
- name: Setup key
uses: ./
with:
ssh-private-key: |
${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
- run: |
git clone https://github.com/mpdude/test-1.git test-1-http
git clone [email protected]:mpdude/test-1.git test-1-git
git clone ssh://[email protected]/mpdude/test-1.git test-1-git-ssh
git clone https://github.com/mpdude/test-2.git test-2-http
git clone [email protected]:mpdude/test-2.git test-2-git
git clone ssh://[email protected]/mpdude/test-2.git test-2-git-ssh

vmo_deployment_keys_demo:
runs-on: ubuntu-latest
container:
image: ubuntu:latest
steps:
- uses: actions/checkout@v3
- run: apt update && apt install -y openssh-client git curl
- if: ${{ env.ACT }}
name: Hack container for local development
run: |
curl -fsSL https://deb.nodesource.com/setup_16.x | bash -s
apt-get install -y nodejs
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: '16.x'
- name: Setup key
uses: ./
with:
ssh-private-keys: |
{
"[email protected]:vaimo/vsf2_ext-lru-cache-driver.git": "${{ secrets.TEST_1_DEPLOY_KEY }}",
"[email protected]:mpdude/test-2.git": "${{ secrets.TEST_2_DEPLOY_KEY }}"
}
- run: |
git clone https://github.com/vaimo/vsf2_ext-lru-cache-driver.git test-1-http
git clone [email protected]:vaimo/vsf2_ext-lru-cache-driver.git test-1-git
git clone ssh://[email protected]/vaimo/vsf2_ext-lru-cache-driver.git test-1-git-ssh
29 changes: 16 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,21 @@ GitHub Actions only have access to the repository they run for. So, in order to
* 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>
* This key should start with `-----BEGIN ... PRIVATE KEY-----`, consist of many lines and ends with `-----END ... PRIVATE KEY-----`.
5. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v2` line.
5. In your workflow definition file, add the following step. Preferably this would be rather on top, near the `actions/checkout@v3` line.

```yaml
# .github/workflows/my-workflow.yml
jobs:
my_job:
...
steps:
- actions/checkout@v2
# Make sure the @v0.6.0 matches the current version of the
# action
- uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
- actions/checkout@v3
- uses: vaimo/webfactory-ssh-agent-github@feature/json-private-keys
with:
ssh-private-keys: |
{
"[email protected]:vendor/repo-1.git": "${{ secrets.SSH_PRIVATE_KEY }}"
}
- ... other steps
```
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.
Expand All @@ -53,12 +54,14 @@ You can set up different keys as different secrets and pass them all to the acti

```yaml
# ... contens as before
- uses: webfactory/ssh-agent@v0.6.0
- uses: vaimo/webfactory-ssh-agent-github@feature/json-private-keys
with:
ssh-private-key: |
${{ secrets.FIRST_KEY }}
${{ secrets.NEXT_KEY }}
${{ secrets.ANOTHER_KEY }}
ssh-private-keys: |
{
"[email protected]:vendor/repo-1.git": "${{ secrets.FIRST_KEY }}",
"[email protected]:vendor/repo-2.git": "${{ secrets.NEXT_KEY }}",
"[email protected]:vendor/repo-3.git": "${{ secrets.ANOTHER_KEY }}",
}
```

The `ssh-agent` will load all of the keys and try each one in order when establishing SSH connections.
Expand All @@ -80,7 +83,7 @@ To support picking the right key in this use case, this action scans _key commen

The following inputs can be used to control the action's behavior:

* `ssh-private-key`: Required. Use this to provide the key(s) to load as GitHub Actions secrets.
* `ssh-private-keys`: Required. Use this to provide the key(s) to load as GitHub Actions secrets.
* `ssh-auth-sock`: Can be used to control where the SSH agent socket will be placed. Ultimately affects the `$SSH_AUTH_SOCK` environment variable.
* `log-public-key`: Set this to `false` if you want to suppress logging of _public_ key information. To simplify debugging and since it contains public key information only, this is turned on by default.

Expand Down
9 changes: 5 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
name: 'webfactory/ssh-agent'
name: 'vaimo/webfactory-ssh-agent'
description: 'Run `ssh-agent` and load an SSH key to access other private repositories'
inputs:
ssh-private-key:
description: 'Private SSH key to register in the SSH agent'
ssh-private-keys:
description: 'Private SSH key(s) to register in the SSH agent'
required: true
default: 'GitHub'
ssh-auth-sock:
description: 'Where to place the SSH Agent auth socket'
log-public-key:
description: 'Whether or not to log public key fingerprints'
required: false
default: true
runs:
using: 'node16'
using: 'node20'
main: 'dist/index.js'
post: 'dist/cleanup.js'
post-if: 'always()'
Expand Down
57 changes: 36 additions & 21 deletions dist/cleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,13 +292,14 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.issueCommand = void 0;
exports.prepareKeyValueMessage = exports.issueFileCommand = void 0;
// We use any as a valid input type
/* eslint-disable @typescript-eslint/no-explicit-any */
const fs = __importStar(__webpack_require__(747));
const os = __importStar(__webpack_require__(87));
const uuid_1 = __webpack_require__(62);
const utils_1 = __webpack_require__(82);
function issueCommand(command, message) {
function issueFileCommand(command, message) {
const filePath = process.env[`GITHUB_${command}`];
if (!filePath) {
throw new Error(`Unable to find environment variable for file command ${command}`);
Expand All @@ -310,7 +311,22 @@ function issueCommand(command, message) {
encoding: 'utf8'
});
}
exports.issueCommand = issueCommand;
exports.issueFileCommand = issueFileCommand;
function prepareKeyValueMessage(key, value) {
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
const convertedValue = utils_1.toCommandValue(value);
// These should realistically never happen, but just in case someone finds a
// way to exploit uuid generation let's not allow keys or values that contain
// the delimiter.
if (key.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
}
if (convertedValue.includes(delimiter)) {
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
}
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`;
}
exports.prepareKeyValueMessage = prepareKeyValueMessage;
//# sourceMappingURL=file-command.js.map

/***/ }),
Expand Down Expand Up @@ -1668,7 +1684,6 @@ const file_command_1 = __webpack_require__(102);
const utils_1 = __webpack_require__(82);
const os = __importStar(__webpack_require__(87));
const path = __importStar(__webpack_require__(622));
const uuid_1 = __webpack_require__(62);
const oidc_utils_1 = __webpack_require__(742);
/**
* The code to exit an action
Expand Down Expand Up @@ -1698,20 +1713,9 @@ function exportVariable(name, val) {
process.env[name] = convertedVal;
const filePath = process.env['GITHUB_ENV'] || '';
if (filePath) {
const delimiter = `ghadelimiter_${uuid_1.v4()}`;
// These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter.
if (name.includes(delimiter)) {
throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`);
}
if (convertedVal.includes(delimiter)) {
throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`);
}
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`;
file_command_1.issueCommand('ENV', commandValue);
}
else {
command_1.issueCommand('set-env', { name }, convertedVal);
return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val));
}
command_1.issueCommand('set-env', { name }, convertedVal);
}
exports.exportVariable = exportVariable;
/**
Expand All @@ -1729,7 +1733,7 @@ exports.setSecret = setSecret;
function addPath(inputPath) {
const filePath = process.env['GITHUB_PATH'] || '';
if (filePath) {
file_command_1.issueCommand('PATH', inputPath);
file_command_1.issueFileCommand('PATH', inputPath);
}
else {
command_1.issueCommand('add-path', {}, inputPath);
Expand Down Expand Up @@ -1769,7 +1773,10 @@ function getMultilineInput(name, options) {
const inputs = getInput(name, options)
.split('\n')
.filter(x => x !== '');
return inputs;
if (options && options.trimWhitespace === false) {
return inputs;
}
return inputs.map(input => input.trim());
}
exports.getMultilineInput = getMultilineInput;
/**
Expand Down Expand Up @@ -1802,8 +1809,12 @@ exports.getBooleanInput = getBooleanInput;
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function setOutput(name, value) {
const filePath = process.env['GITHUB_OUTPUT'] || '';
if (filePath) {
return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value));
}
process.stdout.write(os.EOL);
command_1.issueCommand('set-output', { name }, value);
command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value));
}
exports.setOutput = setOutput;
/**
Expand Down Expand Up @@ -1932,7 +1943,11 @@ exports.group = group;
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function saveState(name, value) {
command_1.issueCommand('save-state', { name }, value);
const filePath = process.env['GITHUB_STATE'] || '';
if (filePath) {
return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value));
}
command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value));
}
exports.saveState = saveState;
/**
Expand Down
Loading
Loading