Lesson 253 · AWS Learning Path

AWS 253: Cross-account access with AWS STS

· Published · 11 min read

Labelled process diagram for AWS 253: Trusted source principal to STS AssumeRole evaluation to Temporary role session to Target resource authorization and audit, with decision, proof and rejection evidence.

Why this matters to an architect

AWS accounts are security boundaries. A deployment pipeline in a Tools account, a security responder in a Security account, or a vendor platform outside the organization often needs temporary, narrowly scoped access to another account. AWS Security Token Service (STS) AssumeRole supplies that access without copying permanent keys into the target.

Cross-account access is a two-sided agreement: the source principal must be permitted to request the role, and the target role must trust that principal under the right conditions. After assumption, the temporary role session still faces its permission policy, boundary, session policy, SCP/RCP, resource policy, KMS policy, and request context. “AssumeRole succeeded” never means “every target action is allowed.”

Outcomes

By the end, you can:

  • explain STS, roles, role sessions, trust policies, temporary credentials, and cross-account delegation;
  • prove both the source-account and target-account authorization sides;
  • scope trust by principal, organization, ExternalId, MFA, SourceIdentity, session name, and tags;
  • distinguish third-party ExternalId from AWS-service SourceArn/SourceAccount confused-deputy controls;
  • design session duration, role chaining, Regional endpoint use, ABAC tags, and permissions;
  • read CloudTrail attribution without mistaking a session name for verified identity;
  • diagnose assumption failure separately from target-resource denial;
  • contain sessions safely and avoid exposing the access key, secret, or session token.

History and core vocabulary

STS underpins IAM roles and federation: a trusted caller exchanges its current proof for an access key ID, secret access key, and session token that expire. These credentials work with signed AWS API requests much like long-term keys, but are generated dynamically and disappear at expiry. Modern AWS architecture prefers role credentials supplied through SDK/CLI credential providers over embedded keys.

ObjectMeaning
IAM roletarget-account identity with a trust policy and permissions
trust policyresource policy on the role specifying who may request a session and under what conditions
caller identity policysource-side permission to call sts:AssumeRole on the target role
role permission policywhat the resulting role may attempt after assumption
role sessiontemporary principal such as arn:aws:sts::222233334444:assumed-role/DeployRole/build-184
session policyoptional additional limiter passed at assumption; never expands the role
session tagtemporary principal attribute used for ABAC/audit; may be transitive when authorized
SourceIdentitypersistent, controlled attribution value recorded through a role chain
ExternalIdtenant-specific value generated/controlled by a third-party deputy to prevent customer confusion

The two-account authorization handshake

Assume Account A caller arn:aws:iam::111122223333:role/BuildRunner needs Account B role arn:aws:iam::444455556666:role/ProductionDeploy.

Account A normally grants:

{
  "Effect": "Allow",
  "Action": ["sts:AssumeRole", "sts:SetSourceIdentity", "sts:TagSession"],
  "Resource": "arn:aws:iam::444455556666:role/ProductionDeploy"
}

Account B's role trust policy grants only the required source:

{
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:role/BuildRunner"},
  "Action": ["sts:AssumeRole", "sts:SetSourceIdentity", "sts:TagSession"],
  "Condition": {
    "StringEquals": {"aws:PrincipalOrgID": "o-example", "aws:RequestTag/Environment": "prod"},
    "StringLike": {"sts:SourceIdentity": "build-*"},
    "ForAllValues:StringEquals": {"aws:TagKeys": ["Environment", "Repository"]}
  }
}

The role's permissions should then allow only the deployment resources/actions. An organization SCP can narrow either account; a permissions boundary can narrow either role; the supplied session policy can narrow the resulting session; target resource policies and KMS key policy still apply. AWS251's evaluation logic remains mandatory.

For cross-account assumption, an allow is usually needed in both the caller identity policy and target trust policy. Same-account trust has nuances where a direct principal grant can itself authorize assumption, but explicit caller permissions are clearer and cross-account designs must not rely on that exception.

Principal scope and deletion behavior

"Principal":{"AWS":"arn:aws:iam::111122223333:root"} does not mean only Account A's root user. It delegates trust to Account A, whose administrators can authorize its identities. Prefer an exact governed role and add organization/attribute conditions where appropriate.

When a trust policy names an exact IAM role ARN, IAM stores the role's unique principal ID. Deleting and recreating a role with the same name gives it a new ID, so the old trust breaks and may display an unknown principal ID. This protects against name-reuse privilege escalation. Update and re-save the trust after an approved recreation; do not replace exact trust with Principal: "*" as a quick fix.

Some advanced designs use Principal: "*" plus aws:PrincipalArn conditions to match role paths. This does not have the same principal-ID transformation and has authorization implications described in AWS251. Use it only with deliberate policy analysis, explicit denies/organization controls, and negative tests.

