diff options
| author | Franck Cuny <franck@fcuny.net> | 2026-01-16 18:58:03 -0800 |
|---|---|---|
| committer | Franck Cuny <franck@fcuny.net> | 2026-01-16 19:20:32 -0800 |
| commit | be8a70645220298b40be1b44e0888e9f54c0ce89 (patch) | |
| tree | 7fa192e9907a0199cc32ef5bd24f41007078c32d /secrets | |
| parent | rekey all secrets with my age keys on the yubikeys (diff) | |
| download | infra-be8a70645220298b40be1b44e0888e9f54c0ce89.tar.gz | |
simplify secrets management with dynamic public key generation
Diffstat (limited to 'secrets')
| -rw-r--r-- | secrets/secrets.nix | 199 |
1 files changed, 75 insertions, 124 deletions
diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 3e0c38a..6c0b0a6 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,130 +1,81 @@ +# run `nix eval --file secrets.nix` to check that the file is properly generated let - hosts = { - bree = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFM4wZaYwz8kuu6lNrdrN6QOyouGQ0v1ye+Iwh1jawNi"; - mba = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDLQTIPZraE+jpMqGkh8yUhNFzRJbMarX5Mky3nETw6c"; - mbp = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINXiA49xsrOJp7wOTYeX5+9o3gly8LyN6gvJoNVQmswv"; - rivendell = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID76U5kt8DfBbuP16rMzfBTVTpjjPFKWnnheMALaCQEd"; - argonath = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHi9jHqRjpMzXlznTXi4nEtlRlFfyIzB6Ur9A+HDfFoq"; - }; - users = { - fcuny = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdyJepi/NyO6d9eP8m48Ga/gdjB5ENHRXYM1ZqFZR8t"; - }; - age = [ + inherit (builtins) + all + any + attrValues + concatMap + elem + elemAt + filter + getFlake + hasAttr + isList + length + listToAttrs + split + ; + + flake = getFlake (toString ../.); + + last = list: elemAt list (length list - 1); + + flatten = x: if isList x then concatMap flatten x else [ x ]; + + unique = + list: + let + go = + acc: remaining: + if remaining == [ ] then + acc + else + let + head = builtins.head remaining; + tail = builtins.tail remaining; + in + if elem head acc then go acc tail else go (acc ++ [ head ]) tail; + in + go [ ] list; + + hostsWithRequiredAttrs = + requiredAttrs: hosts: filter (host: all (attr: hasAttr attr host) requiredAttrs) hosts; + + hostConfigsList = + (map (host: host.config) (attrValues flake.nixosConfigurations)) + ++ (map (host: host.config) (attrValues flake.darwinConfigurations)); + + hostsWithSecrets = hostsWithRequiredAttrs [ "publicKey" "age" ] hostConfigsList; + + toLocalSecretPath = path: last (split "/secrets/" path); + + secretsList = unique ( + flatten ( + map ( + host: map (secret: toLocalSecretPath (toString secret.file)) (attrValues host.age.secrets) + ) hostsWithSecrets + ) + ); + + getPublicKeysForSecret = + secretName: + let + hostsUsingSecret = filter ( + host: + any (secret: secretName == toLocalSecretPath (toString secret.file)) (attrValues host.age.secrets) + ) hostsWithSecrets; + in + unique (map (host: host.publicKey) hostsUsingSecret); + + fcuny = [ "age1yubikey1qv92lk8ckjm2qs900h89pz9myl3nfjnz7fc0eluppexyfgc0pfnjusaje3w" "age1yubikey1qd30fnnxd2uh9lgw0dr7nwvmn003rmzkrg87xfw67gdsf7u0lhm3kd4w8ul" "age1yubikey1qwrxced5j32ks5cc5aqffwz68yva9ukkz6tx5xm2sjn8swl2evtlsjlmsy9" - ]; in -{ - "acme-cloudflare-env.age".publicKeys = [ - users.fcuny - hosts.argonath - ] - ++ age; - - "restic-pw.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - "restic-nas-smb-config.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - # ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINE3mdcVS7+DPr7MZzIh3JsuI5t4z83j7ZAdAYxFLW4S rsync-nas - "rsync-ssh-nas.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - # this is the SSH key we use to access the remote builder. - "ssh-remote-builder.age".publicKeys = [ - users.fcuny - hosts.mba - ] - ++ age; - - "miniflux-oidc.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - "grafana-oidc.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - # generated with: - # openssl rand 64 | openssl base64 -A | tr '+/' '-_' | tr -d '=' - "authelia-storage-key.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - # generated with: - # openssl rand 64 | openssl base64 -A | tr '+/' '-_' | tr -d '=' - "authelia-jwt-key.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - # generated with: - # authelia crypto pair rsa generate - "authelia-jwks.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - "authelia-users.yaml.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - "bree/wireguard.age".publicKeys = [ - users.fcuny - hosts.bree - ] - ++ age; - - "bree/disk-passphrase.age".publicKeys = [ - users.fcuny - hosts.bree - ] - ++ age; - - "bree/disk-unlock-key.age".publicKeys = [ - users.fcuny - hosts.bree - ] - ++ age; - - "rivendell/wireguard.age".publicKeys = [ - users.fcuny - hosts.rivendell - ] - ++ age; - - "argonath/wireguard.age".publicKeys = [ - users.fcuny - hosts.argonath - ] - ++ age; - - "anthropic-api-key.age".publicKeys = [ - users.fcuny - hosts.mba - hosts.mbp - ] - ++ age; -} +listToAttrs ( + map (secretName: { + name = secretName; + value.publicKeys = fcuny ++ (getPublicKeysForSecret secretName); + }) secretsList +) |
