IAM Day 3 Lecture
SCS-C03 · Domain 4 · Identity and Access Management · Day 3 of 6

Temporary credentials, roles and trust

Days 1 and 2 were about policies. Today is about how identities actually get credentials: AWS STS, role trust policies, cross-account access, presigned URLs, and workloads inside and outside AWS. The goal: no long-term keys anywhere.

Skill 4.1.2 temporary credentials (STS, presigned URLs)Skill 4.2.1 Roles Anywhere, cross-account, trust policies~90 min read + 30 min lab
01

AWS STS and temporary credentials

AWS Security Token Service (STS) is the service that hands out temporary credentials. Every role you assume, every federated login, every Identity Center session and every Lambda function ends up with credentials from STS. They look like normal access keys, plus a session token and an expiration time. When they expire, they simply stop working; there is nothing to rotate or delete.

Concept profile

STS temporary credentials

often confused with long-term access keys
?What is it?

Short-lived credentials made of an access key ID, a secret access key and a session token, valid for minutes to hours.

⚙How does it work?
  • A caller makes an STS API call (or an AWS service does it for you).
  • STS checks the caller and, for roles, the trust policy.
  • STS returns the credentials with an Expiration time.
  • Every request signed with them must include the session token.
{ }Structure
STS APIWho calls itTypical use
AssumeRoleIAM user or role sessionSwitch role, cross-account, services
AssumeRoleWithSAMLUser signed in to a SAML IdPWorkforce federation (AD FS, Okta, Entra ID)
AssumeRoleWithWebIdentityHolder of an OIDC tokenEKS IRSA, mobile/web apps, GitHub Actions
GetSessionTokenIAM user (long-term keys)Get MFA-backed credentials for the CLI
GetFederationTokenIAM user (long-term keys)Custom identity broker (legacy)
AssumeRootManagement account / delegated adminPrivileged root tasks on member accounts
⇄STS temporary credentials vs long-term access keys
Temporary credentialsLong-term access keys
Key ID prefixASIA…AKIA…
PartsKey ID + secret + session tokenKey ID + secret
Lifetime15 minutes to hours, then expireUntil deleted
RotationAutomatic, nothing to doYou must rotate
If leakedDamage window is short; can also revoke sessionsValid until you deactivate them
!Common mistakes the exam tests
  • Forgetting the session token when configuring temporary credentials by hand.
  • Thinking you can “delete” one temporary credential. You revoke sessions with a Deny instead (section 04).
  • Mixing up durations: AssumeRole default 1 hour, max = role's max session duration (up to 12 h), role chaining max 1 hour.
  • Forgetting that GetSessionToken credentials can't call IAM APIs unless MFA was included.
✓Benefits and use cases
  • No secrets stored in code or on disk.
  • Short blast radius if something leaks.
  • One central place (CloudTrail) shows who assumed what.
Caller user, app, service, IdP user AWS STS AssumeRole AssumeRoleWithSAML AssumeRoleWithWebIdentity GetSessionToken GetFederationToken AssumeRoot Temporary credentials AccessKeyId ASIA… SecretAccessKey SessionToken (must be sent) Expiration 15 min … 36 h nothing to rotate · expires by itself
Every road to AWS access without long-term keys goes through STS.
Think of it like · a hotel front desk

Your home key works forever. A hotel keycard works until checkout.

AWS conceptFamiliar thing
AWS STS≈The hotel front desk
Long-term access key (AKIA)≈Your house key
Temporary credentials (ASIA)≈A hotel keycard
Session token≈The chip in the card that proves it was issued today
Expiration≈Checkout time: the card stops working on its own
Real AWS example · what AssumeRole returns

The CLI output when you assume a role. Note the ASIA prefix and the expiration.

$ aws sts assume-role --role-arn arn:aws:iam::111122223333:role/Auditor \
    --role-session-name minh-audit --duration-seconds 3600
{
  "Credentials": {
    "AccessKeyId": "ASIAEXAMPLE7QF2W",
    "SecretAccessKey": "wJalr...EXAMPLEKEY",
    "SessionToken": "IQoJb3JpZ2luX2VjE...",
    "Expiration": "2026-10-07T09:15:00Z"
  },
  "AssumedRoleUser": {
    "Arn": "arn:aws:sts::111122223333:assumed-role/Auditor/minh-audit"
  }
}

The session name (minh-audit) appears in CloudTrail, so always set something that identifies the person or job.

Exam-style scenario

Administrators use the AWS CLI with IAM user access keys. The security team wants every CLI call that changes IAM to require MFA, without giving up the CLI. What is the BEST approach?

  1. A. Rotate access keys every 30 days.
  2. B. Create an admin role whose trust policy requires aws:MultiFactorAuthPresent = true; admins call sts:AssumeRole with --serial-number and --token-code, and their user policies allow only sts:AssumeRole on that role.
  3. C. Enable MFA on the root user.
  4. D. Put the access keys in Secrets Manager.
Show the worked answer

Answer: B

The role can only be assumed with MFA, and the users themselves have almost no permissions. Every admin action therefore comes from an MFA-backed temporary session. (A similar pattern uses GetSessionToken with MFA plus a policy condition on aws:MultiFactorAuthPresent.)

Why not the others

  • A: Rotation doesn't add MFA.
  • C: Good practice, but unrelated to admin users' CLI calls.
  • D: Still long-term keys with no MFA.
How the exam tests this
  • “Credentials start with ASIA”→ Temporary (STS). AKIA = long-term.
  • “Long job fails after exactly 1 hour”→ Default session length or role chaining cap.
  • “Require MFA for CLI”→ Role trust policy with aws:MultiFactorAuthPresent, or GetSessionToken with MFA.
Must remember
  • Temporary credentials = key ID + secret + session token + expiration.
  • AssumeRole: default 1 h, max = role setting (1–12 h); chaining max 1 h.
  • GetSessionToken / GetFederationToken: 15 min – 36 h (root: 1 h max).
02

Role trust policies

Every role has two kinds of policy. The trust policy answers “who may assume me?” and the permissions policies answer “what can I do once assumed?”. The trust policy is a resource-based policy (the role is the resource), so it has a Principal. Most role problems on the exam come down to reading the trust policy carefully.

Concept profile

Trust policy

often confused with permissions policy
?What is it?

The resource-based policy attached to a role that lists which principals may assume it, with which STS action, and under which conditions.

