canonical / operator

Pure Python framework for writing Juju charms
Apache License 2.0
240 stars 113 forks source link

Design bytes/binary APIs for secrets #869

Open benhoyt opened 1 year ago

benhoyt commented 1 year ago

In the initial secrets implementation we intentionally simplified and currently only allow Python str objects as secrets. However, the Juju secrets design allows binary content and has a base64-encoding mode to send them back and forth. We need some way to model this in the relevant Python Operator Framework functions.

Functions that take secret content like add_secret and set_content can simply be extended to take content as Dict[str, Union[str, bytes]] instead of just Dict[str, str].

However, for functions that return content like get_content and peek_content we need a way to ask them to return bytes. Probably the best way is to add new functions, as that's the clearest separation: get_raw_content (or get_raw) and peek_raw_content. Alternatively we could add an optional raw=True keyword arg (but we have to be careful with get_content caching).

The push/pull/exec Pebble APIs use an encoding keyword arg that defaults to utf-8, and you can set it to None if you want bytes. So it's worth considering if something like that could apply here.

jameinel commented 1 year ago

It is definitely an interesting problem, as you could very easily end up with mixed content. (username is a 'str', but password is a 'bytes'). I wonder if the answer is a way to get the truly raw content as just a bytes/str and allow the users to wrap that into their own types. So that you would end up having a SecretManager of some form, that you could instantiate. Effectively like we have for named relations, you would end up with some form of secret manager that knows what prefixes it supports and that would give you the content.

That said, it doesn't feel like most secrets are binary. For example, certificates are typically text encoded already.

rbarry82 commented 1 year ago

Well, maybe. Certificates could just as easily be DER, and there's CBOR, and krb5 principals/keytabs (if anyone would ever use them). Even if some secrets aren't binary, it's a common enough case that we may as well support it.

The naming of the method doesn't matter a ton (I'd probably go with get_content_raw or peek_content_raw rather than peek_raw_content, but that's more for completion to look nicer in whatever editor), and leave it to authors to cast/unpickle/decode/unmarshal into whatever object they need, or just stream it directly into a Pebble container.

benhoyt commented 1 month ago

Per Madrid discussion, this hasn't been asked for at all, so presumably everyone is fine with text. However, leaving this open as it's still a missing feature in Ops that is supported in Juju.