This repository has no description
0

Configure Feed

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

superconfig / tools / ssh-with-age / flake-module.nix
4.1 kB 134 lines
1{ self, ... }: 2{ 3 perSystem = 4 { pkgs, ... }: 5 let 6 lib = pkgs.lib; 7 8 # Generate key entries from flake structure 9 sshKeyEntries = lib.concatStringsSep "\n" ( 10 lib.mapAttrsToList ( 11 name: key: 12 if key.encrypted && key.private != null then 13 '' 14 ["${name}"]="${key.private}" 15 '' 16 else 17 "" 18 ) self.keys.ssh 19 ); 20 in 21 { 22 packages.ssh-with-age = pkgs.writeShellApplication { 23 name = "ssh-with-age"; 24 runtimeInputs = [ 25 pkgs.openssh 26 pkgs.age 27 pkgs.age-plugin-se 28 pkgs.age-plugin-yubikey 29 pkgs.libfido2 30 ]; 31 text = '' 32 # SSH wrapper that tries each encrypted SSH key with the connected FIDO2 device 33 34 # Key mapping from flake 35 declare -A SSH_KEYS 36 ${sshKeyEntries} 37 38 usage() { 39 echo "Usage: ssh-with-age [ssh_options...] destination" 40 echo " ssh-with-age --list-keys" 41 echo " ssh-with-age --list-devices" 42 echo "" 43 echo "Tries each encrypted SSH key to find one that works with the connected FIDO2 device." 44 exit 1 45 } 46 47 list_keys() { 48 echo "Available encrypted SSH keys:" 49 for key in "''${!SSH_KEYS[@]}"; do 50 echo " $key" 51 done 52 } 53 54 list_devices() { 55 echo "Connected FIDO2 devices:" 56 fido2-token -L 57 } 58 59 if [[ "$1" == "--list-keys" ]]; then 60 list_keys 61 exit 0 62 fi 63 64 if [[ "$1" == "--list-devices" ]]; then 65 list_devices 66 exit 0 67 fi 68 69 if [[ "$1" == "-h" || "$1" == "--help" ]]; then 70 usage 71 fi 72 73 # Create temporary file for decrypted key 74 temp_key=$(mktemp) 75 trap 'rm -f "$temp_key"' EXIT 76 77 # Try each encrypted SSH key 78 found_key="" 79 for key_name in "''${!SSH_KEYS[@]}"; do 80 encrypted_key="''${SSH_KEYS[$key_name]}" 81 82 if [[ ! -f "$encrypted_key" ]]; then 83 continue 84 fi 85 86 echo "Trying key: $key_name..." 87 88 # Try to decrypt with hardware plugins 89 decrypted=false 90 # Try each hardware plugin method 91 if age -d -j fido2-hmac "$encrypted_key" > "$temp_key" 2>/dev/null || \ 92 age -d -j se "$encrypted_key" > "$temp_key" 2>/dev/null || \ 93 age -d -j yubikey "$encrypted_key" > "$temp_key" 2>/dev/null; then 94 decrypted=true 95 fi 96 97 if [[ "$decrypted" == "true" ]]; then 98 99 # Check if this is a FIDO2 key by looking at the key type 100 if grep -q "sk-" "$temp_key"; then 101 # Try to use the key with SSH agent to verify it works with connected device 102 chmod 600 "$temp_key" 103 104 # Test if the key works by trying ssh-add 105 if SSH_ASKPASS=/bin/false ssh-add -T "$temp_key" 2>/dev/null; then 106 found_key="$key_name" 107 echo "✓ Found working key: $key_name" 108 break 109 else 110 echo " Key $key_name requires a different FIDO2 device" 111 fi 112 else 113 echo " Key $key_name is not a FIDO2 key" 114 fi 115 else 116 echo " Could not decrypt $key_name (missing age identity?)" 117 fi 118 done 119 120 if [[ -z "$found_key" ]]; then 121 echo "No matching SSH key found for the connected FIDO2 device." >&2 122 echo "Make sure:" >&2 123 echo " 1. Your FIDO2 device is connected" >&2 124 echo " 2. You have the correct age identity to decrypt the keys" >&2 125 echo " 3. The SSH key was generated with this FIDO2 device" >&2 126 exit 1 127 fi 128 129 # Use the found key with SSH 130 ssh -i "$temp_key" "$@" 131 ''; 132 }; 133 }; 134}