⚙How does it work?
  • Principal types: AWS (accounts, users, roles), Service (ec2.amazonaws.com, lambda.amazonaws.com…), Federated (SAML or OIDC provider).
  • Actions: sts:AssumeRole, sts:AssumeRoleWithSAML, sts:AssumeRoleWithWebIdentity, plus sts:TagSession and sts:SetSourceIdentity when tags or source identity are passed.
  • Conditions add MFA, external ID, organization or source checks.
{ }Structure
{ "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::444455556666:role/Deployer" },
    "Action": "sts:AssumeRole",
    "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
  }] }
⇄Trust policy vs permissions policy
Trust policyPermissions policy
TypeResource-based (role is the resource)Identity-based
Principal elementYesNo
AnswersWho may assume the role?What may the role do?
How manyOne per roleSeveral managed + inline
Typical actionssts:AssumeRole*Any service actions
!Common mistakes the exam tests
  • Putting service permissions in the trust policy, or sts:AssumeRole permissions only on one side in cross-account.
  • Using "Principal": {"AWS": "*"} with no conditions: anyone in any account could assume it.
  • Deleting and recreating a role named in a trust policy: the stored principal ID no longer matches, so you must edit the trust policy again.
  • Forgetting sts:TagSession when an IdP passes session tags.
✓Benefits and use cases
  • Limit who can use powerful roles (MFA, specific roles only).
  • Let AWS services act for you (service principals).
  • Federation with SAML/OIDC providers.
IAM role no password, no keys Trust policy “Who may wear me?” Principal: AWS / Service / Federated Action: sts:AssumeRole* Condition: MFA, ExtId… Permissions policies “What can I do?” Action: s3:GetObject… Resource: arn:… + optional boundary + max session 1–12 h To assume a role, the trust policy must allow you AND (cross-account) your own policy must allow sts:AssumeRole.
Two doors to every role: who can come in, and what they can do inside.
Think of it like · a uniform in a locker

A role is like a work uniform that grants access when you put it on.

AWS conceptFamiliar thing
IAM role≈A uniform hanging in a locker
Trust policy≈The list of people who may open the locker
Permissions policy≈The doors the uniform's badge opens
Assuming the role≈Taking off your own clothes and wearing the uniform
Condition (MFA, external ID)≈“Only if you show your ID card too”
Real AWS example · three kinds of principal in trust policies

Same structure, different principal type.

// AWS service (EC2 instance profile)
"Principal": { "Service": "ec2.amazonaws.com" },  "Action": "sts:AssumeRole"

// Another account (its admins decide who inside may use it)
"Principal": { "AWS": "arn:aws:iam::444455556666:root" }, "Action": "sts:AssumeRole"

// GitHub Actions through an OIDC provider
"Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": { "StringEquals": {
   "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
   "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main" } }

Without the sub condition, any GitHub repository could exchange its token for this role. Always pin the repository and branch.

Exam-style scenario

A role in account B trusts arn:aws:iam::111122223333:role/Deployer. Last week account A deleted Deployer and recreated it with the same name. Now AssumeRole from the new Deployer fails, and the trust policy shows a value like AROAEXAMPLEID instead of the ARN. What should the engineer do?

  1. A. Wait for the trust policy to refresh.
  2. B. Edit the trust policy in account B and put the Deployer role ARN back, so it's mapped to the new role's principal ID.
  3. C. Add sts:AssumeRole to the new Deployer role only.
  4. D. Change the principal to "*".
Show the worked answer

Answer: B

Trust policies store the role's unique principal ID, not just the name. A recreated role has a new ID, so the old entry no longer matches and shows the raw ID. Saving the ARN again maps it to the new ID.

Why not the others

  • A: It never refreshes on its own.
  • C: Needed, but the trust side is what's broken.
  • D: Opens the role to everyone.
How the exam tests this
  • “Role can't be assumed but caller's policy allows it”→ Read the trust policy: principal, action, conditions.
  • “Trust policy shows a strange ID like AROA…”→ The trusted role was deleted and recreated.
  • “CI/CD from GitHub without keys”→ OIDC provider + AssumeRoleWithWebIdentity + condition on sub.
Must remember
  • Trust policy = who may assume; permissions = what it can do.
  • Cross-account: trust policy and caller's sts:AssumeRole permission.
  • Pin OIDC trust with aud and sub conditions.
  • Passing tags needs sts:TagSession in the trust policy.
03

Cross-account roles and the confused deputy

A confused deputy is a trusted party tricked into using its power for someone who shouldn't have it. In AWS it shows up two ways. Cross-account: a vendor that can assume roles in many customer accounts is tricked into assuming the wrong one. Cross-service: an AWS service that writes to your resources is tricked into acting for someone else's resource. Each has its own condition key fix.

Concept profile

sts:ExternalId

often confused with aws:SourceArn / aws:SourceAccount
?What is it?

A secret-like value that a third party must pass when it assumes a role in your account. Your trust policy requires it.

