The API reference shows the action on each endpoint’s own page, so you do not
have to come back here to look one up. Both come from the same place: the
authorization call in the service, read at build time.
The actions
Operations on a specific secret are authorized against that secret’s CRN, with the secret’s tags available as condition context. Only the two collection-level operations are not.Describing a secret does not read it
secrets:GetSecretValue is a different action from secrets:DescribeSecret,
and the split runs all the way through the API: the describe response has no
value field at all, so there is no shape in which metadata and plaintext travel
together. Grant the read action on its own, to the few principals that need it,
on the few secrets they need.
The same split appears on KMS with kms:Decrypt and on
certificates with
certificate:GetCertificateMaterial.
Writing does not imply reading
secrets:PutSecretValue adds a version without returning anything of the old
one, so a rotation job can hold it alone. That is worth doing: a component that
only ever writes new material has no reason to be able to read what is already
there.
Listing cannot be narrowed
secrets:ListSecrets is authorized against the collection rather than against
individual secrets, so restricting it by CRN or tag has no effect. Scope
secrets:GetSecretValue — that is the grant that matters.
Resources
Secrets actions are checked against one resource shape:/, and that is what makes the CRN worth scoping
by. Naming secrets prod/payments/stripe-key rather than
prod-payments-stripe-key lets one statement cover a whole service’s secrets
and nothing else. Names match ^[a-zA-Z0-9][a-zA-Z0-9._/-]{0,255}$.
Conditions
Create carries the tags from the request; every secret-scoped action carries the tags already on the secret:basalt:RequestTag/<key>— what a caller may label a secret as, at create.basalt:ResourceTag/<key>— which existing secrets an action may touch.
Writing a policy
One service reading exactly the secrets under its own path prefix:deny guardrail survives a broad allow.
What a denial looks like
A failed check answers403:
A
404 is not a disguised 403. Ownership is resolved before authorization:
a secret belonging to another account answers 404 because it is not yours
to see, and one you own but lack the action for answers 403. A secret
inside its recovery window is a third case again — it
answers 409 SECRET_DELETED, which means the secret is there and the
credential is fine.