You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
3.0 KiB
Nix

{ config, lib, pkgs, ... }:
with lib;
let
secret-file = types.submodule ({ ... }@moduleAttrs: {
options = {
name = mkOption {
type = types.str;
default = moduleAttrs.config._module.args.name;
};
path = mkOption {
type = types.str;
readOnly = true;
default = "/run/secrets/${removeSuffix ".gpg" (baseNameOf moduleAttrs.config.source-path)}";
};
mode = mkOption {
type = types.str;
default = "0400";
};
owner = mkOption {
type = types.str;
default = "root";
};
group-name = mkOption {
type = types.str;
default = "root";
};
source-path = mkOption {
type = types.str;
default = pkgs.copyPathToStore "${toString ../../secrets}/${config.networking.hostName}/${moduleAttrs.config.name}.gpg";
};
encrypted = mkOption {
type = types.bool;
default = true;
};
enable = mkOption {
type = types.bool;
default = true;
};
};
});
enabledFiles = filterAttrs (n: file: file.enable) config.petabyte.secrets;
mkDecryptSecret = file: pkgs.writeScript "decrypt-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
#!${pkgs.runtimeShell}
set -eu pipefail
if [ ! -f "${file.path}" ]; then
umask 0077
echo "${file.source-path} -> ${file.path}"
${if file.encrypted then ''
${pkgs.gnupg}/bin/gpg --decrypt ${escapeShellArg file.source-path} > ${file.path}
'' else ''
cat ${escapeShellArg file.source-path} > ${file.path}
''}
fi
'';
mkSetupSecret = file: pkgs.writeScript "setup-secret-${removeSuffix ".gpg" (baseNameOf file.source-path)}.sh" ''
#!${pkgs.runtimeShell}
set -eu pipefail
chown ${escapeShellArg file.owner}:${escapeShellArg file.group-name} ${escapeShellArg file.path}
chmod ${escapeShellArg file.mode} ${escapeShellArg file.path}
'';
in {
options.petabyte.secrets = mkOption {
type = with types; attrsOf secret-file;
default = {};
};
config = mkIf (enabledFiles != {}) {
system.activationScripts = let
files = unique (map (flip removeAttrs ["_module"]) (attrValues enabledFiles));
decrypt = ''
function fail() {
rm $1
echo "failed to decrypt $1"
}
echo setting up secrets...
mkdir -p /run/secrets
chown 0:0 /run/secrets
chmod 0755 /run/secrets
${concatMapStringsSep "\n" (file: ''
${mkDecryptSecret file} || fail ${file.path}
'') files}
'';
setup = ''
echo setting up secrets...
${concatMapStringsSep "\n" (file: ''
${mkSetupSecret file} || echo "failed to set up ${file.path}"
'') files}
'';
in {
decrypt-secrets.text = "source ${pkgs.writeText "setup-secrets.sh" decrypt}";
setup-secrets = stringAfter [ "users" "groups" ] "source ${pkgs.writeText "setup-secrets.sh" setup}";
users.deps = [ "decrypt-secrets" ];
};
};
}