This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

tools.ssh-yubikey: init

+118
+25
tools/ssh-yubikey/flake-module.nix
··· 1 + { self, ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + { 6 + packages.ssh-yubikey = self.libWithPkgs.${pkgs.system}.makeWrapper pkgs.openssh { 7 + env = { 8 + KEYS_DIR = "${self}/keys"; 9 + SSH = "${pkgs.openssh}/bin/ssh"; 10 + }; 11 + runtimeInputs = with pkgs; [ 12 + age 13 + age-plugin-yubikey 14 + age-plugin-fido2-hmac 15 + yubikey-manager 16 + libfido2 17 + self.packages.${pkgs.system}.age-detect 18 + ]; 19 + wrapper = { exePath, envString, ... }: '' 20 + ${envString} 21 + ${builtins.readFile ./ssh-yubikey} 22 + ''; 23 + }; 24 + }; 25 + }
+93
tools/ssh-yubikey/ssh-yubikey
··· 1 + #!/usr/bin/env bash 2 + set -euo pipefail 3 + set -x 4 + 5 + # SSH wrapper that automatically uses the correct YubiKey/Solo2 key 6 + # based on which device is currently connected 7 + 8 + SSH="${SSH:-ssh}" 9 + 10 + # Find keys directory - either from KEYS_DIR env var or relative to script 11 + if [[ -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 19 + fi 20 + TMPDIR="${TMPDIR:-/tmp}" 21 + 22 + # Function to detect connected security key 23 + detect_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 35 + decrypt_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 68 + main() { 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 + 93 + main "$@"