aws-ct-execution-role-enter-account
A management-account principal that can assume AWSControlTowerExecution enters every enrolled member account as administrator.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?ct_exec_role) ==
Role and ?ct_exec_role.name == 'AWSControlTowerExecution'
account_of(?ct_exec_role) != account_of(?principal) # cross-account: member != mgmt
account_of(?principal) == <organization management account> # SCPs do not apply here; the role only trusts the mgmt account
?principal holds EFFECTIVE sts:AssumeRole on the role ARN (identity policy — trust alone is insufficient)
emit
| source type | Identity |
|---|---|
| target type | Account |
| source | ?principal |
| target | <account of ?ct_exec_role> |
| permissions | sts:AssumeRole |
| conditions | trust_relationship iam_permission |
| state logic | ACTIVE when ?principal is a management-account principal AND its identity policy grants sts:AssumeRole on arn:aws:iam::<member>:role/AWSControlTowerExecution (trust policy already admits the mgmt account). CONDITIONAL(iam_permission) when the caller's sts:AssumeRole scope is unresolved/only-wildcard; POTENTIAL when the caller is not confirmed to be a mgmt-account principal. This is the AWS cross-account CanAssume->CanEnterAccount case already generalized by can-control.yaml enter-account-via-assume — this rule specializes it to the CT role and drives the fan-out to EVERY enrolled account (one edge per member carrying AWSControlTowerExecution). |
Narrative
{principal.name} (management account) can assume AWSControlTowerExecution in account {account.name}, obtaining AdministratorAccess there - a foothold in every Control-Tower-enrolled account.
Raw rule rules/derived/aws/controltower.yaml
id: aws-ct-execution-role-enter-account
emits: CanEnterAccount
description: A management-account principal that can assume AWSControlTowerExecution enters every enrolled
member account as administrator.
match:
- - principal: null
- CanAssume
- ct_exec_role: null
where:
- node_type(?ct_exec_role) == Role and ?ct_exec_role.name == 'AWSControlTowerExecution'
- 'account_of(?ct_exec_role) != account_of(?principal) # cross-account: member != mgmt'
- 'account_of(?principal) == <organization management account> # SCPs do not apply here; the role only
trusts the mgmt account'
- "?principal holds EFFECTIVE sts:AssumeRole on the role ARN (identity policy \u2014 trust alone is insufficient)"
emit:
source_type: Identity
target_type: Account
source: ?principal
target: <account of ?ct_exec_role>
permissions:
- sts:AssumeRole
conditions:
- trust_relationship
- iam_permission
state_logic: "ACTIVE when ?principal is a management-account principal AND its identity policy grants\
\ sts:AssumeRole on arn:aws:iam::<member>:role/AWSControlTowerExecution (trust policy already admits\
\ the mgmt account). CONDITIONAL(iam_permission) when the caller's sts:AssumeRole scope is unresolved/only-wildcard;\
\ POTENTIAL when the caller is not confirmed to be a mgmt-account principal. This is the AWS cross-account\
\ CanAssume->CanEnterAccount case already generalized by can-control.yaml enter-account-via-assume\
\ \u2014 this rule specializes it to the CT role and drives the fan-out to EVERY enrolled account\
\ (one edge per member carrying AWSControlTowerExecution)."
confidence: min(contributing_confidences) * 0.95
derived_from:
- <CanAssume edge_id (principal -> AWSControlTowerExecution)>
false_positive_note: "The role's trust policy admits the mgmt account, but assuming it STILL requires\
\ the caller's own identity policy to grant sts:AssumeRole on the role ARN \u2014 do not emit ACTIVE\
\ from the trust edge alone. Only management-account principals qualify (SCPs cannot restrict them,\
\ and members are not trusted). Emit one CanEnterAccount per enrolled account that has the role; skip\
\ accounts where the role was removed/renamed. Cite can-control.yaml enter-account-via-assume \u2014\
\ do not duplicate the generic assume->enter roll-up."
narrative: "{principal.name} (management account) can assume AWSControlTowerExecution in account {account.name},\
\ obtaining AdministratorAccess there \u2014 a foothold in every Control-Tower-enrolled account."