CoursesAdvanced cloud securityIdentity & access at scale

Policy evaluation, boundaries & escalation paths

Deny/allow order, permission boundaries, and access analyzers.

Expert35 min · lesson 3 of 15

Cloud authorization is not "does a policy allow this?" — it is the result of several policy types evaluated together, with denials and ceilings that override grants. To reason about who can really do what, you have to know the evaluation order, and then hunt for the permission combinations that let a low-privilege identity quietly promote itself.

The evaluation order, precisely

For an AWS request the logic is: start denied by default; an explicit Deny anywhere (identity policy, resource policy, SCP, boundary) wins immediately and ends the decision; otherwise the action is allowed only if it is permitted by the identity or resource policy AND permitted by any permission boundary AND permitted by every SCP in the account path. Grants are additive but every ceiling must agree. GCP and Azure differ in mechanism but share the principle: an explicit deny and an org-level ceiling both trump a local allow.

a permission boundary caps delegated power
# A boundary policy: no matter what a delegated admin attaches to a role,
# that role can never exceed these actions. Grants beyond it are silently void.
{
"Version": "2012-10-17",
"Statement": [
{ "Effect": "Allow",
"Action": ["s3:*","dynamodb:*","logs:*","cloudwatch:*"],
"Resource": "*" },
{ "Effect": "Deny",
"Action": ["iam:*","organizations:*","account:*"],
"Resource": "*" }
]
}
# A team lead can now create roles freely for app work, but cannot mint an
# admin role — the boundary denies iam:* even if their grant allows it.

Hunting escalation paths

Least privilege fails quietly when a set of individually-reasonable permissions compose into "become admin". The classic is iam:PassRole combined with a compute service: if an identity may pass a powerful role to a new Lambda or EC2 instance and invoke it, it has inherited that role. Others include iam:CreatePolicyVersion (rewrite a policy you are attached to), iam:AttachUserPolicy, or updating a trust policy to add yourself. Access Analyzer and the policy simulator exist to surface exactly these reachable paths before an attacker walks them.

What decides an authorization
must all permit
identity / resource policy
the actual grant
permission boundary
ceiling on the identity
SCP / org policy
ceiling on the whole account
overrides everything
explicit Deny
any source — ends the decision
escalation to hunt
iam:PassRole + run compute
inherit a stronger role
edit attached policy / trust
rewrite your own limits
Grants are additive; ceilings are conjunctive; denies are absolute. Escalation lives in the actions that let you change the grants themselves.
iam:PassRole is the one to watch
PassRole rarely looks dangerous in a review because it does nothing on its own. Paired with lambda:CreateFunction, ec2:RunInstances, or a similar "run something as this role" action, it is a full privilege-escalation primitive. Constrain every PassRole to specific role ARNs with a Condition, never Resource: "*", and audit who holds it.