⚙How does it work?
  • The vendor generates a unique external ID for each customer.
  • The customer puts that ID in the role's trust policy condition.
  • The vendor passes it on every AssumeRole call.
  • If another customer gives the vendor your role ARN, the vendor sends that customer's ID, which doesn't match yours.
{ }Structure
"Condition": { "StringEquals": { "sts:ExternalId": "a-7f3e9c" } }
⇄sts:ExternalId vs aws:SourceArn / aws:SourceAccount
sts:ExternalIdaws:SourceArn / aws:SourceAccount
Problem solvedCross-account confused deputy (third party assuming roles)Cross-service confused deputy (AWS service acting on your resource)
WhereRole trust policyResource policy granting a service principal (S3, SNS, KMS…)
ValueUnique ID chosen by the vendorARN / account of the resource the service acts for
Org-wide versionn/aaws:SourceOrgID, aws:SourceOrgPaths (also in RCPs)
!Common mistakes the exam tests
  • Thinking the external ID is a password. It isn't secret; it prevents mix-ups.
  • Letting the customer choose the external ID; the vendor should generate it, unique per customer.
  • Using ExternalId to protect a bucket from a service principal (that's SourceArn/SourceAccount).
  • Using aws:PrincipalOrgID for service principals: they don't carry it.
✓Benefits and use cases
  • SaaS monitoring or cost tools that assume roles in customer accounts.
  • Bucket policies for CloudTrail, Config or S3 event notifications to SNS/SQS.
  • Org-wide confused deputy guardrail with an RCP.
SaaS vendor the “deputy”: can assume roles in customer accounts Customer AExternalId = a-7f3e Attackeranother customer whoenters A's role ARN A's role trust policysts:ExternalId = a-7f3evendor + A's ID → ✓ Call made for attackersends attacker's IDID mismatch → ✗ denied
The external ID ties each customer's role to that customer's identity at the vendor.
Think of it like · a valet parking service

A valet can drive any car in the garage, so it must hand back the right one.

AWS conceptFamiliar thing
SaaS vendor≈The valet with keys to every car
Role ARN≈The parking spot number
External ID≈Your claim ticket number, unique to your car
Attacker≈Someone who reads your spot number and asks for your car
Trust policy check≈The valet checks the ticket, not just the spot number
Real AWS example · cross-service protection on an SNS topic

S3 may publish event notifications to this topic only for one bucket in one account.

{ "Effect": "Allow",
  "Principal": { "Service": "s3.amazonaws.com" },
  "Action": "SNS:Publish",
  "Resource": "arn:aws:sns:eu-west-1:111122223333:uploads-topic",
  "Condition": {
    "ArnLike":      { "aws:SourceArn":     "arn:aws:s3:::uploads-bucket" },
    "StringEquals": { "aws:SourceAccount": "111122223333" } } }

Without these conditions, any S3 bucket in any account could be configured to publish to your topic through the S3 service.

Exam-style scenario

A cost-optimization SaaS asks each customer to create a role it can assume. The security team wants to make sure another customer of the same vendor cannot trick the vendor into reading their account. What should the role's trust policy include?

  1. A. A condition on aws:PrincipalOrgID equal to the company's organization ID.
  2. B. The vendor's account as principal and a condition requiring sts:ExternalId equal to the unique ID the vendor issued to this company.
  3. C. A condition on aws:SourceArn equal to the vendor's account.
  4. D. A requirement for MFA.
Show the worked answer

Answer: B

This is the textbook cross-account confused deputy. The external ID, unique per customer and generated by the vendor, makes sure the vendor only assumes your role while working for you.

Why not the others

  • A: The vendor isn't in your organization, so this would block it entirely.
  • C: SourceArn is for service principals acting on resources, not vendors assuming roles.
  • D: The vendor's automation can't do MFA, and MFA doesn't stop the mix-up.
How the exam tests this
  • “Third party assumes roles in many customer accounts”→ sts:ExternalId, unique per customer.
  • “Bucket policy grants an AWS service principal”→ Add aws:SourceArn / aws:SourceAccount.
  • “Protect all resources in the org from cross-service confused deputy”→ RCP with aws:SourceOrgID.
Must remember
  • Cross-account deputy → ExternalId (trust policy).
  • Cross-service deputy → SourceArn / SourceAccount / SourceOrgID (resource policy).
  • Service principals have no aws:PrincipalOrgID.
04

Session tags, source identity and revoking sessions

Once a session exists, three tools help you control and trace it. Session tags carry attributes (team, project) into the session for ABAC. Source identity records who really started a chain of role sessions, and it can't be changed later in the chain. Revoking sessions cuts off leaked temporary credentials immediately, before they expire.

Concept profile

Revoking role sessions

often confused with rotating access keys
?What is it?

A way to invalidate every temporary credential issued for a role before a chosen time, by adding a Deny that checks aws:TokenIssueTime.

⚙How does it work?
  • In the IAM console, choose Revoke active sessions on the role.
  • IAM attaches an inline policy named AWSRevokeOlderSessions to the role.
  • It denies everything when aws:TokenIssueTime is earlier than now.
  • Anyone legitimate simply assumes the role again and gets fresh credentials.
{ }Structure
{ "Effect": "Deny", "Action": "*", "Resource": "*",
  "Condition": { "DateLessThan": { "aws:TokenIssueTime": "2026-10-07T08:00:00Z" } } }
⇄Revoking sessions vs rotating access keys
Revoke role sessionsRotate / deactivate access keys
ForTemporary credentials of a roleLong-term keys of an IAM user
HowDeny on aws:TokenIssueTimeDeactivate, then delete the key
EffectAll sessions issued before T stop workingThat key stops working
Users affectedMust assume the role againNeed a new key
!Common mistakes the exam tests
  • Trying to delete the leaked temporary key: it can't be deleted.
  • Deleting the whole role (breaks every workload) instead of revoking.
  • Forgetting to investigate: search CloudTrail for the leaked access key ID.
  • Forgetting sts:TagSession in the trust policy when passing tags.
✓Benefits and use cases
  • Incident response for leaked role credentials.
  • Session tags for ABAC (Day 5).
  • Source identity to trace which human started a chain of role assumptions.
time Revoke time T Issued before T aws:TokenIssueTime < T → every request denied Issued after T fresh AssumeRole calls → work normally Leaked credentials are cut off immediately; legitimate users just assume the role again.
Revoking is a Deny with a timestamp: old sessions fail, new ones work.
Think of it like · hotel keycards after a break-in

When a keycard is stolen, the hotel doesn't hunt for it; it invalidates every card printed before now.

AWS conceptFamiliar thing
Revoke active sessions≈Re-key the locks: every card printed before 3 pm stops working
aws:TokenIssueTime≈The print time on each card
Legitimate users≈Go to reception and get a new card
Session tags≈A note printed on the card: team, project
Source identity≈The guest's name on the card, which can't be changed
Real AWS example · passing session tags and a source identity

The trust policy must allow sts:TagSession and sts:SetSourceIdentity for this to work.

$ aws sts assume-role \
    --role-arn arn:aws:iam::111122223333:role/DataAnalyst \
    --role-session-name minh \
    --tags Key=Project,Value=Atlas Key=CostCenter,Value=CC42 \
    --transitive-tag-keys Project \
    --source-identity minh@example.com

Project is transitive, so it stays on the session if Minh chains into another role. Tags attached to the role itself are not transitive. Source identity appears in CloudTrail for every action in the chain.

Exam-style scenario

GuardDuty reports that credentials for role DataPipeline (access key ID starting ASIA) are being used from an unknown IP address. The role is used by several workloads. What should the engineer do FIRST to stop the attacker with the least disruption?

  1. A. Delete the role.
  2. B. Use Revoke active sessions on the role, which denies all sessions issued before now; workloads get fresh credentials when they next assume the role.
  3. C. Deactivate the access key in the IAM console.
  4. D. Detach all policies from the role permanently.
Show the worked answer

Answer: B

Temporary credentials can't be deactivated individually. Revoking adds a Deny on aws:TokenIssueTime, cutting off the attacker's copy while legitimate callers simply assume the role again. Next, investigate in CloudTrail and find how the credentials leaked.

Why not the others

  • A: Breaks every workload and destroys evidence of the configuration.
  • C: Only IAM user long-term keys can be deactivated.
  • D: Breaks legitimate workloads and is slower to restore.
How the exam tests this
  • “Leaked ASIA… credentials”→ Revoke active sessions (AWSRevokeOlderSessions).
  • “IdP passes tags; AssumeRole fails”→ Trust policy lacks sts:TagSession.
  • “Trace the human behind chained roles”→ Source identity.
Must remember
  • Revoke = inline AWSRevokeOlderSessions denying aws:TokenIssueTime < now.
  • Session tags need sts:TagSession; max 50 per session.
  • Transitive tags survive role chaining; role tags don't.
Official sources: Revoke sessions Session tags
05

Amazon S3 presigned URLs

A presigned URL lets someone without AWS credentials download or upload one specific S3 object for a limited time. Your application signs the URL with its own credentials, so the URL can never do more than the signer can, and it stops working when it expires or when the signer's credentials stop being valid.

Concept profile

S3 presigned URL

often confused with making the object public
?What is it?

A URL for one S3 operation on one object, with your signature and an expiry time in the query string.

⚙How does it work?
  • Your code (with s3:GetObject or s3:PutObject) creates the URL locally; no API call is needed.
  • Anyone with the URL can use it until it expires.
  • S3 checks the signature, the expiry, and that the signer still has the permission.
  • Max expiry: 12 hours from the console, 7 days from CLI/SDK with SigV4 and IAM user credentials.
  • Signed with temporary credentials? It dies when those credentials expire, whatever expiry you set.
{ }Structure
$ aws s3 presign s3://reports/q3.pdf --expires-in 900
https://reports.s3.eu-west-1.amazonaws.com/q3.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256
  &X-Amz-Credential=ASIA...%2F20261007%2Feu-west-1%2Fs3%2Faws4_request
  &X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=...
⇄Presigned URL vs making the object public
Presigned URLPublic object / bucket
Who can accessOnly people holding the URLAnyone on the internet
Time limitYes (seconds to 7 days)No
ScopeOne object, one operationEverything that is public
Block Public AccessNot affectedMust be turned off
RevocationRemove the signer's permission or let it expireChange the policy
!Common mistakes the exam tests
  • Expecting a 7-day URL signed by a Lambda role to last 7 days. It ends when the role session expires.
  • Thinking the URL grants permissions the signer doesn't have.
  • Forgetting that anyone who gets the URL can use it (it's a bearer link).
  • Confusing it with CloudFront signed URLs (for content served through CloudFront).
✓Benefits and use cases
  • Let customers download their invoice.
  • Let browsers upload files directly to S3 without passing through your servers.
  • Share a file with a partner for one hour.
Your app has s3:GetObject signs locally Presigned URL …/report.pdf?X-Amz-Credential=… &X-Amz-Expires=3600 &X-Amz-Signature=… Anyone with the URL no AWS account needed S3 checks: is the signature valid, not expired, and does the SIGNER still have permission?
The URL carries the signer's authority, limited to one object and a time window.
Think of it like · a signed visitor pass

A resident can write a visitor pass for one guest, valid until a set time.

AWS conceptFamiliar thing
Signer (app/role)≈The resident who signs the pass
Presigned URL≈The signed pass: one door, one time window
Expiry≈“Valid until 6 pm”
Signer's credentials expire≈The resident moves out, so every pass they signed becomes invalid
s3:signatureAge≈Building rule: no pass older than 10 minutes is accepted
Real AWS example · limiting every presigned URL to 10 minutes

A bucket policy can reject old signatures, whatever expiry the signer chose.

{ "Sid": "DenyOldSignatures",
  "Effect": "Deny",
  "Principal": "*",
  "Action": "s3:*",
  "Resource": "arn:aws:s3:::reports/*",
  "Condition": { "NumericGreaterThan": { "s3:signatureAge": "600000" } } }

s3:signatureAge is in milliseconds, so 600000 = 10 minutes. You can also add aws:SourceIp or aws:SourceVpce conditions to limit where URLs can be used.

Exam-style scenario

A Lambda function generates download links with a 7-day expiry for customers. Customers report links stop working after a few hours. The function's role allows s3:GetObject. What is the cause?

  1. A. S3 caps presigned URLs at 1 hour.
  2. B. The URL was signed with the Lambda role's temporary credentials, and a presigned URL stops working when the signing credentials expire.
  3. C. The bucket policy blocks anonymous access.
  4. D. Lambda can't create presigned URLs.
Show the worked answer

Answer: B

A presigned URL is only valid while the signing credentials are. Role session credentials last hours, so the link dies with them. Better design: generate a fresh short-lived URL when the customer clicks “download”.

Why not the others

  • A: The limit is 7 days (SDK/CLI) or 12 hours (console).
  • C: Presigned URLs work without the bucket being public.
  • D: Any code with credentials can sign URLs.
How the exam tests this
  • “Temporary access to one object for someone without AWS credentials”→ Presigned URL.
  • “Link expires earlier than set”→ Signed with temporary credentials.
  • “Enforce a maximum URL age”→ Bucket policy Deny on s3:signatureAge.
Must remember
  • Max expiry: console 12 h, CLI/SDK (SigV4) 7 days.
  • URL power = signer's power; dies with signer's credentials.
  • Anyone with the URL can use it.
06

IAM Roles Anywhere

Servers, containers and applications outside AWS (your data centre, another cloud) used to need IAM user access keys. IAM Roles Anywhere replaces them: the workload proves its identity with an X.509 certificate issued by a certificate authority you trust, and receives temporary credentials for an IAM role.

Concept profile

IAM Roles Anywhere

often confused with IAM user access keys on servers
?What is it?

A service that exchanges an X.509 certificate from a trusted CA for temporary AWS credentials for an IAM role.

⚙How does it work?
  • Create a trust anchor: AWS Private CA or your own CA's certificate bundle.
  • Create a role whose trust policy trusts rolesanywhere.amazonaws.com.
  • Create a profile listing which roles can be used (and one optional session policy).
  • On the server, the credential helper signs a CreateSession request with the certificate's private key and returns temporary credentials.
{ }Structure
// Trust policy of the role
{ "Effect": "Allow",
  "Principal": { "Service": "rolesanywhere.amazonaws.com" },
  "Action": ["sts:AssumeRole", "sts:TagSession", "sts:SetSourceIdentity"],
  "Condition": {
    "ArnEquals": { "aws:SourceArn": "arn:aws:rolesanywhere:eu-west-1:111122223333:trust-anchor/PROD-TA-ID" },
    "StringEquals": { "aws:PrincipalTag/x509Subject/CN": "billing-server-01" } } }
⇄IAM Roles Anywhere vs IAM user access keys on servers
Roles AnywhereIAM user keys on servers
Credential on the serverCertificate + private keyLong-term access key
AWS credentialsTemporary, auto-expiringPermanent until rotated
RevocationRevoke the certificate (import a CRL), or disable the trust anchor/profileDeactivate the key
Fits withExisting PKINothing extra
!Common mistakes the exam tests
  • Forgetting the trust boundary is the account: certificates from any trust anchor in the account can assume any role trusting Roles Anywhere, unless the trust policy adds conditions such as aws:SourceArn (trust anchor) or certificate attributes.
  • Choosing Roles Anywhere for workloads running on AWS (use instance profiles, task roles…).
  • Forgetting CRL import for revoked certificates.
✓Benefits and use cases
  • On-premises apps calling S3, KMS, Secrets Manager.
  • Workloads in other clouds.
  • Hybrid servers in regulated environments with an existing PKI.
On-prem server X.509 cert + private key aws_signing_helper CreateSession IAM Roles Anywhere Trust anchorAWS Private CA or your CA Profileroles + one session policy CRL (optional)revoked certs rejected IAM role trusts rolesanywhere.amazonaws.com → temporary creds
A certificate goes in, temporary credentials come out. No access keys on the server.
Think of it like · a passport at an embassy

A foreign visitor proves who they are with a passport from a government the embassy trusts.

AWS conceptFamiliar thing
X.509 certificate≈Your passport
Your CA / AWS Private CA≈The government that issued it
Trust anchor≈The embassy's list of governments it trusts
Profile≈The kinds of visa the embassy offers
Temporary credentials≈A visa valid for a short stay
CRL≈The list of cancelled passports
Real AWS example · using the credential helper with the AWS CLI

The helper is configured as a credential_process, so every SDK and the CLI pick up temporary credentials automatically.

# ~/.aws/config on the on-prem server
[profile onprem]
credential_process = aws_signing_helper credential-process \
    --certificate /etc/pki/billing-server-01.pem \
    --private-key /etc/pki/billing-server-01.key \
    --trust-anchor-arn arn:aws:rolesanywhere:eu-west-1:111122223333:trust-anchor/PROD-TA-ID \
    --profile-arn arn:aws:rolesanywhere:eu-west-1:111122223333:profile/PROFILE-ID \
    --role-arn arn:aws:iam::111122223333:role/BillingOnPrem

Protect the private key on the server (file permissions, TPM or HSM); it now plays the role the access key used to.

Exam-style scenario

A company has two trust anchors in one account: one for the production CA and one for the development CA. Both are used with IAM Roles Anywhere. The security team must make sure development servers can never obtain credentials for the production role. What should the engineer do?

  1. A. Put the two trust anchors in different Regions.
  2. B. Add a condition to the production role's trust policy that aws:SourceArn equals the production trust anchor ARN (optionally also matching certificate subject attributes).
  3. C. Use a separate profile for each environment only.
  4. D. Shorten the session duration of the production role.
Show the worked answer

Answer: B

By default, any trust anchor in the account can be used to assume any role that trusts Roles Anywhere. Pinning the trust policy to the production trust anchor (and certificate attributes) closes that gap.

Why not the others

  • A: Regions don't separate trust; the role is global.
  • C: Profiles help, but the role's trust policy is what enforces the boundary.
  • D: Doesn't stop development servers getting credentials.
How the exam tests this
  • “On-prem servers need AWS access without long-term keys”→ IAM Roles Anywhere with X.509 certificates.
  • “Limit which certificates can use a role”→ Trust policy conditions: aws:SourceArn (trust anchor), aws:PrincipalTag/x509….
  • “Revoke a compromised server certificate”→ Import a CRL into Roles Anywhere.
Must remember
  • Trust anchor = which CA; profile = which roles + session policy.
  • Role trusts rolesanywhere.amazonaws.com.
  • Trust boundary is the account: pin trust anchors in the trust policy.
07

Roles for workloads on AWS

Inside AWS, every compute service has its own way to give code a role, so you never need keys. EC2 uses an instance profile and the instance metadata service (use IMDSv2). Lambda has an execution role. ECS has two roles, which the exam loves to confuse. EKS uses IRSA or EKS Pod Identity. Creating any of them requires iam:PassRole.

Concept profile

ECS task role

often confused with ECS task execution role
?What is it?

The role your application code inside the containers uses to call AWS services.

⚙How does it work?
  • Set as taskRoleArn in the task definition.
  • The SDK in the container gets its credentials from this role only; it doesn't inherit the host's permissions.
  • The separate task execution role (executionRoleArn) is used by the ECS/Fargate agent to pull images, send logs and fetch secrets for environment variables.
{ }Structure
{ "family": "orders-api",
  "taskRoleArn":      "arn:aws:iam::111122223333:role/OrdersApiTaskRole",
  "executionRoleArn": "arn:aws:iam::111122223333:role/ecsTaskExecutionRole",
  "containerDefinitions": [ ... ] }
⇄ECS task role vs ECS task execution role
Task roleTask execution role
Used byYour application codeECS / Fargate agent
Typical permissionsS3, DynamoDB, SQS…ECR pull, CloudWatch Logs, Secrets Manager/SSM for env vars
FieldtaskRoleArnexecutionRoleArn
Missing it causesApp gets AccessDeniedTask fails to start (image pull, logs, secrets)
!Common mistakes the exam tests
  • Putting app permissions on the execution role.
  • Giving tasks access through the EC2 instance role, so every task on the host shares it.
  • Forgetting iam:PassRole for whoever registers the task definition.
  • EC2: leaving IMDSv1 enabled (use IMDSv2 to resist SSRF).
✓Benefits and use cases
  • Per-service least privilege for containers.
  • No keys in images or environment variables.
  • Clear audit trail per task role in CloudTrail.
ECS task ECS / Fargate agentstarts the task Your app containerSDK calls Task EXECUTION rolepull image from ECRwrite logsfetch secrets for env vars Task roleS3, DynamoDB, SQS…whatever the appcode calls
Two roles, two jobs: the agent sets up the task, the app does its work.
ComputeHow the code gets a roleWatch out for
EC2Instance profile, credentials from instance metadataRequire IMDSv2; one role for all apps on the instance
LambdaExecution roleOne role per function for least privilege
ECSTask role (app) + task execution role (agent)Don't mix them up
EKSIRSA (AssumeRoleWithWebIdentity via the cluster's OIDC provider) or EKS Pod IdentityPin the service account in the trust policy
Think of it like · a restaurant kitchen

Two kinds of staff need different keys.

AWS conceptFamiliar thing
Task execution role≈The delivery driver's key: brings ingredients (images), drops off paperwork (logs)
Task role≈The chef's key: uses the pantry and fridge (S3, DynamoDB)
Instance role shared by all tasks≈One master key for every cook in the building: too broad
iam:PassRole≈The manager's permission to hand a key to a new employee
Real AWS example · EKS IRSA trust policy pinned to one service account

Only pods using the orders service account in namespace shop can assume this role.

{ "Effect": "Allow",
  "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE" },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": { "StringEquals": {
    "oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:sub": "system:serviceaccount:shop:orders",
    "oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE:aud": "sts.amazonaws.com" } } }

