From 0a2aae3a43b7b91c4863e47fbd5b3a86f97a078b Mon Sep 17 00:00:00 2001 From: Chaos Date: Tue, 15 Nov 2022 13:42:28 +0000 Subject: [PATCH] change secrets management to its own module and update hetzner-vm with it --- hosts/hetzner-vm/secrets-db.nix | 68 ----- hosts/hetzner-vm/secrets.nix | 178 ++++++------- .../services/gitlab-static-sites.nix | 6 +- .../hetzner-vm/services/mailserver/config.nix | 6 +- .../services/mailserver/dovecot.nix | 3 +- .../services/mailserver/opendkim.nix | 3 +- .../services/mailserver/postfix.nix | 2 +- .../hetzner-vm/services/mailserver/rspamd.nix | 2 +- hosts/hetzner-vm/services/mailserver/ssl.nix | 4 +- .../hetzner-vm/services/mailserver/vmail.nix | 2 +- .../services/mailserver/webmail.nix | 4 +- hosts/hetzner-vm/services/mpd.nix | 10 +- hosts/hetzner-vm/services/restic.nix | 12 +- hosts/hetzner-vm/services/wireguard.nix | 14 +- hosts/nixos.nix | 1 + modules/nixos/secrets.nix | 251 ++++++++++++++++++ presets/nixos/normal-encrypted-drive.nix | 3 +- 17 files changed, 371 insertions(+), 198 deletions(-) delete mode 100644 hosts/hetzner-vm/secrets-db.nix create mode 100644 modules/nixos/secrets.nix diff --git a/hosts/hetzner-vm/secrets-db.nix b/hosts/hetzner-vm/secrets-db.nix deleted file mode 100644 index d4c4490..0000000 --- a/hosts/hetzner-vm/secrets-db.nix +++ /dev/null @@ -1,68 +0,0 @@ -{ }: { - mpd_control_password = { - user = "mpd"; - group = "mpd"; - permissions = "660"; - path = "/secrets/mpd_control_password"; - }; - music_stream_passwd = { - user = "nginx"; - group = "nginx"; - permissions = "660"; - path = "/secrets/music_stream_passwd"; - }; - chaos_mail_passwd = { - user = "dovecot2"; - group = "dovecot2"; - permissions = "660"; - path = "/secrets/chaos_mail_passwd"; - }; - gitlab_env = { - user = "gitlab_artifacts_sync"; - group = "gitlab_artifacts_sync"; - permissions = "660"; - path = "/secrets/gitlab_env"; - }; - restic_password = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/restic_password"; - }; - restic_env = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/restic_env"; - }; - wg_privkey = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/wg_privkey"; - }; - wg_preshared_tablet = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/wg_preshared_tablet"; - }; - wg_preshared_vault = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/wg_preshared_vault"; - }; - wg_preshared_storage = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/wg_preshared_storage"; - }; - wg_preshared_iphone8 = { - user = "root"; - group = "root"; - permissions = "660"; - path = "/secrets/wg_preshared_iphone8"; - }; -} diff --git a/hosts/hetzner-vm/secrets.nix b/hosts/hetzner-vm/secrets.nix index 853602c..510e242 100644 --- a/hosts/hetzner-vm/secrets.nix +++ b/hosts/hetzner-vm/secrets.nix @@ -1,97 +1,87 @@ -{ pkgs, ... }: -let secrets-db = (import ./secrets-db.nix { }); -in { - systemd.tmpfiles.rules = [ "d /secrets - root root" ]; - environment.systemPackages = [ - (pkgs.writeShellScriptBin "init-secrets" '' - set -e -o pipefail +{ pkgs, ... }: { + services.secrets = { + enable = true; - VAULT_ADDR_DEFAULT="https://vault.owo.monster" - [ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" + extraPackages = with pkgs; + [ + # for music & mail passwd files + apacheHttpd + ]; - export PATH=$PATH:${pkgs.vault}/bin - export PATH=$PATH:${pkgs.jq}/bin - export PATH=$PATH:${pkgs.apacheHttpd}/bin - - kv_get() { - vault kv get -format json $1 - } - - simple_get() { - kv_get $1 | jq .data.data$2 -r - } - - file=${secrets-db.mpd_control_password.path} - echo $file - simple_get "/api-keys/mpd" .password > $file - chown ${secrets-db.mpd_control_password.user}:${secrets-db.mpd_control_password.group} $file - chmod ${secrets-db.mpd_control_password.permissions} $file - - file=${secrets-db.music_stream_passwd.path} - echo $file - username=$(simple_get "/api-keys/music-stream" .username) - password=$(simple_get "/api-keys/music-stream" .password) - htpasswd -bc $file "$username" "$password" - chown ${secrets-db.music_stream_passwd.user}:${secrets-db.music_stream_passwd.group} $file - chmod ${secrets-db.music_stream_passwd.permissions} $file - - file=${secrets-db.chaos_mail_passwd.path} - echo $file - password=$(simple_get "/passwords/mail" .password) - htpasswd -nbB "" "$password" | cut -d: -f2 > $file - chown ${secrets-db.chaos_mail_passwd.user}:${secrets-db.chaos_mail_passwd.group} $file - chmod ${secrets-db.chaos_mail_passwd.permissions} $file - - file=${secrets-db.gitlab_env.path} - echo $file - token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token) - echo "GITLAB_TOKEN=$token" > $file - chown ${secrets-db.gitlab_env.user}:${secrets-db.gitlab_env.group} $file - chmod ${secrets-db.gitlab_env.permissions} $file - - file=${secrets-db.restic_password.path} - echo $file - simple_get "/private-public-keys/restic/HetznerVM" .password > $file - chown ${secrets-db.restic_password.user}:${secrets-db.restic_password.group} $file - chmod ${secrets-db.restic_password.permissions} $file - - file=${secrets-db.restic_env.path} - echo $file - RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/HetznerVM" .username) - RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/HetznerVM" .password) - echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/HetznerVM" > $file - chown ${secrets-db.restic_env.user}:${secrets-db.restic_env.group} $file - chmod ${secrets-db.restic_env.permissions} $file - - file=${secrets-db.wg_privkey.path} - echo $file - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > $file - chown ${secrets-db.wg_privkey.user}:${secrets-db.wg_privkey.group} $file - chmod ${secrets-db.wg_privkey.permissions} $file - - file=${secrets-db.wg_preshared_tablet.path} - echo $file - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.tablet > $file - chown ${secrets-db.wg_preshared_tablet.user}:${secrets-db.wg_preshared_tablet.group} $file - chmod ${secrets-db.wg_preshared_tablet.permissions} $file - - file=${secrets-db.wg_preshared_vault.path} - echo $file - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > $file - chown ${secrets-db.wg_preshared_vault.user}:${secrets-db.wg_preshared_vault.group} $file - chmod ${secrets-db.wg_preshared_vault.permissions} $file - - file=${secrets-db.wg_preshared_storage.path} - echo $file - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.storage > $file - chown ${secrets-db.wg_preshared_storage.user}:${secrets-db.wg_preshared_storage.group} $file - chmod ${secrets-db.wg_preshared_storage.permissions} $file - - file=${secrets-db.wg_preshared_iphone8.path} - echo $file - simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > $file - chown ${secrets-db.wg_preshared_iphone8.user}:${secrets-db.wg_preshared_iphone8.group} $file - chmod ${secrets-db.wg_preshared_iphone8.permissions} $file - '') - ]; + secrets = { + mpd_control_password = { + user = "mpd"; + group = "mpd"; + fetchScript = '' + simple_get "/api-keys/mpd" .password > $secretFile + ''; + }; + music_stream_passwd = { + user = "nginx"; + group = "nginx"; + fetchScript = '' + username=$(simple_get "/api-keys/music-stream" .username) + password=$(simple_get "/api-keys/music-stream" .password) + htpasswd -bc $secretFile "$username" "$password" 2>/dev/null + ''; + }; + chaos_mail_passwd = { + user = "dovecot2"; + group = "dovecot2"; + fetchScript = '' + password=$(simple_get "/passwords/mail" .password) + htpasswd -nbB "" "$password" 2>/dev/null | cut -d: -f2 > $secretFile + ''; + }; + gitlab_env = { + user = "gitlab_artifacts_sync"; + group = "gitlab_artifacts_sync"; + fetchScript = '' + token=$(simple_get "/api-keys/gitlab/gitlab_pages_serve" .token) + echo "GITLAB_TOKEN=$token" > $secretFile + ''; + }; + restic_password = { + fetchScript = '' + simple_get "/private-public-keys/restic/HetznerVM" .password > $secretFile + ''; + }; + restic_env = { + fetchScript = '' + RESTIC_USERNAME=$(simple_get "/api-keys/storage/restic/HetznerVM" .username) + RESTIC_PASSWORD=$(simple_get "/api-keys/storage/restic/HetznerVM" .password) + echo "RESTIC_REPOSITORY=rest:https://$RESTIC_USERNAME:$RESTIC_PASSWORD@storage-restic.owo.monster/HetznerVM" > $secretFile + ''; + }; + wg_privkey = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .private > $secretFile + ''; + }; + wg_preshared_tablet = { + path = "/secrets/wg_preshared_tablet"; + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.tablet > $secretFile + ''; + }; + wg_preshared_vault = { + path = "/secrets/wg_preshared_vault"; + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.vault > $secretFile + ''; + }; + wg_preshared_storage = { + path = "/secrets/wg_preshared_storage"; + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.storage > $secretFile + ''; + }; + wg_preshared_iphone8 = { + path = "/secrets/wg_preshared_iphone8"; + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > $secretFile + ''; + }; + }; + }; } diff --git a/hosts/hetzner-vm/services/gitlab-static-sites.nix b/hosts/hetzner-vm/services/gitlab-static-sites.nix index a11c121..21cb9f2 100644 --- a/hosts/hetzner-vm/services/gitlab-static-sites.nix +++ b/hosts/hetzner-vm/services/gitlab-static-sites.nix @@ -1,9 +1,9 @@ -{ ... }: -let secrets-db = (import ../secrets-db.nix { }); +{ config, ... }: +let secrets = config.services.secrets.secrets; in { services.gitlab_artifacts_sync = { enable = true; - credentialsEnvironmentFile = "${secrets-db.gitlab_env.path}"; + credentialsEnvironmentFile = "${secrets.gitlab_env.path}"; repos = [ { repoName = "ChaotiCryptidz/VaultUI"; diff --git a/hosts/hetzner-vm/services/mailserver/config.nix b/hosts/hetzner-vm/services/mailserver/config.nix index 2aa670a..7786228 100644 --- a/hosts/hetzner-vm/services/mailserver/config.nix +++ b/hosts/hetzner-vm/services/mailserver/config.nix @@ -1,5 +1,5 @@ -{ }: -let secrets-db = (import ../../secrets-db.nix { }); +{ config }: +let secrets = config.services.secrets.secrets; in rec { fqdn = "mail.owo.monster"; domains = [ @@ -21,7 +21,7 @@ in rec { accounts = { "chaoticryptidz@owo.monster" = { name = "chaoticryptidz@owo.monster"; - passwordFile = "${secrets-db.chaos_mail_passwd.path}"; + passwordFile = "${secrets.chaos_mail_passwd.path}"; aliases = [ "all@owo.monster" # for sending from diff --git a/hosts/hetzner-vm/services/mailserver/dovecot.nix b/hosts/hetzner-vm/services/mailserver/dovecot.nix index d65956d..6bd0883 100644 --- a/hosts/hetzner-vm/services/mailserver/dovecot.nix +++ b/hosts/hetzner-vm/services/mailserver/dovecot.nix @@ -1,7 +1,6 @@ { config, pkgs, lib, ... }: let - mail_config = (import ./config.nix { }); - + mail_config = (import ./config.nix { config = config; }); passwdDir = "/run/dovecot2"; passwdFile = "${passwdDir}/passwd"; diff --git a/hosts/hetzner-vm/services/mailserver/opendkim.nix b/hosts/hetzner-vm/services/mailserver/opendkim.nix index d51eea3..8747ac9 100644 --- a/hosts/hetzner-vm/services/mailserver/opendkim.nix +++ b/hosts/hetzner-vm/services/mailserver/opendkim.nix @@ -1,7 +1,6 @@ { config, lib, pkgs, ... }: let - mail_config = (import ./config.nix { }); - + mail_config = (import ./config.nix { config = config; }); dkimUser = config.services.opendkim.user; dkimGroup = config.services.opendkim.group; diff --git a/hosts/hetzner-vm/services/mailserver/postfix.nix b/hosts/hetzner-vm/services/mailserver/postfix.nix index 21c5c8f..6abebf1 100644 --- a/hosts/hetzner-vm/services/mailserver/postfix.nix +++ b/hosts/hetzner-vm/services/mailserver/postfix.nix @@ -1,7 +1,7 @@ { config, pkgs, lib, ... }: let - mail_config = (import ./config.nix { }); + mail_config = (import ./config.nix { config = config; }); submissionHeaderCleanupRules = pkgs.writeText "submission_header_cleanup_rules" ('' /^Received:/ IGNORE diff --git a/hosts/hetzner-vm/services/mailserver/rspamd.nix b/hosts/hetzner-vm/services/mailserver/rspamd.nix index 4702f7d..97ef645 100644 --- a/hosts/hetzner-vm/services/mailserver/rspamd.nix +++ b/hosts/hetzner-vm/services/mailserver/rspamd.nix @@ -1,7 +1,7 @@ { config, pkgs, lib, ... }: let - mail_config = (import ./config.nix { }); + mail_config = (import ./config.nix { config = config; }); ports = (import ../../ports.nix { }); diff --git a/hosts/hetzner-vm/services/mailserver/ssl.nix b/hosts/hetzner-vm/services/mailserver/ssl.nix index f645704..62d7017 100644 --- a/hosts/hetzner-vm/services/mailserver/ssl.nix +++ b/hosts/hetzner-vm/services/mailserver/ssl.nix @@ -1,6 +1,6 @@ -{ pkgs, ... }: +{ config, pkgs, ... }: let - mail_config = (import ./config.nix { }); + mail_config = (import ./config.nix { config = config; }); acmeRoot = "/var/lib/acme/acme-challenge"; in { diff --git a/hosts/hetzner-vm/services/mailserver/vmail.nix b/hosts/hetzner-vm/services/mailserver/vmail.nix index 3f75c94..760527e 100644 --- a/hosts/hetzner-vm/services/mailserver/vmail.nix +++ b/hosts/hetzner-vm/services/mailserver/vmail.nix @@ -1,6 +1,6 @@ { config, pkgs, lib, ... }: let - mail_config = (import ./config.nix { }); + mail_config = (import ./config.nix { config = config; }); v = mail_config.vmail_config; sieve_directory = mail_config.sieve_directory; diff --git a/hosts/hetzner-vm/services/mailserver/webmail.nix b/hosts/hetzner-vm/services/mailserver/webmail.nix index e40f8b3..d3ac29c 100644 --- a/hosts/hetzner-vm/services/mailserver/webmail.nix +++ b/hosts/hetzner-vm/services/mailserver/webmail.nix @@ -1,5 +1,5 @@ -{ ... }: -let mail_config = (import ./config.nix { }); +{ config, ... }: +let mail_config = (import ./config.nix { config = config; }); in { services.roundcube = { enable = true; diff --git a/hosts/hetzner-vm/services/mpd.nix b/hosts/hetzner-vm/services/mpd.nix index e2998e9..8027060 100644 --- a/hosts/hetzner-vm/services/mpd.nix +++ b/hosts/hetzner-vm/services/mpd.nix @@ -1,7 +1,7 @@ -{ pkgs, lib, tree, ... }: +{ config, pkgs, lib, tree, ... }: let ports = (import ../ports.nix { }); - secrets-db = (import ../secrets-db.nix { }); + secrets = config.services.secrets.secrets; in { environment.systemPackages = with pkgs; [ mpc_cli ]; @@ -10,7 +10,7 @@ in { network.listenAddress = "0.0.0.0"; musicDirectory = "https://storage-webdav.owo.monster/music_ro/"; credentials = [{ - passwordFile = "${secrets-db.mpd_control_password.path}"; + passwordFile = "${secrets.mpd_control_password.path}"; permissions = [ "read" "add" "control" "admin" ]; }]; extraConfig = '' @@ -53,14 +53,14 @@ in { proxyPass = "http://127.0.0.1:${toString ports.mpd-opus}"; extraConfig = '' auth_basic "Music Password"; - auth_basic_user_file ${secrets-db.music_stream_passwd.path}; + auth_basic_user_file ${secrets.music_stream_passwd.path}; ''; }; "/flac" = { proxyPass = "http://127.0.0.1:${toString ports.mpd-flac}"; extraConfig = '' auth_basic "Music Password"; - auth_basic_user_file ${secrets-db.music_stream_passwd.path}; + auth_basic_user_file ${secrets.music_stream_passwd.path}; ''; }; }; diff --git a/hosts/hetzner-vm/services/restic.nix b/hosts/hetzner-vm/services/restic.nix index a2f9047..b8ec92a 100644 --- a/hosts/hetzner-vm/services/restic.nix +++ b/hosts/hetzner-vm/services/restic.nix @@ -1,7 +1,7 @@ { lib, config, pkgs, ... }: let - secrets-db = (import ../secrets-db.nix { }); - mail_config = (import ./mailserver/config.nix { }); + secrets = config.services.secrets.secrets; + mail_config = (import ./mailserver/config.nix { config = config; }); backupPrepareCommand = "${ (pkgs.writeShellScriptBin "backupPrepareCommand" '' @@ -12,8 +12,8 @@ in { environment.systemPackages = [ (pkgs.writeShellScriptBin "restic-hetzner-vm" '' env \ - RESTIC_PASSWORD_FILE=${secrets-db.restic_password.path} \ - $(cat ${secrets-db.restic_env.path}) \ + RESTIC_PASSWORD_FILE=${secrets.restic_password.path} \ + $(cat ${secrets.restic_env.path}) \ ${pkgs.restic}/bin/restic $@ '') ]; @@ -40,8 +40,8 @@ in { # repository is overrided in environmentFile to contain auth # make sure to keep up to date when changing repository repository = "rest:https://storage-restic.owo.monster/HetznerVM"; - passwordFile = "${secrets-db.restic_password.path}"; - environmentFile = "${secrets-db.restic_env.path}"; + passwordFile = "${secrets.restic_password.path}"; + environmentFile = "${secrets.restic_env.path}"; timerConfig = { OnBootSec = "1m"; diff --git a/hosts/hetzner-vm/services/wireguard.nix b/hosts/hetzner-vm/services/wireguard.nix index 36a307e..ced5141 100644 --- a/hosts/hetzner-vm/services/wireguard.nix +++ b/hosts/hetzner-vm/services/wireguard.nix @@ -1,35 +1,35 @@ -{ ... }: -let secrets-db = (import ../secrets-db.nix { }); +{ config, ... }: +let secrets = config.services.secrets.secrets; in { networking.wg-quick.interfaces = { wg0 = { address = [ "10.69.42.1/32" ]; listenPort = 51820; - privateKeyFile = "${secrets-db.wg_privkey.path}"; + privateKeyFile = "${secrets.wg_privkey.path}"; peers = [ # tablet { publicKey = "jXA0DeprEaL/ARQ3K81l8xWuUI5C/90DcY3bIfcIjz8="; - presharedKeyFile = "${secrets-db.wg_preshared_tablet.path}"; + presharedKeyFile = "${secrets.wg_preshared_tablet.path}"; allowedIPs = [ "10.69.42.2/32" ]; } # vault { publicKey = "IGq+WanFM/bKNUkwjO/0AAtDhJLvtvU+mVxH27QyHTc="; - presharedKeyFile = "${secrets-db.wg_preshared_vault.path}"; + presharedKeyFile = "${secrets.wg_preshared_vault.path}"; endpoint = "vault.servers.genderfucked.monster:51820"; allowedIPs = [ "10.69.42.3/32" ]; } # storage { publicKey = "biNNeCkjAWi2jUVoL5+1pBtXGa3OFZi4DltB2dqGjGg="; - presharedKeyFile = "${secrets-db.wg_preshared_storage.path}"; + presharedKeyFile = "${secrets.wg_preshared_storage.path}"; allowedIPs = [ "10.69.42.4/32" ]; } # iphone8 { publicKey = "2BgT08bDKh8WlFFSeRArI9a1GpFgUyqEApvJy4KgAmw="; - presharedKeyFile = "${secrets-db.wg_preshared_iphone8.path}"; + presharedKeyFile = "${secrets.wg_preshared_iphone8.path}"; allowedIPs = [ "10.69.42.5/32" ]; } ]; diff --git a/hosts/nixos.nix b/hosts/nixos.nix index 69b5fdb..2be64e7 100644 --- a/hosts/nixos.nix +++ b/hosts/nixos.nix @@ -21,6 +21,7 @@ let tree.impure.modules.nixos.rclone-serve tree.impure.modules.nixos.rclone-sync + tree.impure.modules.nixos.secrets ]; nixosUnstableSystem = nixpkgs-unstable.lib.nixosSystem; diff --git a/modules/nixos/secrets.nix b/modules/nixos/secrets.nix new file mode 100644 index 0000000..64ccfed --- /dev/null +++ b/modules/nixos/secrets.nix @@ -0,0 +1,251 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.secrets; + defaultPackages = with pkgs; [ pkgs.vault pkgs.jq ]; + +in { + options = { + services.secrets = { + enable = mkOption { + type = types.bool; + default = false; + }; + + debug = mkOption { + type = types.bool; + default = false; + }; + + createSecretsDir = mkOption { + type = types.bool; + default = true; + }; + + secretsDirUser = mkOption { + type = types.str; + default = "root"; + }; + + secretsDirGroup = mkOption { + type = types.str; + default = "root"; + }; + + secretsDir = mkOption { + type = types.str; + default = "/secrets"; + }; + + vaultURL = mkOption { + type = types.str; + default = "https://vault.owo.monster"; + description = "default Vault URL, can be overrided with env variables"; + }; + + extraFunctions = mkOption { + type = types.lines; + default = ""; + description = "extra bash functions to add to top of script"; + }; + + extraPackages = mkOption { + type = types.listOf types.package; + default = [ ]; + description = "extra packages for script"; + }; + + secrets = mkOption { + type = types.attrsOf (types.submodule ({ config, name, ... }: { + options = { + user = mkOption { + type = types.str; + default = "root"; + }; + group = mkOption { + type = types.str; + default = "root"; + }; + permissions = mkOption { + type = types.str; + default = "660"; + }; + path = mkOption { + type = types.str; + default = "${cfg.secretsDir}/${name}"; + }; + + fetchScript = mkOption { + type = types.lines; + description = '' + script used to fetch secrets, $file is secret.path + ''; + }; + + checkScript = mkOption { + type = types.nullOr types.lines; + default = null; + description = '' + script used to check contents of secret file, set LOCAL_FAIL to true on failure + ''; + }; + + manual = mkOption { + type = types.bool; + default = false; + description = "should the secret be manually deployed"; + }; + }; + })); + }; + }; + }; + + config = mkMerge [ + (mkIf (cfg.enable) (let + scriptBase = '' + set -e -o pipefail + ${if cfg.debug then "set -x" else ""} + ''; + + manualSecrets = filterAttrs (name: secret: secret.manual) cfg.secrets; + nonManualSecrets = filterAttrs (name: secret: !secret.manual) cfg.secrets; + + initScript = '' + ${scriptBase} + + VAULT_ADDR_DEFAULT="${cfg.vaultURL}" + [ -n "$VAULT_ADDR" ] && export VAULT_ADDR="$VAULT_ADDR_DEFAULT" + + kv_get() { + vault kv get -format json "$1" + } + + simple_get() { + kv_get "$1" | jq ".data.data$2" -r + } + + ${cfg.extraFunctions} + '' + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: secret: '' + if [[ ! -f "${secret.path}" ]]; then + echo "Initializing Secret ${secret.path}" + else + echo "Updating Secret ${secret.path}" + fi + + secretFile="${secret.path}" + ${secret.fetchScript} + + chown ${secret.user}:${secret.group} "${secret.path}" + chmod ${secret.permissions} "${secret.path}" + '') nonManualSecrets)) + (lib.concatStringsSep "\n" (lib.mapAttrsToList + (name: secret: '' + if [[ ! -f "${secret.path}" ]]; then + echo "Manual Secret ${secret.path} Doesn't Exist" + exit 1 + fi + + echo "Updating Permissions on Manual Secret ${secret.path}" + + chown ${secret.user}:${secret.group} "${secret.path}" + chmod ${secret.permissions} "${secret.path}" + '') manualSecrets)) + '' + echo "Secrets Deployed" + ''; + + checkScript = '' + ${scriptBase} + + getUser() { + stat --format "%U" "$1" 2>/dev/null + } + + getGroup() { + stat --format "%U" "$1" 2>/dev/null + } + + getPermissions() { + stat --format "%a" "$1" 2>/dev/null + } + + GLOBAL_FAIL=false + '' + (lib.concatStringsSep "\n" (lib.mapAttrsToList (name: secret: '' + LOCAL_FAIL=false + + echo "Secret: ${name}" + echo "Checking ${secret.path}" + + # some variables which can be used by checkScript + # shellcheck disable=SC2034 + secretFile="${secret.path}" + + if [[ -f "${secret.path}" ]]; then + echo "✅ File Exists" + else + echo "❌ File Does Not Exist" + LOCAL_FAIL=true + fi + + if getUser "${secret.path}" >/dev/null && [[ "$(getUser "${secret.path}")" == "${secret.user}" ]]; then + echo "✅ File Is Owned By Correct User" + else + echo "❌ File Is Not Owned By Correct User (${secret.user})" + LOCAL_FAIL=true + fi + + if getGroup "${secret.path}" >/dev/null && [[ "$(getGroup "${secret.path}")" == "${secret.group}" ]]; then + echo "✅ File Is Owned By Correct Group" + else + echo "❌ File Is Not Owned By Correct Group (${secret.user})" + LOCAL_FAIL=true + fi + + if getPermissions "${secret.path}" >/dev/null && [[ "$(getPermissions "${secret.path}")" -eq "${secret.permissions}" ]]; then + echo "✅ File Has Correct Permissions" + else + echo "❌ File Does Not Have Correct Permissions (${secret.permissions})" + LOCAL_FAIL=true + fi + + ${if secret.checkScript != null then secret.checkScript else ""} + + if [[ "$LOCAL_FAIL" == "true" ]]; then + echo "❌ File Did Not Pass The Vibe Check" + GLOBAL_FAIL=true + else + echo "✅ File Passed The Vibe Check" + fi + + echo + '') cfg.secrets)) + '' + if [[ "$GLOBAL_FAIL" == "true" ]]; then + echo "❌ One Or More Secrets Did Not Pass The Vibe Check" + exit 1 + else + echo "✅ All Secrets Passed The Vibe Check" + fi + ''; + + in { + environment.systemPackages = [ + (pkgs.writeShellApplication { + name = "secrets-check"; + runtimeInputs = defaultPackages ++ cfg.extraPackages; + text = checkScript; + }) + (pkgs.writeShellApplication { + name = "secrets-init"; + runtimeInputs = defaultPackages ++ cfg.extraPackages; + text = initScript; + }) + ]; + + })) + + (mkIf (cfg.enable && cfg.createSecretsDir) { + systemd.tmpfiles.rules = [ + "d ${cfg.secretsDir} - ${cfg.secretsDirUser} ${cfg.secretsDirGroup}" + ]; + }) + ]; +} diff --git a/presets/nixos/normal-encrypted-drive.nix b/presets/nixos/normal-encrypted-drive.nix index dae85cd..d34e054 100644 --- a/presets/nixos/normal-encrypted-drive.nix +++ b/presets/nixos/normal-encrypted-drive.nix @@ -35,7 +35,8 @@ in { initrd.luks.devices = { "${drive_data.root_mapper_name}" = { device = "${drive_data.encrypted_root_path}"; - keyFile = "${usb_data.encryption_keys_path}/${config.networking.hostName}.key"; + keyFile = + "${usb_data.encryption_keys_path}/${config.networking.hostName}.key"; preLVM = false; allowDiscards = true; };