ExternalId and confused deputies

ExternalId addresses a particular multi-tenant third-party problem. A vendor that assumes customer roles must generate and control a unique unpredictable-enough identifier per customer. Your trust policy requires your assigned value, and the vendor includes it when acting for you. Another vendor customer cannot cause the vendor to send your ExternalId merely by supplying your role ARN.

ExternalId is visible in role configuration and is not a password. It does not replace exact vendor principal trust, least-privilege role permissions, session attribution, contract/offboarding, or monitoring. The vendor - not each customer - must control uniqueness, or one customer may choose another customer's value.

For an AWS service principal accessing a resource on behalf of a service resource/account, use supported confused-deputy condition keys such as aws:SourceArn, aws:SourceAccount, aws:SourceOrgID, or aws:SourceOrgPaths according to that service's documentation. Do not mechanically put an ExternalId into a CloudTrail-to-S3 bucket policy or assume every service supplies every condition key.

MFA, network, and organization conditions

For human-operated sensitive roles, a trust condition can require aws:MultiFactorAuthPresent=true; AssumeRole then includes MFA device serial and token code. Federated/Identity Center MFA context and condition availability differ, so test the actual path rather than copying an IAM-user example.

IP or VPC endpoint conditions in a trust policy restrict where assumption occurs, not necessarily where the resulting credentials can be used. If location must constrain all target API use, apply an appropriate identity/SCP/resource control too, with exceptions for AWS services and approved networks. Avoid brittle controls that block incident recovery.

aws:PrincipalOrgID can deny principals outside your organization while permitting delegated roles inside it. Account moves and external vendors need explicit design. Always test anonymous/service principal implications when using broad deny conditions.

SourceIdentity, session names, and CloudTrail

RoleSessionName appears in the assumed-role ARN and CloudTrail. A caller chooses it unless policy constrains sts:RoleSessionName; therefore --role-session-name alice is a label, not proof Alice authenticated.

SourceIdentity is designed for durable attribution. Require an IdP-controlled employee/build identifier using sts:SourceIdentity, and authorize sts:SetSourceIdentity in the caller permission and target trust. Once set, it persists in role chaining and cannot be changed in the chain. Subsequent requests expose aws:SourceIdentity, and CloudTrail can record it. Control the value source - AWS does not validate that alice@example really belongs to Alice.

CloudTrail should show the source AssumeRole event, target role ARN, caller identity, request conditions, session name, source identity, tags, endpoint, and resulting assumed-role context. The later target API event shows the session issuer and access-key ID. Correlate both accounts and UTC times. Redact identifiers/tokens before sharing.

Session tags and ABAC

Passing tags requires sts:TagSession in applicable source/trust permissions. Constrain keys and values with aws:TagKeys and aws:RequestTag/<key>; do not let a pipeline claim Environment=prod or Department=Security freely. One value is supported per session-tag key.

Mark only required keys transitive. Transitive tags follow role chains and can replace matching role-tag values in later sessions. Conflicting inherited tags can make assumption fail. Packed session policy/tag size also has a separate limit; inspect PackedPolicySize instead of counting only JSON characters.

Duration and role chaining

For a direct AssumeRole, requested duration must be within the API minimum (normally 900 seconds) and the role's maximum session duration, up to 12 hours. Federation APIs and service-issued credentials have their own rules.

When credentials from Role 1 assume Role 2, that is role chaining and the new session is limited to one hour even if Role 2 allows longer. Long chains also complicate attribution, tags, availability, and policy analysis. Prefer a direct, well-attributed assumption into the final role where architecture permits.

Expiry stops future use, but temporary credentials cannot be extended. A client obtains a new session if it can still call AssumeRole. Remove the assumption path to prevent renewal. IAM's revoke sessions feature adds an AWSRevokeOlderSessions inline policy that denies sessions older than a chosen time; understand and preserve that policy during response. Other emergency controls include targeted trust/identity/SCP/resource denies. Test blast radius before containment.

Regional STS endpoints and credential providers

Configure the SDK/CLI Region and use Regional STS endpoints for predictable latency, resilience, quotas, and audit location. The legacy global endpoint's routing has evolved and differs by DNS source and opt-in Region. Global endpoint events and aws:RequestedRegion behavior can surprise policy/log searches; check CloudTrail endpointType and awsServingRegion.

Applications should use an SDK credential-provider chain, named role_arn/source_profile, web identity, task role, or instance role. Never print assume-role JSON in shared logs, commit it, pass secrets in process arguments, or manually rotate copied values. The session token is required together with the key and secret.

Example profile (use an approved non-key source profile):