Without the sub condition, any pod in the cluster could assume the role.

Exam-style scenario

An application in an ECS task gets AccessDenied when writing to a DynamoDB table. The task definition has only executionRoleArn set, pointing to a role that allows ECR, CloudWatch Logs and dynamodb:PutItem. What should the engineer do?

  1. A. Add DynamoDB permissions to the EC2 instance role.
  2. B. Create a task role with dynamodb:PutItem, set it as taskRoleArn, and remove the DynamoDB permission from the execution role.
  3. C. Add an SCP allowing DynamoDB.
  4. D. Store access keys as an ECS secret.
Show the worked answer

Answer: B

Application code uses the task role. The execution role is only for the ECS agent. Moving the permission keeps both roles least-privilege.

Why not the others

  • A: Shares the permission with every task on the host and may not even apply on Fargate.
  • C: SCPs never grant.
  • D: Reintroduces long-term keys.
How the exam tests this
  • “Container app gets AccessDenied, task starts fine”→ Missing task role permissions.
  • “Task fails to pull image or read secrets”→ Task execution role.
  • “EKS pod needs AWS access”→ IRSA or EKS Pod Identity; pin the service account.
  • “Protect EC2 credentials from SSRF”→ Require IMDSv2.
Must remember
  • ECS: task role = app, execution role = agent.
  • IRSA = AssumeRoleWithWebIdentity + OIDC provider + sub condition.
  • Attaching a role to a service needs iam:PassRole.
