modules/age: add option to disable symlinking

There are some cases where it may be better or even required to have the
secret be a file that is not a symlink. Setting

    age.secrets.some-secret.symlink = false;

will disable the default functionality of symlinking secrets and instead
just forcibly move them to their `path`.
This commit is contained in:
Cole Helbling 2021-11-08 09:45:34 -08:00
parent e538664435
commit 7bb0b5d7f1
2 changed files with 26 additions and 2 deletions

View file

@ -193,6 +193,22 @@ randomness in `age`'s encryption algorithms, the files always change
when rekeyed, even if the identities do not. (This eventually could be when rekeyed, even if the identities do not. (This eventually could be
improved upon by reading the identities from the age file.) improved upon by reading the identities from the age file.)
## Don't symlink secret
If your secret cannot be a symlink, you should set the `symlink` option to `false`:
```nix
{
age.secrets.some-secret = {
file = ./secret;
path = "/var/lib/some-service/some-secret";
symlink = false;
};
}
```
Instead of first decrypting the secret to `/run/agenix` and then symlinking to its `path`, the secret will instead be forcibly moved to its `path`. Please note that, currently, there are no cleanup mechanisms for secrets that are not symlinked by agenix.
## Threat model/Warnings ## Threat model/Warnings
This project has not be audited by a security professional. This project has not be audited by a security professional.

View file

@ -16,7 +16,11 @@ let
identities = builtins.concatStringsSep " " (map (path: "-i ${path}") cfg.sshKeyPaths); identities = builtins.concatStringsSep " " (map (path: "-i ${path}") cfg.sshKeyPaths);
installSecret = secretType: '' installSecret = secretType: ''
_truePath="${cfg.secretsMountPoint}/$_count/${secretType.name}" ${if secretType.symlink then ''
_truePath="${cfg.secretsMountPoint}/$_agenix_generation/${secretType.name}"
'' else ''
_truePath="${secretType.path}"
''}
echo "decrypting '${secretType.file}' to '$_truePath'..." echo "decrypting '${secretType.file}' to '$_truePath'..."
TMP_FILE="$_truePath.tmp" TMP_FILE="$_truePath.tmp"
mkdir -p "$(dirname "$_truePath")" mkdir -p "$(dirname "$_truePath")"
@ -28,7 +32,10 @@ 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"
mv -f "$TMP_FILE" "$_truePath" mv -f "$TMP_FILE" "$_truePath"
[ "${secretType.path}" != "/run/agenix/${secretType.name}" ] && ln -sfn "/run/agenix/${secretType.name}" "${secretType.path}"
${optionalString secretType.symlink ''
[ "${secretType.path}" != "/run/agenix/${secretType.name}" ] && ln -sfn "/run/agenix/${secretType.name}" "${secretType.path}"
''}
''; '';
isRootSecret = st: (st.owner == "root" || st.owner == "0") && (st.group == "root" || st.group == "0"); isRootSecret = st: (st.owner == "root" || st.owner == "0") && (st.group == "root" || st.group == "0");
@ -83,6 +90,7 @@ let
Group of the file. Group of the file.
''; '';
}; };
symlink = mkEnableOption "symlinking secrets to their destination" // { default = true; };
}; };
}); });
in in