mirror of
https://github.com/ryantm/agenix.git
synced 2024-11-25 11:08:30 +03:00
overhaul on change actions
compare the decrypted secrets, and make use of /run/nixos/activation-{restart,reload}-list
This commit is contained in:
parent
5a98964a52
commit
34f637d93e
3 changed files with 45 additions and 49 deletions
|
@ -2,11 +2,11 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1638587357,
|
"lastModified": 1653996475,
|
||||||
"narHash": "sha256-2ySMW3QARG8BsRPmwe7clTbdCuaObromOKewykP+UJc=",
|
"narHash": "sha256-r/UA7h3Dfgf4dlOCkakpqejf1Tagfb+6T+9OdT0qBgU=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "e34c5379866833f41e2a36f309912fa675d687c7",
|
"rev": "ec6eaba9dfcfdd11547d75a193e91e26701bf7e3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, options, lib, pkgs, ... }:
|
{ config, options, lib, utils, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
with lib;
|
||||||
|
|
||||||
|
@ -18,8 +18,10 @@ let
|
||||||
installSecret = secretType: ''
|
installSecret = secretType: ''
|
||||||
${if secretType.symlink then ''
|
${if secretType.symlink then ''
|
||||||
_truePath="${cfg.secretsMountPoint}/$_agenix_generation/${secretType.name}"
|
_truePath="${cfg.secretsMountPoint}/$_agenix_generation/${secretType.name}"
|
||||||
|
_oldPath="${cfg.secretsMountPoint}/$(( _agenix_generation - 1 ))/${secretType.name}"
|
||||||
'' else ''
|
'' else ''
|
||||||
_truePath="${secretType.path}"
|
_truePath="${secretType.path}"
|
||||||
|
_oldPath=_truePath
|
||||||
''}
|
''}
|
||||||
echo "decrypting '${secretType.file}' to '$_truePath'..."
|
echo "decrypting '${secretType.file}' to '$_truePath'..."
|
||||||
TMP_FILE="$_truePath.tmp"
|
TMP_FILE="$_truePath.tmp"
|
||||||
|
@ -33,8 +35,18 @@ let
|
||||||
)
|
)
|
||||||
chmod ${secretType.mode} "$TMP_FILE"
|
chmod ${secretType.mode} "$TMP_FILE"
|
||||||
chown ${secretType.owner}:${secretType.group} "$TMP_FILE"
|
chown ${secretType.owner}:${secretType.group} "$TMP_FILE"
|
||||||
|
|
||||||
|
# see if there's been any change from the last generation
|
||||||
|
changes=$(${pkgs.rsync}/bin/rsync --dry-run -aHAX -i "$TMP_FILE" "$_oldPath")
|
||||||
|
|
||||||
mv -f "$TMP_FILE" "$_truePath"
|
mv -f "$TMP_FILE" "$_truePath"
|
||||||
|
|
||||||
|
[ "$changes" != "" ] && {
|
||||||
|
echo '${lib.concatStringsSep "\n" secretType.reloadUnits}' >> /run/nixos/activation-reload-list
|
||||||
|
echo '${lib.concatStringsSep "\n" secretType.restartUnits}' >> /run/nixos/activation-restart-list
|
||||||
|
${secretType.onChange}
|
||||||
|
}
|
||||||
|
|
||||||
${optionalString secretType.symlink ''
|
${optionalString secretType.symlink ''
|
||||||
[ "${secretType.path}" != "${cfg.secretsDir}/${secretType.name}" ] && ln -sfn "${cfg.secretsDir}/${secretType.name}" "${secretType.path}"
|
[ "${secretType.path}" != "${cfg.secretsDir}/${secretType.name}" ] && ln -sfn "${cfg.secretsDir}/${secretType.name}" "${secretType.path}"
|
||||||
''}
|
''}
|
||||||
|
@ -96,16 +108,22 @@ let
|
||||||
Group of the decrypted secret.
|
Group of the decrypted secret.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
action = mkOption {
|
onChange = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "";
|
default = "";
|
||||||
description = "A script to run when secret is updated.";
|
description = "A script to run when secret is updated.";
|
||||||
};
|
};
|
||||||
services = mkOption {
|
reloadUnits = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf utils.systemdUtils.lib.unitNameType;
|
||||||
default = [];
|
default = [];
|
||||||
description = "The systemd services that uses this secret. Will be restarted when the secret changes.";
|
description = "The systemd services to reload when the secret changes.";
|
||||||
example = "[ wireguard-wg0 ]";
|
example = literalExpression ''[ "wireguard-wg0.service" ]'';
|
||||||
|
};
|
||||||
|
restartUnits = mkOption {
|
||||||
|
type = types.listOf utils.systemdUtils.lib.unitNameType;
|
||||||
|
default = [];
|
||||||
|
description = "The systemd services to restart when the secret changes.";
|
||||||
|
example = literalExpression ''[ "wireguard-wg0.service" ]'';
|
||||||
};
|
};
|
||||||
symlink = mkEnableOption "symlinking secrets to their destination" // { default = true; };
|
symlink = mkEnableOption "symlinking secrets to their destination" // { default = true; };
|
||||||
};
|
};
|
||||||
|
@ -183,11 +201,6 @@ in
|
||||||
mkdir -p "${cfg.secretsMountPoint}/$_agenix_generation"
|
mkdir -p "${cfg.secretsMountPoint}/$_agenix_generation"
|
||||||
chmod 0751 "${cfg.secretsMountPoint}/$_agenix_generation"
|
chmod 0751 "${cfg.secretsMountPoint}/$_agenix_generation"
|
||||||
ln -sfn "${cfg.secretsMountPoint}/$_agenix_generation" ${cfg.secretsDir}
|
ln -sfn "${cfg.secretsMountPoint}/$_agenix_generation" ${cfg.secretsDir}
|
||||||
|
|
||||||
(( _agenix_generation > 1 )) && {
|
|
||||||
echo "[agenix] removing old secrets (generation $(( _agenix_generation - 1 )))..."
|
|
||||||
rm -rf "${cfg.secretsMountPoint}/$(( _agenix_generation - 1 ))"
|
|
||||||
}
|
|
||||||
'';
|
'';
|
||||||
deps = [
|
deps = [
|
||||||
"specialfs"
|
"specialfs"
|
||||||
|
@ -216,7 +229,7 @@ in
|
||||||
};
|
};
|
||||||
|
|
||||||
# Other secrets need to wait for users and groups to exist.
|
# Other secrets need to wait for users and groups to exist.
|
||||||
system.activationScripts.agenix = {
|
system.activationScripts.agenixNonRoot = {
|
||||||
text = installNonRootSecrets;
|
text = installNonRootSecrets;
|
||||||
deps = [
|
deps = [
|
||||||
"users"
|
"users"
|
||||||
|
@ -227,38 +240,21 @@ in
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services = lib.mkMerge
|
# named "agenix" for others to depend on the last activationScript (and thereby all the rest)
|
||||||
(lib.mapAttrsToList
|
system.activationScripts.agenix = {
|
||||||
(name: {action, services, file, path, mode, owner, group, ...}:
|
# cleanup old generation
|
||||||
let
|
text = ''
|
||||||
fileHash = builtins.hashFile "sha256" file;
|
(( _agenix_generation > 1 )) && {
|
||||||
restartTriggers = [ fileHash path mode owner group ];
|
echo "[agenix] removing old secrets (generation $(( _agenix_generation - 1 )))..."
|
||||||
in
|
rm -rf "${cfg.secretsMountPoint}/$(( _agenix_generation - 1 ))"
|
||||||
lib.mkMerge [
|
}
|
||||||
(lib.genAttrs services (_: { inherit restartTriggers; }))
|
'';
|
||||||
(lib.mkIf (action != "") {
|
deps = [
|
||||||
"agenix-${name}-action" = {
|
"specialfs"
|
||||||
inherit restartTriggers;
|
"agenixMountSecrets"
|
||||||
|
"agenixRoot"
|
||||||
# We execute the action on reload so that it doesn't happen at
|
"agenixNonRoot"
|
||||||
# startup. The only disadvantage is that it won't trigger the
|
];
|
||||||
# first time the service is created.
|
};
|
||||||
reload = action;
|
};
|
||||||
reloadIfChanged = true;
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
script = " "; # systemd complains if we only set ExecReload
|
|
||||||
|
|
||||||
# Give it a reason for starting
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
})
|
|
||||||
]) cfg.secrets);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import "${nixpkgs}/nixos/tests/make-test-python.nix"
|
||||||
|
|
||||||
age.secrets.ex1 = {
|
age.secrets.ex1 = {
|
||||||
file = ../example/passwordfile-user1.age;
|
file = ../example/passwordfile-user1.age;
|
||||||
action = "echo bar > /tmp/foo";
|
onChange = "echo bar > /tmp/foo";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue