-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modules/age: symlink files into place #27
Conversation
8944f50
to
28b3369
Compare
Old secrets generations are removed in 368584b. From what I can tell with my last few minutes of testing, works well. |
42facc9
to
b3480ac
Compare
Been using this for a few days and it's been working flawlessly. Switching secrets, rebooting, the whole kit and caboodle. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, I find this a bit harder to reason about than the previous solution.
For example: why do we need /run/secrets
? Can't we symlink /run/secrets.d/N
into secretType.path
?
modules/age.nix
Outdated
(umask 0400; LANG=${config.i18n.defaultLocale} ${ageBin} --decrypt ${identities} -o "$TMP_FILE" "${secretType.file}") | ||
chmod ${secretType.mode} "$TMP_FILE" | ||
chown ${secretType.owner}:${secretType.group} "$TMP_FILE" | ||
mv -f "$TMP_FILE" '${secretType.path}' | ||
mv -f "$TMP_FILE" "${cfg.secretsMountPoint}/$_count/${secretType.name}" | ||
[ "${secretType.path}" != "/run/secrets/${secretType.name}" ] && ln -sfn "/run/secrets/${secretType.name}" "${secretType.path}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So IIUC, if secretType.path
is e.g. /foo/bar
, the secret will be symlinked both into /foo/bar
and /run/secrets/bar
.
Is this necessarily what a user wants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say yes (and it's how sops-nix behaves, IIRC). /run/secrets
should be the single source of truth for the secrets on the system, so that switching a secrets generation "expires" any removed secrets (resulting in a dead symlink, if names don't collide). (While /run/secrets.d/##
is the actual source of truth, /run/secrets
is a static reference to it; otherwise, it would be hard to refer to secrets when they change with every switch
of the configuration.)
This would definitely increase complexity, but maybe we could store a sort of manifest in /run/secrets.d
that lists the secret name and its secretType.path
, so we can unlink
them all prior to switching secrets generations.
Hey @ryantm, sorry to bump this, but just wanted to see if there's anything blocking this from being merged? This project seems really nice but this is the one feature holding me back from using it over sops-nix. |
8e1c150
to
4991bc4
Compare
Rebased and squashed. |
Is there anything missing to get this merged? 😅 |
Bump? 🙃 |
@ryantm Are you only waiting on me to document the change of (FWIW, I've been running against this branch for the past few months; no troubles.) |
Maybe I knew why at some point, but I don't remember now. Is there some good explanation somewhere for why you want to change it to work like this? |
I'd like to be able to use this for system-level secret management, not just for secrets in my nix configuration. Symlinking to /run/secrets allows me to access them in a consistent place. |
@kclejeune Thanks for explaining. I think it sounds like you are saying you have a NixOS machine that has some program that is not managed by NixOS that you want to be able to access a secret that is managed by NixOS. Is that right? |
That's correct! My primary use case is actually on nix-darwin, where I can't manage as many things declaratively, but the same need exists on my NixOS system too. |
It would be really helpful if one could specify if the secret to be installed should be created as a symlink or just a copy because some tools like openssh do not allow e.g. ssh keys to be symlinks. |
I've also noticed this problem with symlinked secrets in the Java ecosystem. Specifically Elasticsearch. |
The main question would be, how copied secrets will be cleaned up if they are removed from the nixos configuration.. Otherwise this could lead to non reproducible system when the system relies on secret file that are no more present in the configuration. |
Unless I'm mistaken, I don't think the current implementation in If all that's necessary to make this mergeable is:
I can do that. |
@cole-h yeah I think that's it (aside from current merge conflicts) thank you! |
@ryantm Is there any place in particular you'd like me to call out the switch from |
@cole-h I think we can just put something additional in the release notes. Is it the case that we are relying on $_count to not be clobbered by some other activation script? I'm thinking it should be named something else if that is case, like $agenix_generation. I was wondering if it is possible to use the same generation number as NixOS. Then we wouldn't need to generate a variable and it might be slightly helpful for debugging things. |
Sorry, this slipped my mind! I'll get back to it this weekend. I'll make the change to How do we get the generation? Reading the |
Is this the approach that sops-nix uses? Intuitively I don't see too much of a reason to match it to the system generation as long as it works with rollbacks. |
Sounds fine to keep it separate I just guessing maybe the generation was easily available as an env var or something |
This follows sops-nix's implementation, where it creates a `/run/secrets.d` ramfs mountpoint and a "generation" each time the activation script runs, and then symlinks `/run/secrets` to `/run/secrets.d/[generation]`.
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`.
I don't remember, but either way, it should work with rollbacks since the path to the encrypted secret is referenced from the system activation script. Even if you run it multiple times, it will just create a new generation with the expected decrypted secrets each time. (I lied earlier -- I found time tonight to change the variable name hehe) |
This follows sops-nix's implementation, where it creates a
/run/secrets.d
ramfs mountpoint and a "generation" each timethe activation script runs, and then symlinks
/run/secrets
to/run/secrets.d/[generation]
.Fixes #26.
Fixes #21.
TODO (maybe): is it possible to not create a new generation each time activation runs (if nothing changed)? Does sops-nix do this?While possible, this would introduce a decent amount of complexity for (IMHO) no gain. Since we remove old secrets generations, I think this is unnecessary.