aws-secretsmanager-cmk-gated-read

Gates the existing explicit CanReadSecret edge on kms:Decrypt (CONDITIONAL(key_permission)) when the secret is CMK-encrypted.

derived aws emits

match

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

{'principal': None} CanReadSecret {'secret': None}

where

node_class(?secret) == Secret ?principal has EFFECTIVE secretsmanager:GetSecretValue on ?secret ?secret.KmsKeyId is a customer-managed CMK (NOT alias/aws/secretsmanager)

emit

Raw rule rules/derived/aws/secretsmanager.yaml

id: aws-secretsmanager-cmk-gated-read
kind: state_annotation
annotates: CanReadSecret
description: Gates the existing explicit CanReadSecret edge on kms:Decrypt (CONDITIONAL(key_permission))
  when the secret is CMK-encrypted.
match:
- - principal: null
  - CanReadSecret
  - secret: null
where:
- node_class(?secret) == Secret
- ?principal has EFFECTIVE secretsmanager:GetSecretValue on ?secret
- ?secret.KmsKeyId is a customer-managed CMK (NOT alias/aws/secretsmanager)
annotation:
  target_edge:
  - principal: null
  - CanReadSecret
  - secret: null
  set_state: CONDITIONAL
  set_conditions:
  - iam_permission
  - resource_policy
  - key_permission
  state_logic: "Set CONDITIONAL(key_permission) \u2014 the caller holds GetSecretValue but decrypt on\
    \ the wrapping CMK is unproven. The generic decrypt-gates-secret-read rule upgrades this edge to ACTIVE\
    \ iff the caller also holds CanDecrypt on the exact CMK that wraps this secret. BLOCKED if a key-policy/SCP\
    \ Deny hits kms:Decrypt or a resource-policy Deny hits GetSecretValue."
  derived_from:
  - <explicit CanReadSecret(GetSecretValue) edge_id>
  - <wraps(?cmk,?secret) link>
  false_positive_note: Secrets Manager calls kms:Decrypt on the caller's behalf against the secret's CMK;
    GetSecretValue alone WITHOUT decrypt on that CMK yields AccessDeniedException. Do NOT leave the explicit
    edge ACTIVE from GetSecretValue alone on a CMK secret. The decrypt must be on the EXACT CMK that wraps
    THIS secret (DescribeSecret.KmsKeyId), honoring kms:ViaService/EncryptionContext conditions. This
    rule SETS the gate; the generic decrypt-gates-secret-read rule performs the upgrade. Produces no edge.
  narrative: "{principal.name} can call secretsmanager:GetSecretValue on {secret.name}, but the value\
    \ is CMK-encrypted \u2014 reading the plaintext also requires kms:Decrypt on the wrapping CMK; without\
    \ it this stays CONDITIONAL(key_permission)."
move · open · esc close