AWS Identity Pipeline
How AWS judges a request, and how callers get credentials to send it.
Every AWS request answers four questions
Maya lists the reports bucket from her laptop. Follow the one request and see what AWS reads from it before S3 does anything.
Maya's CLI sends one signed HTTPS request to the reports bucket. Before S3 lists anything, AWS has to decide whether this request may run.
What travels over the wire
GET /?list-type=2 HTTP/1.1Host: amzn-s3-demo-bucket-reports.s3.amazonaws.comAuthorization: AWS4-HMAC-SHA256 Credential=ASIA…DEMO/20261015/ap-south-1/s3/aws4_request, …X-Amz-Security-Token: [session token]X-Amz-Date: 20261015T104200ZThe access key ID in the signature belongs to a temporary credential set, and that set belongs to a role session. The session is who is asking, not Maya's laptop or her name.
What AWS knows so far
- Principal
arn:aws:sts::222222222222:assumed-role/SupportRead/mayanew
S3 turns the API call into an action and a resource. ListObjectsV2 is checked as s3:ListBucket, and it acts on the bucket itself, not on the objects inside it.
What AWS knows so far
- Principal
arn:aws:sts::222222222222:assumed-role/SupportRead/maya- Action
s3:ListBucketnew- Resource
arn:aws:s3:::amzn-s3-demo-bucket-reportsnew
The connection adds facts about where and how the request came: the source IP, whether it came through a VPC endpoint, whether it used TLS, and the time. Policies read these as condition keys.
What AWS knows so far
- Principal
arn:aws:sts::222222222222:assumed-role/SupportRead/maya- Action
s3:ListBucket- Resource
arn:aws:s3:::amzn-s3-demo-bucket-reports- aws:SourceIp
203.0.113.24new- aws:SecureTransport
truenew- aws:CurrentTime
2026-10-15T10:42:00Znew
AWS gathers every policy that applies: the role's identity policy, the bucket policy, the organization's SCPs and the role's permissions boundary. It compares the request with each one. AWS calls the four parts of a request PARC: Principal, Action, Resource and Condition.
The request context
- Principal
arn:aws:sts::222222222222:assumed-role/SupportRead/maya- Action
s3:ListBucket- Resource
arn:aws:s3:::amzn-s3-demo-bucket-reports- aws:SourceIp
203.0.113.24- aws:SecureTransport
true- aws:CurrentTime
2026-10-15T10:42:00Z
A request becomes a request context
AWS turns each signed request into a request context: who sent it, the action, the resource, and facts about the request such as the source IP and time. Every policy is matched against that context. The signature only proves the request came from the credential holder; whether the action is allowed is decided by the policies.
- WHO
- Principal: the session or user that signed
- WHAT
- Action + Resource ARN
- FROM WHERE
- Condition keys from the request
- HOW
- Effect and type of each policy that applies
aws sts get-caller-identityAn API name and its IAM action can differ: ListObjectsV2 is authorized as s3:ListBucket. The Service Authorization Reference lists the action and resource type for every API.
IAM: the request context ↗S3: policy actions ↗IAM: Signature Version 4 ↗
THE POINT TO KEEPBefore reading a policy, write the request as principal, action, resource and context; every policy is matched against those four answers.
Nothing is allowed until a policy says so
Start the SupportRead role with no permissions, then add one statement and get its resource wrong.
The role is new and has no policies. Every request starts out denied, and with no Allow anywhere it stays denied. AWS calls this an implicit deny.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policystops hereNo statement in the role's policy allows s3:ListBucket.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDImplicit deny: no Allow applies to this request.
One statement in the role's identity policy names the action and the bucket. It matches the request, nothing denies it, and S3 returns the listing.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
ALLOWEDAn Allow applies and nothing denies or caps it.
Identity policy on SupportRead
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadReports", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports" } ]}This statement names bucket/*, which means the objects. ListBucket acts on the bucket itself, so the statement doesn't match and the request is denied again.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policystops hereIts Allow names amzn-s3-demo-bucket-reports/*, the objects. s3:ListBucket is checked against the bucket ARN, so the statement doesn't match.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDImplicit deny: no Allow applies to this request.
Identity policy on SupportRead
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadReports", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports/*" } ]}Implicit deny is the starting point
Every request starts denied. A request runs only if a policy has an Allow statement whose action, resource and condition all match it, and nothing else denies or caps it. A statement that almost matches allows nothing.
- Default
- Implicit deny
- An Allow must match
- Action, Resource, Condition
- ListBucket resource
- arn:aws:s3:::amzn-s3-demo-bucket-reports
- GetObject resource
- arn:aws:s3:::amzn-s3-demo-bucket-reports/*
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::222222222222:role/SupportRead --action-names s3:ListBucket --resource-arns arn:aws:s3:::amzn-s3-demo-bucket-reportsThe account root user is the one documented exception to the default deny: it starts with full access to its own account, which is why it should not be used for daily work.
IAM: how requests are allowed or denied ↗S3: policy actions ↗
THE POINT TO KEEPAccess is the exception: with no matching Allow, the answer is no, and an Allow has to match the action and the exact resource form.
A condition decides whether an Allow applies
Add one condition to the Allow: only from the office IP range. Then send the same call from three places.
The request comes from 203.0.113.24, inside 203.0.113.0/24. The Condition matches, so the Allow applies.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
ALLOWEDAn Allow applies and nothing denies or caps it.
Identity policy on SupportRead
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadReports", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports", "Condition": { "IpAddress": { "aws:SourceIp": "203.0.113.0/24" } } } ]}The same credentials from 198.51.100.7. The Condition doesn't match, so that Allow simply doesn't apply. No other Allow exists, so the request is denied.
NOT A DENYA failed Condition switches off its own statement. Another Allow could still grant the call; only a Deny statement blocks it outright.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policystops hereIts Allow statement doesn't apply. Its Condition needs aws:SourceIp in 203.0.113.0/24, and this request doesn't match.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDImplicit deny: no Allow applies to this request.
An EC2 instance in the office VPC reaches S3 through a gateway endpoint. Requests through an endpoint carry no aws:SourceIp, so the IP condition can't match.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policystops hereIts Allow statement doesn't apply. Its Condition needs aws:SourceIp in 203.0.113.0/24, and this request has no aws:SourceIp because it came through a VPC endpoint.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDImplicit deny: no Allow applies to this request.
For traffic through the endpoint, check the endpoint's ID with aws:SourceVpce. Now the instance's request matches.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
ALLOWEDAn Allow applies and nothing denies or caps it.
The condition, rewritten
"Condition": { "StringEquals": { "aws:SourceVpce": "vpce-0a1b2c3d4e5f60718" }}Conditions read the request context
A Condition is part of the statement that holds it. When a condition key in it doesn't match, or the request doesn't carry that key at all, the statement doesn't apply. With no other Allow, the result is an implicit deny.
- aws:SourceIp
- public IP; absent through a VPC endpoint
- aws:SourceVpce
- present only through a VPC endpoint
- aws:SecureTransport
- whether the request used TLS
- Missing key
- an ordinary operator doesn't match
CloudTrail event → sourceIPAddress, vpcEndpointIdaws:MultiFactorAuthPresent is only in the context for temporary credentials. AWS recommends a Deny with BoolIfExists set to false, so that requests signed with long-term access keys, which carry no MFA key, are denied too.
IAM: global condition keys ↗S3: bucket policies for VPC endpoints ↗IAM: the request context ↗
THE POINT TO KEEPA condition narrows the statement it sits in; when the request lacks the key or the value differs, that Allow drops out, which is different from being denied.
One Deny beats every Allow, and ceilings cap the rest
The HOW of a decision is more than one policy. Keep the role's Allow in place and change one other policy at a time.
No Deny matches, the SCP leaves room for S3, the identity policy allows the call and the role's boundary includes it.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
ALLOWEDAn Allow applies and nothing denies or caps it.
The bucket owner protects the bucket: Deny s3:DeleteBucket to every principal. Maya's role allows DeleteBucket, and so does the bucket policy, but one matching Deny ends the evaluation.
How AWS decides
SupportRead/maya → s3:DeleteBucket amzn-s3-demo-bucket-reports- Explicit denystops hereThe bucket policy says Deny s3:DeleteBucket to every principal. One matching Deny ends the evaluation.
- SCP on the caller's accountnot reachedNot reached: this account already said no.
- Bucket policynot reachedNot reached: this account already said no.
- Identity policynot reachedNot reached: this account already said no.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDExplicit deny: one Deny beats every Allow.
Bucket policy statement
{ "Sid": "NeverDeleteBucket", "Effect": "Deny", "Principal": "*", "Action": "s3:DeleteBucket", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports"}The organization replaced FullAWSAccess on this account with an SCP that allows only EC2 and CloudWatch. The role's own Allow can't reach past that ceiling.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountstops hereThe SCP has no Allow for S3 actions, so nothing in this account can use S3, whatever its own policies say.
- Bucket policynot reachedNot reached: this account already said no.
- Identity policynot reachedNot reached: this account already said no.
- Permissions boundarynot reachedNot reached: this account already said no.
DENIEDImplicit deny: the SCP sets no room for S3.
SCP on account 222…
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:*", "cloudwatch:*" ], "Resource": "*" } ]}The role has a permissions boundary that allows only s3:GetObject. ListBucket is in the identity policy but outside the boundary, so it is denied.
How AWS decides
SupportRead/maya → s3:ListBucket amzn-s3-demo-bucket-reports- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarystops hereThe role's boundary leaves out s3:ListBucket. A boundary caps the role, including grants a bucket policy gives the role.
DENIEDImplicit deny: the boundary caps the role.
Grants and ceilings
Identity policies and bucket policies grant. SCPs, permissions boundaries and session policies only set a ceiling: they never grant anything, but an action outside them is denied. A Deny statement in any of these policies overrides every Allow.
- Explicit Deny
- ends the evaluation
- SCP
- ceiling for principals in member accounts
- Permissions boundary
- ceiling for one user or role
- Session policy
- ceiling for one role session
AccessDenied message → "because no … policy allows" or "with an explicit deny in a … policy"SCPs don't limit principals in the organization's management account or service-linked roles. Resource control policies (RCPs) are the matching ceiling on resources; they are left out of this example.
IAM: how requests are allowed or denied ↗Organizations: SCPs ↗IAM: session policies and boundaries ↗
THE POINT TO KEEPTo be allowed, a request needs one matching Allow and must fit under every ceiling that applies; one matching Deny anywhere ends it.
Across accounts, both sides must say yes
Maya reads the bucket directly from her DeveloperAccess session in account 111…, without assuming a role. Turn each side's Allow on and off.
Maya's role in 111… allows GetObject on the bucket. Account 222… owns the bucket and hasn't agreed, so the request is denied.
How AWS decides
DeveloperAccess/maya → s3:GetObject amzn-s3-demo-bucket-reports/2026/q3.csv- Caller account 111… · Explicit denypassesNo Deny statement in the caller account's policies.
- Caller account 111… · SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Caller account 111… · Identity policypassesThe role's policy allows s3:GetObject on amzn-s3-demo-bucket-reports/*.
- Caller account 111… · Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
- Bucket account 222… · Explicit denypassesNo Deny statement matches this request.
- Bucket account 222… · Bucket policystops hereIt has no statement for this principal.
DENIEDImplicit deny: across accounts, the bucket policy must allow too.
Now the bucket policy names DeveloperAccess, but Maya's own account gives her role no Allow. Account 111… says no.
How AWS decides
DeveloperAccess/maya → s3:GetObject amzn-s3-demo-bucket-reports/2026/q3.csv- Caller account 111… · Explicit denypassesNo Deny statement in the caller account's policies.
- Caller account 111… · SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Caller account 111… · Identity policystops hereNo statement in the role's policy allows s3:GetObject.
- Caller account 111… · Permissions boundarynot reachedNot reached: this account already said no.
- Bucket account 222… · Explicit denypassesNo Deny statement matches this request.
- Bucket account 222… · Bucket policypassesIt allows DeveloperAccess to s3:GetObject.
DENIEDImplicit deny: across accounts, the identity policy must allow too.
AWS evaluates the request once in each account. Both evaluations allow it, so S3 returns the object.
How AWS decides
DeveloperAccess/maya → s3:GetObject amzn-s3-demo-bucket-reports/2026/q3.csv- Caller account 111… · Explicit denypassesNo Deny statement in the caller account's policies.
- Caller account 111… · SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Caller account 111… · Identity policypassesThe role's policy allows s3:GetObject on amzn-s3-demo-bucket-reports/*.
- Caller account 111… · Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
- Bucket account 222… · Explicit denypassesNo Deny statement matches this request.
- Bucket account 222… · Bucket policypassesIt allows DeveloperAccess to s3:GetObject.
ALLOWEDBoth accounts allow the request.
Identity policy on DeveloperAccess (111…)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadReports", "Effect": "Allow", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports/*" } ]}Bucket policy (222…)
{ "Version": "2012-10-17", "Statement": [ { "Sid": "ShareReports", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::111111111111:role/DeveloperAccess" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports/*" } ]}Compare Maya's SupportRead session, which lives in 222… with the bucket. Inside one account, the bucket policy alone allows the request.
How AWS decides
SupportRead/maya → s3:GetObject amzn-s3-demo-bucket-reports/2026/q3.csv- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt allows SupportRead to s3:GetObject.
- Identity policypassesNo statement in the role's policy allows s3:GetObject. The bucket policy already allowed it, so in one account that is enough.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
ALLOWEDAn Allow applies and nothing denies or caps it.
Two evaluations, one answer
For a cross-account request, AWS evaluates the request in the caller's account, where the identity policy and its ceilings apply, and in the resource's account, where the resource policy applies. It allows the request only if both evaluations allow it.
- Caller's account
- identity policy, SCP, boundary
- Resource's account
- bucket policy, RCP
- Same account
- either an identity or a resource policy can allow
- Exceptions
- role trust and KMS key policies must name the principal
aws sts get-caller-identity --query AccountThis is one of two ways across accounts. The other is the Cross-account view later on this page: assume a role in the bucket's account and act as a principal there.
IAM: cross-account evaluation ↗IAM: how requests are allowed or denied ↗
THE POINT TO KEEPA request that crosses an account boundary needs an Allow on both sides; inside one account, either side can grant it.
Ask the four questions yourself
Set who is asking, what they want, how the policies read and where the call comes from. The trail shows each check in the order AWS documents.
The SupportRead session lists the reports bucket in its own account. Its identity policy allows it, and nothing denies it.
How AWS decides
ALLOWEDAn Allow applies and nothing denies or caps it.
- Account 222…
- Explicit denypassesNo Deny statement matches this request.
- SCP on the caller's accountpassesThe organization lets principals in this account use S3. An SCP sets a ceiling; it grants nothing.
- Bucket policypassesIt has no statement for this principal. In one account, the identity policy can allow it instead.
- Identity policypassesThe role's policy allows s3:ListBucket on amzn-s3-demo-bucket-reports.
- Permissions boundarypassesThe role has no boundary, or its boundary includes this action.
The request context
- Principal
arn:aws:sts::222222222222:assumed-role/SupportRead/maya- Action
s3:ListBucket- Resource
arn:aws:s3:::amzn-s3-demo-bucket-reports- aws:PrincipalArn
arn:aws:iam::222222222222:role/SupportRead- aws:PrincipalAccount
222222222222- aws:SourceIp
203.0.113.24- aws:SecureTransport
true
Identity policy on SupportRead (222…)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ReadReports",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::amzn-s3-demo-bucket-reports"
}
]
}Bucket policy on amzn-s3-demo-bucket-reports (222…)
{
"Version": "2012-10-17",
"Statement": []
}A model of one S3 decision
The simulator follows AWS's documented order: explicit deny, SCP, bucket policy, identity policy, permissions boundary. For a caller in another account it runs one evaluation per account. It doesn't call AWS.
- Left out
- RCPs, session policies, ACLs, Block Public Access
- Bucket
- amzn-s3-demo-bucket-reports
- Accounts
- 111… caller · 222… bucket
aws iam simulate-principal-policy … or IAM Access Analyzer policy checksA real anonymous request also has to get past S3 Block Public Access, which is on by default for new buckets.
IAM: how requests are allowed or denied ↗IAM: cross-account evaluation ↗IAM: global condition keys ↗
THE POINT TO KEEPName the principal, action, resource and context first; then look for a Deny, check each ceiling, and find the Allow, in each account the request touches.
From identity to authorized request
Choose a source path, then follow credentials and authorization through six stages.
Identity source
Who or what is requesting?
Authenticate
Prove the source identity
Obtain credentials
Select or exchange for AWS creds
Sign the request
AWS credentials on an API call
GET /?list-type=2
Host: s3.amazonaws.com
Authorization: AWS4-HMAC-SHA256
X-Amz-Security-Token: …Authorization
Can this action happen?
AWS resource
Run the permitted action
Common identity flows
Choose a route to see the whole path
More routes 4
IAM user keys · Long-term IAM user keys can sign API requests directly. They do not become temporary just because the request passes an identity stage.
- 1IAM userLegacy user in account 111…
- 2Access keyKey ID identifies; secret signs locally
- 3Current credentialsNo STS exchange in this path
- 4SigV4 requestSession token is absent for long-term keys
- 5IAM policiesUser and resource policies apply
- 6S3 ListBucketAllowed in this fixture
Identity Center · The Identity Center access token obtains AWS role credentials. It is different from the AWS session token that accompanies the resource request.
- 1MayaWorkforce identity at an IdP
- 2Browser sign-inIdentity Center access token
- 3GetRoleCredentialsAssigned account and role
- 4AWS role credentialsSigV4 uses AWS session token
- 5Evaluate requestAccount-role permission context
- 6S3 ListBucketAllowed in this fixture
Cross-account role · AssumeRole and the later S3 request are two authorizations. A valid target session can still be denied at S3.
- 1Maya’s role sessionAccount 111… is the caller
- 2Signed STS requestSource permission + target trust
- 3AssumeRoleSTS issues account 222… session
- 4New SupportRead setUse new set for the next request
- 5Target-role policiesSeparate resource decision
- 6S3 ListBucketAllowed in this fixture
EKS Pod · IRSA · IRSA uses a Kubernetes service account token with STS web identity. EKS Pod Identity uses a different delivery path.
- 1Pod service accountIRSA-specific path
- 2OIDC tokenToken issuer, audience and subject
- 3AssumeRoleWithWebIdentityNo starting AWS key required
- 4Role credentialsSDK signs with returned AWS set
- 5Pod request policyRole and applicable controls
- 6S3 ListBucketAllowed in this fixture
EC2 instance role · The SDK’s EC2 provider supplies temporary credentials. Application code does not need to call AssumeRole for its own instance role.
- 1EC2 workloadApplication runs on the instance
- 2Instance profileInstance profile associates role
- 3IMDS providerSDK retrieves and refreshes a set
- 4Role credentialsSDK signs the request
- 5Role policiesEvaluate the instance-role session
- 6S3 ListBucketAllowed in this fixture
Lambda execution · iam:PassRole can authorize the role association when the function is configured; Lambda later uses the execution role.
- 1Lambda functionService runs the function
- 2Service trustLambda assumes execution role
- 3Runtime credentialsCredentials provided in runtime
- 4Execution-role sessionSDK signs resource request
- 5Role policiesRole and applicable controls
- 6S3 ListBucketAllowed in this fixture
Federated user · SAML · The SAML assertion is the input to the STS exchange; it is not the AWS credential set returned for signing.
- 1Workforce userEnterprise IdP authenticates
- 2SAML assertionAssertion supplies identity proof
- 3AssumeRoleWithSAMLSTS validates assertion and trust
- 4Role credentialsAWS set signs later request
- 5Role policiesRole and applicable controls
- 6S3 ListBucketAllowed in this fixture
Workload · OIDC · A matching token, configured provider and role trust are required. An arbitrary OIDC token grants no AWS access.
- 1CI workloadExternal workload identity
- 2OIDC identity tokenTrusted issuer, audience, subject
- 3AssumeRoleWithWebIdentitySTS validates token and trust
- 4Role credentialsAWS set signs later request
- 5Role policiesRole and applicable controls
- 6S3 ListBucketAllowed in this fixture
S3 denied · The failure is at the later S3 authorization boundary. Reworking the role trust policy would not add s3:ListBucket.
- 1Maya’s role sessionSame caller as cross-account path
- 2Signed STS requestSource and trust both permit issuance
- 3AssumeRole allowedSTS returns target credentials
- 4Valid SupportRead setRequest signature is valid
- 5S3 denies ListBucketMissing s3:ListBucket in this fixture
- 6No listingResource action blocked
Credential example
Fictional values · no live AWS call
aws configure --profile legacy-user
aws sts get-caller-identity --profile legacy-user
# A user access key can sign directly.
# This path has no AWS session token.
# Never paste the secret into a shared script.For an IAM user with long-term keys, there is no temporary credential exchange in this direct request.
aws sts assume-role \
--role-arn arn:aws:iam::222222222222:role/SupportRead \
--role-session-name maya --profile workforce
# Response (fictional values)
Credentials: {
AccessKeyId: ASIA…DEMO,
SecretAccessKey: [redacted],
SessionToken: [redacted],
Expiration: 2026-10-15T14:32:56Z
}The caller uses existing AWS credentials for ordinary AssumeRole. The returned set belongs to a new session.
import boto3
# Uses the configured provider chain.
s3 = boto3.client("s3")
response = s3.list_objects_v2(
Bucket="amzn-s3-demo-bucket-reports"
)
# The provider renews temporary credentials when supported.The provider selects credentials and may refresh them; application code should not paste a temporary set into its configuration.
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::222222222222:role/ReportReader \
--role-session-name ci-report \
--web-identity-token file://token.jwt
# Returns temporary AWS credentials after trust validation.This exchange accepts a trusted identity token and does not require pre-existing AWS keys.
aws sts assume-role-with-saml \
--role-arn arn:aws:iam::222222222222:role/ReportReader \
--principal-arn arn:aws:iam::222222222222:saml-provider/CompanyIdP \
--saml-assertion [BASE64_ASSERTION]
# Returns temporary AWS credentials.The SAML assertion is proof supplied by the IdP. The response is an AWS credential set.
Key concepts
Choose a topic to inspect its mechanismAdvanced topics
The source proves who it is. A provider supplies credentials. The signed request is then authorized for its specific action and resource.
From identity to resource
Choose a source path, trace how it obtains or selects credentials, inspect the signed request, and then locate the authorization decision. The same pipeline exposes a direct IAM user path, a workforce Identity Center path, role assumption, and workload federation.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
Depends on selected flowA role ARN and a session ARN are identifiers, not credentials. Temporary AWS credentials also differ from an Identity Center access token.
Identity Center: GetRoleCredentials ↗AWS STS: AssumeRole ↗IAM: using temporary credentials ↗IAM: Signature Version 4 ↗IAM: role and role-session principals ↗STS: GetFederationToken ↗IAM: policy evaluation ↗
THE POINT TO KEEPThe source proves who it is. A provider supplies credentials. Each signed request is authorized for its action and resource.
Browser sign-in is the beginning of the credential journey
Start with the workforce profile in account 111111111111. The CLI obtains AWS credentials after the human signs in.
Configuration selects an account and role
- 1ProfileCURRENT
- 2BrowserNEXT
- 3SSO tokenNEXT
- 4AWS credentialsNEXT
- 5S3 requestNEXT
[profile workforce]
sso_session = company
sso_account_id = 111111111111
sso_role_name = DeveloperAccess
[sso-session company]
sso_start_url = https://example.awsapps.com/start
sso_region = ap-south-1
sso_registration_scopes = sso:account:accessConfiguration selects an account and role
The workforce profile points to an sso-session, an account, and an assigned role. It tells the CLI where to obtain credentials; it contains no AWS secret key.
- Credential context
- No AWS credentials yet
- Acting identity
- Not established
- Profile
- workforce
- Account
- 111111111111
Authenticate Maya through the browser
- 1ProfileCOMPLETE
- 2BrowserCURRENT
- 3SSO tokenNEXT
- 4AWS credentialsNEXT
- 5S3 requestNEXT
Authenticate Maya through the browser
aws sso login starts the configured Identity Center authorization flow. The identity source authenticates Maya. Current CLI v2 uses PKCE by default; device authorization is an explicit alternative.
- Credential context
- Browser authentication in progress
- Acting identity
- Maya at the identity source
The CLI holds an Identity Center access token
- 1ProfileCOMPLETE
- 2BrowserCOMPLETE
- 3SSO tokenCURRENT
- 4AWS credentialsNEXT
- 5S3 requestNEXT
The CLI holds an Identity Center access token
A successful login establishes the Identity Center session and tool-managed token cache. That access token is used with Identity Center APIs; it is not the AWS session token used for a SigV4 S3 request.
- Credential context
- Identity Center access token
- Acting identity
- Maya’s Identity Center session
GetRoleCredentials returns AWS role credentials
- 1ProfileCOMPLETE
- 2BrowserCOMPLETE
- 3SSO tokenCOMPLETE
- 4AWS credentialsCURRENT
- 5S3 requestNEXT
GetRoleCredentials returns AWS role credentials
When a command needs AWS credentials, the CLI provider calls GetRoleCredentials for the selected account and assigned role using the Identity Center access token. AWS returns an access key ID, secret key, session token, and expiration.
- Credential context
- Temporary AWS role credentials
- Acting identity
- AWSReservedSSO_DeveloperAccess… / maya
The resource request uses the AWS credential set
- 1ProfileCOMPLETE
- 2BrowserCOMPLETE
- 3SSO tokenCOMPLETE
- 4AWS credentialsCOMPLETE
- 5S3 requestCURRENT
The resource request uses the AWS credential set
The CLI signs the AWS API request with the selected AWS credentials and includes the AWS session token. Identity Center sign-in and authorization of that resource request are separate decisions.
- Credential context
- SigV4 + AWS session token
- Acting identity
- arn:aws:sts::111111111111:assumed-role/AWSReservedSSO_DeveloperAccess_a1b2c3d4e5f67890/maya
Configuration selects an account and role
The workforce profile points to an sso-session, an account, and an assigned role. It tells the CLI where to obtain credentials; it contains no AWS secret key.
- Profile
- workforce
- Account
- 111111111111
No AWS credentials yetVerified October 15, 2026: CLI v2.22.0 and later default to PKCE. --use-device-code selects device authorization. Cache files are tool-managed.
AWS CLI: configure Identity Center ↗AWS CLI: Identity Center concepts ↗Identity Center: GetRoleCredentials ↗
THE POINT TO KEEPThe Identity Center access token gets role credentials; the AWS session token accompanies the signed AWS request.
Identity Center configures a role inside the account
The group assignment selects who gets access; the permission set describes the account-side role to provision.
A permission set provisions an account-side IAM role
Identity Center configuration
Workforce account · 111…
Assigned users can request credentials for this account role.
A permission set provisions an account-side IAM role
Assigning a user or group to an AWS account through a permission set causes Identity Center to create and manage an AWSReservedSSO_ role in that account. The permission set is a template; the account role supplies the permissions used by its sessions.
- Credential context
- Configuration creates no credential in your profile
- Acting identity
- Account-side AWSReservedSSO_ role
- Identity Center
- Group + account assignment + permission set
- AWS account
- Managed role, trust and permissions
A permission set provisions an account-side IAM role
Assigning a user or group to an AWS account through a permission set causes Identity Center to create and manage an AWSReservedSSO_ role in that account. The permission set is a template; the account role supplies the permissions used by its sessions.
- Identity Center
- Group + account assignment + permission set
- AWS account
- Managed role, trust and permissions
Configuration creates no credential in your profileRemoving all assignments for a permission set in an account and assigning it again can change the role’s ARN suffix. Review policies that reference that ARN.
Identity Center: provisioned IAM roles ↗AWS CLI: configure Identity Center ↗
THE POINT TO KEEPThe permission set is the template; an account-side IAM role is what the issued session uses.
Workloads need a credential provider, not a human login
Keep the same report-reading job and change where it runs. Watch what supplies the SDK’s credential set.
An instance profile connects EC2 to its role
An instance profile connects EC2 to its role
Attach the role through an instance profile. An SDK’s EC2 provider retrieves temporary credentials through Instance Metadata Service; the workload signs requests as that role’s session. IMDS access and instance configuration affect delivery.
- Credential context
- IMDS → SDK credential provider
- Acting identity
- ReportWorker session
- Role association
- Instance profile
- Avoid
- Baking access keys into the image
Application credentials come from the task role
Application credentials come from the task role
The container credential provider receives credentials for the task IAM role. The task execution role is a separate role used by ECS for platform work such as image pulls and log delivery; it does not substitute for the application’s task role.
- Credential context
- Container provider → SDK
- Acting identity
- ReportTask session
- Application
- Task role
- Platform operations
- Task execution role
Lambda supplies execution-role credentials
Lambda supplies execution-role credentials
The service assumes the execution role and supplies temporary credentials to the function runtime. Function code uses the SDK’s normal provider; it does not need to call AssumeRole just to use its own execution role.
- Credential context
- Runtime credential provider → SDK
- Acting identity
- ReportFunction execution-role session
- Trust principal
- lambda.amazonaws.com
- Role user
- Function workload
A workload token can bootstrap AWS access
A workload token can bootstrap AWS access
AssumeRoleWithWebIdentity validates an identity-provider token against the configured provider and role trust. It does not require pre-existing AWS credentials. Restrict the intended audience and subject; possession of an arbitrary OIDC token grants no AWS role access.
- Credential context
- OIDC token → STS → AWS credentials
- Acting identity
- Federated workload role session
- Input
- Trusted provider’s identity token
- Trust conditions
- Audience and subject appropriate to the provider
An instance profile connects EC2 to its role
Attach the role through an instance profile. An SDK’s EC2 provider retrieves temporary credentials through Instance Metadata Service; the workload signs requests as that role’s session. IMDS access and instance configuration affect delivery.
- Role association
- Instance profile
- Avoid
- Baking access keys into the image
IMDS → SDK credential providerProvider support, refresh and precedence vary by SDK and version. IAM user access keys can also sign AssumeRole, but they are not the workforce path shown here.
SDKs: credential providers ↗EC2: roles and instance profiles ↗ECS: task role ↗Lambda: execution role ↗STS: AssumeRoleWithWebIdentity ↗
THE POINT TO KEEPIdentify the workload’s role and provider. An OIDC identity token can bootstrap AWS credentials without an AWS access key.
The CLI signs the request without sending the secret key
Use SupportRead’s temporary credentials for one header-signed S3 ListObjectsV2 call.
The secret key stays with the signer
Local process
- Secret access key
- Stays here
- Request + signing key
- Calculate signature
On the wire → S3
GET /?list-type=2
Host: amzn-s3-demo-bucket-reports.s3.amazonaws.com
Authorization: AWS4-HMAC-SHA256
Credential=ASIA…DEMO/…
SignedHeaders=…
Signature=[calculated value]
X-Amz-Security-Token: [session token]Identify the session → evaluate s3:ListBucket.
The secret key stays with the signer
For this header-signed S3 example, the CLI uses the secret access key to derive a signing key and calculate a signature over canonical request data. The access key ID identifies the credential; the AWS session token accompanies temporary credentials. HTTPS protects the exchange. A correct signature does not grant the requested action.
- Credential context
- Access key ID + signature + session token sent
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
The secret key stays with the signer
For this header-signed S3 example, the CLI uses the secret access key to derive a signing key and calculate a signature over canonical request data. The access key ID identifies the credential; the AWS session token accompanies temporary credentials. HTTPS protects the exchange. A correct signature does not grant the requested action.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
Access key ID + signature + session token sentThis is SigV4 with temporary credentials over HTTPS. Presigned URLs and services with other authentication schemes are outside this view.
IAM: Signature Version 4 ↗IAM: using temporary credentials ↗
THE POINT TO KEEPThe secret computes the signature locally; the service still needs to authorize the requested action.
Cross-account access has two separate requests
First ask STS for SupportRead in production. Then use that session to ask S3 for the report listing.
STS issues the target session; S3 allows the request
Workforce · 111…
Production · 222…
First blocking boundary: complete
STS issues the target session; S3 allows the request
Maya’s source session signs AssumeRole for SupportRead in production. Caller permission and target-role trust both allow this cross-account request. STS returns a new credential set; the later S3 request uses SupportRead’s session and is authorized separately.
- Credential context
- New SupportRead credentials
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
The source side does not permit AssumeRole
Workforce · 111…
Production · 222…
First blocking boundary: AssumeRole
The source side does not permit AssumeRole
The source role’s effective permissions do not allow sts:AssumeRole on SupportRead in this preset. Target trust alone cannot grant this cross-account access. No target credential set is issued.
- Credential context
- No target credentials issued
- Acting identity
- Source session remains available
The target role does not trust this caller
Workforce · 111…
Production · 222…
First blocking boundary: AssumeRole
The target role does not trust this caller
The source side permits AssumeRole, but the target-role trust policy does not admit the source principal in this preset. STS denies session creation, before the production S3 request exists.
- Credential context
- No target credentials issued
- Acting identity
- Source session remains available
AssumeRole succeeds; the resource request fails
Workforce · 111…
Production · 222…
First blocking boundary: S3 request
AssumeRole succeeds; the resource request fails
STS issues SupportRead credentials, but the later S3 ListBucket request is denied in this preset. Investigate the session’s resource permissions and applicable policies; changing who can assume the role does not itself grant ListBucket.
- Credential context
- Valid SupportRead credentials
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
STS issues the target session; S3 allows the request
Maya’s source session signs AssumeRole for SupportRead in production. Caller permission and target-role trust both allow this cross-account request. STS returns a new credential set; the later S3 request uses SupportRead’s session and is authorized separately.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
New SupportRead credentialsThese four presets isolate documented boundaries; they do not run AWS’s complete policy engine. Same-account direct trust has additional identity-policy nuances. Other applicable policies can still deny access.
AWS STS: AssumeRole ↗IAM: cross-account evaluation ↗IAM: session policies and boundaries ↗
THE POINT TO KEEPPermission to create a role session and permission to use a resource are different decisions.
A second role starts a new permission context
The workforce session is already a role session, so its AssumeRole request to production is role chaining.
Role credentials assuming a role is role chaining
Source permissions stay with the source session. They are not added to SupportRead.
Role credentials assuming a role is role chaining
The Identity Center role session in the workforce account calls AssumeRole for SupportRead. This is role chaining: the resulting session is limited to one hour even if SupportRead permits a longer maximum. The new session uses target-role permissions rather than a union with the source role.
- Credential context
- SupportRead session · up to 1 hour here
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
A longer role maximum does not extend a chained session
Source permissions stay with the source session. They are not added to SupportRead.
A longer role maximum does not extend a chained session
A DurationSeconds value of 7200 exceeds the one-hour role-chaining limit, so this request fails. This does not mean all temporary credentials last one hour: the limit here follows the role-to-role path.
- Credential context
- No new credential set
- Acting identity
- Source session remains the caller
Role credentials assuming a role is role chaining
The Identity Center role session in the workforce account calls AssumeRole for SupportRead. This is role chaining: the resulting session is limited to one hour even if SupportRead permits a longer maximum. The new session uses target-role permissions rather than a union with the source role.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
SupportRead session · up to 1 hour hereVerified October 15, 2026: AssumeRole has a 15-minute minimum; a role’s configured maximum can be 1–12 hours. A chained session is capped at one hour. Resource-policy grants and other controls need their own evaluation.
AWS STS: AssumeRole ↗AWS CLI: role profiles ↗IAM: session policies and boundaries ↗
THE POINT TO KEEPRole chaining creates separate credentials with a one-hour maximum; source permissions do not accumulate into the new session.
Who should receive the role’s credentials?
Compare Maya using a role herself with Maya configuring a Lambda function to use an execution role.
The caller receives credentials for its own next request
The caller receives credentials for its own next request
An authorized caller sends an STS AssumeRole request and receives temporary credentials. That caller chooses the returned set to sign a later AWS request.
- Credential context
- Returned to the calling application
- Acting identity
- Caller uses the resulting role session
The service uses the execution role later
The service uses the execution role later
When Maya creates a Lambda function with a role ARN, iam:PassRole is checked as part of the service API authorization. PassRole is not an API operation and returns no credentials. Lambda must be trusted by the role; the passed role and Lambda function are in the same account.
- Credential context
- None returned by PassRole
- Acting identity
- Lambda later uses the execution-role session
The caller receives credentials for its own next request
An authorized caller sends an STS AssumeRole request and receives temporary credentials. That caller chooses the returned set to sign a later AWS request.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
Returned to the calling applicationScope iam:PassRole to approved role ARNs and, where appropriate, iam:PassedToService. Audit the service API event, such as CreateFunction; there is no separate PassRole API event.
THE POINT TO KEEPAssumeRole returns credentials to the caller. PassRole authorizes a service-role association.
ExternalId binds the deputy to the customer
A reporting vendor serves several customers. Each customer trusts the vendor, but only for the expected tenant context.
The vendor selects the customer’s configured external ID
The vendor selects the customer’s configured external ID
The vendor authenticates the reports customer, then obtains its configured role ARN and vendor-generated external ID from the tenant record. The target trust requires the trusted vendor principal and the matching external ID.
- Credential context
- Customer-role credentials issued
- Acting identity
- Vendor session in the customer account
Knowing the role ARN does not select its external ID
Knowing the role ARN does not select its external ID
Another vendor customer supplies the reports role ARN. The vendor still chooses the external ID from the authenticated other-tenant record. The mismatch fails the customer role’s trust condition. An external ID is a tenant-binding value, not a password or a substitute for vendor authentication.
- Credential context
- No customer-role credentials issued
- Acting identity
- Vendor’s starting session
The vendor selects the customer’s configured external ID
The vendor authenticates the reports customer, then obtains its configured role ARN and vendor-generated external ID from the tenant record. The target trust requires the trusted vendor principal and the matching external ID.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
Customer-role credentials issuedThe vendor generates and controls a unique ExternalId per customer. It is not a secret, a password, or a replacement for the vendor principal and scoped permissions.
THE POINT TO KEEPThe vendor chooses ExternalId from its authenticated tenant record; a customer-supplied role ARN alone cannot choose the tenant.
An upstream login and AWS credentials have different clocks
Distinguish refreshing a provider from keeping an exported access-key snapshot in a shell.
Refresh replaces a credential set before it expires
Illustrative timing · each row has its own expiration
Refresh replaces a credential set before it expires
A configured refresh-capable provider obtains a fresh AWS credential set while its upstream authorization remains usable. The old access key and expiration do not mutate. Identity Center tokens and account-role credentials have separate validity periods.
- Credential context
- New credential set replaces the selected set
- Acting identity
- A session of the selected account role
A copied credential set has no refresh mechanism
Illustrative timing · each row has its own expiration
A copied credential set has no refresh mechanism
Copying access key, secret key, and session token into environment variables gives the process a snapshot. It does not copy the original provider’s refresh behavior. When those credentials expire, obtain a new set or use the provider directly.
- Credential context
- Expired exported credential snapshot
- Acting identity
- Expired session credentials
An upstream session can stop future refresh
Illustrative timing · each row has its own expiration
An upstream session can stop future refresh
If the Identity Center session is no longer usable, the provider cannot keep obtaining account-role credentials; the CLI can require aws sso login. Browser or SSO logout is not an instant revocation mechanism for every already-issued AWS role credential.
- Credential context
- Refresh blocked at upstream session
- Acting identity
- Earlier AWS credentials have their own expiry
Refresh replaces a credential set before it expires
A configured refresh-capable provider obtains a fresh AWS credential set while its upstream authorization remains usable. The old access key and expiration do not mutate. Identity Center tokens and account-role credentials have separate validity periods.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
New credential set replaces the selected setTimeline lengths are illustrative, not service defaults. Reauthentication, credential expiration and revocation are separate mechanisms; do not treat logout as immediate revocation of every issued session.
AWS CLI: Identity Center concepts ↗IAM: using temporary credentials ↗SDKs: credential providers ↗AWS CLI: role profiles ↗
THE POINT TO KEEPA provider obtains a new credential set. It does not extend the lifetime of the old one.
Trace the request back through the role session
Read the session ARN, the issuing role and optional attribution context without mistaking a label for proof of a person.
The role ARN names configuration; the session ARN names the acting principal
{
"userIdentity": {
"type": "AssumedRole",
"arn": "arn:aws:sts::222222222222:assumed-role/SupportRead/maya",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"arn": "arn:aws:iam::222222222222:role/SupportRead"
},
"sourceIdentity": "maya@example.com"
}
}
}- arn
- The session making this request.
- sessionIssuer.arn
- The role that defines its permission context.
- sourceIdentity
- Optional origin, constrained at issuance. This field is illustrative.
The role ARN names configuration; the session ARN names the acting principal
CloudTrail records the assumed-role identity and session issuer for resource requests. A session name is useful context, not independently verified human identity. SourceIdentity can preserve an origin across role chaining when configured; session tags carry attributes, with only transitive tags persisting through chaining.
- Credential context
- Temporary session credentials
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
- SourceIdentity
- Needs sts:SetSourceIdentity and constrained values
- Session tags
- Need sts:TagSession; constrain allowed keys and values
The role ARN names configuration; the session ARN names the acting principal
CloudTrail records the assumed-role identity and session issuer for resource requests. A session name is useful context, not independently verified human identity. SourceIdentity can preserve an origin across role chaining when configured; session tags carry attributes, with only transitive tags persisting through chaining.
- SourceIdentity
- Needs sts:SetSourceIdentity and constrained values
- Session tags
- Need sts:TagSession; constrain allowed keys and values
Temporary session credentialsPrefer role principals in policies where practical. Direct grants to role-session principals have different interactions with implicit denies from boundaries and session policies; use the authorization explorer for that decision.
IAM: source identity ↗IAM: session tags ↗IAM: role and role-session principals ↗IAM: session policies and boundaries ↗
THE POINT TO KEEPAudit the acting session and its issuer. Constrain the context that callers are allowed to attach.
Find the first credential boundary that failed
Choose a symptom, then reveal the evidence one check at a time. These are deterministic teaching transcripts, not live AWS calls.
Inspect the credentials selected by this process
Check 1
$ aws configure listaccess_key ****************DEMO env secret_key ****************DEMO env
The winning source is the environment in this fixture; do not print the secrets.
Check 2
$ aws sts get-caller-identityAccount: 111111111111 Arn: arn:aws:iam::111111111111:user/legacy-build
The request used the legacy user, not SupportRead. Check the process environment and choose the intended profile.
Verify provider → identify caller → locate failed request → narrow permissions → retest and inspect CloudTrail.
Inspect the credentials selected by this process
In this fixture the command omitted --profile and environment credentials won over the profile selected through AWS_PROFILE. Inspect provider selection and the actual caller before editing production trust.
- Credential context
- Environment credentials selected
- Acting identity
- arn:aws:iam::111111111111:user/legacy-build
The target session was never created
Check 1
$ aws sts get-caller-identity --profile workforceAccount: 111111111111 Arn: …assumed-role/AWSReservedSSO_DeveloperAccess_a1b2c3d4e5f67890/maya
The intended source session is active.
Check 2
$ aws sts assume-role --profile workforce --role-arn arn:aws:iam::222222222222:role/SupportRead --role-session-name mayaAccessDenied on sts:AssumeRole Fixture finding: target trust excludes this source role.
Review caller permission, target trust, conditions and applicable guardrails. The API error alone does not prove which policy failed.
Verify provider → identify caller → locate failed request → narrow permissions → retest and inspect CloudTrail.
The target session was never created
This fixture has valid source credentials but fails at target-role trust. Start with the actual caller, then inspect both sides of this cross-account exchange and its conditions. This is distinct from failure of the later S3 request.
- Credential context
- Source credentials only
- Acting identity
- arn:aws:sts::111111111111:assumed-role/AWSReservedSSO_DeveloperAccess_a1b2c3d4e5f67890/maya
Valid credentials do not prove permission to list the bucket
Check 1
$ aws sts get-caller-identity --profile prod-readAccount: 222222222222 Arn: arn:aws:sts::222222222222:assumed-role/SupportRead/maya
The target session is selected. GetCallerIdentity does not test S3 permission.
Check 2
$ aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket-reports --profile prod-readAccessDenied on ListObjectsV2 IAM permission required: s3:ListBucket on the bucket ARN
Inspect role/session permissions, applicable boundaries, Organizations controls, resource policy and request context.
Verify provider → identify caller → locate failed request → narrow permissions → retest and inspect CloudTrail.
Valid credentials do not prove permission to list the bucket
The target role session exists in production, but ListBucket is denied. The identity flow has succeeded; investigate the resource authorization decision with the correct action and bucket ARN.
- Credential context
- Valid SupportRead credentials
- Acting identity
- arn:aws:sts::222222222222:assumed-role/SupportRead/maya
Find the provider that can obtain a fresh set
Check 1
$ aws sts get-caller-identityExpiredToken: the security token included in the request is expired
Locate the expired credential source rather than treating this as a permission denial.
Check 2
$ aws configure listaccess_key ****************DEMO env secret_key ****************DEMO env
Remove the stale snapshot from this process and use the configured provider; sign in again if its upstream session requires it.
Verify provider → identify caller → locate failed request → narrow permissions → retest and inspect CloudTrail.
Find the provider that can obtain a fresh set
A process using an exported snapshot reaches its credential expiration. Changing the target role’s trust policy cannot refresh those environment values.
- Credential context
- Expired environment snapshot
- Acting identity
- No current usable session credentials
Temporary credentials include a session token
Check 1
$ Inspect credential configuration without printing valuesAWS_ACCESS_KEY_ID: set AWS_SECRET_ACCESS_KEY: set AWS_SESSION_TOKEN: missing
The temporary credential tuple is incomplete. Exact service error wording varies.
Check 2
$ Use a configured refresh-capable providerProvider supplies access key ID + secret key + session token + expiration
The credential provider should supply and refresh the complete set.
Verify provider → identify caller → locate failed request → narrow permissions → retest and inspect CloudTrail.
Temporary credentials include a session token
An access key ID and secret alone are incomplete for this temporary session. Keep all three credential values from the same issuance; do not combine values from different sessions.
- Credential context
- Session token missing
- Acting identity
- Temporary session cannot authenticate correctly
Inspect the credentials selected by this process
In this fixture the command omitted --profile and environment credentials won over the profile selected through AWS_PROFILE. Inspect provider selection and the actual caller before editing production trust.
- Starting actor
- Maya or the selected workload
- Resource goal
- List the production report bucket
Environment credentials selectedExact AWS error wording varies. A generic AccessDenied does not identify a single failing policy. GetCallerIdentity identifies the caller and does not prove S3 permission.
AWS CLI: configuration precedence ↗STS: GetCallerIdentity ↗AWS CLI: configure list ↗IAM: cross-account evaluation ↗
THE POINT TO KEEPFirst verify the provider and actual caller; then separate issuance failure from resource authorization failure.