This repository has no description
2.5 kB
93 lines
1#!/usr/bin/env bash
2set -euo pipefail
3set -x
4
5# SSH wrapper that automatically uses the correct YubiKey/Solo2 key
6# based on which device is currently connected
7
8SSH="${SSH:-ssh}"
9
10# Find keys directory - either from KEYS_DIR env var or relative to script
11if [[ -z "${KEYS_DIR:-}" ]]; then
12 # Get the real script location (resolving symlinks)
13 SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)"
14 KEYS_DIR="$SCRIPT_DIR/../../keys"
15 if [[ ! -d "$KEYS_DIR" ]]; then
16 echo "Error: Keys directory not found at $KEYS_DIR. Set KEYS_DIR environment variable." >&2
17 exit 1
18 fi
19fi
20TMPDIR="${TMPDIR:-/tmp}"
21
22# Function to detect connected security key
23detect_key() {
24 # Use age-detect to find connected key
25 eval "$(age-detect)"
26
27 # Clean up identity file if created
28 [[ -n "${IDENTITY_FILE:-}" ]] && rm -f "$IDENTITY_FILE"
29
30 # Return detected key name
31 echo "${DETECTED_KEY:-}"
32}
33
34# Function to decrypt key
35decrypt_key() {
36 local key_name="$1"
37 local tmp_key="$TMPDIR/ssh-${key_name}-$$"
38
39 case "$key_name" in
40 yubi1|yubi2)
41 # Decrypt with YubiKey age plugin
42 echo "AGE-PLUGIN-YUBIKEY-1M2PLUQYZ242EPUSSHDFWJ" | \
43 age --decrypt -i - "$KEYS_DIR/ssh/${key_name}.age" > "$tmp_key" || {
44 echo "Failed to decrypt $key_name" >&2
45 rm -f "$tmp_key"
46 return 1
47 }
48 ;;
49 solo2)
50 # Decrypt with Solo2 FIDO2-HMAC
51 age -d -j fido2-hmac "$KEYS_DIR/ssh/${key_name}.age" > "$tmp_key" || {
52 echo "Failed to decrypt $key_name" >&2
53 rm -f "$tmp_key"
54 return 1
55 }
56 ;;
57 *)
58 echo "Unknown key type: $key_name" >&2
59 return 1
60 ;;
61 esac
62
63 chmod 600 "$tmp_key"
64 echo "$tmp_key"
65}
66
67# Main logic
68main() {
69 local detected_key
70 detected_key=$(detect_key)
71
72 if [[ -z "$detected_key" ]]; then
73 # No security key detected, fallback to normal SSH
74 exec "$SSH" "$@"
75 fi
76
77 echo "Using security key: $detected_key" >&2
78
79 # Decrypt the key
80 local decrypted_key
81 if decrypted_key=$(decrypt_key "$detected_key"); then
82 # Clean up on exit
83 trap 'rm -f '"$decrypted_key"'' EXIT
84
85 # Execute SSH with the decrypted key
86 exec "$SSH" -i "$decrypted_key" "$@"
87 else
88 echo "Failed to decrypt key, falling back to normal SSH" >&2
89 exec "$SSH" "$@"
90 fi
91}
92
93main "$@"