08

Cheatsheet extras: Lambda’s two policies and the custom identity broker

The cheat sheet’s troubleshooting chapter has a section on Lambda access and a long story about a custom identity broker. Both are about choosing the right policy or STS API, so they belong with today’s topics.

Concept profile

Lambda execution role

often confused with the Lambda function (resource-based) policy
?What is it?

The IAM role that Lambda assumes when your function runs. Its permissions decide what the function’s code can do: write logs, read S3, call KMS, read a secret.

⚙How does it work?
  • Trust policy allows lambda.amazonaws.com to assume the role; you choose it when you create the function.
  • Minimum for logs: AWSLambdaBasicExecutionRole (CreateLogGroup, CreateLogStream, PutLogEvents). In a VPC also AWSLambdaVPCAccessExecutionRole.
  • Give each function its own role so permissions stay least privilege.
  • The function policy is the other side: a resource-based policy on the function that lists who may invoke it (lambda:InvokeFunction), for example events.amazonaws.com, s3.amazonaws.com or another account.
  • The console adds the function policy for you when you add a trigger; with the CLI, SDK or CloudFormation you add it yourself (add-permission / AWS::Lambda::Permission).
{ }Structure
InvokersEventBridge ruleS3 event notificationAPI Gateway, SNSanother account Lambda function Function (resource) policyWHO may call lambda:InvokeFunction Execution roleWHAT the code may do AWS APIsCloudWatch LogsS3, DynamoDBKMS (+ key policy)Secrets ManagerEC2, SQS…
Two policies, two directions: in through the function policy, out through the execution role.
⇄Lambda execution role vs the Lambda function (resource-based) policy
Execution roleFunction (resource) policy
AnswersWhat can the function do?Who can call the function?
TypeIAM role (identity-based permissions)Resource-based policy on the function
Principallambda.amazonaws.com assumes itServices or accounts that invoke
Symptom when wrongFunction runs but AccessDenied inside (no logs, KMS, S3, secret)Function never runs; EventBridge FailedInvocations, S3 can’t deliver
Fix withAdd the action to the role (and the KMS key policy if needed)aws lambda add-permission with SourceArn / SourceAccount
!Common mistakes the exam tests
  • Adding the invoke permission to the execution role: invokers are checked against the function policy.
  • Giving a function an IAM user’s access keys in environment variables instead of using the role.
  • Forgetting the KMS key policy when the function decrypts with a customer managed key (the role alone may not be enough).
  • Allowing s3.amazonaws.com to invoke without SourceArn/SourceAccount: any bucket could trigger it (confused deputy).
