Your deployment calls s3:PutObject, but S3 returns AccessDenied. The useful starting point is the request itself: which principal signed it, which action did it ask for, which resource did it name, and which context values travelled with it?
This page keeps one request in view as it moves through IAM:
arn:aws:sts::111122223333:assumed-role/AppDeployer/darshan → s3:PutObject → arn:aws:s3:::prod-artifacts/releases/app.zip
AWS builds request context, finds every policy that applies, looks for a sufficient grant, applies the relevant limits, and lets any applicable explicit deny win. The diagrams organize documented policy relationships so you can reason about them; they do not represent AWS’s internal implementation order.
Principal: who signed the request?
A principal is the entity AWS authorizes for this request. A person or workload may begin the journey, but temporary credentials often mean that an assumed-role session becomes the runtime principal that calls S3. That distinction affects which policies and condition keys match. Principal forms ↗
arn:aws:sts::111122223333:assumed-role/AWSReservedSSO_AppDeployer_…/darshan- Credential type
- Temporary role credentials
- Request context
- Account, session, tags, MFA and organization facts can affect matching conditions.
The person or workload that starts an action may first become a role session. Authorization follows the runtime principal and its request context. An IAM group organizes user permissions; it cannot authenticate or appear in a policy’s Principal element.
Policies: where can permission come from?
Authentication establishes who is calling. Authorization comes from policy statements that match the action, resource, principal where required, and condition context. Identity and resource policies can supply permissions; other policy types cap those permissions or govern a specific access path. IAM policy types ↗
In the same account, either side can often supply a sufficient allow. Across accounts, the caller’s account and the resource-owning account normally must both authorize access.
Identity-based
- Attached to
- User, group, or role
- Can grant?
- Yes
The attached identity is the implied principal.
Identity and resource policies are the ordinary grant sources. Boundaries, session policies, SCPs and RCPs reduce the available permissions. Endpoint policies, ACLs and RAM participate only for their supported path or resource model.
- Effect
- Allow or deny a matching request
- Principal
- Implied by the attached role
- Action
- The API operation
- Resource
- The target ARN
- Condition
- Facts that must match
{
"Version": "2012-10-17",
"Statement": {
"Sid": "PublishRelease",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::prod-artifacts/releases/*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/Environment": "prod"
}
}
}
}An identity policy cannot contain Principal; the user, group or role it is attached to supplies that identity. A resource policy must name the principal receiving the permission.
AWS services differ in which resources and policy elements they support. A pattern that works for an S3 bucket policy may not transfer unchanged to a KMS key policy or another service.
Evaluation: why was it allowed or denied?
The durable rules are straightforward: a request begins implicitly denied, it needs a relevant allow, limiting policies must permit the request when they apply, and an explicit deny overrides an allow. The details depend on the principal, accounts, resource-policy support, and the exact kind of principal named by a resource policy. Evaluation logic ↗
- 1Grantidentity policy
- 2Boundaryoptional ceiling
- 3Sessionoptional filter
- 4SCPprincipal ceiling
- 5RCPresource ceiling
- 6No denyall applicable policies
Where resource-policy grants change this model
A resource policy grant to a user ARN, role ARN, or assumed-role session ARN can interact differently with permissions boundaries and session policies. This lab deliberately follows a role session whose grant comes from its role’s identity policy. See the principal edge-case section below before applying this pipeline to a direct resource-policy grant.
A request begins denied. A relevant grant must survive every limiter that applies to this path. Any applicable explicit deny wins, even when all other controls allow the request.
Role and session principals are different
arn:aws:iam::111…:role/BatchJobImplicit denies in the role’s boundary or session policy can still limit the grant.
arn:aws:sts::111…:assumed-role/BatchJob/run-482Within the same account, boundary and session-policy implicit denies do not limit this direct session grant.
When a same-account resource policy grants directly to an assumed-role session ARN, permissions-boundary and session-policy implicit denies do not limit that direct grant. An applicable explicit deny still wins. A grant to the IAM role ARN remains limited by the role’s boundary and session policy. AWS recommends using role principals where possible. Detailed allow and deny evaluation ↗
Guardrails: how is power capped?
Permissions boundaries help a platform team delegate role creation without allowing each new role to exceed an approved maximum. SCPs define a maximum for principals in member accounts as policy inheritance moves from the organization root through OUs to an account. RCPs provide the resource-side Organizations control for supported services.
Application team’s role policy
Select the actions the team wants to grant.
s3:GetObjects3:PutObjectkms:DecryptEffective permissions
s3:GetObjects3:PutObjectkms:DecryptOutside the boundary
Boundary ∩ identity policy = possible identity-policy permissions. Boundary alone = zero permissions.
- Organization rootDeny leaving the organization
- Management accountOutside SCP enforcement
- Production OUDeny disabling CloudTrail
- Payments OUApproved Regions only
- prod-payments accountMember account
- Payments OUApproved Regions only
prod-payments account
Root: cannot leave the organization
Production OU: cannot stop CloudTrail
Payments OU: selected actions limited to approved Regions
These restrictions still apply when the principal has AdministratorAccess.
SCPs affect principals in member accounts, including the member account root user. They do not restrict principals in the management account, and they never grant permissions.
A permissions boundary follows one IAM user or role. An SCP follows the organization path to a member account. Both constrain existing grants; neither creates one.
Region guardrails need care because some AWS services use global endpoints or do not operate in an ordinary regional request path. A production policy should include the appropriate global-service exceptions rather than treating the diagram’s “approved Regions” label as a complete SCP.
Sessions: what happens when a role is assumed?
An IAM role stores trust and permissions configuration. When an authorized caller invokes AssumeRole, AWS STS creates a named role session and returns an access key ID, secret access key, session token, and expiration. Those credentials represent the session until they expire. Temporary credentials ↗
Principal, STS operation and conditions
role
Service actions, resources and conditions
- 1Call AssumeRole
The caller requests AppDeployer and names the new session.
- 2Authorize assumption
STS evaluates caller authorization, the role trust policy and its conditions where required.
- 3Create role session
The resulting principal is AppDeployer / darshan.
- 4Return credentials
STS returns four values that the session can use until expiration.
AccessKeyId: ASIA…SecretAccessKey: ••••••••SessionToken: IQoJ…Expiration: 2026-09-10T10:42:00ZA trust policy authorizes an STS operation such as AssumeRole; it does not grant S3 or KMS access. The resulting role session uses temporary credentials to sign later service requests, which receive their own authorization decisions.
AssumeRoleWithSAML and AssumeRoleWithWebIdentity change how the caller proves its identity to STS. GetFederationToken creates a federated-user session for older custom-broker patterns. The separate Identity and Credential Flows page follows those credential artifacts in more depth.
Cross-account: which two sides must agree?
Cross-account access is not synonymous with assuming a role. A caller can assume a role in the target account, or supported resources can grant the original external principal direct access. Both patterns require the appropriate caller-side and target-side authorization, but they produce different runtime principals. Cross-account evaluation ↗
Original caller
prod-artifacts
A role trust policy permits assumption; the role’s permissions govern the later service request. Direct resource access keeps the Account A identity as the caller and normally requires permission from both account sides.
Least privilege: how do you refine access?
Least privilege is easier to maintain when you treat a policy as an evidence-backed draft. Start with the task, validate the syntax and service support, test the actual request, observe use, and remove permissions that the principal does not need.
- Define the taskName the actor, resource and trust boundary.
- Start narrowlyChoose plausible actions, resources and conditions.
- Validate and testCatch syntax, unsupported resources and missing context.
- Observe real useInspect CloudTrail and Access Analyzer evidence.
- Remove and repeatShrink permissions as evidence improves.
"Action": "s3:*",
"Resource": "*"→"Action": "s3:PutObject",
"Resource":
"arn:aws:s3:::prod-artifacts/releases/*"Begin with the task, verify the policy, observe what the principal actually uses, and remove unused access. Protect policy-management and iam:PassRole paths because they can expand what another principal can do.
Prefer federation and temporary role credentials for people and workloads. Use strong identity-provider controls for privileged humans, separate everyday and elevated roles, govern tags before relying on ABAC, review external trust, and log sensitive policy changes and unusual role assumptions.
Diagnose an AccessDenied
Start with the failed request rather than reading every policy in the account. An AWS error can identify one reason for denial without listing every reason, so work outward from evidence.
| Step | Question | Evidence |
|---|---|---|
| 1. Resolve the principal | Which credentials signed this request? | sts get-caller-identity, workload credential source, and CloudTrail session ARN |
| 2. Capture the request | Which action, resource, Region, tags, network origin, and parameters were evaluated? | CloudTrail event, service error, request configuration, and relevant condition keys |
| 3. Separate accounts | Where does the principal live, and who owns the resource? | Account IDs in the principal and resource ARNs |
| 4. Find the grant | Which identity or resource statement should allow this exact request? | Matching action, resource, principal, and conditions |
| 5. Check limiters | Does each applicable boundary, session policy, SCP, RCP, or endpoint policy permit it? | Policies at the identity, session, network path, account, OU, and organization levels |
| 6. Search explicit denies | Does any applicable statement deny the request? | Identity, resource, endpoint, Organizations, key, and service-specific policies |
Policy Simulator and IAM Access Analyzer can narrow the investigation, but confirm their findings against the service’s authorization model and the actual request context. Broader administrator access cannot overcome an explicit deny.
Sources and documentation
- Policies and permissions in IAM
- Policy evaluation logic
- How AWS evaluates requests to allow or deny access
- Processing request context and the PARC model
- Principal policy element and principal forms
- Permissions boundaries for IAM entities
- Service control policies
- Temporary security credentials
- Cross-account policy evaluation logic
- Grant least privilege
- IAM AccessDenied troubleshooting