[profile production-deploy]
role_arn = arn:aws:iam::444455556666:role/ProductionDeploy
source_profile = tools-federated
role_session_name = controlled-build-session
region = ap-south-1

Cross-account role versus resource policy

A role session changes the principal to the target-account role and is useful for multiple services or services without resource policies. A cross-account resource policy grants a source principal access to that resource without changing its principal; the caller retains source-account permissions. S3, SQS, SNS, KMS, Secrets Manager, and others have service-specific combinations and limitations.

Choose based on principal identity, action breadth, audit, policy ownership, and service semantics - not convenience. Cross-partition delegation (for example aws to aws-cn) is not supported through ordinary cross-account roles/resource policies.

Practical lab

Download the AWS253 cross-account STS pack. It contains:

  • TWO_ACCOUNT_TRUST_WORKBOOK.md;
  • SUPPLIED_STS_CASES.md with six failures;
  • THIRD_PARTY_AND_SERVICE_DEPUTY.md;
  • SESSION_ATTRIBUTION_AND_RESPONSE.md;
  • ANSWER_DIRECTIONS.md, opened after independent diagnosis.

Design Tools-to-Production pipeline access and vendor read-only access. Prove exact caller, target trust, conditions, role permissions, session limit, target resource/KMS access, CloudTrail fields, unauthorized negative tests, and emergency containment. The supplied no-create route is complete.

Read-only inspection and safe CLI

With both owners' approval:

aws sts get-caller-identity --profile tools-federated
aws iam get-role --role-name ProductionDeploy --profile target-audit \
  --query 'Role.{Arn:Arn,MaxSession:MaxSessionDuration,Trust:AssumeRolePolicyDocument}'
aws iam list-attached-role-policies --role-name ProductionDeploy --profile target-audit
aws iam list-role-policies --role-name ProductionDeploy --profile target-audit
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
  --region ap-south-1 --profile target-audit

Do not run assume-role unless explicitly authorized. If testing is approved, let an SDK/CLI profile consume returned credentials rather than displaying them. A successful get-caller-identity proves the current principal only; add scoped allowed and forbidden resource tests.

Troubleshooting matrix

SymptomInspectLikely cause
AccessDenied on AssumeRolecaller ARN/policy/boundary/SCP + target trust/conditionshandshake failure
recreated source role deniedtrust displays principal IDstale unique principal reference
vendor works for wrong tenantprincipal and ExternalId generation/mappingconfused deputy
SourceIdentity request deniedcaller permission and every chain trustmissing sts:SetSourceIdentity
tag request deniedsts:TagSession, allowed keys/values, inherited tagstag authorization/conflict
duration >1 hour deniedcaller is already assumed rolerole-chaining cap
AssumeRole works, KMS failsrole permission, key policy/grant, SCP, contexttarget authorization
audit says “alice” only in session namesource identity/IdP evidence absentcaller-controlled attribution
expected Regional event absentendpoint type/serving Region/global event searchendpoint/audit scope
revoked caller starts new sessiontrust/caller assumption path remainsrenewal not blocked

Cost and cleanup

STS and IAM roles have no hourly resource charge. CloudTrail data events/Lake, S3 retention, CloudWatch, Config, Access Analyzer, SIEM, KMS, network transfer, and third-party tooling can cost money. STS quotas and policy limits change; use current Service Quotas/API documentation and design retries with jitter.

The supplied lab creates nothing. In an approved sandbox, remove test resource grants before the test role only after checking dependencies; delete source permissions and trust intentionally; remove test CloudTrail data according to retention policy; and prove no credentials can be renewed. Temporary credentials may remain usable until expiry unless contained. Never print them as cleanup evidence.

Knowledge check

  1. Which permission is required in each account for cross-account AssumeRole?
  2. Why does an account-root principal in trust include more than the root user?
  3. Why can deleting and recreating a trusted role break assumption?
  4. Who must generate and control a third-party ExternalId, and is it a secret?
  5. When should aws:SourceArn and aws:SourceAccount be used instead?
  6. Why is a role session name weaker attribution than controlled SourceIdentity?
  7. What permissions and controls are required for session tags?
  8. What is the role-chaining duration limit?
  9. Why can a successful assumption still produce an S3/KMS denial?
  10. How do you stop session renewal versus contain already issued sessions?
  11. Why prefer Regional STS endpoints?
  12. When is a resource policy better than assuming a target role?

Lesson acceptance

Pass requires exact source/target policy proof; six correct diagnoses; trust principal and role-recreation analysis; correct ExternalId and service-deputy controls; controlled SourceIdentity/session-name/tag design; direct versus chained duration; Regional endpoint/audit plan; target permission and KMS/resource proof; positive and unauthorized negative tests; containment and renewal prevention; credential-safe tooling; and no-create or verified cleanup evidence.

Official sources

Advertisement