secrets.nix: Remove age secrets management
This commit is contained in:
parent
e094afc4a0
commit
d0bd09896a
@ -14,7 +14,6 @@
|
|||||||
# Deployment
|
# Deployment
|
||||||
bij
|
bij
|
||||||
colmena
|
colmena
|
||||||
agenix
|
|
||||||
clerie-sops
|
clerie-sops
|
||||||
clerie-sops-edit
|
clerie-sops-edit
|
||||||
sops
|
sops
|
||||||
|
44
flake.lock
44
flake.lock
@ -1,26 +1,5 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"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": {
|
"bij": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs": [
|
||||||
@ -59,28 +38,6 @@
|
|||||||
"url": "https://git.clerie.de/clerie/chaosevents.git"
|
"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": {
|
"fernglas": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"flake-utils": "flake-utils",
|
"flake-utils": "flake-utils",
|
||||||
@ -299,7 +256,6 @@
|
|||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"agenix": "agenix",
|
|
||||||
"bij": "bij",
|
"bij": "bij",
|
||||||
"chaosevents": "chaosevents",
|
"chaosevents": "chaosevents",
|
||||||
"fernglas": "fernglas",
|
"fernglas": "fernglas",
|
||||||
|
10
flake.nix
10
flake.nix
@ -3,10 +3,6 @@
|
|||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
nixpkgs-krypton.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs-krypton.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
||||||
agenix = {
|
|
||||||
url = "github:ryantm/agenix";
|
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
|
||||||
bij = {
|
bij = {
|
||||||
url = "git+https://git.clerie.de/clerie/bij.git";
|
url = "git+https://git.clerie.de/clerie/bij.git";
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
@ -37,7 +33,7 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
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;
|
lib = import ./lib inputs;
|
||||||
helper = lib.flake-helper;
|
helper = lib.flake-helper;
|
||||||
in {
|
in {
|
||||||
@ -115,8 +111,6 @@
|
|||||||
overlays = [
|
overlays = [
|
||||||
self.overlays.clerie
|
self.overlays.clerie
|
||||||
(_: _: {
|
(_: _: {
|
||||||
inherit (agenix.packages.${system})
|
|
||||||
agenix;
|
|
||||||
inherit (chaosevents.packages.${system})
|
inherit (chaosevents.packages.${system})
|
||||||
chaosevents;
|
chaosevents;
|
||||||
inherit (ssh-to-age.packages.${system})
|
inherit (ssh-to-age.packages.${system})
|
||||||
@ -136,9 +130,7 @@
|
|||||||
chromium-incognito
|
chromium-incognito
|
||||||
iot-data
|
iot-data
|
||||||
nix-remove-result-links
|
nix-remove-result-links
|
||||||
nixfiles-add-secret
|
|
||||||
nixfiles-auto-install
|
nixfiles-auto-install
|
||||||
nixfiles-generate-backup-secrets
|
|
||||||
nixfiles-generate-config
|
nixfiles-generate-config
|
||||||
nixfiles-update-ssh-host-keys
|
nixfiles-update-ssh-host-keys
|
||||||
print-afra
|
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 {
|
rec {
|
||||||
generateNixosSystem = {
|
generateNixosSystem = {
|
||||||
@ -28,8 +28,6 @@ rec {
|
|||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
self.overlays.clerie
|
self.overlays.clerie
|
||||||
(_: _: {
|
(_: _: {
|
||||||
inherit (agenix.packages."x86_64-linux")
|
|
||||||
agenix;
|
|
||||||
inherit (bij.packages."${system}")
|
inherit (bij.packages."${system}")
|
||||||
bij;
|
bij;
|
||||||
inherit (chaosevents.packages."x86_64-linux")
|
inherit (chaosevents.packages."x86_64-linux")
|
||||||
@ -38,21 +36,12 @@ rec {
|
|||||||
];
|
];
|
||||||
clerie.monitoring = nixpkgs.lib.attrsets.optionalAttrs (group != null) { serviceLevel = group; };
|
clerie.monitoring = nixpkgs.lib.attrsets.optionalAttrs (group != null) { serviceLevel = group; };
|
||||||
})
|
})
|
||||||
agenix.nixosModules.default
|
|
||||||
fernglas.nixosModules.default
|
fernglas.nixosModules.default
|
||||||
fieldpoc.nixosModules.default
|
fieldpoc.nixosModules.default
|
||||||
nixos-exporter.nixosModules.default
|
nixos-exporter.nixosModules.default
|
||||||
solid-xmpp-alarm.nixosModules.solid-xmpp-alarm
|
solid-xmpp-alarm.nixosModules.solid-xmpp-alarm
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
(../hosts + "/${name}/configuration.nix")
|
(../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
|
# Automatically load secrets from sops file for host
|
||||||
({ config, lib, ... }: {
|
({ config, lib, ... }: {
|
||||||
sops.defaultSopsFile = ../hosts + "/${name}/secrets.json";
|
sops.defaultSopsFile = ../hosts + "/${name}/secrets.json";
|
||||||
|
@ -23,12 +23,10 @@ let
|
|||||||
|
|
||||||
backupServiceUnits = listToAttrs (map ({jobName, jobOptions, targetName, targetOptions}: let
|
backupServiceUnits = listToAttrs (map ({jobName, jobOptions, targetName, targetOptions}: let
|
||||||
jobPasswordFile = if jobOptions.passwordFile != null then jobOptions.passwordFile else
|
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.sops.secrets."clerie-backup-job-${jobName}".path;
|
||||||
config.age.secrets."clerie-backup-job-${jobName}".path;
|
|
||||||
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
||||||
targetPasswordFile = if targetOptions.passwordFile != null then targetOptions.passwordFile else
|
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.sops.secrets."clerie-backup-target-${targetName}".path;
|
||||||
config.age.secrets."clerie-backup-target-${targetName}".path;
|
|
||||||
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
||||||
in
|
in
|
||||||
nameValuePair "clerie-backup-${jobName}-${targetName}" {
|
nameValuePair "clerie-backup-${jobName}-${targetName}" {
|
||||||
@ -73,12 +71,10 @@ let
|
|||||||
|
|
||||||
backupCommands = map ({jobName, jobOptions, targetName, targetOptions}: let
|
backupCommands = map ({jobName, jobOptions, targetName, targetOptions}: let
|
||||||
jobPasswordFile = if jobOptions.passwordFile != null then jobOptions.passwordFile else
|
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.sops.secrets."clerie-backup-job-${jobName}".path;
|
||||||
config.age.secrets."clerie-backup-job-${jobName}".path;
|
|
||||||
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
repoPath = if jobOptions.repoPath == null then "/${config.networking.hostName}/${jobName}" else jobOptions.repoPath;
|
||||||
targetPasswordFile = if targetOptions.passwordFile != null then targetOptions.passwordFile else
|
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.sops.secrets."clerie-backup-target-${targetName}".path;
|
||||||
config.age.secrets."clerie-backup-target-${targetName}".path;
|
|
||||||
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
targetUsername = if targetOptions.username == null then config.networking.hostName else targetOptions.username;
|
||||||
in pkgs.writeShellApplication {
|
in pkgs.writeShellApplication {
|
||||||
name = "clerie-backup-${jobName}-${targetName}";
|
name = "clerie-backup-${jobName}-${targetName}";
|
||||||
|
@ -55,8 +55,7 @@ in
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
privateKeyFile = if cfg.privateKeyFile != null then cfg.privateKeyFile else
|
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.sops.secrets.wg-monitoring.path;
|
||||||
config.age.secrets.wg-monitoring.path;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,8 +66,7 @@ in
|
|||||||
networking.wireguard.interfaces = {
|
networking.wireguard.interfaces = {
|
||||||
wg-clerie = {
|
wg-clerie = {
|
||||||
privateKeyFile = if cfg.privateKeyFile != null then cfg.privateKeyFile else
|
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.sops.secrets.wg-clerie.path;
|
||||||
config.age.secrets.wg-clerie.path;
|
|
||||||
ips = cfg.ipv6s ++ cfg.ipv4s;
|
ips = cfg.ipv6s ++ cfg.ipv4s;
|
||||||
table = "wg-clerie";
|
table = "wg-clerie";
|
||||||
peers = [
|
peers = [
|
||||||
|
@ -98,7 +98,7 @@ in
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
boot.initrd.secrets = {
|
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 {};
|
chromium-incognito = final.callPackage ./chromium-incognito {};
|
||||||
iot-data = final.python3.pkgs.callPackage ./iot-data {};
|
iot-data = final.python3.pkgs.callPackage ./iot-data {};
|
||||||
nix-remove-result-links = final.callPackage ./nix-remove-result-links {};
|
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-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-generate-config = final.callPackage ./nixfiles/nixfiles-generate-config.nix {};
|
||||||
nixfiles-update-ssh-host-keys = final.callPackage ./nixfiles/nixfiles-update-ssh-host-keys.nix {};
|
nixfiles-update-ssh-host-keys = final.callPackage ./nixfiles/nixfiles-update-ssh-host-keys.nix {};
|
||||||
print-afra = final.callPackage ./print-afra {};
|
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