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.libfido2 29 ]; 30 text = '' 31 # SSH wrapper that tries each encrypted SSH key with the connected FIDO2 device 32 33 # Key mapping from flake 34 declare -A SSH_KEYS 35 ${sshKeyEntries} 36 37 usage() { 38 echo "Usage: ssh-with-age [ssh_options...] destination" 39 echo " ssh-with-age --list-keys" 40 echo " ssh-with-age --list-devices" 41 echo "" 42 echo "Tries each encrypted SSH key to find one that works with the connected FIDO2 device." 43 exit 1 44 } 45 46 list_keys() { 47 echo "Available encrypted SSH keys:" 48 for key in "''${!SSH_KEYS[@]}"; do 49 echo " $key" 50 done 51 } 52 53 list_devices() { 54 echo "Connected FIDO2 devices:" 55 fido2-token -L 56 } 57 58 if [[ "$1" == "--list-keys" ]]; then 59 list_keys 60 exit 0 61 fi 62 63 if [[ "$1" == "--list-devices" ]]; then 64 list_devices 65 exit 0 66 fi 67 68 if [[ "$1" == "-h" || "$1" == "--help" ]]; then 69 usage 70 fi 71 72 # Create temporary file for decrypted key 73 temp_key=$(mktemp) 74 trap 'rm -f "$temp_key"' EXIT 75 76 # Try each encrypted SSH key 77 found_key="" 78 for key_name in "''${!SSH_KEYS[@]}"; do 79 encrypted_key="''${SSH_KEYS[$key_name]}" 80 81 if [[ ! -f "$encrypted_key" ]]; then 82 continue 83 fi 84 85 echo "Trying key: $key_name..." 86 87 # Try to decrypt with repository age keys 88 decrypted=false 89 for age_key in ${toString (builtins.attrValues self.keys.age)}; do 90 if age -d -j fido2-hmac "$encrypted_key" > "$temp_key" 2>/dev/null || \ 91 age -d -j se "$encrypted_key" > "$temp_key" 2>/dev/null; then 92 decrypted=true 93 break 94 fi 95 done 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}