✓Benefits and use cases
  • Clear troubleshooting: “can’t do X” → role; “isn’t triggered” → function policy.
  • Cross-account invoke without sharing credentials.
  • One role per function = small blast radius.
Think of it like · a taxi

A taxi has two separate sets of rules.

AWS conceptFamiliar thing
Function policy≈Who is allowed to hail this taxi (the dispatch list)
Execution role≈Where the driver is allowed to drive once the trip starts
SourceArn condition≈“Only pick up calls from the hotel at 12 High Street”, not from anyone who knows the number
Missing function policy≈Customers wave, but the taxi never stops
Missing execution-role permission≈The taxi starts the trip but is stopped at the toll gate
Real AWS example · letting an EventBridge rule invoke a function

When you create the rule with the CLI or IaC, you must add the invoke permission yourself.

$ aws lambda add-permission --function-name isolate-instance \
    --statement-id eventbridge-guardduty --action lambda:InvokeFunction \
    --principal events.amazonaws.com \
    --source-arn arn:aws:events:eu-west-1:111122223333:rule/guardduty-high

$ aws lambda get-policy --function-name isolate-instance --query Policy --output text
{"Version":"2012-10-17","Statement":[{"Sid":"eventbridge-guardduty","Effect":"Allow",
 "Principal":{"Service":"events.amazonaws.com"},"Action":"lambda:InvokeFunction",
 "Resource":"arn:aws:lambda:eu-west-1:111122223333:function:isolate-instance",
 "Condition":{"ArnLike":{"AWS:SourceArn":"arn:aws:events:eu-west-1:111122223333:rule/guardduty-high"}}}]}

