aws-kms-decrypt-unlocks-secret
Decrypt on a CMK completes the key_permission gate for a secret encrypted under it.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanDecrypt {'key': None}
{'secret': None} ContainsResourceReference {'key': None}
where
node_class(?secret) ==
Secret
structural link: the secret store entry references its encrypting CMK via ContainsResourceReference (the store->key 'encrypted-by' relation per providers/aws/kms.md §13); NOT LocatedIn, whose target set is [AdministrativeBoundary, Network] and cannot point at a key. NOTE: ContainsResourceReference source set is [Data, Storage, Compute] — a bare Secret-class source needs the schema owners to widen CRR's source to include Secret, or the consuming service emits the CRR from the Storage/Data store node that holds the secret; do not fall back to LocatedIn(secret->key), which is schema-invalid
?secret is encrypted with CMK ?key (Secrets Manager KmsKeyId / SSM SecureString KeyId)
?principal also holds the control-plane read action on ?secret (secretsmanager:GetSecretValue or ssm:GetParameter) — otherwise this only satisfies the KEY half of the gate
emit
| source | ?principal |
|---|---|
| target | ?secret |
| permissions | kms:Decrypt secretsmanager:GetSecretValue ssm:GetParameter |
| conditions | iam_permission resource_policy key_permission condition_expression |
| state logic | if ?principal has BOTH the secret-read action AND kms:Decrypt (this edge): ACTIVE; if only kms:Decrypt is confirmed: CONDITIONAL(iam_permission) — the secret-store read is still required; if the CanDecrypt input was CONDITIONAL(resource_policy/condition_expression): inherit that |
Narrative
{principal.name} can decrypt {key.name} (kms:Decrypt), satisfying the encryption-key gate on {secret.name}; with the store-read action it reads the secret value.
Raw rule rules/derived/aws/kms.yaml
id: aws-kms-decrypt-unlocks-secret
emits: CanReadSecret
description: Decrypt on a CMK completes the key_permission gate for a secret encrypted under it.
match:
- - principal: null
- CanDecrypt
- key: null
- - secret: null
- ContainsResourceReference
- key: null
where:
- node_class(?secret) == Secret
- "structural link: the secret store entry references its encrypting CMK via ContainsResourceReference\
\ (the store->key 'encrypted-by' relation per providers/aws/kms.md \xA713); NOT LocatedIn, whose target\
\ set is [AdministrativeBoundary, Network] and cannot point at a key. NOTE: ContainsResourceReference\
\ source set is [Data, Storage, Compute] \u2014 a bare Secret-class source needs the schema owners to\
\ widen CRR's source to include Secret, or the consuming service emits the CRR from the Storage/Data\
\ store node that holds the secret; do not fall back to LocatedIn(secret->key), which is schema-invalid"
- ?secret is encrypted with CMK ?key (Secrets Manager KmsKeyId / SSM SecureString KeyId)
- "?principal also holds the control-plane read action on ?secret (secretsmanager:GetSecretValue or ssm:GetParameter)\
\ \u2014 otherwise this only satisfies the KEY half of the gate"
emit:
source: ?principal
target: ?secret
permissions:
- kms:Decrypt
- secretsmanager:GetSecretValue
- ssm:GetParameter
conditions:
- iam_permission
- resource_policy
- key_permission
- condition_expression
state_logic: "if ?principal has BOTH the secret-read action AND kms:Decrypt (this edge): ACTIVE; if\
\ only kms:Decrypt is confirmed: CONDITIONAL(iam_permission) \u2014 the secret-store read is still\
\ required; if the CanDecrypt input was CONDITIONAL(resource_policy/condition_expression): inherit\
\ that"
confidence: min(contributing_confidences) * 0.95
derived_from:
- <CanDecrypt edge_id>
- <ContainsResourceReference secret->key edge_id>
false_positive_note: "This models the KEY half of the CanReadSecret gate. Reading a Secrets Manager/SSM\
\ SecureString value needs BOTH the store read action AND kms:Decrypt on the encrypting CMK. Do not\
\ emit ACTIVE from kms:Decrypt alone \u2014 the store-read action (secretsmanager:GetSecretValue /\
\ ssm:GetParameter with WithDecryption) is still required. If the CMK is the AWS-managed aws/secretsmanager\
\ or aws/ssm key, kms:Decrypt is implicitly granted to callers of the store action via kms:ViaService\
\ \u2014 do not double-count as a separate gate. Honor kms:EncryptionContext (Secrets Manager binds\
\ SecretARN)."
narrative: '{principal.name} can decrypt {key.name} (kms:Decrypt), satisfying the encryption-key gate
on {secret.name}; with the store-read action it reads the secret value.'