AWS Training
Modules Listen All tracks

← Design Secure Architectures

Starts this lesson and continues through 25 more to the end of certification prep.

Policy evaluation — the only thing you must actually know

Why this lesson comes first

Task statement 1.1 is "design secure access to AWS resources", and its skills list includes "Designing a flexible authorization model that includes IAM users, groups, roles, and policies" and "Designing a role-based access control strategy (for example, AWS Security Token Service [AWS STS], role switching, cross-account access)".

You cannot design an authorization model if you don't know how AWS combines policies. And the reason this is worth a whole lesson rather than a paragraph is that AWS combines different policy types with different operators. Some union. Some intersect. Miss which is which and you will confidently pick a wrong answer that looks correct.

The decision, in the order AWS makes it

AWS documents the request flow in three steps: authenticate the principal, process the request context to determine which policies apply, then evaluate. (Policy evaluation logic, verified 2026-09-21)

For the exam, compress it to three outcomes:

Outcome When Beats
Explicit deny Any applicable policy has "Effect": "Deny" matching the request Everything. Always.
Explicit allow Some applicable policy allows, and no policy denies, and every ceiling allows Default deny
Default deny Nothing allows it —

The important half of that table is the first row, and AWS repeats it in every pairwise combination it documents: "An explicit deny in either of these policies overrides the allow."

⚠️ There is no "allow wins" case anywhere in IAM. If you find yourself reasoning "but the identity policy grants admin, so…", stop. A Deny in an SCP, a resource policy, a permissions boundary or a session policy ends the request regardless of how broad the allow is. AWS makes the point bluntly about SCPs: a user "can't use that permission, even if the account administrator attaches the AdministratorAccess IAM policy with / permissions to the user." (SCPs)

Union or intersection? The table to memorise

This is the part that decides questions. Each row is quoted or paraphrased directly from the policy evaluation logic page (verified 2026-09-21).

Combination Operator AWS's words
Identity-based + resource-based (same account) Union "The resulting permissions are the union of the permissions of the two types. If an action is allowed by an identity-based policy, a resource-based policy, or both, then AWS allows the action."
Identity-based + permissions boundary Intersection "The resulting permissions are the intersection of the two categories."
Identity-based + SCP / RCP Intersection "The resulting permissions are the intersection of the user's policies, service control policies (SCPs), and resource control policy (RCP). This means that an action must be allowed by all three policy types."
Role's identity policy + session policy Intersection "The resulting session's permissions are the intersection of the role's identity-based policy and the session policies." (AssumeRole)

So: one union, three intersections. The union is the odd one out, and it is the one exam questions exploit — because it means an S3 bucket policy alone can grant access to a principal in the same account that has no S3 permissions in its identity policy at all.

Two details that follow from this and are worth stating explicitly:

A resource policy can grant, in the same account, with no identity policy. AWS says it about role trust policies, which are resource policies: "When a resource-based policy grants access to a principal in the same account, no additional identity-based policy is required." (AssumeRole)

The SCP intersection is documented for the case where the resource has no resource policy. The evaluation page scopes its SCP statement to "a resource that doesn't have a resource-based policy configured". Don't over-extend it. What does generalise is the deny half: "An explicit deny in the identity-based policy, an SCP, or an RCP overrides the allow."

Cross-account: both sides, every time

Same-account is a union. Cross-account is not — it is an AND across the account boundary. The trusting account must allow the principal, and the trusted account must allow its principal to make the call.

AWS spells out the two-sidedness for role assumption:

"To assume a role from a different account, your AWS account must be trusted by the role. The trust relationship is defined in the role's trust policy when the role is created. … A user who wants to access a role in a different account must also have permissions that are delegated from the account administrator. The administrator must attach a policy that allows the user to call AssumeRole for the ARN of the role in the other account." — AssumeRole

And SCPs stop at the organization boundary. From the SCP page, worth reading twice because it is a favourite distractor:

"SCPs affect only IAM users and roles that are managed by accounts that are part of the organization. SCPs don't affect resource-based policies directly. They also don't affect users or roles from accounts outside the organization. For example, consider an Amazon S3 bucket that's owned by account A in an organization. The bucket policy (a resource-based policy) grants access to users from account B outside the organization. Account A has an SCP attached. That SCP doesn't apply to those outside users in account B."

Design rule: an SCP is a control on your principals, not on your resources. If the requirement is "nobody outside the org may read this bucket", the SCP is the wrong tool — that is a resource control policy or a bucket policy with an aws:PrincipalOrgID condition.

The confused deputy, and ExternalId

Task statement 1.1 lists "Determining the appropriate use of resource policies for AWS services". The classic case is a third party — a monitoring vendor, say — that needs a role in your account.

A cross-account role is usually trusted at the account level, which is broader than you want. AWS's own framing:

