-
Notifications
You must be signed in to change notification settings - Fork 886
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
Add support for age. #688
Add support for age. #688
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #688 +/- ##
===========================================
- Coverage 36.74% 33.51% -3.23%
===========================================
Files 22 23 +1
Lines 3217 3076 -141
===========================================
- Hits 1182 1031 -151
+ Misses 1916 1913 -3
- Partials 119 132 +13
Continue to review full report at Codecov.
|
I have not tested but from a basic code review it looks good to me. I am not affiliated with the project but I assume that the maintainers also want to see some unit tests before they merge this. |
Thanks for the work :) Two concerns:
|
My main motivation for having this is an alternative for deploying sops on servers in none-cloud environments (no azure, no aws, no GCP) because key generation/provision with GPG is overly complex:
Key sharing is actually something I don't want to do in this case because unlike gpg keys those are machines rather than persons. |
I understand AGE has some benefits, and I'm unfortunately painfully aware of the issues with GPG. Maybe documentation saying "put your AGE keys here" would be enough. I don't know if AGE has a standard location to put keys in. I want to have a better look at AGE before fully reviewing this PR regardless. |
On servers one could even use the ssh host key, which is already present on most Linux servers. Also hosters like github already expose ssh public keys, which can be used: https://github.com/FiloSottile.keys |
The location of the private keys I chose is based on a similar pattern in the PR I was referencing, as noted in the description. The setup here is a little odd in that we don't save any sort of path or identifier for the private key in the encrypted file—it has to be derived from the public key somehow. I suspect that age is intentionally agnostic on key management so that systems that use it can do whatever is most appropriate, but in our case it is unfortunate not to have a convention for where to find private keys that we could leverage. Perhaps @FiloSottile can share if there is any particular guidance on key management. Also, I don't think age is an acronym, so it doesn't need to be capitalized. 😛 |
Seems to be a bit relevant: #692 |
Made some changes:
|
Nevermind these are private keys... |
age/keysource.go
Outdated
for scanner.Scan() { | ||
line := scanner.Text() | ||
|
||
if strings.HasPrefix(line, "AGE-SECRET-KEY") { | ||
privateKey = line | ||
break | ||
} | ||
} |
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.
It would be nice to just copy this function: https://github.com/FiloSottile/age/blob/189041b668629795593766bcb8d3f70ee248b842/cmd/age/parse.go#L36
Then it would not just support the age format but also ssh keys like age does.
Same goes for encrypting.
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.
@FiloSottile How does making the linked code available via age's library sound? Ideally this logic wouldn't be duplicated in sops or it could get out of sync with what age does over time.
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.
That would be the ideal case.
I think the next thing upstream would ask for is to provide a section in the README. I can also help out here. |
Thanks for the review, @Mic92! That was very helpful. I fixed some of the smaller points, but I think it would make sense to see what Filippo says about opening up more functionality through the library before proceeding with the other changes. |
That makes sense. Maybe we can fix this upstream. |
Hmm good question. The key files format is more part of the age CLI than the API, but maybe it should be exposed. Give me a couple days to think about it. |
If fundamental parts like key location is not part of age api than will see inconsistency in the ecosystem on how age is integrated into applications. |
I could see it being a separate lib that sits in between the current lib and the CLI, so that it's possible to use the base library just for encryption and decryption without anything more. The intermediate "storage" library could be consumed by both the CLI and third-party software like sops that wants to use the same conventions for storing keys as the CLI. |
I don't know sops enough to tell you about your use case in particular, but I expect most application that use age to keep separate keys. age doesn't have the concept of a "user key" that is used for all applications that use age, and I don't want that kind of overloading. If you rotate your sops key you shouldn't have to worry about your password manager or backups at the same time. What we might want to expose is the key file format, not the location. Can I ask why the interest in supporting SSH keys? age supports them so one can encrypt to someone who doesn't have an age key without waiting a round-trip for them to generate it. Here it looks like you could just generate an age key? |
The current workflow is that developers have a gnupg key that is distributed across the team (i.e. through public key server). On the server side there is some sort of key management service provided by some cloud provider. With age I hope to have a solution that lucks less than gnupg for users and also an alternative for non-cloud servers, which do not have access to an cloud-based vault.
If you have configuration shared in a team they are likely to have some sort of version control and hence you have public keys i.e. https://github.com/Mic92.keys This makes further key exchange unnecessary. The same is true for servers where configuration is deployed. Most of them already have ssh private host keys: i.e. /etc/ssh/ssh_host_ed25519_key This ssh key is already trusted and easy to obtain. |
I think that keeping separate keys for sops is what I would want us to recommend in most use-cases. At the same time, that doesn't mean that there cannot be a set default "age private key directory" where all of your keys are kept, even if it's 1 or more key per application. |
This sounds good to me. Not having a direct equivalent to a PGP key is a good thing about age, and we shouldn't be trying to shoehorn that back in for sops usage. It makes sense to me to have a sops-specific directory to store age keys that are used specifically and only for the purpose of sops. It'd definitely be nice to have a standard key file format, though! |
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.
Thank you all for working on this and for your patience. I added a section to the age docs about key management, which matches what you are doing and recommends not adding support for SSH keys at all.
https://pkg.go.dev/filippo.io/[email protected]#hdr-Key_management
I also added ParseIdentities
to make it easier to parse the private key file.
Co-authored-by: Jörg Thalheim <[email protected]>
Updated to the latest age beta and made changes suggested by Filippo. Still looking for a sops maintainer with time for final review and hopefully merge! |
LGTM. I'll give it a couple of days to see if @ajvb has time to review, otherwise I'll just merge. |
🎉 This is really exciting! I should be able to get to a review sometime tomorrow. |
Thank you so much @jimmycuadra, @FiloSottile, @Mic92, and @colemickens - very exciting to get this in here. |
@jimmycuadra Thank you for the age integration. I'll will test it soon. ❤️ |
Implements support for age as I requested in #603. I'm not a Go programmer and was learning the sops code as I went, so there's likely a lot I missed here. But the basic encrypt and decrypt operations are working for me! I used #569 as a reference for how to do this, as suggested by @jvehent.
Example (this has been simplified in more recent commits. See #688 (comment)):
Things that I know are missing:
TestsDocumentationAbility to customize where sops looks for private key material.Which of these things would be necessary to get basic support merged? I can't guarantee a lot of time to work on this so I'm hoping to scope it down as small as possible. Alternatively, if someone wants to use my branch as a starting point and take over, that'd be great.