From 1db41702260510a9a0e54be1c28e8c31b56d36c0 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 22 Aug 2024 23:27:15 +0200 Subject: [PATCH] cluster/services/consul: bootstrap ACLs --- cluster/services/consul/bootstrap.nix | 65 +++++++++++++++++++++++++++ cluster/services/consul/default.nix | 4 +- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 cluster/services/consul/bootstrap.nix diff --git a/cluster/services/consul/bootstrap.nix b/cluster/services/consul/bootstrap.nix new file mode 100644 index 0000000..263fc4c --- /dev/null +++ b/cluster/services/consul/bootstrap.nix @@ -0,0 +1,65 @@ +{ cluster, config, lib, pkgs, ... }: + +let + sentinelFile = "/var/lib/consul/nixos-acl-bootstrapped"; + bootstrapTokenFile = "/run/keys/consul-bootstrap-token"; + bootstrapConfig = "consul-bootstrap-config.json"; + writeRules = rules: pkgs.writeText "consul-policy.json" (builtins.toJSON rules); +in + +{ + systemd.services = { + consul-acl-bootstrap = { + requires = [ "consul.service" ]; + after = [ "consul.service" ]; + wantedBy = [ "multi-user.target" ]; + + unitConfig.ConditionPathExists = "!${sentinelFile}"; + serviceConfig = { + Type = "oneshot"; + PrivateTmp = true; + }; + environment.CONSUL_HTTP_ADDR = config.links.consulAgent.tuple; + path = [ + config.services.consul.package + pkgs.jq + ]; + script = '' + umask 77 + if consul acl bootstrap --format=json > ${bootstrapConfig}; then + echo Bootstrapping: + jq -r .SecretID < ${bootstrapConfig} > ${bootstrapTokenFile} + export CONSUL_HTTP_TOKEN_FILE=${bootstrapTokenFile} + consul acl policy create --name operator-read --description "Read-only operator actions" --rules @${writeRules { operator = "read"; }} + consul acl policy create --name smt-read --description "Allow reading the encrypted system management token" --rules @${writeRules { key_prefix."secrets/locksmith/consul-systemManagementToken/".policy = "read"; }} + consul acl token update --id 00000000-0000-0000-0000-000000000002 --append-policy-name operator-read --append-policy-name smt-read + else + echo Bootstrap is already in progress elsewhere. + touch ${sentinelFile} + fi + ''; + }; + locksmith-provider-consul = { + unitConfig.ConditionPathExists = bootstrapTokenFile; + distributed.enable = lib.mkForce false; + environment = { + CONSUL_HTTP_ADDR = config.links.consulAgent.tuple; + CONSUL_HTTP_TOKEN_FILE = bootstrapTokenFile; + }; + postStop = '' + rm -f ${bootstrapTokenFile} + touch ${sentinelFile} + ''; + }; + }; + + services.locksmith.providers.consul = { + wantedBy = [ "consul-acl-bootstrap.service" ]; + after = [ "consul-acl-bootstrap.service" ]; + secrets.systemManagementToken = { + nodes = cluster.config.services.consul.nodes.agent; + checkUpdate = "test -e ${bootstrapTokenFile}"; + command = "cat ${bootstrapTokenFile}"; + }; + }; +} diff --git a/cluster/services/consul/default.nix b/cluster/services/consul/default.nix index ee4e374..4458321 100644 --- a/cluster/services/consul/default.nix +++ b/cluster/services/consul/default.nix @@ -14,6 +14,7 @@ in nodes = { agent = [ "checkmate" "grail" "thunderskin" "VEGAS" "prophet" ]; ready = config.services.consul.nodes.agent; + bootstrap = [ "grail" "VEGAS" ]; }; nixos = { agent = [ @@ -21,10 +22,11 @@ in ./remote-api.nix ]; ready = ./ready.nix; + bootstrap = ./bootstrap.nix; }; simulacrum = { enable = true; - deps = [ "wireguard" ]; + deps = [ "wireguard" "locksmith" ]; settings = ./test.nix; }; };