150 lines
4.1 KiB
Nix
150 lines
4.1 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
flake-parts-lib,
|
|
inputs,
|
|
den,
|
|
...
|
|
}:
|
|
let
|
|
inherit (lib) mkOption types;
|
|
cfg = config.secrets;
|
|
in
|
|
{
|
|
options.secrets = {
|
|
masterKeys = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [ ];
|
|
description = "A list of master keys for encrypting secrets.";
|
|
};
|
|
secretsDir = mkOption {
|
|
type = types.str;
|
|
default = null;
|
|
description = "Path to the directory containing secrets relative to flake root.";
|
|
};
|
|
formatter = mkOption {
|
|
type = lib.types.functionTo lib.types.unspecified;
|
|
default = pkgs: pkgs.prettier;
|
|
description = "The formatter function to use for formatting sops file";
|
|
};
|
|
nixosModule = mkOption {
|
|
type = types.deferredModule;
|
|
readOnly = true;
|
|
description = "NixOS module configuration for managing sops secrets.";
|
|
};
|
|
};
|
|
|
|
config =
|
|
let
|
|
secrets = builtins.fromJSON (builtins.readFile "${inputs.self}/${cfg.secretsDir}/secrets.json");
|
|
all_keys = lib.flatten (lib.concatAttrValues per_host_keys);
|
|
per_host_keys = lib.mergeAttrsList (
|
|
lib.flatten (
|
|
map (
|
|
x:
|
|
builtins.mapAttrs (
|
|
name: value:
|
|
let
|
|
v = value.sopsPublic or [ ];
|
|
type = builtins.typeOf v;
|
|
vv =
|
|
if type == "string" then
|
|
[ v ]
|
|
else if type == "list" then
|
|
v
|
|
else
|
|
throw "Unexpected type ${type} for sopsPublic in host ${name}";
|
|
in
|
|
vv
|
|
) x
|
|
) (builtins.attrValues den.hosts)
|
|
)
|
|
);
|
|
secret_map = lib.mapAttrs (
|
|
name: value:
|
|
let
|
|
keys = lib.unique (
|
|
lib.flatten (map (k: per_host_keys.${k}) value.hosts)
|
|
++ (lib.optionals value.global all_keys)
|
|
++ cfg.masterKeys
|
|
);
|
|
in
|
|
{
|
|
inherit (value)
|
|
format
|
|
neededForUsers
|
|
hosts
|
|
global
|
|
;
|
|
inherit keys;
|
|
}
|
|
) secrets;
|
|
rules = lib.mapAttrsToList (name: value: {
|
|
path_regex = "${cfg.secretsDir}/${name}$";
|
|
key_groups = [ { age = value.keys; } ];
|
|
}) secret_map;
|
|
sops_secrets_map = lib.concatMapAttrs (
|
|
name: value:
|
|
let
|
|
hasHost = (lib.elem "wawa" value.hosts) || value.global;
|
|
in
|
|
if hasHost then
|
|
{
|
|
${name} = {
|
|
inherit (value) format neededForUsers;
|
|
sopsFile = inputs.self + "/${cfg.secretsDir}/${name}";
|
|
};
|
|
}
|
|
else
|
|
{ }
|
|
) secret_map;
|
|
in
|
|
{
|
|
secrets.nixosModule =
|
|
{ ... }:
|
|
{
|
|
config.sops.secrets = sops_secrets_map;
|
|
};
|
|
perSystem =
|
|
{ pkgs, self', ... }:
|
|
let
|
|
formatted =
|
|
let
|
|
unformatted = (pkgs.formats.yaml { }).generate ".sops.yaml" {
|
|
creation_rules = rules;
|
|
};
|
|
in
|
|
pkgs.stdenvNoCC.mkDerivation {
|
|
name = ".sops-yaml-formatted";
|
|
src = unformatted;
|
|
phases = [ "format" ];
|
|
format = ''
|
|
cp $src .sops.yaml
|
|
chmod +w .sops.yaml
|
|
${lib.getExe (cfg.formatter pkgs)} .sops.yaml
|
|
cp .sops.yaml $out
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
packages.write-sops-config = pkgs.writeShellApplication {
|
|
name = "write-sops-config";
|
|
text = ''
|
|
cp ${formatted} .sops.yaml
|
|
find ${cfg.secretsDir} -type f ! -name "secrets.json" -exec ${pkgs.lib.getExe pkgs.sops} updatekeys -y {} \;
|
|
'';
|
|
};
|
|
checks.check-sops-config =
|
|
pkgs.runCommand "check-sops-config"
|
|
{
|
|
nativeBuildInputs = [ pkgs.diffutils ];
|
|
}
|
|
''
|
|
set -e
|
|
diff -u ${inputs.self}/.sops.yaml ${formatted}
|
|
touch $out
|
|
'';
|
|
};
|
|
};
|
|
}
|