gcp-kms-can-decapsulate

cloudkms.cryptoKeyVersions.useToDecapsulate lets a principal decapsulate a shared secret with a KEM key.

derived gcp emits CanDecrypt

match (effective permission)

{ "action": "cloudkms.cryptoKeyVersions.useToDecapsulate", "resource_type": "google.cloud.kms.CryptoKey" }

where

CryptoKey.purpose is a KEM (key-encapsulation) purpose — the Decapsulate API recovers the shared secret from a ciphertext encapsulation (RAW/PQC KEM) the effective action is cloudkms.cryptoKeyVersions.useToDecapsulate specifically — useToDecrypt does NOT apply to a KEM key and is NOT accepted here at least one CryptoKeyVersion is ENABLED

emit

target typeEncryptionKey
source<principal>
target<CryptoKey (EncryptionKey subtype, KEM)>
permissionscloudkms.cryptoKeyVersions.useToDecapsulate
conditionsiam_permission resource_policy key_permission service_state
state logicACTIVE if useToDecapsulate resolves on a KEM key AND >=1 version ENABLED; CONDITIONAL(service_state) if all versions DISABLED (re-enableable by a cryptoKeyVersions.update holder); BLOCKED if all versions DESTROYED, or a VPC-SC perimeter / IAM deny policy denies cloudkms.cryptoKeyVersions.useToDecapsulate at the effective scope (denied_by=<perimeter/deny>).

Narrative

{principal.name} can decapsulate the shared secret of KEM key {key.name} (cloudkms.cryptoKeyVersions.useToDecapsulate) - recovering the wrapped secret.

Raw rule rules/derived/gcp/kms.yaml

id: gcp-kms-can-decapsulate
emits: CanDecrypt
description: cloudkms.cryptoKeyVersions.useToDecapsulate lets a principal decapsulate a shared secret
  with a KEM key.
match_effective_permission:
  action: cloudkms.cryptoKeyVersions.useToDecapsulate
  resource_type: google.cloud.kms.CryptoKey
where:
- "CryptoKey.purpose is a KEM (key-encapsulation) purpose \u2014 the Decapsulate API recovers the shared\
  \ secret from a ciphertext encapsulation (RAW/PQC KEM)"
- "the effective action is cloudkms.cryptoKeyVersions.useToDecapsulate specifically \u2014 useToDecrypt\
  \ does NOT apply to a KEM key and is NOT accepted here"
- at least one CryptoKeyVersion is ENABLED
emit:
  target_type: EncryptionKey
  source: <principal>
  target: <CryptoKey (EncryptionKey subtype, KEM)>
  permissions:
  - cloudkms.cryptoKeyVersions.useToDecapsulate
  conditions:
  - iam_permission
  - resource_policy
  - key_permission
  - service_state
  state_logic: ACTIVE if useToDecapsulate resolves on a KEM key AND >=1 version ENABLED; CONDITIONAL(service_state)
    if all versions DISABLED (re-enableable by a cryptoKeyVersions.update holder); BLOCKED if all versions
    DESTROYED, or a VPC-SC perimeter / IAM deny policy denies cloudkms.cryptoKeyVersions.useToDecapsulate
    at the effective scope (denied_by=<perimeter/deny>).
  confidence: min(contributing_confidences) * 0.97
  derived_from:
  - <effective cloudkms.cryptoKeyVersions.useToDecapsulate grant>
  false_positive_note: "useToDecapsulate is a DISTINCT permission from useToDecrypt and applies ONLY to\
    \ KEM-purpose keys. A useToDecrypt grant does NOT confer decapsulation and a useToDecapsulate grant\
    \ does NOT confer decrypt \u2014 do not cross-map them. Emit only when the effective action is useToDecapsulate\
    \ on a KEM key with >=1 ENABLED version. Recovering a KEM shared secret is a decrypt-equivalent capability\
    \ (models as CanDecrypt) but keep the permission name exact."
  narrative: "{principal.name} can decapsulate the shared secret of KEM key {key.name} (cloudkms.cryptoKeyVersions.useToDecapsulate)\
    \ \u2014 recovering the wrapped secret."
move · open · esc close