aws-secretsmanager-cross-account-read
Gates the existing explicit cross-account CanReadSecret edge on the secret resource policy AND the CMK key policy.
derived
aws
emits
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_class(?secret) ==
Secret
?external.account != ?secret.account
?secret resource policy grants secretsmanager:GetSecretValue to ?external
?secret is CMK-encrypted (cross-account reads cannot use aws/secretsmanager)
optional
Present → upgrade the emitted state; absent → downgrade (not a hard requirement).
{'external': None}
CanDecrypt {'cmk': None}
emit
Raw rule rules/derived/aws/secretsmanager.yaml
id: aws-secretsmanager-cross-account-read
kind: state_annotation
annotates: CanReadSecret
description: Gates the existing explicit cross-account CanReadSecret edge on the secret resource policy
AND the CMK key policy.
match:
- - external: null
- CanReadSecret
- secret: null
where:
- node_class(?secret) == Secret
- ?external.account != ?secret.account
- ?secret resource policy grants secretsmanager:GetSecretValue to ?external
- ?secret is CMK-encrypted (cross-account reads cannot use aws/secretsmanager)
optional:
- - external: null
- CanDecrypt
- cmk: null
annotation:
target_edge:
- external: null
- CanReadSecret
- secret: null
set_state: CONDITIONAL
set_conditions:
- resource_policy
- key_permission
- iam_permission
state_logic: 'if the resource policy grants GetSecretValue to ?external AND matched(optional[0]) with
?cmk == wrapping CMK (CMK key policy grants kms:Decrypt to ?external): set ACTIVE; else CONDITIONAL(resource_policy,
key_permission). BLOCKED on any Deny in the resource policy, CMK key policy, or an SCP on either account.'
derived_from:
- <explicit CanReadSecret(GetSecretValue) edge_id>
- <CrossAccountTrust(resource policy) edge_id>
- <CanDecrypt(?cmk) edge_id?>
false_positive_note: Cross-account access requires BOTH the secret resource policy AND the CMK key policy
to allow the external principal AND the external principal's own identity policy to allow GetSecretValue
(three-way AND). The AWS-managed key CANNOT be shared cross-account, so a cross-account grant on a
managed-key secret does not actually work -> do not set ACTIVE. Honor SourceArn/ aws:PrincipalOrgID
conditions on the resource policy. Produces no edge.
narrative: '{external.name} (account {external.account}) is granted secretsmanager:GetSecretValue on
{secret.name} by its resource policy; with kms:Decrypt on the wrapping CMK it can read the cross-account
credential.'