Managing Secrets
Configuration guide for the MetaRouter secret store, an encrypted key-value store for
sensitive values like API credentials, access tokens, and cloud storage keys.
Managing secrets is done through the Control CLI only. There is no in-app UI for secrets at this time. See
CLI tools for installing and configuring the CLI.
How It Works
- Store a secret once, by ID, through the
controlCLI. - Reference it from a configuration with a
secret_ref(the secret's ID) plus
$$secret.KEY$$placeholders. Placeholders resolve to real values at runtime. The
plaintext secret is never stored in the configuration.
Roles and Permissions
Secret operations require a role that carries the matching permission. create:secret covers
create, clone, and dangerous update. read:secret covers get. delete:secret covers delete.
| Role | create:secret | read:secret | delete:secret |
|---|---|---|---|
| Deployment Manager | yes | yes | no |
| Integration Manager | yes | yes | no |
| Admin | yes | yes | no |
Deletes are not currently availableContact your MetaRouter dedicated support team if you need a secret deleted.
The Secret Object
- A secret is a flat map of string keys to string values, plus identifying metadata. The
id
is what configurations point at viasecret_ref. - Values are write-only by default. Storing a secret never echoes values back. Reading
them requires a separate, tightly scoped permission.
| Field | Required | Notes |
|---|---|---|
id | yes | Unique identifier. Used as the secret_ref from configurations. |
description | yes | Free-text purpose of the secret. |
values | yes | Map of secret key-value pairs. Must contain at least one entry. |
author | no | Set automatically by the CLI. Leave it out of your file. |
created_at | no | Stamped server-side on create. Read-only. |
CLI Configuration
Create
- Write the secret to a YAML or JSON file, then create it. The file is parsed strictly and
unknown fields are rejected. - Create is collision-safe. Creating a secret whose
idalready exists fails. This is a
guardrail against silently overwriting a live secret. Overwriting is always explicit.
control create secret -f <secret.yaml> # create a new secret from a file
control create secret --example # print the annotated example configid: replay-source
description: AWS creds for replay bucket
values:
AWS_ACCESS_KEY: value
AWS_SECRET_KEY: valueClone
- Create a new secret from an existing one, optionally dropping or overriding keys. Merge
order: start from the source's values, apply--remove-values, then apply the values in
-f(file values win on conflict). The result must contain at least one value. - An interactive run shows a masked diff and prompts before writing.
--clone-fromand--dangerously-update-secretcannot be combined.
control create secret -f <new-secret.yaml> --clone-from <source-id> # copy, then merge file values
control create secret -f <new-secret.yaml> --clone-from <source-id> --remove-values k1,k2 # copy, dropping keysGet and Delete
getreturns plaintext. There is no masking on this path. It requires the
read:secretpermission. Keep that permission tightly scoped.- Deletion is permanent and prompts for confirmation in an interactive terminal. Deleting a
non-existent ID succeeds without error (idempotent). - Deletion requires
delete:secret, which no role currently includes. See
Roles and Permissions.
control get secret <id> # returns values in plaintext, requires read:secret permission
control delete secret <id> # permanent, prompts for confirmationUpdate (dangerous)
- To intentionally overwrite an existing secret, pass
--dangerously-update-secret. An
interactive run prints a diff with all values masked as******(modified keys are flagged)
and prompts for confirmation before writing.
Prefer clone over in-place updateA dangerous update overwrites the live secret immediately. Secrets have no staged or
draft state, so anything referencing it throughsecret_ref, including configurations
actively serving traffic, resolves against the new values on its next resolution. The safer
path is to clone to a new ID, then point your configuration'ssecret_refat the
new secret.
control create secret -f <secret.yaml> --dangerously-update-secretReferencing Secrets in Configuration
- Credentials are never inline. A configuration sets
secret_refto the ID of the secret
to resolve against, and puts$$secret.KEY$$placeholders in its string fields, whereKEY
is a key in that secret'svaluesmap. - Placeholders work in any string field of a configuration that supports a
secret_ref,
including nested fields, map values, and endpoint URLs.
id: replay-test
sourceConfig:
source:
s3:
region: us-east-1
bucket: mr-test-replay-us-east-1
# here are the $$ variable references
credentials:
accessKey: $$secret.AWS_ACCESS_KEY$$
secretKey: $$secret.AWS_SECRET_KEY$$
# here is the secert id
secretRef: replay-source
globPattern: replay-test/**.json.gz
scopes:
writeKeys:
- retl_replay
events:
- identify
- page
- order_completedResolution Rules
Resolution is all-or-nothing per configuration:
| Configuration state | Result |
|---|---|
$$secret.KEY$$ references but empty secret_ref | Fails. secret_ref is required. |
A referenced KEY missing from the secret | Fails with secret key "KEY" not found in secret "<secret_ref>". |
When Resolution Happens
- On create or update, the configuration is validated:
secret_refmust point at an
existing secret, and that secret must contain every$$secret.KEY$$key the configuration
references. A gap is rejected with a fix hint. Resolved values are never persisted into the
stored configuration. - At runtime, placeholders resolve into the running configuration just before use. Runtime
views that return resolved configurations expose plaintext and are gated behind elevated
permissions.
FAQs
Can I list all secrets?
No. Secrets are fetched individually by ID with control get secret <id>, which requires the
read:secret permission.
How do I rotate a credential?
Prefer cloning to a new ID and re-pointing the configuration's secret_ref. Overwriting in
place with --dangerously-update-secret also works, but it changes what every referencing
configuration resolves to on its next resolution. Both paths show a masked diff before
writing.
What happens if a configuration references a key the secret doesn't have?
Validation fails on create or update with secret key "KEY" not found in secret "<secret_ref>". Resolution is all-or-nothing. A configuration never runs with a partially
resolved value.
Can one secret be shared by multiple configurations?
Yes. Any number of configurations can set the same secret_ref. Remember that an in-place
update changes what all of them resolve to on their next resolution.
Can I update just one key in a secret?
Yes, with clone. --clone-from starts from the source's values and merges your file's values
over them. A file containing only the changed key produces a full copy with that one key
replaced. To change it in place instead, pass the full desired state with
--dangerously-update-secret.
Updated 2 days ago