mirror of
https://github.com/webfactory/ssh-agent.git
synced 2025-04-24 06:52:13 +00:00
add git deploy key wrapper functionality
This commit is contained in:
parent
73d2440ad4
commit
17860381fc
9 changed files with 88 additions and 8 deletions
12
README.md
12
README.md
|
@ -57,14 +57,20 @@ The `ssh-agent` will load all of the keys and try each one in order when establi
|
||||||
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
|
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.
|
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.
|
||||||
|
|
||||||
Also, when using **Github deploy keys**, GitHub servers will accept the first known key. But since deploy keys are scoped to a single repository, you might get the error message `fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.` if the wrong key/repository combination is tried.
|
You might want to [try a wrapper script around `ssh`](https://gist.github.com/mpdude/e56fcae5bc541b95187fa764aafb5e6d) that can pick the right key, based on key comments. See [our blog post](https://www.webfactory.de/blog/using-multiple-ssh-deploy-keys-with-github) for the full story.
|
||||||
|
|
||||||
In both cases, you might want to [try a wrapper script around `ssh`](https://gist.github.com/mpdude/e56fcae5bc541b95187fa764aafb5e6d) that can pick the right key, based on key comments. See [our blog post](https://www.webfactory.de/blog/using-multiple-ssh-deploy-keys-with-github) for the full story.
|
Also, when using **Github deploy keys**, GitHub servers will accept the first known key. But since deploy keys are scoped to a single repository, you might get the error message `fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.` if the wrong key/repository combination is tried.
|
||||||
|
For this scenario, you'll want to set `use-git-deploy-key-wrapper` to `true` and create your key with a comment that has the git SSH url in it. For example:
|
||||||
|
```
|
||||||
|
ssh-keygen -t ed25519 -a 100 -C "ssh://git@github.com/ORGANIZATION/REPO.git" -m PEM -N "" -f ~/.ssh/REPO -q
|
||||||
|
```
|
||||||
|
**Please note that `git@github.com` is followed by a `/`, not a `:`**
|
||||||
|
|
||||||
## Exported variables
|
## Exported variables
|
||||||
The action exports the `SSH_AUTH_SOCK` and `SSH_AGENT_PID` environment variables through the Github Actions core module.
|
The action exports the `SSH_AUTH_SOCK`, `SSH_AGENT_PID` and `GIT_SSH_COMMAND` environment variables through the Github Actions core module.
|
||||||
The `$SSH_AUTH_SOCK` is used by several applications like git or rsync to connect to the SSH authentication agent.
|
The `$SSH_AUTH_SOCK` is used by several applications like git or rsync to connect to the SSH authentication agent.
|
||||||
The `$SSH_AGENT_PID` contains the process id of the agent. This is used to kill the agent in post job action.
|
The `$SSH_AGENT_PID` contains the process id of the agent. This is used to kill the agent in post job action.
|
||||||
|
The `$GIT_SSH_COMMAND` contains the path to the `git-deploy-key-wrapper` shell script. Git will use this value for SSH interactions instead of the SSH executable.
|
||||||
|
|
||||||
## Known issues and limitations
|
## Known issues and limitations
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ inputs:
|
||||||
required: true
|
required: true
|
||||||
ssh-auth-sock:
|
ssh-auth-sock:
|
||||||
description: 'Where to place the SSH Agent auth socket'
|
description: 'Where to place the SSH Agent auth socket'
|
||||||
|
use-git-deploy-key-wrapper:
|
||||||
|
description: 'Enable usage of git deploy key wrapper for multiple repositories with individual deploy keys'
|
||||||
|
default: false
|
||||||
runs:
|
runs:
|
||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
|
|
|
@ -5,6 +5,14 @@ try {
|
||||||
// Kill the started SSH agent
|
// Kill the started SSH agent
|
||||||
console.log('Stopping SSH agent')
|
console.log('Stopping SSH agent')
|
||||||
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
|
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
|
||||||
|
|
||||||
|
const home = process.env['HOME'];
|
||||||
|
const homeSsh = `${home}/.ssh`;
|
||||||
|
const gitSSHWrapperPath = path.join(homeSsh, 'git-deploy-key-wrapper.sh');
|
||||||
|
if (fs.existsSync(gitSSHWrapperPath)) {
|
||||||
|
console.log('Removing ssh git SSH wrapper');
|
||||||
|
fs.unlinkSync(gitSSHWrapperPath);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
console.log('Error stopping the SSH agent, proceeding anyway');
|
console.log('Error stopping the SSH agent, proceeding anyway');
|
||||||
|
|
8
dist/cleanup.js
vendored
8
dist/cleanup.js
vendored
|
@ -129,6 +129,14 @@ try {
|
||||||
// Kill the started SSH agent
|
// Kill the started SSH agent
|
||||||
console.log('Stopping SSH agent')
|
console.log('Stopping SSH agent')
|
||||||
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
|
execSync('kill ${SSH_AGENT_PID}', { stdio: 'inherit' })
|
||||||
|
|
||||||
|
const home = process.env['HOME'];
|
||||||
|
const homeSsh = `${home}/.ssh`;
|
||||||
|
const gitSSHWrapperPath = path.join(homeSsh, 'git-deploy-key-wrapper.sh');
|
||||||
|
if (fs.existsSync(gitSSHWrapperPath)) {
|
||||||
|
console.log('Removing ssh git SSH wrapper');
|
||||||
|
fs.unlinkSync(gitSSHWrapperPath);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error.message);
|
console.log(error.message);
|
||||||
console.log('Error stopping the SSH agent, proceeding anyway');
|
console.log('Error stopping the SSH agent, proceeding anyway');
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
# The last argument is the command to be executed on the remote end, which is something
|
# The last argument is the command to be executed on the remote end, which is something
|
||||||
# like "git-upload-pack 'webfactory/ssh-agent.git'". We need the repo path only, so we
|
# like "git-upload-pack 'webfactory/ssh-agent.git'". We need the repo path only, so we
|
||||||
|
# Terraform ends up bing "git-upload-pack '/webfactory/ssh-agent.git'"
|
||||||
# loop over this last argument to get the last part of if.
|
# loop over this last argument to get the last part of if.
|
||||||
for last in ${!#}; do :; done
|
for last in ${!#}; do :; done
|
||||||
|
|
||||||
|
@ -12,6 +13,9 @@ trap "rm -f $key_file" EXIT
|
||||||
eval last=$last
|
eval last=$last
|
||||||
|
|
||||||
# Try to pick the right key
|
# Try to pick the right key
|
||||||
ssh-add -L | grep --word-regexp --max-count=1 $last > $key_file
|
# No "--word-regexp" because Terraforms usage of git ends up as
|
||||||
|
# "git-upload-pack 'webfactory/ssh-agent.git'". "--word-regexp" will not match it.
|
||||||
|
# Other integrations still work without "--word-regexp"
|
||||||
|
ssh-add -L | grep --max-count=1 $last > $key_file
|
||||||
|
|
||||||
ssh -i $key_file "$@"
|
ssh -i $key_file "$@"
|
9
dist/index.js
vendored
9
dist/index.js
vendored
|
@ -163,6 +163,15 @@ try {
|
||||||
console.log("Keys added:");
|
console.log("Keys added:");
|
||||||
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||||
|
|
||||||
|
const useGitSSHWrapper = core.getInput('use-git-deploy-key-wrapper');
|
||||||
|
if(useGitSSHWrapper) {
|
||||||
|
const gitSSHWrapperFileName = 'git-deploy-key-wrapper.sh';
|
||||||
|
const gitSSHWrapperPath = path.join(homeSsh, gitSSHWrapperFileName);
|
||||||
|
fs.copyFileSync(path.join(process.cwd(), gitSSHWrapperFileName), gitSSHWrapperPath);
|
||||||
|
fs.chmodSync(gitSSHWrapperPath, "755");
|
||||||
|
|
||||||
|
core.exportVariable('GIT_SSH_COMMAND', gitSSHWrapperPath);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
9
index.js
9
index.js
|
@ -46,6 +46,15 @@ try {
|
||||||
console.log("Keys added:");
|
console.log("Keys added:");
|
||||||
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||||
|
|
||||||
|
const useGitSSHWrapper = core.getInput('use-git-deploy-key-wrapper');
|
||||||
|
if(useGitSSHWrapper) {
|
||||||
|
const gitSSHWrapperFileName = 'git-deploy-key-wrapper.sh';
|
||||||
|
const gitSSHWrapperPath = path.join(homeSsh, gitSSHWrapperFileName);
|
||||||
|
fs.copyFileSync(path.join(process.cwd(), gitSSHWrapperFileName), gitSSHWrapperPath);
|
||||||
|
fs.chmodSync(gitSSHWrapperPath, "755");
|
||||||
|
|
||||||
|
core.exportVariable('GIT_SSH_COMMAND', gitSSHWrapperPath);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,14 @@ const fs = require('fs')
|
||||||
const buildDir = path.join(process.cwd(), 'build')
|
const buildDir = path.join(process.cwd(), 'build')
|
||||||
const distDir = path.join(process.cwd(), 'dist')
|
const distDir = path.join(process.cwd(), 'dist')
|
||||||
|
|
||||||
const buildIndexJs = path.join(buildDir, 'index.js')
|
const gitSSHWrapperFileName = 'git-deploy-key-wrapper.sh';
|
||||||
const distIndexJs = path.join(distDir, 'index.js')
|
const gitSSHWrapper = path.join(process.cwd(), 'wrapper', gitSSHWrapperFileName);
|
||||||
const distCleanupJs = path.join(distDir, 'cleanup.js')
|
|
||||||
|
const buildIndexJs = path.join(buildDir, 'index.js');
|
||||||
|
const buildGitSSHWrapper = path.join(buildDir, gitSSHWrapperFileName);
|
||||||
|
const distIndexJs = path.join(distDir, 'index.js');
|
||||||
|
const distGitSSHWrapper = path.join(distDir, gitSSHWrapperFileName);
|
||||||
|
const distCleanupJs = path.join(distDir, 'cleanup.js');
|
||||||
|
|
||||||
if (!fs.existsSync(buildDir)) {
|
if (!fs.existsSync(buildDir)) {
|
||||||
fs.mkdirSync(buildDir)
|
fs.mkdirSync(buildDir)
|
||||||
|
@ -29,6 +34,13 @@ if (fs.existsSync(distCleanupJs)) {
|
||||||
}
|
}
|
||||||
fs.renameSync(buildIndexJs, distCleanupJs)
|
fs.renameSync(buildIndexJs, distCleanupJs)
|
||||||
|
|
||||||
|
console.log(`Copying "${gitSSHWrapperFileName}"`);
|
||||||
|
fs.copyFileSync(gitSSHWrapper, buildGitSSHWrapper);
|
||||||
|
if (fs.existsSync(distGitSSHWrapper)) {
|
||||||
|
fs.unlinkSync(distGitSSHWrapper);
|
||||||
|
}
|
||||||
|
fs.renameSync(buildGitSSHWrapper, distGitSSHWrapper);
|
||||||
|
|
||||||
console.log('Cleaning up...')
|
console.log('Cleaning up...')
|
||||||
fs.rmdirSync(buildDir)
|
fs.rmdirSync(buildDir)
|
||||||
|
|
||||||
|
|
21
wrapper/git-deploy-key-wrapper.sh
Normal file
21
wrapper/git-deploy-key-wrapper.sh
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# The last argument is the command to be executed on the remote end, which is something
|
||||||
|
# like "git-upload-pack 'webfactory/ssh-agent.git'". We need the repo path only, so we
|
||||||
|
# Terraform ends up bing "git-upload-pack '/webfactory/ssh-agent.git'"
|
||||||
|
# loop over this last argument to get the last part of if.
|
||||||
|
for last in ${!#}; do :; done
|
||||||
|
|
||||||
|
# Don't use "exec" to run "ssh" below; then the trap won't work.
|
||||||
|
key_file=$(mktemp -u)
|
||||||
|
trap "rm -f $key_file" EXIT
|
||||||
|
|
||||||
|
eval last=$last
|
||||||
|
|
||||||
|
# Try to pick the right key
|
||||||
|
# No "--word-regexp" because Terraforms usage of git ends up as
|
||||||
|
# "git-upload-pack 'webfactory/ssh-agent.git'". "--word-regexp" will not match it.
|
||||||
|
# Other integrations still work without "--word-regexp"
|
||||||
|
ssh-add -L | grep --max-count=1 $last > $key_file
|
||||||
|
|
||||||
|
ssh -i $key_file "$@"
|
Loading…
Add table
Reference in a new issue