From 2d7d0a4a8ace67ac01846ee0633e3304a4462db2 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 10 Jul 2024 21:09:33 +0200 Subject: [PATCH] cluster/services/locksmith: implement provider options --- cluster/services/locksmith/default.nix | 16 +++- cluster/services/locksmith/provider.nix | 101 ++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 cluster/services/locksmith/provider.nix diff --git a/cluster/services/locksmith/default.nix b/cluster/services/locksmith/default.nix index 5cc9547..0b782b2 100644 --- a/cluster/services/locksmith/default.nix +++ b/cluster/services/locksmith/default.nix @@ -2,9 +2,17 @@ { services.locksmith = { - nodes.receiver = config.services.consul.nodes.agent; - nixos.receiver = [ - ./receiver.nix - ]; + nodes = { + receiver = config.services.consul.nodes.agent; + provider = config.services.consul.nodes.agent; + }; + nixos = { + receiver = [ + ./receiver.nix + ]; + provider = [ + ./provider.nix + ]; + }; }; } diff --git a/cluster/services/locksmith/provider.nix b/cluster/services/locksmith/provider.nix new file mode 100644 index 0000000..cc8f568 --- /dev/null +++ b/cluster/services/locksmith/provider.nix @@ -0,0 +1,101 @@ +{ config, depot, lib, pkgs, ... }: + +let + kvRoot = "secrets/locksmith"; + activeProvders = lib.filterAttrs (_: cfg: lib.any (secret: secret.nodes != []) (lib.attrValues cfg.secrets)) config.services.locksmith.providers; +in + +{ + options.services.locksmith = with lib; { + providers = mkOption { + type = types.attrsOf (types.submodule ({ ... }: { + options = { + wantedBy = mkOption { + type = types.listOf types.str; + default = []; + }; + after = mkOption { + type = types.listOf types.str; + default = []; + }; + secrets = mkOption { + type = types.attrsOf (types.submodule ({ ... }: { + options = { + nodes = mkOption { + type = types.listOf types.str; + default = []; + }; + command = mkOption { + type = types.coercedTo types.str (package: "${package}") types.package; + }; + owner = mkOption { + type = types.str; + default = "root"; + }; + group = mkOption { + type = types.str; + default = "root"; + }; + mode = mkOption { + type = types.str; + default = "0400"; + }; + }; + })); + }; + }; + })); + }; + }; + + config.systemd.services = lib.mapAttrs' (providerName: providerConfig: { + name = "locksmith-provider-${providerName}"; + value = let + providerRoot = "${kvRoot}/${providerName}"; + in { + description = "Locksmith Provider | ${providerName}"; + distributed.enable = true; + inherit (providerConfig) wantedBy after; + serviceConfig = { + PrivateTmp = true; + LoadCredential = lib.mkForce []; + }; + path = [ + config.services.consul.package + pkgs.age + ]; + script = let + activeSecrets = lib.filterAttrs (_: secret: secret.nodes != []) providerConfig.secrets; + activeNodes = lib.unique (lib.flatten (lib.mapAttrsToList (_: secret: secret.nodes) activeSecrets)); + secretNames = map (name: "${providerRoot}-${name}/") (lib.attrNames activeSecrets); + + createSecret = { path, nodes, owner, mode, group, command }: '' + consul kv put ${lib.escapeShellArg path}/mode ${lib.escapeShellArg mode} + consul kv put ${lib.escapeShellArg path}/owner ${lib.escapeShellArg owner} + consul kv put ${lib.escapeShellArg path}/group ${lib.escapeShellArg group} + ${lib.concatStringsSep "\n" (map (node: '' + consul kv put ${lib.escapeShellArg path}/recipient/${node} "$( (${command}) | age --encrypt --armor -r ${lib.escapeShellArg depot.hours.${node}.ssh.id.publicKey})" + '') nodes)} + ''; + in '' + # create/update secrets + ${lib.pipe activeSecrets [ + (lib.mapAttrsToList (secretName: secretConfig: createSecret { + path = "${providerRoot}-${secretName}"; + inherit (secretConfig) nodes mode owner group command; + })) + (lib.concatStringsSep "\n") + ]} + + # delete leftover secrets of this provider + consul kv get --keys '${providerRoot}-' | grep -v ${lib.concatStringsSep " \\\n " (map (secret: "-e ${lib.escapeShellArg secret}") secretNames)} | xargs --no-run-if-empty -n1 consul kv delete --recurse + + # notify + ${lib.pipe activeNodes [ + (map (node: "consul event --name=chant:locksmith --node=${node}")) + (lib.concatStringsSep "\n") + ]} + ''; + }; + }) activeProvders; +}