The Juju 3.0 release delivered the first tranche of secrets functionality, primarily aimed at allowing charm developers to add secrets to their charms. In this release, the sensitive content of the secrets was stored in the Juju backend database along with the rest of the model artefacts.
In Juju 3.1 (starting with beta1), Juju admins gain the ability to use 2 new secret backends:
- Hashicorp Vault
Here we’ll give a brief introduction to the new feature.
For machine (vm) models, the default backend will continue to be the Juju model database. For container (k8s) models, secrets will default to being stored in the model’s k8s namespace. Using a Vault backend is opt-in for any model type.
Secret backends are configured per model.
Configuring a Vault backend
The minimum information needed to configure a Vault backend is the API address and access token. These can be added to a YAML file and passed to a model.
cat > vault_config.yaml <<EOF endpoint: http://10.0.0.1:8200 token: s.eujhj EOF juju add-secret-backend mysecrets vault \ --config=/path/to/vault_config.yaml \ token-rotate=7d
Note: the initial Juju 3.1 release will very likely not initially support token rotation
All possible Vault configuration attributes are (see Vault documentation for more detail):
We’ve seen above that the
add-secret-backend command is used to add a new backend to the controller for subsequent use by hosted models. The complete set of relevant commands is:
add-secret-backend - Add a new secret backend to the controller. update-secret-backend - Update an existing secret backend on the controller. remove-secret-backend - Removes a secret backend from the controller. secret-backends - Displays the secret backends available for storing secret content. show-secret-backend - Displays the specified secret backend.
juju help <commandname> for more detail on each command.
Configuring a Juju model
Each Juju Model can be configured to use a specific backend if the default is not suitable. The relevant model config attribute is
The out-of-the-box value for this attribute is
auto, meaning that:
- for machine models, the
internalbackend is used (Juju model database)
- for k8s models, the
localbackend is used (k8s model namespace)
The valid values for
To configure a model to use a Vault backend, simply set the
secret-backend config to the backend name that was added to the controller.
juju model-config secret-backend myvault
When adding a new model, if a different backend to the configured controller wide default is required:
juju add-model foo --config secret-backend=myothervault
Listing backends will show the backends configured on the controller and some relevant detail. For k8s models using the
auto backend, we use the
-local suffix with the model name to describe each backend. eg the output below includes “auto” (kubernetes) backends for two k8s models foo and bar.
juju secret-backends Backend Type Secrets Message internal controller 134 foo-local kubernetes 30 bar-local kubernetes 30 myvault vault 20 sealed
--reveal option can be use with YAML or JSON output to show sensitive backend config like API token.
To view just a single backend in YAML format, use the
show-model command is enhance to include info about that model’s secret backend(s).
juju show-model mymodel: name: admin/mymodel short-name: mymodel model-uuid: deadbeef-0bad-400d-8000-4b1d0d06f00d model-type: iaas controller-uuid: deadbeef-1bad-500d-9000-4b1d0d06f00d controller-name: kontroll owner: admin cloud: aws region: us-east-1 type: ec2 life: alive status: current: available users: admin: display-name: admin access: admin last-connection: just now machines: "0": cores: 0 "1": cores: 2 secret-backends: myothersecrets: status: active secrets: 6 mysecrets: status:draining secrets: 5
Changing a secret backend
You may notice that the
show-model output above has 2 backends shown. Once a secret backend has been configured for a model, we may want to change it to a different one. There’s 2 scenarios:
- backend is empty or contains only orphaned revisions
- backend contains revisions which are still being tracked
In either case, the user simply updates the model config.
juju model-config secret-backend=myothersecrets
After the switch, any new secret revisions are stored in the new backend. Existing revisions continue to be read from the old backend.
Migrating models with secrets
If a model has secrets stored in a secret backend like Vault, migrating that model to a new controller requires an extra step. The target controller must be set up to use the same (Vault) backend as is available on the source controller. This is done by running
add-secret-backend on the target controller and using the
import-id option to use the same internal backend ID as on the source controller.
On the source controller, inspect the backend(s) in use by the model to be migrated. The relevant backends can be discovered by running
juju show-model as described earlier. For any in-use backends, use the
show-secret-backend command (or just list them all with
--format yaml) to see the ID of the relevant backend(s). Before running the migration, add the backend(s) to the target controller, eg
juju switch sourcecontroller juju show-secret-backend myvault myvault: backend: vault config: endpoint: http://10.0.0.77:8200 secrets: 0 status: active id: 63c8ad37c906eb278540e942 juju switch targetcontroller juju add-secret-backend --config /path/to/backendcfg.yaml --import-id 63c8ad37c906eb278540e942
Now a migration can be run as normal and any secrets will be correctly migrated with the model.
Coming to Juju 3.2
If the old backend has secrets that are still being tracked, Juju will start a background worker to migrate current/in-use revisions to the new backend.