Fork 0

97 lines
3.4 KiB

Because I'm way too lazy I'm automatically generating the secret files config.
Secrets can be found below
Pubkeys can be found for the specific host below
The users have their keys below
Secrets get encrypted for the host they are in and the users specified.
Every host with a secrets directory has an entry for a secret called "new".
This exist to overcome the chicken and egg problem.
Create a secret with them name new in the specific secrets directory and rename it afterwards with the suffix .age.
Returns an attrset for a given directory,
having the name of a subdirectory as its attribute names
and the contents of the containing ssh.pub file as their value
clerie = "ssh-ed25519 AAAA...";
pubkeysFor = directory: let
instances = builtins.attrNames (builtins.readDir directory);
instancesWithPubkey = builtins.filter (i: builtins.pathExists (directory + "/${i}/ssh.pub")) instances;
builtins.listToAttrs (map (i: { name = i; value = builtins.readFile (directory + "/${i}/ssh.pub"); }) instancesWithPubkey);
users = pubkeysFor ./users;
hosts = pubkeysFor ./hosts;
Returns secret configuration for a given hostname
secretsForHost = hostname: let
Returns a list of all file names in the secrets directory of the specified host
secretsFiles = builtins.attrNames (builtins.readDir (./hosts + "/${hostname}/secrets"));
Returns all file names that end with .age
listOfSecrets = builtins.filter (i:
# Make sure the file name is longer than the file extension
(builtins.stringLength i) > 4
# Take the last four letters of the file name and check if it is .age
&& builtins.substring ((builtins.stringLength i) - 4) (builtins.stringLength i) i == ".age"
) secretsFiles;
# Make sure the host has a secrets directory
builtins.pathExists (./hosts + "/${hostname}/secrets")
# Make sure the host has a public ssh key provided
&& builtins.pathExists (./hosts + "/${hostname}/ssh.pub")
This map specifies all public keys for which a given secret file should be encrypted
It returns a list of name value pairs
The name is the path to the secret file
The value is an attribute set containing a list of public keys as a string
(secret: {
name = "hosts/${hostname}/secrets/${secret}";
value = {
publicKeys = [
# Hardcode clerie's public key here
# No other user should have access to any secrets
# A host should only have access to their own secrets
# All file names of already existing secrets plus the magic "new" secret
(listOfSecrets ++ [ "new" ])
# Answer with an empty list, if no secrets are provided for a host
# We just have a list of name value pairs that need to get transformed into an attribute set
builtins.listToAttrs (
# Provide a list of secrets for a given hostname
(hostname: secretsForHost hostname)
# Names of all hosts
(builtins.attrNames (builtins.readDir ./hosts))