gcp-certmanager-sign-cmek-gate

Issue from a KMS-backed CA; the signature is performed by the CAS service agent, not the caller.

derived gcp emits CanSignAs

match (effective permission)

{ "action": "privateca.certificates.create", "resource_type": "google.privateca.CaPool" }

where

principal ALSO has EFFECTIVE privateca.caPools.use on the SAME pool the target CA is KMS-backed (Enterprise tier over a customer Cloud KMS/HSM key)

emit

source typeIdentity
source<principal>
target<CA pool node (SigningKey)>
permissionsprivateca.certificates.create privateca.caPools.use
conditionsiam_permission key_permission
state logicACTIVE if the CAS service agent (service-PROJECT_NUMBER@gcp-sa-privateca.iam.gserviceaccount.com) holds cloudkms.cryptoKeyVersions.useToSign on the CA signing key AND the key/version and CA are ENABLED; CONDITIONAL(key_permission) if the service-agent grant or key/CA state is unknown; BLOCKED if the service agent lacks the grant OR the key is DISABLED/DESTROYED OR the CA is DISABLED OR a KMS deny applies.

Narrative

{principal.name} can issue certificates from KMS-backed CA pool {capool.name} (privateca.certificates.create + caPools.use); the CAS service agent (not the caller) signs via cloudkms.cryptoKeyVersions.useToSign on the CA key - issuance holds while the agent retains that grant and the key/CA is enabled.

Raw rule rules/derived/gcp/certmanager.yaml

id: gcp-certmanager-sign-cmek-gate
emits: CanSignAs
description: Issue from a KMS-backed CA; the signature is performed by the CAS service agent, not the
  caller.
match_effective_permission:
  action: privateca.certificates.create
  resource_type: google.privateca.CaPool
where:
- principal ALSO has EFFECTIVE privateca.caPools.use on the SAME pool
- the target CA is KMS-backed (Enterprise tier over a customer Cloud KMS/HSM key)
emit:
  source_type: Identity
  source: <principal>
  target: <CA pool node (SigningKey)>
  permissions:
  - privateca.certificates.create
  - privateca.caPools.use
  conditions:
  - iam_permission
  - key_permission
  state_logic: ACTIVE if the CAS service agent (service-PROJECT_NUMBER@gcp-sa-privateca.iam.gserviceaccount.com)
    holds cloudkms.cryptoKeyVersions.useToSign on the CA signing key AND the key/version and CA are ENABLED;
    CONDITIONAL(key_permission) if the service-agent grant or key/CA state is unknown; BLOCKED if the
    service agent lacks the grant OR the key is DISABLED/DESTROYED OR the CA is DISABLED OR a KMS deny
    applies.
  confidence: min(contributing_confidences) * 0.93
  derived_from:
  - <effective privateca.certificates.create grant>
  - <effective privateca.caPools.use grant>
  - <service-agent KMS useToSign binding>
  false_positive_note: "GCP-SPECIFIC: the key_permission gate is on the CAS SERVICE AGENT, NOT the caller.\
    \ Do NOT require the caller to hold cloudkms.* \u2014 a caller with certificates.create + caPools.use\
    \ issues successfully while the service agent keeps useToSign. Requiring caller KMS access (AWS ACM\
    \ PCA style) yields false negatives. Downgrade to CONDITIONAL/BLOCKED only on the SERVICE AGENT's\
    \ grant and the key/CA enabled state."
  narrative: "{principal.name} can issue certificates from KMS-backed CA pool {capool.name} (privateca.certificates.create\
    \ + caPools.use); the CAS service agent (not the caller) signs via cloudkms.cryptoKeyVersions.useToSign\
    \ on the CA key \u2014 issuance holds while the agent retains that grant and the key/CA is enabled."
move · open · esc close