From dca1d5d96c82e01b69fe77225a7559b4684828d8 Mon Sep 17 00:00:00 2001 From: Sn0wCrack <442287+Sn0wCrack@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:18:38 +1000 Subject: [PATCH 1/4] feat: start working on better self hosted runner support essentially attempt to spawn ssh agent independently and kill it when the action is over --- action.yaml | 6 ++++++ cleanup.js | 20 ++++++++++++++++++++ index.js | 23 +++++++++++++++++------ 3 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 cleanup.js diff --git a/action.yaml b/action.yaml index f69e11f..05d9a1f 100644 --- a/action.yaml +++ b/action.yaml @@ -33,6 +33,11 @@ inputs: default: '' description: Content of `~/.ssh/known_hosts` file. + disable-strict-host-checking: + required: false + default: 'true' + description: Disable Strict Host Checking if no known_hosts are provided + ssh-config: required: false default: '' @@ -71,6 +76,7 @@ inputs: runs: using: 'node20' main: 'index.js' + post: 'cleanup.js' branding: color: blue diff --git a/cleanup.js b/cleanup.js new file mode 100644 index 0000000..ef86c34 --- /dev/null +++ b/cleanup.js @@ -0,0 +1,20 @@ +import core from '@actions/core' +import { $ } from 'zx' + +void (async function main() { + try { + await cleanup() + } catch (err) { + core.setFailed(err.message) + } +})() + +async function cleanup() { + if (core.getBooleanInput('skip-ssh-setup')) { + return + } + + // Remove all keys from ssh-agent and kill process + await $`ssh-add -D` + await $`kill \$SSH_AGENT_PID` +} diff --git a/index.js b/index.js index b50cc0b..33a261e 100644 --- a/index.js +++ b/index.js @@ -15,15 +15,24 @@ async function ssh() { return } - let sshHomeDir = `${process.env['HOME']}/.ssh` + const sshHomeDir = `${process.env['HOME']}/.ssh` if (!fs.existsSync(sshHomeDir)) { fs.mkdirSync(sshHomeDir) } - let authSock = '/tmp/ssh-auth.sock' - await $`ssh-agent -a ${authSock}` - core.exportVariable('SSH_AUTH_SOCK', authSock) + await $`eval \`ssh-agent\`` + + const sshAgentSocket = await $`echo \$SSH_AUTH_SOCKET` + + const sshAgentProcessId = await $`echo \$SSH_AGENT_PID` + + if (!sshAgentSocket || !sshAgentProcessId) { + throw new Error('Failed to start ssh-agent') + } + + core.exportVariable('SSH_AUTH_SOCK', sshAgentSocket.trim()) + core.exportVariable('SSH_AGENT_PID', sshAgentProcessId.trim()) let privateKey = core.getInput('private-key') if (privateKey !== '') { @@ -39,8 +48,10 @@ async function ssh() { fs.appendFileSync(`${sshHomeDir}/known_hosts`, knownHosts) fs.chmodSync(`${sshHomeDir}/known_hosts`, '600') } else { - fs.appendFileSync(`${sshHomeDir}/config`, `StrictHostKeyChecking no`) - fs.chmodSync(`${sshHomeDir}/config`, '600') + if (core.getBooleanInput('disable-strict-host-checking')) { + fs.appendFileSync(`${sshHomeDir}/config`, `StrictHostKeyChecking no`) + fs.chmodSync(`${sshHomeDir}/config`, '600') + } } let sshConfig = core.getInput('ssh-config') From 7e185f29528389a30009b0fd95734f8e7ed20f5e Mon Sep 17 00:00:00 2001 From: Sn0wCrack <442287+Sn0wCrack@users.noreply.github.com> Date: Thu, 19 Sep 2024 14:48:15 +1000 Subject: [PATCH 2/4] fix: get ssh agent details via regex instead doesn't seem like eval persists the environment variables --- index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 33a261e..7478775 100644 --- a/index.js +++ b/index.js @@ -21,11 +21,17 @@ async function ssh() { fs.mkdirSync(sshHomeDir) } - await $`eval \`ssh-agent\`` + const sshAgentOutput = await $`ssh-agent` - const sshAgentSocket = await $`echo \$SSH_AUTH_SOCKET` + const sshAgentSocket = sshAgentOutput + .stdout + .match(/SSH_AUTH_SOCK=(?.*); export SSH_AUTH_SOCK;/) + ?.groups['path'] ?? null; - const sshAgentProcessId = await $`echo \$SSH_AGENT_PID` + const sshAgentProcessId = sshAgentOutput + .stdout + .match(/SSH_AGENT_PID=(?\d+); export SSH_AGENT_PID;/) + ?.groups['pid'] ?? null; if (!sshAgentSocket || !sshAgentProcessId) { throw new Error('Failed to start ssh-agent') From 5ade4b973dfd7fcdd2d8a136d4c137282b59bdb6 Mon Sep 17 00:00:00 2001 From: Sn0wCrack <442287+Sn0wCrack@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:09:27 +1000 Subject: [PATCH 3/4] fix: persist agent pid in state instead --- cleanup.js | 4 +++- index.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cleanup.js b/cleanup.js index ef86c34..2ae0493 100644 --- a/cleanup.js +++ b/cleanup.js @@ -14,7 +14,9 @@ async function cleanup() { return } + const sshAgentPid = core.getState('ssh-agent-pid') + // Remove all keys from ssh-agent and kill process await $`ssh-add -D` - await $`kill \$SSH_AGENT_PID` + await $`kill ${sshAgentPid}` } diff --git a/index.js b/index.js index 7478775..3b556c4 100644 --- a/index.js +++ b/index.js @@ -38,7 +38,9 @@ async function ssh() { } core.exportVariable('SSH_AUTH_SOCK', sshAgentSocket.trim()) - core.exportVariable('SSH_AGENT_PID', sshAgentProcessId.trim()) + core.exportVariable('SSH_AGENT_PID', ) + + core.saveState('ssh-agent-pid', sshAgentProcessId.trim()) let privateKey = core.getInput('private-key') if (privateKey !== '') { From 50eb1df62e5f52e4bd4453a30e5fc6f726aa5735 Mon Sep 17 00:00:00 2001 From: Sn0wCrack <442287+Sn0wCrack@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:24:55 +1000 Subject: [PATCH 4/4] fix: persisting ssh agent pid in environment variable chore: add comment explaining why we regex output --- index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 3b556c4..9655fab 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,9 @@ async function ssh() { fs.mkdirSync(sshHomeDir) } + // Unfortunately running the output into bash or eval-ing it does + // not persist the exported environment variables, so instead we + // parse out the variables via regex, not ideal but works a treat. const sshAgentOutput = await $`ssh-agent` const sshAgentSocket = sshAgentOutput @@ -38,7 +41,7 @@ async function ssh() { } core.exportVariable('SSH_AUTH_SOCK', sshAgentSocket.trim()) - core.exportVariable('SSH_AGENT_PID', ) + core.exportVariable('SSH_AGENT_PID', sshAgentProcessId.trim()) core.saveState('ssh-agent-pid', sshAgentProcessId.trim())