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.

derived gcp emits CanReadData

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanDecrypt {'key': None} {'principal': None} CanReadData {'store': None}

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>
permissionscloudkms.cryptoKeyVersions.useToDecrypt
conditionsiam_permission resource_policy key_permission network_reachability
state logicREFINES 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).'
move · open · esc close