From ed7e0c4db55b269272a63c396feca668ae4ba1ba Mon Sep 17 00:00:00 2001 From: chaos Date: Thu, 14 Sep 2023 13:54:56 +0100 Subject: [PATCH] wireguard for raspberry, outputs.nix tidy, enable generating of vault policies --- data/chaos_wireguard_internal.nix | 4 + hosts/hetzner-vm/containers/music/default.nix | 6 +- hosts/hetzner-vm/hetzner-vm.nix | 1 + hosts/hetzner-vm/profiles/wireguard.nix | 6 + hosts/hetzner-vm/secrets.nix | 39 +++- hosts/lappy-t495/profiles/wireguard.nix | 2 +- hosts/raspberry/profiles/wireguard.nix | 33 +++ hosts/raspberry/secrets.nix | 17 ++ hosts/vault/profiles/wireguard.nix | 6 + hosts/vault/secrets.nix | 14 ++ modules/nixos/secrets-lib/lib.nix | 27 ++- modules/nixos/secrets.nix | 19 ++ outputs.nix | 215 ++++++++++-------- 13 files changed, 284 insertions(+), 105 deletions(-) create mode 100644 hosts/raspberry/profiles/wireguard.nix diff --git a/data/chaos_wireguard_internal.nix b/data/chaos_wireguard_internal.nix index 5f6365e..77fbd85 100644 --- a/data/chaos_wireguard_internal.nix +++ b/data/chaos_wireguard_internal.nix @@ -20,5 +20,9 @@ ip = "10.69.42.4"; public = "rEioKieZqI3UaJGGaSC/yaHfdZE9VKpsq355x4dHgCs="; }; + raspberry = { + ip = "10.69.42.5"; + public = "IGq+WanFM/bKNUkwjO/0AAtDhJLvtvU+mVxH27QyHTc="; + }; }; } diff --git a/hosts/hetzner-vm/containers/music/default.nix b/hosts/hetzner-vm/containers/music/default.nix index fa4181c..f7e15b3 100644 --- a/hosts/hetzner-vm/containers/music/default.nix +++ b/hosts/hetzner-vm/containers/music/default.nix @@ -41,11 +41,7 @@ in { }; })); - config = { - config, - pkgs, - ... - }: { + config = {config, ...}: { _module.args = { inherit inputs; inherit tree; diff --git a/hosts/hetzner-vm/hetzner-vm.nix b/hosts/hetzner-vm/hetzner-vm.nix index ff8b96a..8d6d57f 100644 --- a/hosts/hetzner-vm/hetzner-vm.nix +++ b/hosts/hetzner-vm/hetzner-vm.nix @@ -21,6 +21,7 @@ ] ++ (lib.forEach [ "social" + "storage" "music" "quassel" "piped" diff --git a/hosts/hetzner-vm/profiles/wireguard.nix b/hosts/hetzner-vm/profiles/wireguard.nix index f0d6c49..62e6d2d 100644 --- a/hosts/hetzner-vm/profiles/wireguard.nix +++ b/hosts/hetzner-vm/profiles/wireguard.nix @@ -28,6 +28,12 @@ in { presharedKeyFile = "${secrets.wg_preshared_lappy-t495.path}"; allowedIPs = ["${data.hosts.lappy-t495.ip}/32"]; } + # raspberry + { + publicKey = "${data.hosts.raspberry.public}"; + presharedKeyFile = "${secrets.wg_preshared_raspberry.path}"; + allowedIPs = ["${data.hosts.raspberry.ip}/32"]; + } ]; }; }; diff --git a/hosts/hetzner-vm/secrets.nix b/hosts/hetzner-vm/secrets.nix index c214884..8853b8a 100644 --- a/hosts/hetzner-vm/secrets.nix +++ b/hosts/hetzner-vm/secrets.nix @@ -32,6 +32,33 @@ in { "${group}" = getGID group; })); + requiredVaultPaths = [ + "api-keys/data/mpd" + "api-keys/data/music-stream" + + "api-keys/data/gitlab/gitlab_pages_serve" + + "api-keys/data/storage/restic/Mail" + "api-keys/data/storage/restic/Social" + "api-keys/data/storage/restic/Quassel" + "api-keys/data/storage/restic/Piped" + + "api-keys/data/chaos_mail/system" + "api-keys/data/chaos_mail/gotosocial" + + "passwords/data/soulseek" + "passwords/data/slskd" + "passwords/data/mail" + + "private-public-keys/data/wireguard/chaos-internal/hetzner-vm" + "private-public-keys/data/restic/Mail" + "private-public-keys/data/restic/Social" + "private-public-keys/data/restic/Quassel" + "private-public-keys/data/restic/Piped" + + "infra/data/private-mail-aliases" + ]; + secrets = { # Used directly by server # for fetching gitlab static sites @@ -50,23 +77,25 @@ in { ''; }; 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_iphone8 = { - path = "/secrets/wg_preshared_iphone8"; fetchScript = '' simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" .preshared_keys.iphone8 > "$secretFile" ''; }; wg_preshared_lappy-t495 = { - path = "/secrets/wg_preshared_lappy-t495"; fetchScript = '' simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" ".preshared_keys.lappy_t495" > "$secretFile" ''; }; + wg_preshared_raspberry = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/hetzner-vm" ".preshared_keys.raspberry" > "$secretFile" + ''; + }; # Container: music mpd_control_password = { @@ -109,8 +138,6 @@ in { ''; }; private_mail_aliases = { - user = "root"; - group = "root"; fetchScript = '' kv_get "/infra/private-mail-aliases" | jq .data.data | jq -r 'to_entries|map("\(.key) \(.value.to)")[]' > "$secretFile" ''; @@ -154,8 +181,6 @@ in { ''; }; social_env_secrets = { - user = "root"; - group = "root"; fetchScript = '' smtp_password=$(simple_get "/api-keys/chaos_mail/gotosocial" .password) echo "GTS_SMTP_PASSWORD=$smtp_password" > "$secretFile" diff --git a/hosts/lappy-t495/profiles/wireguard.nix b/hosts/lappy-t495/profiles/wireguard.nix index c7cd78d..c7649b5 100644 --- a/hosts/lappy-t495/profiles/wireguard.nix +++ b/hosts/lappy-t495/profiles/wireguard.nix @@ -14,7 +14,7 @@ in { { publicKey = "${data.hosts.hetzner-vm.public}"; presharedKeyFile = "${secrets.wg_preshared_hetzner-vm.path}"; - allowedIPs = ["${data.hosts.hetzner-vm.ip}/32"]; + allowedIPs = ["${data.hosts.hetzner-vm.ip}/24"]; endpoint = "${data.hosts.hetzner-vm.endpoint}"; persistentKeepalive = 25; } diff --git a/hosts/raspberry/profiles/wireguard.nix b/hosts/raspberry/profiles/wireguard.nix new file mode 100644 index 0000000..b404d1d --- /dev/null +++ b/hosts/raspberry/profiles/wireguard.nix @@ -0,0 +1,33 @@ +{config, ...}: let + secrets = config.services.secrets.secrets; + data = import ../../../data/chaos_wireguard_internal.nix {}; + + persistentKeepalive = 15; +in { + networking.firewall.trustedInterfaces = ["wg0"]; + networking.wg-quick.interfaces = { + wg0 = { + address = ["${data.hosts.raspberry.ip}/32"]; + privateKeyFile = "${secrets.wg_priv.path}"; + + peers = [ + # hetzner-vm + { + publicKey = "${data.hosts.hetzner-vm.public}"; + presharedKeyFile = "${secrets.wg_preshared_hetzner-vm.path}"; + allowedIPs = ["${data.hosts.hetzner-vm.ip}/24"]; + endpoint = "${data.hosts.hetzner-vm.endpoint}"; + inherit persistentKeepalive; + } + # vault + { + publicKey = "${data.hosts.vault.public}"; + presharedKeyFile = "${secrets.wg_preshared_vault.path}"; + allowedIPs = ["${data.hosts.vault.ip}/32"]; + endpoint = "${data.hosts.vault.endpoint}"; + inherit persistentKeepalive; + } + ]; + }; + }; +} diff --git a/hosts/raspberry/secrets.nix b/hosts/raspberry/secrets.nix index 83d7454..9b6d932 100644 --- a/hosts/raspberry/secrets.nix +++ b/hosts/raspberry/secrets.nix @@ -30,6 +30,23 @@ sed -i "s/WIFI_PASSWORD/$password/" "$secretFile" ''; }; + + # for internal wireguard VPN + wg_priv = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/raspberry" .private > "$secretFile" + ''; + }; + wg_preshared_hetzner-vm = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/raspberry" .preshared_keys.hetzner_vm > "$secretFile" + ''; + }; + wg_preshared_vault = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/raspberry" .preshared_keys.vault > "$secretFile" + ''; + }; }; }; } diff --git a/hosts/vault/profiles/wireguard.nix b/hosts/vault/profiles/wireguard.nix index 0033c6e..4e2ae28 100644 --- a/hosts/vault/profiles/wireguard.nix +++ b/hosts/vault/profiles/wireguard.nix @@ -29,6 +29,12 @@ in { presharedKeyFile = "${secrets.wg_preshared_lappy-t495.path}"; allowedIPs = ["${data.hosts.lappy-t495.ip}/32"]; } + # raspberry + { + publicKey = "${data.hosts.raspberry.public}"; + presharedKeyFile = "${secrets.wg_preshared_raspberry.path}"; + allowedIPs = ["${data.hosts.raspberry.ip}/32"]; + } ]; }; }; diff --git a/hosts/vault/secrets.nix b/hosts/vault/secrets.nix index dbb8893..7a7b916 100644 --- a/hosts/vault/secrets.nix +++ b/hosts/vault/secrets.nix @@ -1,6 +1,15 @@ {...}: { services.secrets = { enable = true; + + requiredVaultPaths = [ + "private-public-keys/data/wireguard/chaos-internal/vault" + + "private-public-keys/data/restic/Vault" + + "api-keys/data/storage/restic/Vault" + ]; + secrets = { restic_password = { fetchScript = '' @@ -34,6 +43,11 @@ simple_get "/private-public-keys/wireguard/chaos-internal/vault" ".preshared_keys.lappy_t495" > "$secretFile" ''; }; + wg_preshared_raspberry = { + fetchScript = '' + simple_get "/private-public-keys/wireguard/chaos-internal/vault" ".preshared_keys.raspberry" > "$secretFile" + ''; + }; }; }; } diff --git a/modules/nixos/secrets-lib/lib.nix b/modules/nixos/secrets-lib/lib.nix index 41d4cf7..eec08ce 100644 --- a/modules/nixos/secrets-lib/lib.nix +++ b/modules/nixos/secrets-lib/lib.nix @@ -7,7 +7,7 @@ inherit (lib.lists) forEach unique flatten; inherit (lib.strings) concatStringsSep optionalString; inherit (lib.attrsets) mapAttrsToList filterAttrs; - inherit (pkgs) writeShellApplication; + inherit (pkgs) writeShellApplication writeText; genScripts = cfg: let scriptBase = '' @@ -288,4 +288,29 @@ in { text = scripts.initScript; }) ); + + genVaultPolicy = ( + cfg: name: let + inherit (cfg) requiredVaultPaths; + + policies = forEach requiredVaultPaths (policyConfig: let + path = + if isString policyConfig + then policyConfig + else policyConfig.path; + capabilities = + if isString policyConfig + then ["read" "list"] + else policyConfig.capabilities; + + escapeString = str: "\"" + str + "\""; + in '' + path "${path}" { + capabilities = [${concatStringsSep "," (forEach capabilities escapeString)}] + } + ''); + in (writeText "vault-policy-${name}.hcl" '' + ${concatStringsSep "\n" policies} + '') + ); } diff --git a/modules/nixos/secrets.nix b/modules/nixos/secrets.nix index b846388..ec233c3 100644 --- a/modules/nixos/secrets.nix +++ b/modules/nixos/secrets.nix @@ -47,6 +47,25 @@ in { default = "/secrets"; }; + requiredVaultPaths = mkOption { + type = types.listOf (types.oneOf [ + types.str + (types.submodule { + options = { + path = mkOption { + type = types.str; + }; + capabilities = mkOption { + type = types.listOf types.str; + default = ["read" "list"]; + }; + }; + }) + ]); + default = []; + description = "default vault paths as API path, not kv2 path"; + }; + vaultURL = mkOption { type = types.str; default = "https://vault.owo.monster"; diff --git a/outputs.nix b/outputs.nix index 88f3a45..5db9b53 100644 --- a/outputs.nix +++ b/outputs.nix @@ -2,6 +2,8 @@ nixpkgs = inputs.nixpkgs-unstable; lib = nixpkgs.lib; + inherit (lib.attrsets) mergeAttrsList; + hosts = import ./hosts inputs; in { @@ -13,100 +15,131 @@ in deploy-rs = inputs.deploy-rs; }; } - // (inputs.flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { - inherit system; - overlays = [ - (import ./overlay) - ]; - }; - - secretsLib = import ./modules/nixos/secrets-lib/lib.nix { - inherit (nixpkgs) lib; - inherit pkgs; - }; - - secretsInitScriptForSystem = system_name: let - systemConfig = self.nixosConfigurations.${system_name}.config; - systemSecretsConfig = systemConfig.services.secrets; + // (inputs.flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = import nixpkgs { + inherit system; + overlays = [ + (import ./overlay) + ]; + }; in - secretsLib.mkSecretsInitScript systemSecretsConfig "${system_name}"; + lib.foldl' lib.recursiveUpdate {} [ + { + formatter = pkgs.alejandra; - secretsInitScriptForSystemContainer = system_name: container_name: let - systemConfig = self.nixosConfigurations.${system_name}.config; - containerConfig = systemConfig.containers.${container_name}.config; - containerSecretsConfig = containerConfig.services.secrets; - in - secretsLib.mkSecretsInitScript containerSecretsConfig "${system_name}-${container_name}"; + devShell = pkgs.mkShell { + VAULT_API_ADDR = "https://vault.owo.monster"; + packages = + (with pkgs; [ + git + nano + bat + nix + vault-bin + ]) + ++ (with self.packages."${system}"; [ + mk-enc-usb + mk-normal-enc-ssd + mk-dual-enc-ssd + mk-raspberry-ext-drive + ]); + }; - secretsInitAppForSystem = system_name: packages: let - name = "secrets-init-${system_name}"; - package = packages."${name}"; - in { - type = "app"; - program = "${package}/bin/${name}"; - }; + packages = { + inherit (pkgs) comic-code comic-sans; + inherit (pkgs) mk-enc-usb mk-normal-enc-ssd mk-dual-enc-ssd mk-raspberry-ext-drive; + inherit (pkgs) gotosocial; + }; + } - secretsInitAppForSystemContainer = system_name: container_name: packages: let - name = "secrets-init-${system_name}-${container_name}"; - package = packages."${name}"; - in { - type = "app"; - program = "${package}/bin/${name}"; - }; - in { - devShell = pkgs.mkShell { - VAULT_API_ADDR = "https://vault.owo.monster"; - packages = - (with pkgs; [ - git - nano - bat - nix - vault-bin - ]) - ++ (with self.packages."${system}"; [ - mk-enc-usb - mk-normal-enc-ssd - mk-dual-enc-ssd - mk-raspberry-ext-drive - ]); - }; + # secrets-init, secrets-check and vault-policy for machines and containers + (let + secretsLib = import ./modules/nixos/secrets-lib/lib.nix { + inherit (nixpkgs) lib; + inherit pkgs; + }; - apps = let - packages = self.packages."${system}"; - in { - mk-enc-usb = { - type = "app"; - program = "${packages.mk-enc-usb}/bin/mk-enc-usb"; - }; - mk-normal-enc-ssd = { - type = "app"; - program = "${packages.mk-normal-enc-ssd}/bin/mk-normal-enc-ssd"; - }; - mk-dual-enc-ssd = { - type = "app"; - program = "${packages.mk-dual-enc-ssd}/bin/mk-dual-enc-ssd"; - }; - mk-raspberry-ext-drive = { - type = "app"; - program = "${packages.mk-raspberry-ext-drive}/bin/mk-raspberry-ext-drive"; - }; - secrets-init-lappy-t495 = secretsInitAppForSystem "lappy-t495" packages; - secrets-init-vault = secretsInitAppForSystem "vault" packages; - secrets-init-hetzner-vm = secretsInitAppForSystem "hetzner-vm" packages; - secrets-init-hetzner-vm-storage = secretsInitAppForSystemContainer "hetzner-vm" "storage" packages; - secrets-init-raspberry = secretsInitAppForSystem "raspberry" packages; - }; + systemConfigForSystem = system_name: self.nixosConfigurations.${system_name}.config; + secretsConfigForSystem = system_name: let + systemConfig = systemConfigForSystem system_name; + in + systemConfig.services.secrets; - packages = { - inherit (pkgs) comic-code comic-sans; - inherit (pkgs) mk-enc-usb mk-normal-enc-ssd mk-dual-enc-ssd; - inherit (pkgs) gotosocial; - secrets-init-lappy-t495 = secretsInitScriptForSystem "lappy-t495"; - secrets-init-vault = secretsInitScriptForSystem "vault"; - secrets-init-hetzner-vm = secretsInitScriptForSystem "hetzner-vm"; - secrets-init-hetzner-vm-storage = secretsInitScriptForSystemContainer "hetzner-vm" "storage"; - secrets-init-raspberry = secretsInitScriptForSystem "raspberry"; - }; - })) + systemConfigForContainer = system_name: container_name: let + systemConfig = systemConfigForSystem system_name; + in + systemConfig.containers.${container_name}.config; + + secretsConfigForContainer = system_name: container_name: let + systemConfig = systemConfigForContainer system_name container_name; + in + systemConfig.services.secrets; + + secretsInitScriptForSystem = system_name: let + secretsConfig = secretsConfigForSystem system_name; + in + secretsLib.mkSecretsInitScript secretsConfig "${system_name}"; + + secretsInitScriptForContainer = system_name: container_name: let + secretsConfig = secretsConfigForContainer system_name container_name; + in + secretsLib.mkSecretsInitScript secretsConfig "${system_name}-container-${container_name}"; + + vaultPolicyForSystem = system_name: let + secretsConfig = secretsConfigForSystem system_name; + in + secretsLib.genVaultPolicy secretsConfig "${system_name}"; + + vaultPolicyForContainer = system_name: container_name: let + secretsConfig = secretsConfigForContainer system_name container_name; + in + secretsLib.genVaultPolicy secretsConfig "${system_name}-container-${container_name}"; + + # All machines/containers with secrets.nix + machines = let + defaults = { + hasHostSecrets = true; + containers = []; + }; + in { + "hetzner-vm" = { + inherit (defaults) hasHostSecrets; + containers = ["storage"]; + }; + "vault" = { + inherit (defaults) hasHostSecrets containers; + }; + "raspberry" = { + inherit (defaults) hasHostSecrets containers; + }; + "lappy-t495" = { + inherit (defaults) hasHostSecrets containers; + }; + "tablet" = { + inherit (defaults) hasHostSecrets containers; + }; + }; + + machinesWithHostSecrets = lib.filter (machine: machines.${machine}.hasHostSecrets) (builtins.attrNames machines); + machinesWithContainers = lib.filter (machine: (builtins.length machines.${machine}.containers) != 0) (builtins.attrNames machines); + in { + packages = mergeAttrsList [ + (mergeAttrsList ( + lib.forEach machinesWithHostSecrets (machine_name: { + "secrets-init-${machine_name}" = secretsInitScriptForSystem machine_name; + "vault-policy-${machine_name}" = vaultPolicyForSystem machine_name; + }) + )) + + (mergeAttrsList (lib.forEach machinesWithContainers (machine_name: let + machine = machines.${machine_name}; + containers = machine.containers; + in (mergeAttrsList (lib.forEach containers (container_name: { + "secrets-init-${machine_name}-container-${container_name}" = secretsInitScriptForContainer machine_name container_name; + "vault-policy-${machine_name}-container-${container_name}" = vaultPolicyForContainer machine_name container_name; + })))))) + ]; + }) + ] + ))