Skip to content

Commit 64e21df

Browse files
authored
feat: Add custom SSH agent action for workflows (#1)
- Introduced `action.sh` to manage SSH host key validation and `known_hosts` setup. - Added `action.yml` for defining a composite GitHub Action, supporting both predefined and dynamically scanned SSH hosts. - Implemented `post_action.sh` to clean up `known_hosts` file post-deployment for enhanced security. - Enhanced validation with warnings and errors for invalid or missing inputs. - Improved security with support for SSH key type filtering and explicit warnings for potential MITM risks. - Integrated `webfactory/ssh-agent` for managing private SSH keys in workflows.
1 parent 89a42c8 commit 64e21df

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

action.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
3+
if [ -z "${SSH_HOST}" ] && [ -z "${SSH_KNOWN_HOSTS}" ]; then
4+
echo ":error file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=Input validation::\
5+
One of the input, 'ssh-host' or 'ssh-known-hosts' must be set. Please update your workflow inputs."
6+
exit 2
7+
else
8+
if [ ! -z "${SSH_KNOWN_HOSTS}" ]; then
9+
if [ ! -z "${SSH_HOST}" ]; then
10+
echo "::warning file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=Input validation::\
11+
Both 'ssh-host' and 'ssh-known-hosts' inputs are set. Using 'ssh-known-hosts'."
12+
fi
13+
echo "${SSH_KNOWN_HOSTS}" >> "${SSH_KNOWN_HOSTS_FILE}"
14+
else
15+
echo "::warning file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=Security risk::\
16+
If an ssh_known_hosts file is constructed using ssh-keyscan without verifying the keys, \
17+
users will be vulnerable to man in the middle attacks. On theother hand, if the security model allows such a risk, \
18+
ssh-keyscan can help in the detection of tampered keyfiles or man in the middle attacks which have begun after \
19+
the ssh_known_hosts file was created."
20+
21+
if [ -z "${SSH_KEY_TYPE}" ]; then
22+
if ! ssh-keyscan "${SSH_HOST}" >> "${SSH_KNOWN_HOSTS_FILE}"; then
23+
echo "::error file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=SSH Keyscan Failed::\
24+
Failed to scan SSH host keys for ${SSH_HOST}"
25+
exit 1
26+
fi
27+
else
28+
if ! ssh-keyscan -t "${SSH_KEY_TYPE}" "${SSH_HOST}" >> "${SSH_KNOWN_HOSTS_FILE}"; then
29+
echo "::error file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=SSH Keyscan Failed::\
30+
Failed to scan SSH host keys for ${SSH_HOST}"
31+
exit 1
32+
fi
33+
fi
34+
fi
35+
fi

action.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: 'apter-tech/ssh-agent'
2+
description: 'Run `ssh-agent`, load an SSH key to access other private repositories and setup `known_hosts` for host verification.',
3+
inputs:
4+
ssh-host:
5+
description: Hostname to fetch SSH keys from using ssh-keyscan.
6+
required: false
7+
ssh-key-type:
8+
description: |
9+
Specify the type of the key to fetch from the scanned hosts. The possible values are “ecdsa”, “ed25519”, “ecdsa-sk”, “ed25519-sk”, or “rsa”.
10+
Multiple values may be specified by separating them with commas. The default is to fetch all the above key types.
11+
required: false
12+
default: 'rsa'
13+
ssh-known-hosts:
14+
description: 'Predefined known hosts to be added directly.'
15+
required: false
16+
# Inputs from webfactory/ssh-agent
17+
ssh-private-key:
18+
description: 'Private SSH key to register in the SSH agent'
19+
required: true
20+
ssh-auth-sock:
21+
description: 'Where to place the SSH Agent auth socket'
22+
required: false
23+
log-public-key:
24+
description: 'Whether or not to log public key fingerprints'
25+
required: false
26+
default: true
27+
ssh-agent-cmd:
28+
description: 'ssh-agent command'
29+
required: false
30+
ssh-add-cmd:
31+
description: 'ssh-add command'
32+
required: false
33+
git-cmd:
34+
description: 'git command'
35+
required: false
36+
runs:
37+
using: 'composite'
38+
steps:
39+
- uses: pyTooling/Actions/with-post-step@9ceefdbf5dceae8c441fc393ed82344c7ca8bbdb # v3.1.1
40+
env:
41+
SSH_HOST: ${{ inputs.ssh-host }}
42+
SSH_KEY_TYPE: ${{ inputs.ssh-key-type }}
43+
SSH_KNOWN_HOSTS: ${{ inputs.ssh-known-hosts }}
44+
SSH_KNOWN_HOSTS_FILE: '~/.ssh/known_hosts'
45+
with:
46+
main: |
47+
./action.sh
48+
post: |
49+
./post_action.sh
50+
- uses: webfactory/ssh-agent@dc588b651fe13675774614f8e6a936a468676387 # v0.9.0
51+
with:
52+
ssh-private-key: ${{ inputs.ssh-private-key }}
53+
ssh-auth-sock: ${{ inputs.ssh-auth-sock }}
54+
log-public-key: ${{ inputs.log-public-key }}
55+
ssh-agent-cmd: ${{ inputs.ssh-agent-cmd }}
56+
ssh-add-cmd: ${{ inputs.ssh-add-cmd }}
57+
git-cmd: ${{ inputs.git-cmd }}
58+

post_action.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env bash
2+
3+
if [ -z "${SSH_KNOWN_HOSTS_FILE}" ]; then
4+
echo "::error file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=Notice::\
5+
${SSH_KNOWN_HOSTS_FILE} environment variable must be set."
6+
else
7+
rm -rf "${SSH_KNOWN_HOSTS_FILE}"
8+
echo "::notice file=$(basename "$0"),line=${LINENO},endLine=${LINENO},title=Notice::\
9+
${SSH_KNOWN_HOSTS_FILE} has been removed."
10+
fi

0 commit comments

Comments
 (0)