Secret

See also: How to manage secrets

In Juju, (starting with Juju 3.0) a secret is a sensitive bit of information (e.g., account credential, password, certificate, SSH key, API key, encryption key, etc.) that a charm needs to know.

Contents:

Secret identifier

Secrets are identified by an automatically-assigned ID (a URI generated by Juju at creation time) or (for user secrets, also) a user-defined name.

Secret taxonomy

Charm

A charm secret is a secret created by a charm. A charm secret is shared with another charm (the secret ‘observer’) over relation data. The secret is tied to the lifecycle of the relation.

Unit

A unit secret is a charm secret created by a unit and owned by the unit.

Application

An application secret is a charm secret created by the leader unit and (because the leader unit does not have a fixed identity) owned by the application (i.e., when the leader unit changes, the secret is owned by the new leader).

User

A user secret is a secret created by a user with a model admin access level and (because this does not have a fixed identity) owned by the model . A user secret is shared with a charm (the secret ‘observer’) via a configuration option. The charm must support the configuration option.

Permissions around secrets

An entity – unit/app or user – that has created / owns the secret can manage it (call secret-set, secret-grant, secret-revoke, secret-info-get, etc.).

An entity that does not own the secret can only view it (call secret-get)-- and only if it has been granted access to it.

Secret lifecycle

This section currently covers only the lifecycle of a charm secret.

Charms can use relations to share secrets, such as API keys, a database’s address, credentials and so on. Like a relation has a “provider” and a “requirer”, so a secret has an “owner” and an “observer” – though these need not coincide with the applications’ roles in the relation.

Every secret has a scope, and that is the relation its lifecycle is tied to. If the relation is removed, the secret will be removed too.

When a unit adds a secret, it becomes that secret’s owner, and it will obtain from Juju a secret ID, which it can then pass to some remote application via relation data. Any remote unit with access to that ID can get the secret (that is, access its contents). Before that is possible, however, the owner needs to grant the secret to the whole application or a specific unit.

Once the remote unit (the secret observer) gets its contents for the first time, it starts to track that secret in Juju – more specifically, its latest revision, as we will see later. When the owner adds the secret, and when the observer gets it, they both have a chance to assign to the secret a label, a locally-unique string that will be associated with that secret and can be used by the charm to refer to the secret “by name”.

The owner can choose at any time to publish a new revision of the secret, that is, change its payload (for example, replace an old key with a new one). When that happens, the observer will be notified by means of a secret-changed event. The observer can then refresh the secret, which means inform Juju that it wishes to start tracking the latest revision. From that moment on, every time the unit gets the secret, it will receive the newly-tracked revision’s contents.

However, a unit does not have to immediately update whenever a new revision becomes available. It can peek the secret’s contents, which means to inspect the latest revision of the secret without updating to it, or choose to do nothing.

When a charm secret is added, the owner can configure it to have a rotation policy (hourly, daily, monthly, and so on). In that case, the owner will be periodically notified, by means of a secret-rotate event, that it is time to rotate the secret – that is, create a new revision for it.

Alternatively, a charm secret can be configured to have an expiration date, that is, a specific point in time at which the charm will be notified by Juju that it is time to retire the secret by means of a secret-expired event.

Juju maintains a list of which observers are tracking each revision of each secret. The idea is that if an observer receives a secret-changed event, it will update the secret and start tracking the latest revision. Once Juju notices that there are no observers left for a given revision, it will notify the secret owner that that secret revision can be safely removed – which corresponds to the secret-remove event.

When a unit gets a secret for the first time it will automatically be set to track the latest revision. A unit cannot choose to track an outdated revision, but it can in principle refuse to update to a newer one.

Contributors: @kelvin.liu , @wallyworld , @hmlanigan, @danieleprocida , @ppasotti, @tmihoc