gcp-kms-setiam-self-grant
cryptoKeys/keyRings.setIamPolicy lets a key manager bind itself a crypto role.
match (effective permission)
{
"any_of": [
{
"action": "cloudkms.cryptoKeys.setIamPolicy",
"resource_type": "google.cloud.kms.CryptoKey"
},
{
"action": "cloudkms.keyRings.setIamPolicy",
"resource_type": "google.cloud.kms.KeyRing"
}
]
}
where
principal has effective cloudkms.cryptoKeys.setIamPolicy on the key OR cloudkms.keyRings.setIamPolicy on its ring (ring binding inherited by every key in the ring — wider blast radius)
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | <principal> |
| target | <principal (self)> |
| permissions | cloudkms.cryptoKeys.setIamPolicy cloudkms.keyRings.setIamPolicy |
| conditions | iam_permission |
| state logic | ACTIVE if setIamPolicy resolves on the key/ring; BLOCKED if an IAM deny / org policy denies it. Chains to CanDecrypt/CanSignAs via a self-bound roles/cloudkms.cryptoKeyEncrypterDecrypter / roles/cloudkms.signer. |
Narrative
{principal.name} can set the IAM policy of key {key.name} (cloudkms.cryptoKeys.setIamPolicy) and grant itself decrypt/sign - breaking KMS separation of duties.
Raw rule rules/derived/gcp/kms.yaml
id: gcp-kms-setiam-self-grant
emits: CanGrantPermission
description: cryptoKeys/keyRings.setIamPolicy lets a key manager bind itself a crypto role.
match_effective_permission:
any_of:
- action: cloudkms.cryptoKeys.setIamPolicy
resource_type: google.cloud.kms.CryptoKey
- action: cloudkms.keyRings.setIamPolicy
resource_type: google.cloud.kms.KeyRing
where:
- "principal has effective cloudkms.cryptoKeys.setIamPolicy on the key OR cloudkms.keyRings.setIamPolicy\
\ on its ring (ring binding inherited by every key in the ring \u2014 wider blast radius)"
emit:
source_type: Identity
target_type: Identity
source: <principal>
target: <principal (self)>
permissions:
- cloudkms.cryptoKeys.setIamPolicy
- cloudkms.keyRings.setIamPolicy
conditions:
- iam_permission
state_logic: ACTIVE if setIamPolicy resolves on the key/ring; BLOCKED if an IAM deny / org policy denies
it. Chains to CanDecrypt/CanSignAs via a self-bound roles/cloudkms.cryptoKeyEncrypterDecrypter / roles/cloudkms.signer.
confidence: min(contributing_confidences) * 0.95
derived_from:
- <effective cloudkms.cryptoKeys.setIamPolicy OR cloudkms.keyRings.setIamPolicy grant>
false_positive_note: 'This is the intended separation-of-duties break: roles/cloudkms.admin holds setIamPolicy
but NOT useTo*, so a key MANAGER is one IAM write from being a key USER. Escalation is realized only
after the self-binding is applied and the version is ENABLED (see gcp-kms-selfgrant-to-decrypt/-to-sign,
emitted POTENTIAL). keyRings.setIamPolicy affects every key in the ring.'
narrative: "{principal.name} can set the IAM policy of key {key.name} (cloudkms.cryptoKeys.setIamPolicy)\
\ and grant itself decrypt/sign \u2014 breaking KMS separation of duties."