2023-05-01 15:19:59 +02:00
|
|
|
/*
|
|
|
|
Because I'm way too lazy I'm automatically generating the secret files config.
|
|
|
|
Secrets can be found below
|
|
|
|
hosts/${hostname}/secrets/*.age
|
|
|
|
|
|
|
|
Pubkeys can be found for the specific host below
|
|
|
|
hosts/${hostname}/ssh.pub
|
|
|
|
The users have their keys below
|
|
|
|
users/${username}/ssh.pub
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2023-05-01 11:37:33 +02:00
|
|
|
let
|
2023-12-07 20:17:31 +01:00
|
|
|
/*
|
|
|
|
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...";
|
|
|
|
}
|
|
|
|
*/
|
2023-05-01 15:08:54 +02:00
|
|
|
pubkeysFor = directory: let
|
|
|
|
instances = builtins.attrNames (builtins.readDir directory);
|
|
|
|
instancesWithPubkey = builtins.filter (i: builtins.pathExists (directory + "/${i}/ssh.pub")) instances;
|
|
|
|
in
|
|
|
|
builtins.listToAttrs (map (i: { name = i; value = builtins.readFile (directory + "/${i}/ssh.pub"); }) instancesWithPubkey);
|
|
|
|
|
|
|
|
users = pubkeysFor ./users;
|
|
|
|
hosts = pubkeysFor ./hosts;
|
|
|
|
|
2023-12-07 20:17:31 +01:00
|
|
|
/*
|
|
|
|
Returns secret configuration for a given hostname
|
|
|
|
*/
|
2023-05-01 15:08:54 +02:00
|
|
|
secretsForHost = hostname: let
|
2023-12-07 20:17:31 +01:00
|
|
|
/*
|
|
|
|
Returns a list of all file names in the secrets directory of the specified host
|
|
|
|
*/
|
2023-05-01 15:08:54 +02:00
|
|
|
secretsFiles = builtins.attrNames (builtins.readDir (./hosts + "/${hostname}/secrets"));
|
2023-12-07 20:17:31 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
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;
|
|
|
|
|
2023-05-01 15:08:54 +02:00
|
|
|
in
|
2023-12-07 20:17:31 +01:00
|
|
|
if
|
|
|
|
# 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")
|
|
|
|
then
|
|
|
|
/*
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
map
|
|
|
|
(secret: {
|
|
|
|
name = "hosts/${hostname}/secrets/${secret}";
|
|
|
|
value = {
|
|
|
|
publicKeys = [
|
|
|
|
# Hardcode clerie's public key here
|
2024-05-10 14:38:13 +02:00
|
|
|
(builtins.readFile (./users + "/clerie/ssh.pub"))
|
2023-12-07 20:17:31 +01:00
|
|
|
# No other user should have access to any secrets
|
|
|
|
|
|
|
|
# A host should only have access to their own secrets
|
|
|
|
hosts."${hostname}"
|
|
|
|
];
|
|
|
|
};
|
|
|
|
})
|
|
|
|
# All file names of already existing secrets plus the magic "new" secret
|
|
|
|
(listOfSecrets ++ [ "new" ])
|
2023-05-01 15:08:54 +02:00
|
|
|
else
|
2023-12-07 20:17:31 +01:00
|
|
|
# Answer with an empty list, if no secrets are provided for a host
|
2023-05-01 15:08:54 +02:00
|
|
|
[];
|
|
|
|
in
|
2023-12-07 20:17:31 +01:00
|
|
|
# We just have a list of name value pairs that need to get transformed into an attribute set
|
|
|
|
builtins.listToAttrs (
|
|
|
|
builtins.concatMap
|
|
|
|
# Provide a list of secrets for a given hostname
|
|
|
|
(hostname: secretsForHost hostname)
|
|
|
|
# Names of all hosts
|
|
|
|
(builtins.attrNames (builtins.readDir ./hosts))
|
|
|
|
)
|