depot/ops/nixos/lib/secretsmgr.nix

168 lines
5 KiB
Nix
Raw Normal View History

# SPDX-FileCopyrightText: 2022 Luke Granger-Brown <depot@lukegb.com>
#
# SPDX-License-Identifier: Apache-2.0
{ depot, pkgs, config, lib, ... }:
let
inherit (lib) mkIf mkOption types concatStringsSep unique optional mkAfter;
pkg = depot.go.secretsmgr;
cfg = config.my.vault.secretsmgr;
jsonFormat = pkgs.formats.json { };
dummyHostKey = pkgs.runCommandLocal "dummy-host-key" {
nativeBuildInputs = [ config.programs.ssh.package ];
} ''
ssh-keygen -q -f $out -N ""
'';
in
{
options.my.vault.secretsmgr = {
enable = mkOption {
type = types.bool;
default = config.my.vault.enable;
};
groups = mkOption {
type = with types; listOf str;
default = [];
};
restartableUnits = mkOption {
type = with types; listOf str;
default = [];
};
acmeCertificates.enable = mkOption {
type = types.bool;
default = true;
};
acmeCertificates.expiryThreshold = mkOption {
type = types.str;
default = "744h";
};
acmeCertificates.config = mkOption {
type = jsonFormat.type;
default = {};
};
acmeCertificates.mount = mkOption {
type = types.str;
default = "acme";
};
sshCertificates.enable = mkOption {
type = types.bool;
default = true;
};
sshCertificates.mount = mkOption {
type = types.str;
default = "ssh-host";
};
sshCertificates.expiryThreshold = mkOption {
type = types.str;
default = "72h";
};
sshCertificates.outputDir = mkOption {
type = types.str;
default = "/var/lib/secretsmgr/ssh";
};
sshCertificates.principals = mkOption {
type = with types; listOf str;
default = let inherit (config.networking) hostName; in [
"${hostName}.as205479.net"
"${hostName}.int.as205479.net"
"${hostName}.otter-acoustic.ts.net"
];
};
sshCertificates.role = mkOption {
type = types.str;
default = config.networking.hostName;
};
};
config = mkIf cfg.enable {
my.vault.secretsmgr.restartableUnits = mkIf cfg.sshCertificates.enable (mkAfter ["sshd.service"]);
users.groups.secretsmgr = {};
users.users.secretsmgr = {
isSystemUser = true;
group = "secretsmgr";
};
systemd.services.secretsmgr = {
requires = ["vault-agent.service"];
after = ["vault-agent.service"];
restartIfChanged = true;
serviceConfig = {
User = "secretsmgr";
Group = "secretsmgr";
SupplementaryGroups = cfg.groups ++ [ "vault-agent" ];
AmbientCapabilities = [ "CAP_SETGID" ];
Type = "oneshot";
ExecStart = concatStringsSep " " ([
"${pkg}/bin/secretsmgr"
"--logtostderr"
] ++ lib.optionals cfg.acmeCertificates.enable [
"--acme_certificates_config=${jsonFormat.generate "secretsmgr-acme-certificates-config.json" cfg.acmeCertificates.config}"
"--acme_certificates_expiry_threshold=${cfg.acmeCertificates.expiryThreshold}"
"--acme_certificates_mount=${cfg.acmeCertificates.mount}"
] ++ [
"--sign_ssh_host_keys=${toString cfg.sshCertificates.enable}"
] ++ lib.optionals cfg.sshCertificates.enable [
"--ssh_host_key_ca_path=${cfg.sshCertificates.mount}"
"--ssh_host_key_expiry_threshold=${cfg.sshCertificates.expiryThreshold}"
"--ssh_host_key_output_dir=${cfg.sshCertificates.outputDir}"
"--ssh_host_key_principals=${concatStringsSep "," cfg.sshCertificates.principals}"
"--ssh_host_key_role=${cfg.sshCertificates.role}"
"--ssh_dummy_host_key=${dummyHostKey}"
"--sshd=${config.programs.ssh.package}/bin/sshd"
]);
};
};
2022-03-18 01:03:55 +00:00
systemd.timers.secretsmgr = {
requires = ["vault-agent.service"];
after = ["vault-agent.service" "network-online.target"];
wantedBy = ["timers.target"];
2022-03-18 01:03:55 +00:00
timerConfig = {
OnActiveSec = "30";
OnUnitInactiveSec = "30min";
};
};
systemd.tmpfiles.rules = [
"d /var/lib/acme 0711 secretsmgr secretsmgr - -"
"d /var/lib/secretsmgr 0711 secretsmgr secretsmgr - -"
"d /var/lib/secretsmgr/ssh 0711 secretsmgr secretsmgr - -"
];
security.polkit.extraConfig = lib.mkAfter ''
// NixOS module: depot/lib/secretsmgr.nix
polkit.addRule(function(action, subject) {
if (action.id !== "org.freedesktop.systemd1.manage-units" ||
subject.user !== "secretsmgr") {
return polkit.Result.NOT_HANDLED;
}
var verb = action.lookup("verb");
if (verb !== "restart" && verb !== "reload-or-restart" && verb != "reload-or-try-restart") {
return polkit.Result.NOT_HANDLED;
}
var allowedUnits = ${builtins.toJSON (unique cfg.restartableUnits)};
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;
});
'';
};
}