"A cross-account role is usually set up to trust everyone in an account. Therefore, the administrator of the trusting account might send an external ID to the administrator of the trusted account. That way, only someone with the ID can assume the role, rather than everyone in the account." — AssumeRole

Verified constraints: ExternalId is 2–1,224 characters, pattern [\w+=,.@:\/-]*.

For MFA-protected assumption the trust policy condition is:

"Condition": { "Bool": { "aws:MultiFactorAuthPresent": true } }

and the caller passes SerialNumber (hardware serial, or the virtual device ARN arn:aws:iam::123456789012:mfa/user) plus a six-digit TokenCode. If MFA is required and TokenCode is missing or expired, AWS returns an access-denied error.

Session numbers that show up in questions

All from AssumeRole and IAM and AWS STS quotas, verified 2026-09-21.

Thing Value
DurationSeconds valid range 900 (15 min) – 43200 (12 hours)
DurationSeconds default 3600 seconds
Role's own max session duration setting configurable 1–12 hours
Role chaining ceiling 1 hour, regardless of the role's setting
Session policy size (inline JSON + all managed ARNs combined) 2,048 characters
Managed policy ARNs passable as session policies 10
Session tags up to 50; key ≤ 128 chars, value ≤ 256 chars
Role session name 2–64 characters
STS request quota 600 requests/sec, per account, per Region

⚠️ Role chaining silently caps you at one hour. AWS: "if you assume a role using role chaining and provide a DurationSeconds parameter value greater than one hour, the operation fails." A pipeline that assumes role A then assumes role B from within that session cannot hold a 12-hour session, no matter what the role is configured for. This is a real production failure mode and an exam distractor at the same time.

⚠️ PackedPolicySize is deprecated. The current field is SessionTokenUtilization — "The percentage (0-100) of the maximum allowed session token size that the returned session token consumes." If you get PackedPolicyTooLarge, session policies and session tags are both charged against the token size, and AWS notes you can hit it "even though you meet the individual session policy and session tag limits".

One quota that saves an argument: "Requests to AWS STS by AWS service principals, such as those used to assume roles for use with an AWS service, do not consume STS request per second quota in your accounts." And for cross-account calls, "only the account making the AssumeRole request impacts the STS quota. The target account does not have any of it's quota consumed."

IAM sizes and quotas worth knowing

From IAM and AWS STS quotas, verified 2026-09-21. The first group is adjustable — AWS publishes it as the table of quotas whose increases "can be automatically approved":

Resource Default Maximum
Roles per account 1,000 10,000
Customer managed policies per account 1,500 10,000
Managed policies per role 20 25
Managed policies per user 10 20
Managed policies per group 10 10
Groups per account 300 500
Role trust policy length 2,048 chars 8,192 chars

The second group cannot be increased at all — "You can't request an increase for the following limits":

Thing Limit
Inline policy total per user 2,048 characters
Inline policy total per role 10,240 characters
Inline policy total per group 5,120 characters
Each customer managed policy 6,144 characters
Role name 64 characters
Role session duration 12 hours

Two notes AWS makes that people trip on. White space doesn't count: "IAM doesn't count white space when calculating the size of a policy against these limits." And the managed-policy limit is the architectural one — 20 managed policies per role against 6,144 characters each is far more room than 10,240 characters of inline policy, which is why "hitting the policy size limit" is usually solved by moving inline policies to managed policies, not by requesting an increase.

Check yourself

  1. A role's identity policy allows s3:*. An SCP on its account allows only ec2:*. What can the role do in S3, and which policy decided it?
  2. An IAM user in account A has no S3 permissions at all. A bucket in account A has a bucket policy naming that user and allowing s3:GetObject. Can they read the object?
  3. Same as (2), but the bucket is in account B. Can they read it?
  4. A CI job assumes deploy-role (max session duration 12 hours) and then, from that session, assumes prod-role with DurationSeconds=28800. What happens?
  5. You must guarantee that no principal outside your organization can read a bucket. Is an SCP the right control?
Answers
  1. Nothing in S3. Identity policy and SCP intersect — "an action must be allowed by all three policy types" — and the SCP doesn't allow S3. The SCP decided it, by not allowing rather than by denying. Note the SCP grants nothing either; it only sets the ceiling.
  2. Yes. Same-account identity and resource policies are a union: "If an action is allowed by an identity-based policy, a resource-based policy, or both, then AWS allows the action."
  3. No — not on the bucket policy alone. Cross-account requires both sides: the bucket policy in B must allow, and the user in A must have an identity policy permitting the call.
  4. It fails. Role chaining limits the session to a maximum of one hour, and DurationSeconds above one hour causes the operation to fail — the role's 12-hour setting is irrelevant once you're chaining.
  5. No. SCPs "affect only IAM users and roles that are managed by accounts that are part of the organization" and don't affect outside principals reached via a resource policy. Use a resource control policy, or a bucket policy condition on aws:PrincipalOrgID.

Teaching this section

Next →Multi-account guardrails