nixfiles/modules/nixos/secrets.nix

172 lines
4.4 KiB
Nix

{
lib,
pkgs,
config,
...
}: let
inherit (lib.modules) mkIf mkMerge;
inherit (lib.options) mkOption;
inherit (lib) types;
inherit (pkgs) writeShellApplication;
cfg = config.services.secrets;
secretsLib = import ./secrets-lib/lib.nix {
inherit lib pkgs;
};
in {
options = {
services.secrets = {
enable = mkOption {
type = types.bool;
default = false;
};
debug = mkOption {
type = types.bool;
default = false;
};
createSecretsDir = mkOption {
type = types.bool;
default = true;
};
secretsDirUser = mkOption {
type = types.either types.str types.int;
default = "root";
};
secretsDirGroup = mkOption {
type = types.either types.str types.int;
default = "root";
};
secretsDir = mkOption {
type = types.str;
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";
description = "default Vault URL, can be overrided with env variables";
};
extraFunctions = mkOption {
type = types.lines;
default = "";
description = "extra bash functions to add to top of script";
};
uidMap = mkOption {
type = types.attrsOf types.int;
default = {};
description = "optional mapping of users to user IDs; required for SYSROOT when user isn't available on host";
};
gidMap = mkOption {
type = types.attrsOf types.int;
default = {};
description = "optional mapping of groups to group IDs; required for SYSROOT when group isn't available on host";
};
packages = mkOption {
type = types.listOf types.package;
default = [];
description = "packages for script";
};
secrets = mkOption {
type = types.attrsOf (types.submodule ({name, ...}: {
options = {
user = mkOption {
type = types.either types.str types.int;
default = "root";
};
group = mkOption {
type = types.either types.str types.int;
default = "root";
};
permissions = mkOption {
type = types.str;
default = "660";
};
path = mkOption {
type = types.str;
default = "${cfg.secretsDir}/${name}";
};
fetchScript = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
script used to fetch secrets, $secretFile is secret.path
'';
};
checkScript = mkOption {
type = types.nullOr types.lines;
default = null;
description = ''
script used to check contents of secret file, set LOCAL_FAIL to true on failure
'';
};
manual = mkOption {
type = types.bool;
default = false;
description = "should the secret be manually deployed";
};
};
}));
};
};
};
config = mkMerge [
(mkIf (cfg.enable) (let
scripts = secretsLib.genScripts cfg;
defaultPackages = with pkgs; [vault-bin jq];
in {
environment.systemPackages = [
(writeShellApplication {
name = "secrets-init";
runtimeInputs = defaultPackages ++ cfg.packages;
text = scripts.initScript;
})
(writeShellApplication {
name = "secrets-check";
runtimeInputs = defaultPackages ++ cfg.packages;
text = scripts.checkScript;
})
];
}))
(mkIf (cfg.enable && cfg.createSecretsDir) {
systemd.tmpfiles.rules = [
"d ${cfg.secretsDir} - ${toString cfg.secretsDirUser} ${toString cfg.secretsDirGroup}"
];
})
];
}