gcp-kms-decrypt-via-execute-as

A principal that can execute as a workload SA holding useToDecrypt can decrypt.

derived gcp emits CanDecrypt

match

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

{'principal': None} CanExecuteAs {'sa': None}

where

?sa has EFFECTIVE cloudkms.cryptoKeyVersions.useToDecrypt on ?key (per-key or inherited) ?key is a CryptoKey (EncryptionKey subtype) with a decrypt purpose (ENCRYPT_DECRYPT / RAW_ENCRYPT_DECRYPT / ASYMMETRIC_DECRYPT) — matching gcp-kms-can-decrypt; Storage is the downstream CanReadData target, NEVER the CanDecrypt target

emit

target typeEncryptionKey
source<principal>
target<CryptoKey ?sa can use (EncryptionKey subtype)>
permissionscloudkms.cryptoKeyVersions.useToDecrypt
conditionsiam_permission resource_policy key_permission service_state
state logicInherits state from the CanExecuteAs input; then ACTIVE if ?sa holds useToDecrypt and >=1 version ENABLED; CONDITIONAL(service_state) if disabled; BLOCKED if denied by VPC-SC/IAM deny.

Narrative

{principal.name}, able to execute as {sa.name}, can decrypt with {key.name} because {sa.name} holds cloudkms.cryptoKeyVersions.useToDecrypt on it.

Raw rule rules/derived/gcp/kms.yaml

id: gcp-kms-decrypt-via-execute-as
emits: CanDecrypt
description: A principal that can execute as a workload SA holding useToDecrypt can decrypt.
match:
- - principal: null
  - CanExecuteAs
  - sa: null
where:
- ?sa has EFFECTIVE cloudkms.cryptoKeyVersions.useToDecrypt on ?key (per-key or inherited)
- "?key is a CryptoKey (EncryptionKey subtype) with a decrypt purpose (ENCRYPT_DECRYPT / RAW_ENCRYPT_DECRYPT\
  \ / ASYMMETRIC_DECRYPT) \u2014 matching gcp-kms-can-decrypt; Storage is the downstream CanReadData target,\
  \ NEVER the CanDecrypt target"
emit:
  target_type: EncryptionKey
  source: <principal>
  target: <CryptoKey ?sa can use (EncryptionKey subtype)>
  permissions:
  - cloudkms.cryptoKeyVersions.useToDecrypt
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  - service_state
  state_logic: Inherits state from the CanExecuteAs input; then ACTIVE if ?sa holds useToDecrypt and >=1
    version ENABLED; CONDITIONAL(service_state) if disabled; BLOCKED if denied by VPC-SC/IAM deny.
  confidence: min(contributing_confidences) * 0.95
  derived_from:
  - <CanExecuteAs edge_id>
  - <?sa useToDecrypt grant>
  false_positive_note: 'Requires the WORKLOAD SA (not the principal directly) to hold useToDecrypt on
    the specific key. This is the canonical CanExecuteAs -> CanDecrypt completion: once code runs as ?sa
    (metadata token), it can decrypt. Do not emit if ?sa''s grant is scoped to a different key.'
  narrative: '{principal.name}, able to execute as {sa.name}, can decrypt with {key.name} because {sa.name}
    holds cloudkms.cryptoKeyVersions.useToDecrypt on it.'
move · open · esc close