diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml index c3bb009..9d8fad0 100644 --- a/.github/workflows/demo.yml +++ b/.github/workflows/demo.yml @@ -1,60 +1,46 @@ -on: [push, pull_request] +on: [ push, pull_request ] jobs: - single_key_demo: + deployment_keys_demo: strategy: + fail-fast: false matrix: - os: [ubuntu-latest, macOS-latest, windows-latest] + os: [ ubuntu-latest, macOS-latest, windows-latest ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - name: Setup key - uses: ./ - with: - ssh-private-key: | - ${{ secrets.DEMO_KEY }} - ${{ secrets.DEMO_KEY_2 }} - - multiple_keys_demo: - strategy: - matrix: - os: [ubuntu-latest, macOS-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - - name: Setup key - uses: ./ - with: - ssh-private-key: ${{ secrets.DEMO_KEY }} + - uses: actions/checkout@v2 + - 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 git@github.com:mpdude/test-1.git test-1-git + git clone ssh://git@github.com/mpdude/test-1.git test-1-git-ssh + git clone https://github.com/mpdude/test-2.git test-2-http + git clone git@github.com:mpdude/test-2.git test-2-git + git clone ssh://git@github.com/mpdude/test-2.git test-2-git-ssh docker_demo: - runs-on: ubuntu-latest + runs-on: ubuntu-latest container: image: ubuntu:latest steps: - - uses: actions/checkout@v2 - - run: apt update && apt install -y openssh-client - - name: Setup key - uses: ./ - with: - ssh-private-key: | - ${{ secrets.DEMO_KEY }} - ${{ secrets.DEMO_KEY_2 }} + - uses: actions/checkout@v2 + - 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 git@github.com:mpdude/test-1.git test-1-git + git clone ssh://git@github.com/mpdude/test-1.git test-1-git-ssh + git clone https://github.com/mpdude/test-2.git test-2-http + git clone git@github.com:mpdude/test-2.git test-2-git + git clone ssh://git@github.com/mpdude/test-2.git test-2-git-ssh - deployment_keys_demo: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - 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 git@github.com:mpdude/test-1.git test-1-git - git clone ssh://git@github.com/mpdude/test-1.git test-1-git-ssh - git clone https://github.com/mpdude/test-2.git test-2-http - git clone git@github.com:mpdude/test-2.git test-2-git - git clone ssh://git@github.com/mpdude/test-2.git test-2-git-ssh diff --git a/dist/index.js b/dist/index.js index ac64344..198776d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -130,77 +130,82 @@ try { return; } - var home; + const { home, sshAgent, sshAdd } = (process.env['OS'] != 'Windows_NT') ? { - if (process.env['OS'] == 'Windows_NT') { - console.log('Preparing ssh-agent service on Windows'); - child_process.execSync('sc config ssh-agent start=demand', { stdio: 'inherit' }); + // Use getent() system call, since this is what ssh does; makes a difference in Docker-based + // Action runs, where $HOME is different from the pwent + home: os.userInfo().homedir, + sshAgent: 'ssh-agent', + sshAdd: 'ssh-add' - home = os.homedir(); - } else { - // Use getent() system call, since this is what ssh does; makes a difference in Docker-based - // Action runs, where $HOME is different from the pwent - var { homedir: home } = os.userInfo(); - } + } : { + + home: os.homedir(), + sshAgent: 'c://progra~1//git//usr//bin//ssh-agent.exe', + sshAdd: 'c://progra~1//git//usr//bin//ssh-add.exe' + + }; const homeSsh = home + '/.ssh'; console.log(`Adding GitHub.com keys to ${homeSsh}/known_hosts`); + fs.mkdirSync(homeSsh, { recursive: true }); fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n'); fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-dss AAAAB3NzaC1kc3MAAACBANGFW2P9xlGU3zWrymJgI/lKo//ZW2WfVtmbsUZJ5uyKArtlQOT2+WRhcg4979aFxgKdcsqAYW3/LS1T2km3jYW/vr4Uzn+dXWODVk5VlUiZ1HFOHf6s6ITcZvjvdbp6ZbpM+DuJT7Bw+h5Fx8Qt8I16oCZYmAPJRtu46o9C2zk1AAAAFQC4gdFGcSbp5Gr0Wd5Ay/jtcldMewAAAIATTgn4sY4Nem/FQE+XJlyUQptPWMem5fwOcWtSXiTKaaN0lkk2p2snz+EJvAGXGq9dTSWHyLJSM2W6ZdQDqWJ1k+cL8CARAqL+UMwF84CR0m3hj+wtVGD/J4G5kW2DBAf4/bqzP4469lT+dF2FRQ2L9JKXrCWcnhMtJUvua8dvnwAAAIB6C4nQfAA7x8oLta6tT+oCk2WQcydNsyugE8vLrHlogoWEicla6cWPk7oXSspbzUcfkjN3Qa6e74PhRkc7JdSdAlFzU3m7LMkXo1MHgkqNX8glxWNVqBSc0YRdbFdTkL0C6gtpklilhvuHQCdbgB3LBAikcRkDp+FCVkUgPC/7Rw==\n'); console.log("Starting ssh-agent"); + const authSock = core.getInput('ssh-auth-sock'); - let sshAgentOutput = '' - if (authSock && authSock.length > 0) { - sshAgentOutput = child_process.execFileSync('ssh-agent', ['-a', authSock]); - } else { - sshAgentOutput = child_process.execFileSync('ssh-agent') - } + const sshAgentArgs = (authSock && authSock.length > 0) ? ['-a', authSock] : []; // Extract auth socket path and agent pid and set them as job variables - const lines = sshAgentOutput.toString().split("\n") - for (const lineNumber in lines) { - const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(lines[lineNumber]) - if (matches && matches.length > 0) { - core.exportVariable(matches[1], matches[2]) - } - } + child_process.execFileSync(sshAgent, sshAgentArgs).toString().split("\n").forEach(function(line) { + const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(line); - console.log("Adding private key to agent"); - privateKey.split(/(?=-----BEGIN)/).forEach(function(key) { - child_process.execSync('ssh-add -', { input: key.trim() + "\n" }); + if (matches && matches.length > 0) { + // This will also set process.env accordingly, so changes take effect for this script + core.exportVariable(matches[1], matches[2]) + console.log(`${matches[1]}=${matches[2]}`); + } }); - console.log("Keys added:"); - child_process.execSync('ssh-add -l', { stdio: 'inherit' }); + console.log("Adding private key(s) to agent"); - child_process.execFileSync('ssh-add', ['-L']).toString().split(/\r?\n/).forEach(function(key) { - let parts = key.match(/\bgithub.com[:/](.*)(?:\.git)?\b/); + privateKey.split(/(?=-----BEGIN)/).forEach(function(key) { + child_process.execFileSync(sshAdd, ['-'], { input: key.trim() + "\n" }); + }); - if (parts == null) { + console.log("Key(s) added:"); + + child_process.execFileSync(sshAdd, ['-l'], { stdio: 'inherit' }); + + console.log('Configuring deployment key(s)'); + + child_process.execFileSync(sshAdd, ['-L']).toString().split(/\r?\n/).forEach(function(key) { + const parts = key.match(/\bgithub\.com[:/]([_.a-z0-9-]+\/[_.a-z0-9-]+)/); + + if (!parts) { return; } - let ownerAndRepo = parts[1]; - let sha256 = crypto.createHash('sha256').update(key).digest('hex'); + const sha256 = crypto.createHash('sha256').update(key).digest('hex'); + const ownerAndRepo = parts[1].replace(/\.git$/, ''); - fs.writeFileSync(`${homeSsh}/${sha256}`, key + "\n", { mode: '600' }); + fs.writeFileSync(`${homeSsh}/key-${sha256}`, key + "\n", { mode: '600' }); - child_process.execSync(`git config --global --replace-all url."git@${sha256}:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`); - child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`); - child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`); + child_process.execSync(`git config --global --replace-all url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`); + child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`); + child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`); - let sshConfig = `\nHost ${sha256}\n` + const sshConfig = `\nHost key-${sha256}.github.com\n` + ` HostName github.com\n` - + ` User git\n` - + ` IdentityFile ${homeSsh}/${sha256}\n` + + ` IdentityFile ${homeSsh}/key-${sha256}\n` + ` IdentitiesOnly yes\n`; fs.appendFileSync(`${homeSsh}/config`, sshConfig); - console.log(`Added deploy-key mapping: Use key "${key}" for GitHub repository ${ownerAndRepo}`); + console.log(`Added deploy-key mapping: Use identity '${homeSsh}/key-${sha256}' for GitHub repository ${ownerAndRepo}`); }); } catch (error) { diff --git a/index.js b/index.js index cf7b562..9bf50bb 100644 --- a/index.js +++ b/index.js @@ -13,77 +13,82 @@ try { return; } - var home; + const { home, sshAgent, sshAdd } = (process.env['OS'] != 'Windows_NT') ? { - if (process.env['OS'] == 'Windows_NT') { - console.log('Preparing ssh-agent service on Windows'); - child_process.execSync('sc config ssh-agent start=demand', { stdio: 'inherit' }); + // Use getent() system call, since this is what ssh does; makes a difference in Docker-based + // Action runs, where $HOME is different from the pwent + home: os.userInfo().homedir, + sshAgent: 'ssh-agent', + sshAdd: 'ssh-add' - home = os.homedir(); - } else { - // Use getent() system call, since this is what ssh does; makes a difference in Docker-based - // Action runs, where $HOME is different from the pwent - var { homedir: home } = os.userInfo(); - } + } : { + + home: os.homedir(), + sshAgent: 'c://progra~1//git//usr//bin//ssh-agent.exe', + sshAdd: 'c://progra~1//git//usr//bin//ssh-add.exe' + + }; const homeSsh = home + '/.ssh'; console.log(`Adding GitHub.com keys to ${homeSsh}/known_hosts`); + fs.mkdirSync(homeSsh, { recursive: true }); fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n'); fs.appendFileSync(`${homeSsh}/known_hosts`, '\ngithub.com ssh-dss AAAAB3NzaC1kc3MAAACBANGFW2P9xlGU3zWrymJgI/lKo//ZW2WfVtmbsUZJ5uyKArtlQOT2+WRhcg4979aFxgKdcsqAYW3/LS1T2km3jYW/vr4Uzn+dXWODVk5VlUiZ1HFOHf6s6ITcZvjvdbp6ZbpM+DuJT7Bw+h5Fx8Qt8I16oCZYmAPJRtu46o9C2zk1AAAAFQC4gdFGcSbp5Gr0Wd5Ay/jtcldMewAAAIATTgn4sY4Nem/FQE+XJlyUQptPWMem5fwOcWtSXiTKaaN0lkk2p2snz+EJvAGXGq9dTSWHyLJSM2W6ZdQDqWJ1k+cL8CARAqL+UMwF84CR0m3hj+wtVGD/J4G5kW2DBAf4/bqzP4469lT+dF2FRQ2L9JKXrCWcnhMtJUvua8dvnwAAAIB6C4nQfAA7x8oLta6tT+oCk2WQcydNsyugE8vLrHlogoWEicla6cWPk7oXSspbzUcfkjN3Qa6e74PhRkc7JdSdAlFzU3m7LMkXo1MHgkqNX8glxWNVqBSc0YRdbFdTkL0C6gtpklilhvuHQCdbgB3LBAikcRkDp+FCVkUgPC/7Rw==\n'); console.log("Starting ssh-agent"); + const authSock = core.getInput('ssh-auth-sock'); - let sshAgentOutput = '' - if (authSock && authSock.length > 0) { - sshAgentOutput = child_process.execFileSync('ssh-agent', ['-a', authSock]); - } else { - sshAgentOutput = child_process.execFileSync('ssh-agent') - } + const sshAgentArgs = (authSock && authSock.length > 0) ? ['-a', authSock] : []; // Extract auth socket path and agent pid and set them as job variables - const lines = sshAgentOutput.toString().split("\n") - for (const lineNumber in lines) { - const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(lines[lineNumber]) - if (matches && matches.length > 0) { - core.exportVariable(matches[1], matches[2]) - } - } + child_process.execFileSync(sshAgent, sshAgentArgs).toString().split("\n").forEach(function(line) { + const matches = /^(SSH_AUTH_SOCK|SSH_AGENT_PID)=(.*); export \1/.exec(line); - console.log("Adding private key to agent"); - privateKey.split(/(?=-----BEGIN)/).forEach(function(key) { - child_process.execSync('ssh-add -', { input: key.trim() + "\n" }); + if (matches && matches.length > 0) { + // This will also set process.env accordingly, so changes take effect for this script + core.exportVariable(matches[1], matches[2]) + console.log(`${matches[1]}=${matches[2]}`); + } }); - console.log("Keys added:"); - child_process.execSync('ssh-add -l', { stdio: 'inherit' }); + console.log("Adding private key(s) to agent"); - child_process.execFileSync('ssh-add', ['-L']).toString().split(/\r?\n/).forEach(function(key) { - let parts = key.match(/\bgithub.com[:/](.*)(?:\.git)?\b/); + privateKey.split(/(?=-----BEGIN)/).forEach(function(key) { + child_process.execFileSync(sshAdd, ['-'], { input: key.trim() + "\n" }); + }); - if (parts == null) { + console.log("Key(s) added:"); + + child_process.execFileSync(sshAdd, ['-l'], { stdio: 'inherit' }); + + console.log('Configuring deployment key(s)'); + + child_process.execFileSync(sshAdd, ['-L']).toString().split(/\r?\n/).forEach(function(key) { + const parts = key.match(/\bgithub\.com[:/]([_.a-z0-9-]+\/[_.a-z0-9-]+)/); + + if (!parts) { return; } - let ownerAndRepo = parts[1]; - let sha256 = crypto.createHash('sha256').update(key).digest('hex'); + const sha256 = crypto.createHash('sha256').update(key).digest('hex'); + const ownerAndRepo = parts[1].replace(/\.git$/, ''); - fs.writeFileSync(`${homeSsh}/${sha256}`, key + "\n", { mode: '600' }); + fs.writeFileSync(`${homeSsh}/key-${sha256}`, key + "\n", { mode: '600' }); - child_process.execSync(`git config --global --replace-all url."git@${sha256}:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`); - child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`); - child_process.execSync(`git config --global --add url."git@${sha256}:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`); + child_process.execSync(`git config --global --replace-all url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`); + child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`); + child_process.execSync(`git config --global --add url."git@key-${sha256}.github.com:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`); - let sshConfig = `\nHost ${sha256}\n` + const sshConfig = `\nHost key-${sha256}.github.com\n` + ` HostName github.com\n` - + ` User git\n` - + ` IdentityFile ${homeSsh}/${sha256}\n` + + ` IdentityFile ${homeSsh}/key-${sha256}\n` + ` IdentitiesOnly yes\n`; fs.appendFileSync(`${homeSsh}/config`, sshConfig); - console.log(`Added deploy-key mapping: Use key "${key}" for GitHub repository ${ownerAndRepo}`); + console.log(`Added deploy-key mapping: Use identity '${homeSsh}/key-${sha256}' for GitHub repository ${ownerAndRepo}`); }); } catch (error) {