This is the function policy. The function’s own permissions (for example ec2:ModifyInstanceAttribute) still come from its execution role.

Exam-style scenario

A team deploys an EventBridge rule (CloudTrail API call events) and a Lambda function with AWS CloudFormation. The rule matches events, and the rule’s FailedInvocations metric rises, but the function’s log group shows no invocations. The execution role has AWSLambdaBasicExecutionRole. What is missing?

  1. A. Add lambda:InvokeFunction to the function’s execution role.
  2. B. Add an AWS::Lambda::Permission resource that lets events.amazonaws.com invoke the function, scoped with the rule’s ARN.
  3. C. Turn on CloudTrail data events for Lambda.
  4. D. Give the EventBridge rule an IAM user’s access key.
Show the worked answer

Answer: B

EventBridge is an invoker, so it is checked against the function’s resource-based policy. The console would have added it automatically; CloudFormation doesn’t.

Why not the others

  • A: The execution role controls what the function does after it starts.
  • C: Data events log invocations; they don’t allow them.
  • D: Never; and EventBridge uses the function policy for Lambda targets.

The custom identity broker (legacy pattern)

Before IAM Identity Center and SAML federation were common, companies wrote an identity broker: an app that checks the user against LDAP/AD, then asks AWS STS for temporary credentials on the user’s behalf. Your cheat sheet walks through it step by step, and old questions still use it. The broker can call either API:

sts:GetFederationTokensts:AssumeRole
Who calls itThe broker’s IAM user (long-term keys)Any IAM principal allowed by the role’s trust policy
Permissions of the resultBroker user’s policies ∩ the session policy you pass (pass none → effectively no permissions)The role’s permissions (∩ an optional session policy)
Duration15 min to 36 h (default 12 h); 1 h max if called as root15 min to the role’s max session (1–12 h)
LimitsCan’t call IAM APIs or most STS APIs; no MFASupports MFA, external ID, source identity
Typical exam answer“custom broker gives each user per-user S3 prefix access”“broker maps the LDAP group to a role”
Older material: “build an identity broker with GetFederationToken”. Today: for workforce users, prefer IAM Identity Center or SAML 2.0 federation (Day 4); a custom broker means you own code that holds long-term IAM user keys. Pick the broker answer only when the question clearly describes LDAP/no SAML support and asks for temporary credentials.
How the exam tests this
  • “Lambda can’t write logs / use a KMS key / read a secret”→ Fix the execution role (plus key policy for KMS).
  • “Service can’t trigger Lambda”→ Fix the function policy (add-permission).
  • “Restrict which bucket can invoke the function”→ SourceArn + SourceAccount in the function policy.
  • “Broker authenticates users against LDAP, then gets credentials”→ GetFederationToken (federated user) or AssumeRole.
  • “Federated user credentials for up to 36 hours”→ GetFederationToken.
Must remember
  • Execution role = what it does; function policy = who calls it.
  • Console adds trigger permissions; CLI/IaC → add-permission.
  • One role per function.
  • GetFederationToken: IAM user calls it, 15 min–36 h, needs a session policy.
  • Prefer Identity Center / SAML over a custom broker.

Latest AWS update · IAM outbound identity federation (November 2025)

Everything in this lecture so far brings an outside identity into AWS (SAML, OIDC, Roles Anywhere). Outbound identity federation goes the other way. An AWS workload, such as a Lambda function or an EC2 role, asks AWS STS for a short-lived, signed JSON Web Token (JWT) and shows it to an external service: another cloud, a SaaS API or your own application. The external service trusts your account’s token issuer, so you never store that service’s long-term API keys in AWS.

Turn it on once per account in IAM → Account settings. AWS then gives the account a unique issuer URL that publishes /.well-known/openid-configuration and its public keys. Workloads call sts:GetWebIdentityToken; tokens last 60 seconds to 1 hour (default 5 minutes), are signed with ES384 or RS256, and every call is logged in CloudTrail.
Think of it like · a visitor badge printed by your own reception desk
AWS conceptFamiliar thing
GetWebIdentityToken≈Asking reception to print a badge for an employee who is visiting a partner company
Issuer URL + public keys≈The partner’s guard has your company’s official stamp on file and checks it
Short token lifetime≈The badge expires after the meeting, so a lost badge is useless tomorrow
AssumeRoleWithWebIdentity≈The opposite: a visitor from outside shows their badge to get into your building
Real AWS example · let one role mint short tokens for one partner API only
{
  "Effect": "Allow",
  "Action": "sts:GetWebIdentityToken",
  "Resource": "*",
  "Condition": {
    "StringEquals": {
      "sts:IdentityTokenAudience": "https://api.partner.example",
      "sts:SigningAlgorithm": "ES384"
    },
    "NumericLessThanEquals": { "sts:DurationSeconds": "300" }
  }
}

Attach this to the Lambda execution role. The partner configures your issuer URL as a trusted OIDC provider and checks the audience and the claims that identify your account and role.

Exam-style scenario

A Lambda function must call a SaaS provider’s API, which accepts OIDC tokens. The security team forbids storing the provider’s API key anywhere in AWS. Which solution has the LEAST operational overhead?

  1. A. Store the API key in Secrets Manager with automatic rotation.
  2. B. Turn on outbound identity federation, allow the execution role sts:GetWebIdentityToken for the provider’s audience, and have the provider trust the account’s issuer URL.
  3. C. Create a Cognito user pool user for the function.
  4. D. Call AssumeRoleWithWebIdentity with a token from the provider.
