secrets.nix: Remove age secrets management
This commit is contained in:
parent
e094afc4a0
commit
d0bd09896a
@ -14,7 +14,6 @@
|
||||
# Deployment
|
||||
bij
|
||||
colmena
|
||||
agenix
|
||||
clerie-sops
|
||||
clerie-sops-edit
|
||||
sops
|
||||
|
44
flake.lock
44
flake.lock
@ -1,26 +1,5 @@
|
||||
{
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"darwin": "darwin",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1682101079,
|
||||
"narHash": "sha256-MdAhtjrLKnk2uiqun1FWABbKpLH090oeqCSiWemtuck=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "2994d002dcff5353ca1ac48ec584c7f6589fe447",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"bij": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -59,28 +38,6 @@
|
||||
"url": "https://git.clerie.de/clerie/chaosevents.git"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1673295039,
|
||||
"narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"ref": "master",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fernglas": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
@ -299,7 +256,6 @@
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"bij": "bij",
|
||||
"chaosevents": "chaosevents",
|
||||
"fernglas": "fernglas",
|
||||
|
10
flake.nix
10
flake.nix
@ -3,10 +3,6 @@
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixpkgs-krypton.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
bij = {
|
||||
url = "git+https://git.clerie.de/clerie/bij.git";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
@ -37,7 +33,7 @@
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
outputs = { self, agenix, nixpkgs, nixos-hardware, chaosevents, fernglas, nixos-exporter, solid-xmpp-alarm, ssh-to-age, ... }@inputs: let
|
||||
outputs = { self, nixpkgs, nixos-hardware, chaosevents, fernglas, nixos-exporter, solid-xmpp-alarm, ssh-to-age, ... }@inputs: let
|
||||
lib = import ./lib inputs;
|
||||
helper = lib.flake-helper;
|
||||
in {
|
||||
@ -115,8 +111,6 @@
|
||||
overlays = [
|
||||
self.overlays.clerie
|
||||
(_: _: {
|
||||
inherit (agenix.packages.${system})
|
||||
agenix;
|
||||
inherit (chaosevents.packages.${system})
|
||||
chaosevents;
|
||||
inherit (ssh-to-age.packages.${system})
|
||||
@ -136,9 +130,7 @@
|
||||
chromium-incognito
|
||||
iot-data
|
||||
nix-remove-result-links
|
||||
nixfiles-add-secret
|
||||
nixfiles-auto-install
|
||||
nixfiles-generate-backup-secrets
|
||||
nixfiles-generate-config
|
||||
nixfiles-update-ssh-host-keys
|
||||
print-afra
|
||||
|
@ -1,4 +1,4 @@
|
||||
{ self, nixpkgs, agenix, bij, chaosevents, fernglas, fieldpoc, nixos-exporter, solid-xmpp-alarm, sops-nix, ... }@inputs:
|
||||
{ self, nixpkgs, bij, chaosevents, fernglas, fieldpoc, nixos-exporter, solid-xmpp-alarm, sops-nix, ... }@inputs:
|
||||
|
||||
rec {
|
||||
generateNixosSystem = {
|
||||
@ -28,8 +28,6 @@ rec {
|
||||
nixpkgs.overlays = [
|
||||
self.overlays.clerie
|
||||
(_: _: {
|
||||
inherit (agenix.packages."x86_64-linux")
|
||||
agenix;
|
||||
inherit (bij.packages."${system}")
|
||||
bij;
|
||||
inherit (chaosevents.packages."x86_64-linux")
|
||||
@ -38,21 +36,12 @@ rec {
|
||||
];
|
||||
clerie.monitoring = nixpkgs.lib.attrsets.optionalAttrs (group != null) { serviceLevel = group; };
|
||||
})
|
||||
agenix.nixosModules.default
|
||||
fernglas.nixosModules.default
|
||||
fieldpoc.nixosModules.default
|
||||
nixos-exporter.nixosModules.default
|
||||
solid-xmpp-alarm.nixosModules.solid-xmpp-alarm
|
||||
sops-nix.nixosModules.sops
|
||||
(../hosts + "/${name}/configuration.nix")
|
||||
# Automatically load secrets from the hosts secrets directory
|
||||
({ lib, ... }: let
|
||||
secretsPath = ../hosts + "/${name}/secrets";
|
||||
in {
|
||||
age.secrets = lib.mapAttrs' (filename: _: lib.nameValuePair (lib.removeSuffix ".age" filename) {
|
||||
file = secretsPath + "/${filename}";
|
||||
}) (lib.filterAttrs (name: type: (type == "regular") && (lib.hasSuffix ".age" name) ) (if builtins.pathExists secretsPath then builtins.readDir secretsPath else {}));
|
||||
})
|
||||
# Automatically load secrets from sops file for host
|
||||
({ config, lib, ... }: {
|
||||
sops.defaultSopsFile = ../hosts + "/${name}/secrets.json";
|
||||
|
@ -23,12 +23,10 @@ let
|
||||
|
||||
backupServiceUnits = listToAttrs (map ({jobName, jobOptions, targetName, targetOptions}: let
|
||||
jobPasswordFile = if jobOptions.passwordFile != null then jobOptions.passwordFile else
|
||||
if builtins.elem "clerie-backup-job-${jobName}" (attrNames config.sops.secrets) then config.sops.secrets."clerie-backup-job-${jobName}".path else
|
||||
config.age.secrets."clerie-backup-job-${jobName}".path;
|
||||
config.sops.secrets."clerie-backup-job-${jobName}".path;
|
||||
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
||||
targetPasswordFile = if targetOptions.passwordFile != null then targetOptions.passwordFile else
|
||||
if builtins.elem "clerie-backup-target-${targetName}" (attrNames config.sops.secrets) then config.sops.secrets."clerie-backup-target-${targetName}".path else
|
||||
config.age.secrets."clerie-backup-target-${targetName}".path;
|
||||
config.sops.secrets."clerie-backup-target-${targetName}".path;
|
||||
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
||||
in
|
||||
nameValuePair "clerie-backup-${jobName}-${targetName}" {
|
||||
@ -73,12 +71,10 @@ let
|
||||
|
||||
backupCommands = map ({jobName, jobOptions, targetName, targetOptions}: let
|
||||
jobPasswordFile = if jobOptions.passwordFile != null then jobOptions.passwordFile else
|
||||
if builtins.elem "clerie-backup-job-${jobName}" (attrNames config.sops.secrets) then config.sops.secrets."clerie-backup-job-${jobName}".path else
|
||||
config.age.secrets."clerie-backup-job-${jobName}".path;
|
||||
config.sops.secrets."clerie-backup-job-${jobName}".path;
|
||||
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
||||
targetPasswordFile = if targetOptions.passwordFile != null then targetOptions.passwordFile else
|
||||
if builtins.elem "clerie-backup-target-${targetName}" (attrNames config.sops.secrets) then config.sops.secrets."clerie-backup-target-${targetName}".path else
|
||||
config.age.secrets."clerie-backup-target-${targetName}".path;
|
||||
config.sops.secrets."clerie-backup-target-${targetName}".path;
|
||||
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
||||
in pkgs.writeShellApplication {
|
||||
name = "clerie-backup-${jobName}-${targetName}";
|
||||
|
@ -55,8 +55,7 @@ in
|
||||
}
|
||||
];
|
||||
privateKeyFile = if cfg.privateKeyFile != null then cfg.privateKeyFile else
|
||||
if builtins.elem "wg-monitoring" (attrNames config.sops.secrets) then config.sops.secrets.wg-monitoring.path else
|
||||
config.age.secrets.wg-monitoring.path;
|
||||
config.sops.secrets.wg-monitoring.path;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -66,8 +66,7 @@ in
|
||||
networking.wireguard.interfaces = {
|
||||
wg-clerie = {
|
||||
privateKeyFile = if cfg.privateKeyFile != null then cfg.privateKeyFile else
|
||||
if builtins.elem "wg-clerie" (attrNames config.sops.secrets) then config.sops.secrets.wg-clerie.path else
|
||||
config.age.secrets.wg-clerie.path;
|
||||
config.sops.secrets.wg-clerie.path;
|
||||
ips = cfg.ipv6s ++ cfg.ipv4s;
|
||||
table = "wg-clerie";
|
||||
peers = [
|
||||
|
@ -98,7 +98,7 @@ in
|
||||
'';
|
||||
|
||||
boot.initrd.secrets = {
|
||||
"/var/src/secrets/wireguard/wg-initrd" = if cfg.privateKeyFile == null then config.age.secrets.wg-clerie.path else cfg.privateKeyFile;
|
||||
"/var/src/secrets/wireguard/wg-initrd" = cfg.privateKeyFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
pkgs.writeShellApplication {
|
||||
name = "nixfiles-add-secret";
|
||||
text = builtins.readFile ./nixfiles-add-secret.sh;
|
||||
runtimeInputs = with pkgs; [
|
||||
agenix
|
||||
git
|
||||
];
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
host="$1"
|
||||
secret="$2"
|
||||
|
||||
mkdir -p "hosts/${host}/secrets"
|
||||
|
||||
agenix -e "hosts/${host}/secrets/new"
|
||||
|
||||
mv "hosts/${host}/secrets/new" "hosts/${host}/secrets/${secret}.age"
|
||||
|
@ -9,9 +9,7 @@ final: prev: {
|
||||
chromium-incognito = final.callPackage ./chromium-incognito {};
|
||||
iot-data = final.python3.pkgs.callPackage ./iot-data {};
|
||||
nix-remove-result-links = final.callPackage ./nix-remove-result-links {};
|
||||
nixfiles-add-secret = final.callPackage ./nixfiles/nixfiles-add-secret.nix {};
|
||||
nixfiles-auto-install = final.callPackage ./nixfiles/nixfiles-auto-install.nix {};
|
||||
nixfiles-generate-backup-secrets = final.callPackage ./nixfiles/nixfiles-generate-backup-secrets.nix {};
|
||||
nixfiles-generate-config = final.callPackage ./nixfiles/nixfiles-generate-config.nix {};
|
||||
nixfiles-update-ssh-host-keys = final.callPackage ./nixfiles/nixfiles-update-ssh-host-keys.nix {};
|
||||
print-afra = final.callPackage ./print-afra {};
|
||||
|
96
secrets.nix
96
secrets.nix
@ -1,96 +0,0 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
let
|
||||
/*
|
||||
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;
|
||||
in
|
||||
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;
|
||||
|
||||
in
|
||||
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
|
||||
(builtins.readFile (./users + "/clerie/ssh.pub"))
|
||||
# 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" ])
|
||||
else
|
||||
# Answer with an empty list, if no secrets are provided for a host
|
||||
[];
|
||||
in
|
||||
# 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))
|
||||
)
|
Loading…
Reference in New Issue
Block a user