Asterrr's Handbook

Temporary credentials and STS

Choosing the right AWS STS API, external IDs against the confused deputy, session policies, tags and source identity, IAM Roles Anywhere, presigned URLs, access key hygiene and centralized root access.

Exam tasks: 4.1 (Skills 4.1.2 mechanisms that issue temporary credentials, 4.1.3 troubleshooting authentication with CloudTrail), 4.2 (Skills 4.2.1 role trust policies and IAM Roles Anywhere, 4.2.3 session policies)

The decision: who (or what) is asking for credentials, what have they already proved, and which STS call turns that proof into the shortest-lived, narrowest session that works?

Which STS API

APICaller signs withLifetime (default / max)MFA in callSession policyWatch out for
AssumeRoleUser or role creds1 h / role max (up to 12 h)YesYesRole chaining caps at 1 hour
AssumeRoleWithSAMLNothing (assertion)1 h / role maxNo, done by IdPYesTrust policy checks SAML:aud
AssumeRoleWithWebIdentityNothing (JWT)1 h / role maxNo, done by IdPYesTrust policy must pin aud and sub
GetSessionTokenIAM user (or root)12 h / 36 h (root 1 h)YesNoCan't call IAM without MFA, can only call AssumeRole in STS
GetFederationTokenIAM user (or root)12 h / 36 h (root 1 h)NoYes, required to get any permissionCan't call IAM or STS through the API
AssumeRootManagement or delegated admin principal15 min maxn/aTask policy (fixed list)Regional endpoint only
  • Every session is at least 15 minutes. Set the role's maximum session duration from 1 to 12 hours.
  • Role chaining (a role session assuming another role) is limited to 1 hour, whatever the role's maximum.
  • sts:GetCallerIdentity needs no permission and always works. It's the first call when debugging "who am I?"
  • Credentials already issued stay valid until they expire, even if you change the role. See revoking sessions.

Exam signal

"CI system (GitHub Actions, GitLab) must deploy without stored keys" means an IAM OIDC provider and AssumeRoleWithWebIdentity, with a trust policy that pins the repository in the sub claim. "Servers in our data centre with certificates from our PKI" means IAM Roles Anywhere.

Trust policies and the confused deputy

A role has two policies: the trust policy (who may assume it) and the permissions policies (what the session may do). Both must be right.

  • Third party assumes your role: require an sts:ExternalId the vendor generates per customer. Without it, another customer of the same vendor could trick the vendor into using your role. That's the confused deputy.
  • AWS service acts on your resource: in resource policies, condition on aws:SourceArn or aws:SourceAccount so the service only acts for your resource, not someone else's.
  • OIDC: never trust a provider without conditions on aud and sub. A GitHub trust with no sub condition lets any repository on GitHub assume the role.
{
  "Effect": "Allow",
  "Principal": { "AWS": "arn:aws:iam::210987654321:root" },
  "Action": "sts:AssumeRole",
  "Condition": { "StringEquals": { "sts:ExternalId": "fernhill-7Q2K9" } }
}

External ID as a secret

The external ID isn't a password, and you shouldn't generate it yourself. It stops the vendor being confused between customers. Protection against someone stealing the vendor's credentials comes from the vendor's own security, not the external ID.

Shaping a session

FeaturePassed asWhat it does
Session policyPolicy (inline) and up to 10 PolicyArnsCaps the session to the intersection with the role's policies
Session tagsTags, or SAML/OIDC attributesBecome aws:PrincipalTag/... for ABAC. Need sts:TagSession in the trust policy
Transitive tagsTransitiveTagKeysSurvive role chaining
Source identitySourceIdentitySet once, can't be changed down the chain, logged in CloudTrail. Needs sts:SetSourceIdentity
Session nameRoleSessionNameAppears in the session ARN and CloudTrail. Condition on sts:RoleSessionName to force a username

Exam signal

"Trace which employee did an action after several role hops" means source identity. The session name can be changed at each hop. Source identity can't.

IAM Roles Anywhere

  • For workloads outside AWS (on-prem servers, other clouds, edge devices) that hold an X.509 certificate.
  • Trust anchor: your CA, either AWS Private CA or an uploaded external CA bundle. Profile: which roles can be assumed and an optional session policy. Role: trusts rolesanywhere.amazonaws.com, ideally with aws:SourceArn pinned to the trust anchor and conditions on certificate attributes.
  • The credential helper signs CreateSession with the private key and returns standard temporary credentials.
  • Import a CRL to revoke certificates. Protect the private key, ideally in a TPM or HSM.

Presigned URLs

  • S3 presigned URLs let someone without AWS credentials GET or PUT one object until expiry.
  • The URL carries the signer's permissions. If those credentials are temporary, the URL dies when they expire, whatever expiry you set. Maximum 7 days with SigV4 and long-term keys.
  • Restrict their use with bucket policy conditions such as s3:signatureAge or aws:SourceIp.

Revoking and hygiene

  • Revoke active role sessions: "Revoke active sessions" on the role adds an inline deny with aws:TokenIssueTime earlier than now. Fixing the policy alone doesn't end sessions already issued. See compromised credentials.
  • Access keys: at most 2 per user, so you can rotate: create, switch, deactivate, delete. Find old or unused keys with the credential report (all users, generated at most every 4 hours, as CSV) and GetAccessKeyLastUsed.
  • Prefer roles for EC2 (instance profiles), Lambda and ECS tasks. Their credentials rotate automatically.
15 min
Minimum session length for any STS credential.
12 h
Highest maximum session duration you can set on a role.
1 h
Cap for chained role sessions, and for root GetSessionToken.
36 h
Longest GetSessionToken or GetFederationToken session for an IAM user.
2
Access keys per IAM user.
4 h
How often you can generate a fresh credential report.

Root user protection

  • Enable centralized root access in the IAM console for the organization. Then you can delete root credentials (password, keys, MFA, certificates) in member accounts, and new accounts have none.
  • Root-only tasks run from the management account or IAM delegated admin with sts:AssumeRoot, scoped by an AWS managed task policy: audit root credentials, delete root credentials, allow password recovery, unlock an S3 bucket policy that denies everyone, unlock an SQS queue policy that denies everyone.
  • For the management account itself (and standalone accounts): MFA on root, no root access keys, alert on root sign-in with EventBridge.
  • Add an SCP that denies actions by arn:aws:iam::*:root in member accounts as a second layer.

Legacy: use Centralized root access with sts:AssumeRoot instead

Keeping a root password and MFA device per member account in a safe, just to fix a locked bucket policy, is no longer necessary. Remove member root credentials and use privileged root tasks instead.

Scenarios

Scenario
A monitoring vendor needs read-only access to 30 customer accounts, including yours. The vendor's platform assumes a role in each customer's account from its own AWS account. What should your role's trust policy contain to prevent the confused deputy problem?
Scenario
An analytics job assumes role A, then from that session assumes role B in another account. Role B has a maximum session duration of 8 hours, and the job requests 4 hours. The call fails. Why?
Scenario
A bank's platform team removed the root passwords from 200 member accounts after enabling centralized root access. A developer then applied a bucket policy that denies s3:* to all principals, and now nobody can edit it. What should the security team do?

Further reading

On this page