Secret push destinations
A secret push destination is a secrets manager this service writes a service account’s password to. When a service account’s password is rotated, the new password is pushed to its destination as a new version of a secret before the service starts accepting it. If the push fails, nothing changes: the old password stays the one in force.
Destinations are registered per realm on Directory → Secret destinations
(/admin/secret-destinations) or through /admin-api/secret-destinations.
A service account names its destination and the secret’s name on its own
page.
What a destination is
Each destination is an application entry in the realm, declared for the Secret push destination family. It holds:
| Member | Provider | What it is |
|---|---|---|
| provider | all | aws, gcp, azure, vault, or file (development mode only) |
| payload | all | password (the bare password) or json |
| region | aws | The AWS region the secrets are in |
| project | gcp | The project a short secret name is in |
| endpoint | azure, vault | The Key Vault URL, or the Vault / OpenBao address. https only |
| mount | vault | The KV version 2 mount; secret when empty |
| field | vault | With the password payload, the field written; value when empty |
| CA certificates | vault | PEM certificates of the CA the Vault listener chains to |
| directory | file | The absolute directory a secret name is a file in |
| write credential | all but file | See below. Write-only |
The json payload is:
{ "username": "svc-backup", "password": "…", "realm": "acme",
"rotatedAt": "2026-10-06T12:00:00.000Z" }
A consumer takes the password out of it by its field, as this service does
with its own secrets (keys.kekField and the like).
The write credential
Each destination has its own credential, separate from the read-only ones this service uses for its own key-encryption key and database password:
| Provider | Credential | What it needs to be allowed |
|---|---|---|
| aws | {"accessKeyId", "secretAccessKey"[, "sessionToken"]} |
secretsmanager:PutSecretValue on the named secrets |
| gcp | a service account key file’s JSON | secretmanager.versions.add on the named secrets |
| azure | {"tenantId", "clientId", "clientSecret"} |
list and set on secrets |
| vault | a token | read on <mount>/metadata/<name>, create and update on <mount>/data/<name> |
The credential is sealed under the key-encryption key, and is never shown
again once set: not on any page, not in any /admin-api answer, not in a
directory read, not in the audit log. reveal-secret refuses it. To change
it, set a new one; to keep it, leave the box empty.
A push never creates a secret
The secret must already exist at the destination. A push writes a new
version of it and nothing else, so the credential needs write on named secrets
only. A push to a secret that does not exist is refused (STS-SECDEST-0003).
- AWS Secrets Manager:
PutSecretValue. - Google Cloud Secret Manager:
AddSecretVersion. A short name is put under the destination’s project. - Azure Key Vault: the secret’s versions are listed first, because
setSecretwould create a missing secret; thensetSecret. - Vault or OpenBao (KV version 2): the secret’s metadata is read for its
current version, and the write names that version (check-and-set). If
somebody wrote a newer version in between, the push is refused
(
STS-SECDEST-0004) and nothing is overwritten. - A file, in development mode only: the password is written into an
existing file under the destination’s directory. A name that leaves the
directory, or a link, is refused. Product mode refuses a file destination
(
STS-SECDEST-0006): a password on this container’s disk is not in a secrets manager.
Test push
Test push writes a canary — a random password nobody uses — to a secret
you name. Use a secret kept for testing: it proves the credential, the
address and the secret exist before a rotation depends on them. A secret a
service account’s rotation writes is refused (STS-SECDEST-0010).
Network
Every address is the one an administrator configured on the destination; no
request can name one. An Azure or Vault address must be https, and the
certificate is always verified — for Vault, against the destination’s own CA
certificates as well as the public roots.
Errors
Every refusal has a code in the STS-SECDEST- range; see
Error codes.