mirror of
https://github.com/Mic92/sops-nix.git
synced 2025-12-26 14:14:58 +08:00
rebase, complete implementation
This commit is contained in:
parent
bb7d636211
commit
aa5caa129b
5 changed files with 149 additions and 208 deletions
|
|
@ -16,6 +16,7 @@ writeTextFile {
|
|||
ageSshKeyPaths = cfg.age.sshKeyPaths;
|
||||
useTmpfs = cfg.useTmpfs;
|
||||
templates = cfg.templates;
|
||||
placeholderBySecretName = cfg.placeholder;
|
||||
userMode = false;
|
||||
logging = {
|
||||
keyImport = builtins.elem "keyImport" cfg.log;
|
||||
|
|
|
|||
|
|
@ -1,40 +1,21 @@
|
|||
{ config, pkgs, lib, options, ... }:
|
||||
with lib;
|
||||
with lib.types;
|
||||
with builtins;
|
||||
let
|
||||
cfg = config.sops;
|
||||
secretsForUsers = lib.filterAttrs (_: v: v.neededForUsers) cfg.secrets;
|
||||
inherit (lib)
|
||||
mkOption
|
||||
mkDefault
|
||||
mapAttrs
|
||||
types
|
||||
;
|
||||
|
||||
users = config.users.users;
|
||||
useSystemdActivation = (options.systemd ? sysusers && config.systemd.sysusers.enable) ||
|
||||
(options.services ? userborn && config.services.userborn.enable);
|
||||
renderScript = ''
|
||||
echo Setting up sops templates...
|
||||
${concatMapStringsSep "\n" (name:
|
||||
let
|
||||
tpl = config.sops.templates.${name};
|
||||
substitute = pkgs.writers.writePython3 "substitute" { }
|
||||
(readFile ./subs.py);
|
||||
subst-pairs = pkgs.writeText "pairs" (concatMapStringsSep "\n"
|
||||
(name:
|
||||
"${toString config.sops.placeholder.${name}} ${
|
||||
config.sops.secrets.${name}.path
|
||||
}") (attrNames config.sops.secrets));
|
||||
in ''
|
||||
mkdir -p "${dirOf tpl.path}"
|
||||
(umask 077; ${substitute} ${tpl.file} ${subst-pairs} > ${tpl.path})
|
||||
chmod "${tpl.mode}" "${tpl.path}"
|
||||
chown "${tpl.owner}:${tpl.group}" "${tpl.path}"
|
||||
'') (attrNames config.sops.templates)}
|
||||
'';
|
||||
in {
|
||||
options.sops = {
|
||||
templates = mkOption {
|
||||
description = "Templates for secret files";
|
||||
type = attrsOf (submodule ({ config, ... }: {
|
||||
type = types.attrsOf (types.submodule ({ config, ... }: {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = singleLineStr;
|
||||
type = types.singleLineStr;
|
||||
default = config._module.args.name;
|
||||
description = ''
|
||||
Name of the file used in /run/secrets/rendered
|
||||
|
|
@ -42,32 +23,32 @@ in {
|
|||
};
|
||||
path = mkOption {
|
||||
description = "Path where the rendered file will be placed";
|
||||
type = singleLineStr;
|
||||
type = types.singleLineStr;
|
||||
default = "/run/secrets/rendered/${config.name}";
|
||||
};
|
||||
content = mkOption {
|
||||
type = lines;
|
||||
type = types.lines;
|
||||
default = "";
|
||||
description = ''
|
||||
Content of the file
|
||||
'';
|
||||
};
|
||||
mode = mkOption {
|
||||
type = singleLineStr;
|
||||
type = types.singleLineStr;
|
||||
default = "0400";
|
||||
description = ''
|
||||
Permissions mode of the rendered secret file in octal.
|
||||
'';
|
||||
};
|
||||
owner = mkOption {
|
||||
type = singleLineStr;
|
||||
type = types.singleLineStr;
|
||||
default = "root";
|
||||
description = ''
|
||||
User of the file.
|
||||
'';
|
||||
};
|
||||
group = mkOption {
|
||||
type = singleLineStr;
|
||||
type = types.singleLineStr;
|
||||
default = users.${config.owner}.group;
|
||||
defaultText = lib.literalExpression ''config.users.users.''${cfg.owner}.group'';
|
||||
description = ''
|
||||
|
|
@ -88,40 +69,21 @@ in {
|
|||
default = { };
|
||||
};
|
||||
placeholder = mkOption {
|
||||
type = attrsOf (mkOptionType {
|
||||
type = types.attrsOf (types.mkOptionType {
|
||||
name = "coercibleToString";
|
||||
description = "value that can be coerced to string";
|
||||
check = strings.isConvertibleWithToString;
|
||||
merge = mergeEqualOption;
|
||||
check = lib.strings.isConvertibleWithToString;
|
||||
merge = lib.mergeEqualOption;
|
||||
});
|
||||
default = { };
|
||||
visible = false;
|
||||
};
|
||||
};
|
||||
|
||||
config = optionalAttrs (options ? sops.secrets)
|
||||
(mkIf (config.sops.templates != { }) {
|
||||
config = lib.optionalAttrs (options ? sops.secrets)
|
||||
(lib.mkIf (config.sops.templates != { }) {
|
||||
sops.placeholder = mapAttrs
|
||||
(name: _: mkDefault "<SOPS:${hashString "sha256" name}:PLACEHOLDER>")
|
||||
(name: _: mkDefault "<SOPS:${builtins.hashString "sha256" name}:PLACEHOLDER>")
|
||||
config.sops.secrets;
|
||||
|
||||
systemd.services.sops-render-secrets = let
|
||||
installServices = [ "sops-install-secrets.service" ] ++ optional (secretsForUsers != { }) "sops-install-secrets-for-users.service";
|
||||
in lib.mkIf (cfg.templates != { } && useSystemdActivation) {
|
||||
wantedBy = [ "sysinit.target" ];
|
||||
requires = installServices;
|
||||
after = installServices;
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
|
||||
script = renderScript;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
};
|
||||
|
||||
system.activationScripts.renderSecrets = mkIf (cfg.templates != { } && !useSystemdActivation)
|
||||
(stringAfter ([ "setupSecrets" ] ++ optional (secretsForUsers != { }) "setupSecretsForUsers")
|
||||
renderScript);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
from sys import argv
|
||||
|
||||
|
||||
def substitute(target: str, subst: str) -> str:
|
||||
with open(target) as f:
|
||||
content = f.read()
|
||||
|
||||
with open(subst) as f:
|
||||
subst_pairs = f.read().splitlines()
|
||||
|
||||
for pair in subst_pairs:
|
||||
placeholder, path = pair.split()
|
||||
if placeholder in content:
|
||||
with open(path) as f:
|
||||
content = content.replace(placeholder, f.read())
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def main() -> None:
|
||||
target = argv[1]
|
||||
subst = argv[2]
|
||||
print(substitute(target, subst))
|
||||
|
||||
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue