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

Proposal: Support for Secrets via Tagged or Term Values #40

Closed
michaelklishin opened this issue Apr 25, 2024 · 7 comments · Fixed by #46
Closed

Proposal: Support for Secrets via Tagged or Term Values #40

michaelklishin opened this issue Apr 25, 2024 · 7 comments · Fixed by #46
Assignees
Milestone

Comments

@michaelklishin
Copy link
Collaborator

michaelklishin commented Apr 25, 2024

Proposal: Support for "Special" String Values (Such as Secrets)

Problem Definition

Cuttlefish does its job well but there's one area where it is not particularly strong: specifying secrets such as passwords, PII or other values that cannot or should not be stored in the config files.

Using advanced.config is an option for those cases but using it is error prone or, for those who are not Erlang-savvy, is often not an option.

Cuttlefish will be more useful in more contexts if it introduces a way to store (references to) such sensitive values.

The Proposal

Cuttlefish can introduce support for "tagged values" that would be translated into
Erlang tuples in the generated configuration file. The value can be specified using a syntax extension, something like this:

  • ${{secret:tls.private_key.password}}
  • {secret:tls.private_key.password}

Or even a sigil (I do not like this idea personally):

  • $secret:tls.private_key.password

With an example app.conf like this

connection.username = cuttlefish
connection.password = ${{secret:connection.password}}

A generated value may look like this:

[
  {my_app, [
    {tls, [
      {private_key, [
        {password, {secret, <<"connection.password">>}}
      ]}
    ]}
  ]}
].

How exactly the {secret, Value} tuple is interpreted by the application should not matter to Cuttlefish, its job would be to generate a special value that can be distinguished by its structure.
The actual secret value then can be retrieved from a suitable secret store.

"Value tags" can be arbitrary strings that will be propagated to the tuple:

connection.username = cuttlefish
connection.password = ${{secret_store_key:connection.password}}

A generated value then will look like this:

[
  {my_app, [
    {tls, [
      {private_key, [
        {password, {secret_store_key, <<"connection.password">>}}
      ]}
    ]}
  ]}
].

Alternatives Considered

It's technically possible to do exactly this already with the help of a relatively simple translation. But for the sake of code/knowledge reuse and establishing a common convention, I'd like to propose this syntactic extension.

@michaelklishin michaelklishin changed the title Proposal: Support for Secrets Proposal: Support for Secrets via Tagged Values Apr 25, 2024
@lukebakken lukebakken self-assigned this Apr 25, 2024
@codeadict
Copy link
Contributor

I love this idea

@lukebakken
Copy link
Collaborator

lukebakken commented Apr 26, 2024

Just an idea...

connection.password.term = {password, {secret, <<"connection.password">>}}

Adding .term (or something like that) means that the value is a literal Erlang one-line term.

[
  {my_app, [
    {tls, [
      {private_key, [
        {password, {secret, <<"connection.password">>}}
      ]}
    ]}
  ]}
]

The reason I suggest this is that there's no way we can guess the right "shape" of the resulting Erlang term for every use-case.

@michaelklishin
Copy link
Collaborator Author

@lukebakken that can work, too. I think for secrets a 2- or 3-tuple would generally do, since you need to specify a "tag" and a value. But if the value would itself have to be a tuple then your proposal (or another way of evaluating an arbitrary term) would work and mine wouldn't.

@michaelklishin michaelklishin changed the title Proposal: Support for Secrets via Tagged Values Proposal: Support for Secrets via Tagged or Term Values Apr 26, 2024
@tburghart
Copy link

Maybe I'm missing something?

In these examples, if I'm understanding them, <<"connection.password">> is a key into some secret store that my_app knows how to retrieve from, right?

Given that my_app is the only actor that has to know how to dereference the key to obtain its secret value, why does cuttlefish need to know anything about it? Isn't it just a simple mapping in the cf schema?

Or are you proposing some means by which cf calls out to an external process to do the lookup and stores the actual secret in advanced.config (an enormous security red flag)?

@michaelklishin
Copy link
Collaborator Author

The problem is not generally different from GitHub Secrets. You cannot put some values into your publicly available YAML, so you put in a key name and that key is looked up by Actions runners.

Sometimes a sensitive value must be provided in a Cuttlefish configuration file. Cuttlefish
can tag such values to make it easier for the apps to understand that "this is not just a string, it's a key name".

@michaelklishin
Copy link
Collaborator Author

Isn't it just a simple mapping in the cf schema?

That everyone needs to do over and over and over and over again, in every app, in every RabbitMQ plugin, consistently.

Team RabbitMQ needs Cuttlefish to provide such as "type" that will be used across a double digit number of schemas.

@michaelklishin
Copy link
Collaborator Author

michaelklishin commented Aug 3, 2024

#46 provides a solution that does not require modifying the parser,
and therefore is much simpler than what I originally had in mind.

@michaelklishin michaelklishin added this to the 3.3.0 milestone Aug 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants