FiloSottile / age

A simple, modern and secure encryption tool (and Go library) with small explicit keys, no config options, and UNIX-style composability.
https://age-encryption.org
BSD 3-Clause "New" or "Revised" License
17.14k stars 501 forks source link

Add gopkg.in/yaml.v3 Marshaller/Unmarshaller #161

Closed sylr closed 3 years ago

sylr commented 3 years ago

I think there is a great lack of a tool which would allow inline crypting/decrypting of yaml data.

Working the Ops side of DevOps I have a lot of YAML (mostly kubernetes manifests) with sensitive data I'd like to cipher inline.

Let me know what you think.

FiloSottile commented 3 years ago

Hey, this is cool! Is there any reason it shouldn't be a separate module though? filippo.io/age should probably not grow support for all the places people might want to use age. I'm planning to start an awesome-age directory of integrations, so I would be happy to include this there.

The only thing I don't really like is the package-global recipients and identities. Is this something that's standard in the ecosystem? If not I would try as much as possible to find a way to scope recipients/identities per use. Otherwise, different parts of a codebase that use the same package would end up conflicting.

sylr commented 3 years ago

Hey, this is cool! Is there any reason it shouldn't be a separate module though? filippo.io/age should probably not grow support for all the places people might want to use age. I'm planning to start an awesome-age directory of integrations, so I would be happy to include this there.

Well, this is a new go module (see go.mod in yaml/v3) :)

I thought that by living in your repo it would be given the most visibility and thus more chances at being well maintained.

Also, I thought that next steps could have been to add yaml crypt/decrypt sub commands to the age binary so keeping it close would be handy.

The only thing I don't really like is the package-global recipients and identities. Is this something that's standard in the ecosystem? If not I would try as much as possible to find a way to scope recipients/identities per use. Otherwise, different parts of a codebase that use the same package would end up conflicting.

I don't like it either but while I managed to include the identities in the Wrapper for Unmarshalling I did not find a way to add recipients for Marshalling other than with package globals.

So to be coherent I chose to both add them via package globals.

FiloSottile commented 3 years ago

Hey, this is cool! Is there any reason it shouldn't be a separate module though? filippo.io/age should probably not grow support for all the places people might want to use age. I'm planning to start an awesome-age directory of integrations, so I would be happy to include this there.

Well, this is a new go module (see go.mod in yaml/v3) :)

I am not a fan of nested modules, and instead I'm ok with adding optional dependencies as long as they are bottled up in a separate package. I meant a 3rd party repository, not just a separate module :)

I thought that by living in your repo it would be given the most visibility and thus more chances at being well maintained.

Well, if I accepted it in here I would be taking full responsibility to maintain it, and I think it's outside the scope of what I want to personally maintain. I am hoping the awesome-age list will help with visibility.

The only thing I don't really like is the package-global recipients and identities. Is this something that's standard in the ecosystem? If not I would try as much as possible to find a way to scope recipients/identities per use. Otherwise, different parts of a codebase that use the same package would end up conflicting.

I don't like it either but while I managed to include the identities in the Wrapper for Unmarshalling I did not find a way to add recipients for Marshalling other than with package globals.

So to be coherent I chose to both add them via package globals.

For Marshalling maybe you could make the EncryptedString type carry a Recipient, and how one sets it is by using a helper like foo.agestr = ageyaml.NewRecipient(r1, r2).EncryptedString("bar"). Wouldn't work for Unmarshalling because then the value is unset, but sounds like you have a solution for that.

sylr commented 3 years ago

That's a good idea, I'll try that.

Do you mind if I continue to work on this here so you can give me inputs ?

Once something acceptable comes out of this I will move it into its own repo.

sylr commented 3 years ago

Ok, so, it turns out nested modules are hell.

I moved the Wrapper to https://github.com/sylr/go-yaml-age.

I finally found a way to avoid package global variables 🎉