Show the worked answer

Answer: B

The function gets a fresh short-lived JWT on every call and no secret exists to store or rotate.

Why not the others

  • A: Still stores the forbidden key.
  • C: User pools are for app users, and this adds a password to manage.
  • D: That is inbound federation: it turns an outside token into AWS credentials, not the other way round.
How the exam tests this
  • “AWS workload must authenticate to an external service without long-term keys”→ Outbound identity federation (sts:GetWebIdentityToken).
  • “External or mobile identity must get AWS credentials”→ AssumeRoleWithWebIdentity / Cognito identity pool (inbound).
  • “Limit token lifetime or audience”→ sts:DurationSeconds, sts:IdentityTokenAudience.
Must remember
  • Outbound = AWS creds → JWT for an outside service.
  • Enable in IAM account settings; one issuer URL per account.
  • Token life 60 s – 1 h, default 5 min.
  • Inbound is AssumeRoleWithWebIdentity; don’t mix them up.
09

Lecture summary map

Day 3 on one screen: the mind map, the “who gets which credential” picture, and the keyword chart.

1. Mind map

① STSASIA + secret + tokenAssumeRole 1 h defaultChaining max 1 h② Trust policyWHO may assumeAWS / Service / FederatedRecreated role breaks it③ Confused deputyCross-account: ExternalIdCross-service: SourceArnOrg-wide: SourceOrgID④ SessionsRevoke: TokenIssueTimeTags need sts:TagSessionSource identity = who⑤ Presigned URLSigner's permissionsConsole 12 h · SDK 7 dDies with signer creds⑥ Roles AnywhereX.509 → temp credsTrust anchor + profilePin aws:SourceArn⑦ Workload rolesECS task vs executionIRSA / Pod IdentityIMDSv2 · PassRoleIAM Day 3temporary credentials
Tap a branch to jump back to that part of the lecture. Try redrawing this map from memory on paper.

2. Who gets which kind of access

Employee at a laptop→IAM Identity Center / SAML federationAssumeRoleWithSAMLApp on EC2 / Lambda / ECS→Role attached to the serviceservice assumes itPod on EKS→IRSA or EKS Pod IdentityAssumeRoleWithWebIdentityServer in your data centre→IAM Roles AnywhereX.509 certificatePartner or SaaS vendor→Cross-account role + ExternalIdAssumeRoleSomeone without AWS access→S3 presigned URLsigner's permissions
If you can fill in the right-hand column from memory, you can answer most Day 3 questions.

3. “If the question says… pick…”

Credentials begin with ASIATemporary STS credentials
Session fails after exactly one hour in a role chainRole chaining 1-hour cap
Require MFA before admin CLI actionsRole trust policy with aws:MultiFactorAuthPresent
Trust policy shows AROA… instead of an ARNRole was deleted and recreated
Vendor assumes roles in many customer accountssts:ExternalId
Service principal writes to your bucket/topicaws:SourceArn / aws:SourceAccount
Leaked role credentialsRevoke active sessions
IdP passes session tags, AssumeRole failsAdd sts:TagSession to trust policy
Download link for a user with no AWS accountS3 presigned URL
Presigned URL dies earlySigned with temporary credentials
On-prem servers need AWS accessIAM Roles Anywhere
Container app AccessDeniedECS task role (not execution role)
GitHub Actions / EKS pods without keysOIDC + AssumeRoleWithWebIdentity, pin sub
Day 3 in one sentence

Nobody should carry a permanent key: everyone borrows a temporary badge from STS, and the trust policy decides who may borrow it.

10

Must-remember cheat sheet

1. ASIA = temporary, AKIA = long-term.
2. Temporary credentials need the session token.
3. AssumeRole: default 1 h, max 12 h (role setting), chaining 1 h.
4. GetSessionToken: no IAM APIs without MFA; only AssumeRole/GetCallerIdentity in STS.
5. Trust policy = who; permissions policy = what.
6. Cross-account assume: trust policy and caller's sts:AssumeRole.
7. Recreated role → trust policy shows principal ID; re-add ARN.
8. ExternalId = cross-account confused deputy.
9. SourceArn / SourceAccount = cross-service confused deputy.
10. Revoke sessions = AWSRevokeOlderSessions on aws:TokenIssueTime.
11. Session tags need sts:TagSession; max 50.
12. Presigned URL: console 12 h, SDK 7 d, dies with signer creds.
13. s3:signatureAge caps URL age (milliseconds).
14. Roles Anywhere: trust anchor + profile + role trusting rolesanywhere.
15. ECS: task role = app; execution role = agent.
16. IRSA: AssumeRoleWithWebIdentity; pin sub.
17. Lambda: execution role = what it does; function policy = who invokes it.
18. GetFederationToken: IAM user calls it, up to 36 h, pass a session policy.
19. Outbound federation: sts:GetWebIdentityToken → JWT for an external service (default 5 min, max 1 h).
11

Core quiz

Check the basics first. Pick an answer, then press Check.

12

Hard quiz

Harder than most real exam questions on purpose. Many combine two rules. Aim for 9 out of 12 before Day 4.

13

Practice test questions (from your mock exams)

These questions come from your own mock exams (the SCS-003 mock 1–9 files in your study folder), matched to this lecture. Wording was tidied and checked against current AWS behavior; where a mock answer was outdated or wrong, the explanation says so. The source is shown at the end of each explanation, like “(Mock 5 · Q12)”. Pick an answer, then press Check. Questions marked (New) were written in October 2026 for exam-guide skills or AWS changes that the mocks don’t cover.

14

Hands-on lab (30 minutes)

  1. Create role lab-mfa-admin whose trust policy allows your IAM user only when aws:MultiFactorAuthPresent is true. Try aws sts assume-role without and then with --serial-number and --token-code.
  2. Run aws sts get-caller-identity with the new credentials and note the assumed-role ARN and the ASIA key.
  3. Create a presigned URL with aws s3 presign … --expires-in 120, open it in a private browser window, wait 2 minutes and try again.
  4. On the role, choose Revoke active sessions, then retry a call with the old credentials and read the error.