Compare commits
55 commits
forgejo
...
debug-wind
Author | SHA1 | Date | |
---|---|---|---|
|
2d8d48e56a | ||
|
5a354bf325 | ||
|
6458b79183 | ||
|
873b13078f | ||
|
3fc2400425 | ||
|
3715bc571d | ||
|
71155bedbe | ||
|
10fed90131 | ||
|
d3770df27e | ||
|
7667967a0a | ||
|
c77dd5afd7 | ||
|
a4b2891e37 | ||
|
7cabdfc0cc | ||
|
da67187c5e | ||
|
64510141b4 | ||
|
8cdc63104f | ||
|
e0d767fd8e | ||
|
feedd601c5 | ||
|
e35dbcbae9 | ||
|
cbf6c2b3c2 | ||
|
2bcaae34da | ||
|
f03f6e3358 | ||
|
7d6e731f4a | ||
|
88bcf9af86 | ||
|
02a6899abb | ||
|
5f971b8d4f | ||
|
ab7e1e8f32 | ||
|
7f61bbc4ae | ||
|
2bde568a83 | ||
|
93c9b23aa1 | ||
|
1606d19f15 | ||
|
8addcca750 | ||
|
166067472e | ||
|
f78cad1cc7 | ||
|
ccd95b931d | ||
|
637f9c791e | ||
|
18f53866de | ||
|
c91aeeb123 | ||
|
25b1b5d69f | ||
|
9406a51fa5 | ||
|
ef63fdb1df | ||
|
7fc4d80a06 | ||
|
9b7e80db62 | ||
|
4d491fcb08 | ||
|
1676d1f2a9 | ||
|
3702096734 | ||
|
253819f283 | ||
|
231e859720 | ||
|
5e4ad4bcc8 | ||
|
c56b9c4c81 | ||
|
d7353c1718 | ||
|
bcd9c12595 | ||
|
ab4471f51e | ||
|
05624726bc | ||
|
2a421d8dab |
5 changed files with 192 additions and 115 deletions
91
.github/workflows/demo.yml
vendored
91
.github/workflows/demo.yml
vendored
|
@ -1,60 +1,45 @@
|
|||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
single_key_demo:
|
||||
strategy:
|
||||
matrix:
|
||||
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 }}
|
||||
|
||||
docker_demo:
|
||||
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 }}
|
||||
|
||||
deployment_keys_demo:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GIT_SSH_COMMAND: ssh -v
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup key
|
||||
uses: ./
|
||||
# - name: Setup key
|
||||
# uses: ./
|
||||
# with:
|
||||
# ssh-private-key: |
|
||||
# ${{ secrets.MPDUDE_TEST_1_DEPLOY_KEY }}
|
||||
# ${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}
|
||||
# - run: |
|
||||
# cat ~/.ssh/config
|
||||
# ssh-add -l
|
||||
# C:/Windows/System32/OpenSSH/ssh.exe -v git@key-2 'echo octocat'
|
||||
- name: Start SSH session
|
||||
uses: luchihoratiu/debug-via-ssh@main
|
||||
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
|
||||
NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }}
|
||||
SSH_PASS: ${{ secrets.SSH_PASS }}
|
||||
|
||||
# git clone git@github.com:mpdude/test-2.git test-2-git
|
||||
# ls -alh ~/.ssh
|
||||
# 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 ssh://git@github.com/mpdude/test-2.git test-2-git-ssh
|
||||
|
||||
# cat > ~/.ssh/5965bf89ab6e2900262e3f6802dfb4d65cb0de539d0fbb97d381e7130a4ba7e9 <<< "${{ secrets.MPDUDE_TEST_2_DEPLOY_KEY }}"
|
||||
# ssh-keygen -p -f ~/.ssh/5965bf89ab6e2900262e3f6802dfb4d65cb0de539d0fbb97d381e7130a4ba7e9 -N secret-passphrase
|
||||
# eval `ssh-agent`
|
||||
# echo "secret-passphrase" | ssh-add ~/.ssh/5965bf89ab6e2900262e3f6802dfb4d65cb0de539d0fbb97d381e7130a4ba7e9
|
||||
# ssh-add -L
|
||||
# git clone git@github.com:mpdude/test-2.git test-2-git
|
||||
# shell: bash
|
||||
|
|
24
askpass.c
Normal file
24
askpass.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
ssh-add on Windows (probably part of the source at https://github.com/PowerShell/openssh-portable)
|
||||
does not/can not read the passphrase from stdin.
|
||||
|
||||
However, when the DISPLAY env var is set and ssh-add is not run from a terminal (however it tests
|
||||
that), it will run the executable pointed to by SSH_ASKPASS in a subprocess and read the passphrase
|
||||
from that subprocess' stdout.
|
||||
|
||||
This program can be used as the SSH_ASKPASS implementation. It will return the passphrase set
|
||||
in the SSH_PASS env variable.
|
||||
|
||||
To cross-compile from Ubuntu, I installed the `mingw-w64` package and ran
|
||||
$ x86_64-w64-mingw32-gcc askpass.c -static -o askpass.exe
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
printf("%s\n", getenv("SSH_PASS"));
|
||||
|
||||
return 0;
|
||||
}
|
BIN
askpass.exe
Executable file
BIN
askpass.exe
Executable file
Binary file not shown.
96
dist/index.js
vendored
96
dist/index.js
vendored
|
@ -119,7 +119,8 @@ const core = __webpack_require__(470);
|
|||
const child_process = __webpack_require__(129);
|
||||
const fs = __webpack_require__(747);
|
||||
const os = __webpack_require__(87);
|
||||
const crypto = __webpack_require__(417);
|
||||
const token = __webpack_require__(417).randomBytes(64).toString('hex');
|
||||
const isWindows = (process.env['OS'] == 'Windows_NT');
|
||||
|
||||
try {
|
||||
const privateKey = core.getInput('ssh-private-key');
|
||||
|
@ -132,10 +133,16 @@ try {
|
|||
|
||||
var home;
|
||||
|
||||
if (process.env['OS'] == 'Windows_NT') {
|
||||
if (isWindows) {
|
||||
console.log('Preparing ssh-agent service on Windows');
|
||||
child_process.execSync('sc config ssh-agent start=demand', { stdio: 'inherit' });
|
||||
|
||||
// Work around https://github.com/PowerShell/openssh-portable/pull/447 by creating a \dev\tty file
|
||||
/*fs.mkdirSync('c:\\dev');
|
||||
fs.closeSync(fs.openSync('c:\\dev\\tty', 'a'));
|
||||
fs.mkdirSync('d:\\dev');
|
||||
fs.closeSync(fs.openSync('d:\\dev\\tty', 'a'));*/
|
||||
|
||||
home = os.homedir();
|
||||
} else {
|
||||
// Use getent() system call, since this is what ssh does; makes a difference in Docker-based
|
||||
|
@ -168,41 +175,68 @@ try {
|
|||
}
|
||||
}
|
||||
|
||||
console.log("Adding private key to agent");
|
||||
console.log("Adding private keys to agent");
|
||||
var keyNumber = 0;
|
||||
|
||||
privateKey.split(/(?=-----BEGIN)/).forEach(function(key) {
|
||||
child_process.execSync('ssh-add -', { input: key.trim() + "\n" });
|
||||
++keyNumber;
|
||||
let keyFile = `${homeSsh}/key_${keyNumber}`;
|
||||
|
||||
// Write private key (unencrypted!) to file
|
||||
console.log(`Write file ${keyFile}`);
|
||||
fs.writeFileSync(keyFile, key.replace("\r\n", "\n").trim() + "\n", { mode: '600' });
|
||||
|
||||
// Set private key passphrase
|
||||
let output = '';
|
||||
try {
|
||||
console.log(`Set passphrase on ${keyFile}`);
|
||||
output = child_process.execFileSync('ssh-keygen', ['-p', '-f', keyFile, '-N', token]);
|
||||
} catch (exception) {
|
||||
fs.unlinkSync(keyFile);
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Load key into agent
|
||||
if (isWindows) {
|
||||
child_process.execFileSync('ssh-add', [keyFile], { env: { ...process.env, ...{ 'DISPLAY': 'fake', 'SSH_PASS': token, 'SSH_ASKPASS': 'D:\\a\\ssh-agent\\ssh-agent\\askpass.exe' } } });
|
||||
} else {
|
||||
child_process.execFileSync('ssh-add', [keyFile], { env: process.env, input: token });
|
||||
}
|
||||
|
||||
output.toString().split(/\r?\n/).forEach(function(key) {
|
||||
let parts = key.match(/^Key has comment '.*\bgithub\.com[:/]([_.a-z0-9-]+\/[_.a-z0-9-]+?)(?=\.git|\s|\')/);
|
||||
|
||||
if (parts == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ownerAndRepo = parts[1];
|
||||
|
||||
child_process.execSync(`git config --global --replace-all url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`);
|
||||
child_process.execSync(`git config --global --add url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`);
|
||||
child_process.execSync(`git config --global --add url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`);
|
||||
|
||||
// On Linux and OS X, IdentitiesOnly=no will send all keys from agent before the explicit key, so use "yes".
|
||||
// On Windows, IdentitiesOnly=yes will ignore keys from the agent, but send explicit keys first; so use "no" (https://github.com/PowerShell/Win32-OpenSSH/issues/1550)
|
||||
//let identitiesOnly = isWindows ? 'no' : 'yes';
|
||||
|
||||
let sshConfig = `\nHost key-${keyNumber}\n`
|
||||
+ ` HostName github.com\n`
|
||||
+ ` User git\n`
|
||||
+ ` IdentitiesOnly yes\n`
|
||||
+ ` AddKeysToAgent yes\n`
|
||||
+ ` IdentityFile ${keyFile}\n`;
|
||||
|
||||
fs.appendFileSync(`${homeSsh}/config`, sshConfig);
|
||||
|
||||
console.log(`Added deploy-key mapping: Use key #${keyNumber} for GitHub repository ${ownerAndRepo}`);
|
||||
});
|
||||
});
|
||||
|
||||
console.log("Keys added:");
|
||||
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||
|
||||
child_process.execFileSync('ssh-add', ['-L']).toString().split(/\r?\n/).forEach(function(key) {
|
||||
let parts = key.match(/\bgithub.com[:/](.*)(?:\.git)?\b/);
|
||||
|
||||
if (parts == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ownerAndRepo = parts[1];
|
||||
let sha256 = crypto.createHash('sha256').update(key).digest('hex');
|
||||
|
||||
fs.writeFileSync(`${homeSsh}/${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}"`);
|
||||
|
||||
let sshConfig = `\nHost ${sha256}\n`
|
||||
+ ` HostName github.com\n`
|
||||
+ ` User git\n`
|
||||
+ ` IdentityFile ${homeSsh}/${sha256}\n`
|
||||
+ ` IdentitiesOnly yes\n`;
|
||||
|
||||
fs.appendFileSync(`${homeSsh}/config`, sshConfig);
|
||||
|
||||
console.log(`Added deploy-key mapping: Use key "${key}" for GitHub repository ${ownerAndRepo}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
|
|
96
index.js
96
index.js
|
@ -2,7 +2,8 @@ const core = require('@actions/core');
|
|||
const child_process = require('child_process');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const crypto = require('crypto');
|
||||
const token = require('crypto').randomBytes(64).toString('hex');
|
||||
const isWindows = (process.env['OS'] == 'Windows_NT');
|
||||
|
||||
try {
|
||||
const privateKey = core.getInput('ssh-private-key');
|
||||
|
@ -15,10 +16,16 @@ try {
|
|||
|
||||
var home;
|
||||
|
||||
if (process.env['OS'] == 'Windows_NT') {
|
||||
if (isWindows) {
|
||||
console.log('Preparing ssh-agent service on Windows');
|
||||
child_process.execSync('sc config ssh-agent start=demand', { stdio: 'inherit' });
|
||||
|
||||
// Work around https://github.com/PowerShell/openssh-portable/pull/447 by creating a \dev\tty file
|
||||
/*fs.mkdirSync('c:\\dev');
|
||||
fs.closeSync(fs.openSync('c:\\dev\\tty', 'a'));
|
||||
fs.mkdirSync('d:\\dev');
|
||||
fs.closeSync(fs.openSync('d:\\dev\\tty', 'a'));*/
|
||||
|
||||
home = os.homedir();
|
||||
} else {
|
||||
// Use getent() system call, since this is what ssh does; makes a difference in Docker-based
|
||||
|
@ -51,41 +58,68 @@ try {
|
|||
}
|
||||
}
|
||||
|
||||
console.log("Adding private key to agent");
|
||||
console.log("Adding private keys to agent");
|
||||
var keyNumber = 0;
|
||||
|
||||
privateKey.split(/(?=-----BEGIN)/).forEach(function(key) {
|
||||
child_process.execSync('ssh-add -', { input: key.trim() + "\n" });
|
||||
++keyNumber;
|
||||
let keyFile = `${homeSsh}/key_${keyNumber}`;
|
||||
|
||||
// Write private key (unencrypted!) to file
|
||||
console.log(`Write file ${keyFile}`);
|
||||
fs.writeFileSync(keyFile, key.replace("\r\n", "\n").trim() + "\n", { mode: '600' });
|
||||
|
||||
// Set private key passphrase
|
||||
let output = '';
|
||||
try {
|
||||
console.log(`Set passphrase on ${keyFile}`);
|
||||
output = child_process.execFileSync('ssh-keygen', ['-p', '-f', keyFile, '-N', token]);
|
||||
} catch (exception) {
|
||||
fs.unlinkSync(keyFile);
|
||||
|
||||
throw exception;
|
||||
}
|
||||
|
||||
// Load key into agent
|
||||
if (isWindows) {
|
||||
child_process.execFileSync('ssh-add', [keyFile], { env: { ...process.env, ...{ 'DISPLAY': 'fake', 'SSH_PASS': token, 'SSH_ASKPASS': 'D:\\a\\ssh-agent\\ssh-agent\\askpass.exe' } } });
|
||||
} else {
|
||||
child_process.execFileSync('ssh-add', [keyFile], { env: process.env, input: token });
|
||||
}
|
||||
|
||||
output.toString().split(/\r?\n/).forEach(function(key) {
|
||||
let parts = key.match(/^Key has comment '.*\bgithub\.com[:/]([_.a-z0-9-]+\/[_.a-z0-9-]+?)(?=\.git|\s|\')/);
|
||||
|
||||
if (parts == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ownerAndRepo = parts[1];
|
||||
|
||||
child_process.execSync(`git config --global --replace-all url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "https://github.com/${ownerAndRepo}"`);
|
||||
child_process.execSync(`git config --global --add url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "git@github.com:${ownerAndRepo}"`);
|
||||
child_process.execSync(`git config --global --add url."git@key-${keyNumber}:${ownerAndRepo}".insteadOf "ssh://git@github.com/${ownerAndRepo}"`);
|
||||
|
||||
// On Linux and OS X, IdentitiesOnly=no will send all keys from agent before the explicit key, so use "yes".
|
||||
// On Windows, IdentitiesOnly=yes will ignore keys from the agent, but send explicit keys first; so use "no" (https://github.com/PowerShell/Win32-OpenSSH/issues/1550)
|
||||
//let identitiesOnly = isWindows ? 'no' : 'yes';
|
||||
|
||||
let sshConfig = `\nHost key-${keyNumber}\n`
|
||||
+ ` HostName github.com\n`
|
||||
+ ` User git\n`
|
||||
+ ` IdentitiesOnly yes\n`
|
||||
+ ` AddKeysToAgent yes\n`
|
||||
+ ` IdentityFile ${keyFile}\n`;
|
||||
|
||||
fs.appendFileSync(`${homeSsh}/config`, sshConfig);
|
||||
|
||||
console.log(`Added deploy-key mapping: Use key #${keyNumber} for GitHub repository ${ownerAndRepo}`);
|
||||
});
|
||||
});
|
||||
|
||||
console.log("Keys added:");
|
||||
child_process.execSync('ssh-add -l', { stdio: 'inherit' });
|
||||
|
||||
child_process.execFileSync('ssh-add', ['-L']).toString().split(/\r?\n/).forEach(function(key) {
|
||||
let parts = key.match(/\bgithub.com[:/](.*)(?:\.git)?\b/);
|
||||
|
||||
if (parts == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
let ownerAndRepo = parts[1];
|
||||
let sha256 = crypto.createHash('sha256').update(key).digest('hex');
|
||||
|
||||
fs.writeFileSync(`${homeSsh}/${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}"`);
|
||||
|
||||
let sshConfig = `\nHost ${sha256}\n`
|
||||
+ ` HostName github.com\n`
|
||||
+ ` User git\n`
|
||||
+ ` IdentityFile ${homeSsh}/${sha256}\n`
|
||||
+ ` IdentitiesOnly yes\n`;
|
||||
|
||||
fs.appendFileSync(`${homeSsh}/config`, sshConfig);
|
||||
|
||||
console.log(`Added deploy-key mapping: Use key "${key}" for GitHub repository ${ownerAndRepo}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue