From 6e6e714cf1b8344286a8d8a17d7a5a976026340c Mon Sep 17 00:00:00 2001 From: Luke Granger-Brown Date: Fri, 11 Mar 2022 14:40:08 +0000 Subject: [PATCH] ops/nixos: init vault-agent-secrets module --- ops/nixos/lib/common.nix | 1 + ops/nixos/lib/vault-agent-acme.nix | 4 + ops/nixos/lib/vault-agent-secrets.nix | 131 ++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 ops/nixos/lib/vault-agent-secrets.nix diff --git a/ops/nixos/lib/common.nix b/ops/nixos/lib/common.nix index e10548b77b..40afd3275f 100644 --- a/ops/nixos/lib/common.nix +++ b/ops/nixos/lib/common.nix @@ -19,6 +19,7 @@ in ../../../third_party/home-manager/nixos ./vault-agent.nix ./vault-agent-acme.nix + ./vault-agent-secrets.nix ]; options.my.specialisationName = lib.mkOption { diff --git a/ops/nixos/lib/vault-agent-acme.nix b/ops/nixos/lib/vault-agent-acme.nix index bb8ef368c9..2ddc945ba7 100644 --- a/ops/nixos/lib/vault-agent-acme.nix +++ b/ops/nixos/lib/vault-agent-acme.nix @@ -110,6 +110,10 @@ let allRestartableUnits = lib.unique (builtins.concatMap (c: (reloadOrRestartUnits c) ++ c.restartUnits) acmeCertificates); in { + imports = [ + ./vault-agent.nix + ]; + options.my.vault.acmeCertificates = mkOption { type = with types; attrsOf (submodule { options = let diff --git a/ops/nixos/lib/vault-agent-secrets.nix b/ops/nixos/lib/vault-agent-secrets.nix new file mode 100644 index 0000000000..6bbdb66d4e --- /dev/null +++ b/ops/nixos/lib/vault-agent-secrets.nix @@ -0,0 +1,131 @@ +# SPDX-FileCopyrightText: 2020 Luke Granger-Brown +# +# SPDX-License-Identifier: Apache-2.0 + +{ pkgs, config, depot, lib, ... }: +let + inherit (lib) mkOption types mkBefore optionalAttrs mkDefault mapAttrs; + + secrets = lib.mapAttrsToList (name: cOrig: cOrig // { inherit name; }) config.my.vault.secrets; + + secretsGroups = lib.unique (map (c: c.group) secrets); + secretsRoot = "/var/lib/secrets"; + + secretsTemplate = map (c: { + contents = c.template; + destination = c.path; + perms = "0640"; + command = let + in pkgs.writeShellScript "post-secret-${c.name}" '' + chgrp "${c.group}" "${c.path}" + ${lib.concatMapStringsSep "\n" (x: '' + /run/current-system/sw/bin/systemctl reload-or-restart ${x} + '') c.reloadOrRestartUnits} + ${lib.concatMapStringsSep "\n" (x: '' + /run/current-system/sw/bin/systemctl restart ${x} + '') c.restartUnits} + ${lib.optionalString (c.command != "") c.command} + ''; + }) secrets; + + secretsTmpdirs = [ + "d ${secretsRoot} 0111 vault-agent vault-agent - -" + ] ++ map (c: "d ${c.parentDir} 0750 vault-agent ${c.group} - -") secrets; + + allRestartableUnits = lib.unique (builtins.concatMap (c: c.reloadOrRestartUnits ++ c.restartUnits) secrets); +in +{ + imports = [ + ./vault-agent.nix + ]; + + options.my.vault.secrets = mkOption { + type = with types; attrsOf (submodule ({ name, config, ...}: { + options = { + name = mkOption { + type = str; + default = name; + readOnly = true; + }; + parentDir = mkOption { + type = path; + default = "${secretsRoot}/${config.name}"; + readOnly = true; + }; + path = mkOption { + type = path; + default = "${config.parentDir}/secret"; + readOnly = true; + }; + + template = mkOption { + type = lines; + description = "Template to use for generating secret output."; + }; + + command = mkOption { + type = lines; + default = ""; + description = "Command to run after writing the secrets file."; + }; + reloadOrRestartUnits = mkOption { + type = listOf str; + default = []; + description = "List of systemd units to reload/restart after writing the secrets file."; + }; + restartUnits = mkOption { + type = listOf str; + default = []; + description = "List of systemd units to restart after writing the secrets file."; + }; + + group = mkOption { + type = str; + description = "Owner group to set for the generated file."; + }; + }; + })); + default = {}; + }; + + config = { + my.vault.settings = { + template = mkBefore secretsTemplate; + }; + + systemd = optionalAttrs config.my.vault.enable { + services.vault-agent = { + serviceConfig = { + SupplementaryGroups = mkBefore secretsGroups; + Before = mkBefore allRestartableUnits; + }; + }; + + tmpfiles.rules = secretsTmpdirs; + }; + + security.polkit.extraConfig = lib.mkAfter '' + // NixOS module: depot/lib/vault-agent-secrets.nix + polkit.addRule(function(action, subject) { + if (action.id !== "org.freedesktop.systemd1.manage-units" || + subject.user !== "vault-agent") { + return polkit.Result.NOT_HANDLED; + } + + var verb = action.lookup("verb"); + if (verb !== "restart" && verb !== "reload-or-restart") { + return polkit.Result.NOT_HANDLED; + } + + var allowedUnits = ${builtins.toJSON allRestartableUnits}; + var unit = action.lookup("unit"); + for (var i = 0; i < allowedUnits.length; i++) { + if (allowedUnits[i] === unit) { + return polkit.Result.YES; + } + } + return polkit.Result.NOT_HANDLED; + }); + ''; + }; +}