Skip to content
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

WIP: Templates #96

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft

WIP: Templates #96

wants to merge 6 commits into from

Conversation

Radvendii
Copy link

implements #95

updates, and thus depends on #87

Radvendii and others added 5 commits January 12, 2022 15:58
represents an action to perform or systemd service to restart when the
secret changes
Co-authored-by: Winter <78392041+winterqt@users.noreply.github.com>
Co-authored-by: Winter <78392041+winterqt@users.noreply.github.com>
These secrets have a template file which refers to other secrets, which
we splice in at activation time. This way we can have part of the file
be secret, and part of it public.
@Radvendii
Copy link
Author

I just realized there's an issue with this: what if we try to derive a template secret before its dependency is in place?

Should we just decode all template secrets after all normal secrets? What about root secrets vs non-root secrets?

I also think a good change to make would be to make a separate attribute: age.derived.foo or age.templates.foo instead of age.secrets.foo. That way we don't have the confusion of file and template existing on the same secret.

Will work on those later.

@Radvendii Radvendii changed the title Templates WIP: Templates Jan 18, 2022
@Radvendii
Copy link
Author

Okay, I implemented all that. The code is more complex than I'd hoped...

@ryantm
Copy link
Owner

ryantm commented Jan 26, 2022

@Radvendii Thank you for your interest in improving agenix. I am not convinced that this template feature needs to be tightly integrated with agenix and suggest that you implement a separate (and general) templating module project that you can use activationScript deps to make run after agenix runs.

@Radvendii
Copy link
Author

There are three reasons I thought it best to include in agenix itself:

  1. The only possible use-case I can think of for a runtime templating system is as part of a secret system. Nothing else exists at runtime but not at build time. And if you have it at build time it's much more convenient to do templating with Nix itself.
  2. The files resulting from applying the templates are also secrets, which means they need the same security options (permissions, locking the directory behind they "keys" group, etc), as well as the restarting services option that I added in add age.secrets.*.{action,service} #87
  3. This is also, by my (very rough) estimation, a common thing to want to do with secrets. There are many configuration files with "password" as a field, and it makes sense to separate the sensitive information from non-sensitive. This has come up while talking with a couple different people about agenix, and I don't know that many people who use agenix.

I won't push the matter any further though. If you think the added complexity is not worth the benefits for this project, I'll implement it separately. If you think it's somewhere in the range of reasonable, I'm happy to keep working at making the addition simpler.

@ryantm
Copy link
Owner

ryantm commented Jan 26, 2022

@Radvendii You're arguments are pretty compelling. I've also noticed a need for templating with secrets, but I've usually get around it by either moving the entire configuration file into the secret or using some configuration include option. I reopened the issue you made for this so we can think about it more.

@Radvendii
Copy link
Author

Yeah, that's the way I've done it also. Unfortunately, not all service's configurations have a way to redirect passwords to another file (two that I've encountered are msmtp and spotify passwords in mopidy). I would definitely say this is a deficiency of those projects, but it does seem to be somewhat common.

And then putting the whole file in a secret does work. That's how I've been doing things. But it ends up with a lot of extra configuration being encrypted.

The problem that someone else had recently that prompted me to actually try to code up a solution was that they had the same password used in two different configuration files. Right now they have to have two different secret files. Not the end of the world, but it would be nice to see an elegant solution to all these small issues.

I'll think more about a more elegant design for this.

@Radvendii
Copy link
Author

Radvendii commented Jan 28, 2022

So another way to structure this, which covers some of the use-cases but not all, is to have a postDecryptHook which runs after the secret gets decrypted, and allows you to apply a template. Or just add a template field to secrets that has one slot for the secret itself.

Pros:

  • Much simpler implementation.
  • No separate "derived secrets" from "normal secrets"

Cons:

  • you can't include more than one secret in a derived secret

@Radvendii
Copy link
Author

We could

  • Let any secret be either encrypted or not encrypted (if not encrypted it just gets copied into the result dir)
  • Let any secret contain references to other secrets
    • @secret-name@ (pro: can be used from non-nix files)
    • /nix/store/<hash>-secret (pro: can be referenced as ${age.secrets.blah.file} from nix code)

Pros:

  • No special types of secrets, just different ways for a secret to be.

Cons:

  • Someone might accidentally refer to a secret from another secret
  • Have to figure out how to order unpacking the secrets.
  • Someone might forget to encrypt a secret, and then it silently goes in the nix store

@ryantm ryantm marked this pull request as draft March 9, 2022 04:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants