gcp-kms-decrypt-gates-cmek-read
useToDecrypt on a CMEK key resolves the key_permission condition on a CanReadData edge the consuming-service rule already emitted.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
the ?store
CanReadData edge already exists (consuming-service rule confirmed the control-plane read perm — storage.objects.get / bigquery.tables.getData / compute.disks.get — AND network reach)
?store is CMEK-encrypted with ?key (defaultKmsKeyName / kmsKeyName on the bucket/dataset/disk references ?key)
emit
| source | <principal> |
|---|---|
| target | <CMEK-encrypted store (Storage/Data) — the SAME store as the matched CanReadData edge> |
| permissions | cloudkms.cryptoKeyVersions.useToDecrypt |
| conditions | iam_permission resource_policy key_permission network_reachability |
| state logic | REFINES the matched CanReadData edge by resolving its key_permission condition. ACTIVE only if the matched CanReadData edge is itself ACTIVE (its data-plane read permission and network reach already satisfied by the consuming rule) AND useToDecrypt resolves with >=1 key version ENABLED; otherwise the matched edge stays gated on its own unmet conditions. BLOCKED if useToDecrypt is denied by VPC-SC / IAM deny (the CMEK read cannot decrypt). |
Narrative
{principal.name} can decrypt with {key.name}, resolving the CMEK key_permission condition on its existing read access to {store.name} (the store-read permission and reach were already confirmed).
Raw rule rules/derived/gcp/kms.yaml
id: gcp-kms-decrypt-gates-cmek-read
emits: CanReadData
description: useToDecrypt on a CMEK key resolves the key_permission condition on a CanReadData edge the
consuming-service rule already emitted.
match:
- - principal: null
- CanDecrypt
- key: null
- - principal: null
- CanReadData
- store: null
where:
- "the ?store CanReadData edge already exists (consuming-service rule confirmed the control-plane read\
\ perm \u2014 storage.objects.get / bigquery.tables.getData / compute.disks.get \u2014 AND network reach)"
- ?store is CMEK-encrypted with ?key (defaultKmsKeyName / kmsKeyName on the bucket/dataset/disk references
?key)
emit:
source: <principal>
target: "<CMEK-encrypted store (Storage/Data) \u2014 the SAME store as the matched CanReadData edge>"
permissions:
- cloudkms.cryptoKeyVersions.useToDecrypt
conditions:
- iam_permission
- resource_policy
- key_permission
- network_reachability
state_logic: REFINES the matched CanReadData edge by resolving its key_permission condition. ACTIVE
only if the matched CanReadData edge is itself ACTIVE (its data-plane read permission and network
reach already satisfied by the consuming rule) AND useToDecrypt resolves with >=1 key version ENABLED;
otherwise the matched edge stays gated on its own unmet conditions. BLOCKED if useToDecrypt is denied
by VPC-SC / IAM deny (the CMEK read cannot decrypt).
confidence: min(contributing_confidences) * 0.9
derived_from:
- <CanDecrypt edge_id>
- <existing CanReadData edge_id>
- <store CMEK reference to ?key>
false_positive_note: 'This rule NEVER manufactures a read path. CanReadData''s data-plane grant (storage.objects.get
/ bigquery.tables.getData / compute.disks.get) and network reachability are OWNED and verified by
the consuming service (GCS/BQ/PD) rule, which must have already emitted the [?principal, CanReadData,
?store] edge this rule matches on. KMS only supplies the decrypt fact that RESOLVES the key_permission
condition on that pre-existing edge. Do NOT emit a fresh CanReadData from a bare CanDecrypt: decrypting
a key without a confirmed store-read grant is not a data-read path.'
narrative: '{principal.name} can decrypt with {key.name}, resolving the CMEK key_permission condition
on its existing read access to {store.name} (the store-read permission and reach were already confirmed).'