Fatskills
Practice. Master. Repeat.
Study Guide: TECH **AWS Security Token Service (STS) & Temporary Credentials: Zero-Fluff Study Guide**
Source: https://www.fatskills.com/aws-certified-solutions-architect-associate/chapter/tech-aws-security-token-service-sts-temporary-credentials-zero-fluff-study-guide

TECH **AWS Security Token Service (STS) & Temporary Credentials: Zero-Fluff Study Guide**

By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.

⏱️ ~8 min read

AWS Security Token Service (STS) & Temporary Credentials: Zero-Fluff Study Guide

For AWS Solutions Architect – Associate (SAA-C03) and Real-World Production


1. What This Is & Why It Matters

STS (Security Token Service) is AWS’s service for issuing short-lived, temporary credentials instead of long-lived IAM access keys. Think of it like a hotel keycard—it works for a limited time, then expires automatically. If someone steals it, they can’t use it forever.

Why This Matters in Production

  • Security: Long-lived IAM keys are a top cause of AWS breaches (e.g., hardcoded in GitHub repos, leaked in logs). Temporary credentials reduce this risk.
  • Compliance: Many security frameworks (SOC2, HIPAA, PCI-DSS) require short-lived credentials.
  • Federation: STS lets you grant AWS access to external users (e.g., contractors, partners) without creating IAM users.
  • Cross-Account Access: Securely delegate permissions between AWS accounts (e.g., Dev → Prod, Vendor → Your Account).

Real-World Scenario

You’re a cloud engineer at a fintech startup. Your CI/CD pipeline needs to deploy code to AWS, but your security team bans long-lived IAM keys. You must: 1. Replace hardcoded keys with temporary credentials.
2. Grant least-privilege access to the pipeline.
3. Rotate credentials automatically (no manual intervention).

If you ignore STS:
- Your IAM keys get leaked → attackers drain your AWS account.
- Auditors fail your compliance check → fines or lost contracts.
- Cross-account access becomes a nightmare (manual key sharing = security risk).


2. Core Concepts & Components


1. Temporary Credentials

  • What: Short-lived AWS credentials (access key, secret key, session token) that expire after 15 minutes to 36 hours (default: 1 hour).
  • Production Insight: Always set the minimum required duration (e.g., 15 mins for a CI job, 1 hour for a developer session). Longer durations = higher risk.

2. STS API Calls

API Call Purpose Production Use Case
AssumeRole Get temp creds for an IAM role Cross-account access, CI/CD pipelines
AssumeRoleWithSAML Federate with SAML (e.g., Okta, ADFS) Enterprise SSO
AssumeRoleWithWebIdentity Federate with OIDC (e.g., Google, Cognito) Mobile/web apps
GetSessionToken Get temp creds for an IAM user MFA-protected access
GetFederationToken Get temp creds for a federated user Legacy apps (avoid; prefer AssumeRole)

3. IAM Roles

  • What: A set of permissions that temporary credentials can assume. Unlike IAM users, roles have no long-lived credentials.
  • Production Insight: Always use roles instead of IAM users for applications, EC2 instances, Lambda functions, etc.

4. Trust Policy

  • What: Defines who can assume a role (e.g., an AWS account, a SAML provider, an OIDC identity).
  • Example:
    json {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Principal": { "AWS": "arn:aws:iam::123456789012:root" },
    "Action": "sts:AssumeRole"
    }
    ] }
  • Production Insight: Restrict the Principal to specific accounts/identities. Wildcards (*) are a security risk.

5. Session Policy

  • What: An optional inline policy that further restricts permissions for a temporary session.
  • Example: A role has s3:*, but a session policy limits it to s3:GetObject for a specific bucket.
  • Production Insight: Use session policies to enforce least privilege for temporary access.

6. External IDs

  • What: A secret string used in AssumeRole to prevent the "confused deputy" problem (a malicious actor tricking your role into acting on their behalf).
  • Example:
    bash aws sts assume-role --role-arn arn:aws:iam::123456789012:role/MyRole --role-session-name MySession --external-id "SuperSecret123"
  • Production Insight: Always use External IDs for cross-account access. Without it, attackers can exploit trust relationships.

7. MFA-Protected API Access

  • What: Require multi-factor authentication (MFA) for sensitive API calls (e.g., DeleteBucket).
  • Example IAM Policy:
    json {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Action": "s3:DeleteBucket",
    "Resource": "*",
    "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } }
    }
    ] }
  • Production Insight: Enforce MFA for all destructive actions (e.g., Delete*, Terminate*, Update*).

8. AWS STS Endpoints

  • Global: https://sts.amazonaws.com (default)
  • Regional: https://sts.<region>.amazonaws.com (e.g., sts.us-east-1.amazonaws.com)
  • Production Insight: Use regional endpoints for lower latency and compliance (e.g., EU data residency requirements).


3. Step-by-Step Hands-On: Replace Long-Lived Keys with STS Temporary Credentials


Prerequisites

  • AWS account with admin IAM permissions.
  • AWS CLI installed (aws --version).
  • A CI/CD pipeline (e.g., GitHub Actions, GitLab CI) or a local script that needs AWS access.

Goal

Replace hardcoded IAM keys in a CI/CD pipeline with STS temporary credentials using AssumeRole.


Step 1: Create an IAM Role for the Pipeline

  1. Go to IAM > Roles > Create Role.
  2. Trusted entity type: AWS account.
  3. An AWS account: Select Another AWS account and enter your account ID.
  4. External ID (optional but recommended): Enter a secret string (e.g., GitHubActionsSecret123).
  5. Permissions: Attach a policy (e.g., AmazonS3FullAccess for this example).
  6. Role name: GitHubActionsDeployRole.
  7. Create the role.

Verify the trust policy:


aws iam get-role --role-name GitHubActionsDeployRole

Expected output (truncated):


{
  "Role": {
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789012:root" },
"Action": "sts:AssumeRole",
"Condition": { "StringEquals": { "sts:ExternalId": "GitHubActionsSecret123" } }
}
]
} } }


Step 2: Configure GitHub Actions to Use STS

  1. Store the External ID as a GitHub Secret:
  2. Go to GitHub Repo > Settings > Secrets > Actions.
  3. Add a secret named AWS_EXTERNAL_ID with value GitHubActionsSecret123.

  4. Create a GitHub Actions Workflow (.github/workflows/deploy.yml):
    ```yaml
    name: Deploy to AWS
    on: [push]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: us-east-1
role-session-name: GitHubActionsDeploy
role-external-id: ${{ secrets.AWS_EXTERNAL_ID }}
role-duration-seconds: 900 # 15 minutes
```

Why this works:
- GitHub Actions assumes the role using STS.
- The role-external-id prevents the confused deputy attack.
- Credentials expire after 15 minutes (least privilege).


Step 3: Test Locally (Optional)

  1. Assume the role manually:
    bash
    aws sts assume-role \
    --role-arn arn:aws:iam::123456789012:role/GitHubActionsDeployRole \
    --role-session-name TestSession \
    --external-id GitHubActionsSecret123
  2. Export the temporary credentials:
    bash
    export AWS_ACCESS_KEY_ID=ASIA...
    export AWS_SECRET_ACCESS_KEY=...
    export AWS_SESSION_TOKEN=...
  3. Test access:
    bash
    aws s3 ls # Should list buckets if the role has S3 permissions

Step 4: Verify in AWS CloudTrail

  1. Go to CloudTrail > Event History.
  2. Filter for AssumeRole events.
  3. Check the userIdentity field to confirm the role was assumed by GitHub Actions.

4. ? Production-Ready Best Practices


Security

  • Never hardcode long-lived IAM keys in code, CI/CD, or config files.
  • Enforce MFA for all AssumeRole calls (use aws:MultiFactorAuthPresent condition).
  • Use External IDs for cross-account access.
  • Restrict role trust policies to specific accounts/identities (no *).
  • Rotate External IDs if compromised (treat them like passwords).

Cost Optimization

  • Set the shortest possible session duration (e.g., 15 mins for CI jobs, 1 hour for dev sessions).
  • Use regional STS endpoints to reduce latency (and costs for cross-region calls).

Reliability & Maintainability

  • Tag IAM roles with Environment, Owner, and Purpose.
  • Use session policies to enforce least privilege for temporary access.
  • Monitor AssumeRole failures in CloudTrail (e.g., AccessDenied errors).

Observability

  • CloudTrail: Log all AssumeRole events.
  • CloudWatch Alarms: Alert on unusual AssumeRole patterns (e.g., spikes in failed attempts).
  • IAM Access Analyzer: Detect unused roles and overly permissive trust policies.


5. ⚠️ Common Mistakes & Traps

Mistake Symptom Fix/Prevention
Not using External ID Attackers exploit trust relationships to assume your role. Always use sts:ExternalId in trust policies.
Overly permissive trust policies Any AWS account can assume your role. Restrict Principal to specific accounts/identities.
Long session durations Temporary credentials live too long → higher risk. Set DurationSeconds to the minimum required (e.g., 900 for CI jobs).
Hardcoding IAM keys in CI/CD Keys leak in logs or Git history → account compromise. Use AssumeRole with GitHub Actions/GitLab CI.
Ignoring MFA for sensitive actions Users delete resources without MFA → accidental data loss. Enforce MFA in IAM policies (e.g., aws:MultiFactorAuthPresent: true).


6. ? Exam/Certification Focus (AWS SAA-C03)


Typical Question Patterns

  1. Scenario: "A developer needs temporary access to an S3 bucket in another AWS account. What’s the most secure way?"
  2. Correct Answer: AssumeRole with an External ID.
  3. Trap: GetFederationToken (not for cross-account) or hardcoded IAM keys.

  4. Scenario: "A mobile app needs to upload files to S3. How should it authenticate?"

  5. Correct Answer: AssumeRoleWithWebIdentity (OIDC federation with Cognito).
  6. Trap: IAM user keys (long-lived = security risk).

  7. Scenario: "A company uses Okta for SSO. How should employees access AWS?"

  8. Correct Answer: AssumeRoleWithSAML.
  9. Trap: Creating IAM users for each employee (scalability nightmare).

Key ⚠️ Trap Distinctions

Concept Trap Reality
AssumeRole vs GetSessionToken GetSessionToken is for cross-account access. GetSessionToken is for IAM users, AssumeRole is for roles.
Session Duration Default is 1 hour (good for most cases). Minimum is 15 mins, maximum is 36 hours (12 hours for GetFederationToken).
External ID Only needed for SAML/OIDC. Always use for cross-account AssumeRole (prevents confused deputy).


7. ? Hands-On Challenge


Challenge

Your team uses a legacy script that hardcodes IAM keys. Replace them with STS temporary credentials using AssumeRole. The script runs on an EC2 instance and needs S3 read-only access.

Solution

  1. Create an IAM role for EC2:
  2. Trust policy:
    json
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Principal": { "Service": "ec2.amazonaws.com" },
    "Action": "sts:AssumeRole"
    }
    ]
    }
  3. Attach AmazonS3ReadOnlyAccess policy.
  4. Name: EC2S3ReadOnlyRole.

  5. Attach the role to the EC2 instance:

  6. Go to EC2 > Instances > Actions > Security > Modify IAM Role.
  7. Select EC2S3ReadOnlyRole.

  8. Update the script to use the role’s temporary credentials:
    bash
    # No need to hardcode keys! The EC2 instance metadata service provides temp creds.
    aws s3 ls s3://your-bucket-name

Why this works:
- EC2 automatically assumes the role and gets temporary credentials from the instance metadata service (169.254.169.254).
- No hardcoded keys = no security risk.


8. ? Rapid-Reference Crib Sheet

Command/Concept Example Notes
AssumeRole (CLI) aws sts assume-role --role-arn arn:aws:iam::123456789012:role/MyRole --role-session-name Test ⚠️ Add --external-id for cross-account.
AssumeRole (Python) sts_client.assume_role(RoleArn="...", RoleSessionName="...") Use boto3.
Session Duration --duration-seconds 900 Min: 900 (15 mins), Max: 3600 (1 hour) for AssumeRole.
External ID --external-id "SuperSecret123" Always use for cross-account.
MFA Condition "Condition": { "Bool": { "aws:MultiFactorAuthPresent": "true" } } Enforce MFA in IAM policies.
EC2 Instance Metadata curl http://169.254.169.254/latest/meta-data/iam/security-credentials/EC2S3ReadOnlyRole Returns temp creds for the instance’s role.
STS Regional Endpoint https://sts.us-east-1.amazonaws.com Use for lower latency.
Trust Policy "Principal": { "AWS": "arn:aws:iam::123456789012:root" } ⚠️ Restrict to specific accounts.
Session Policy "Policy": "{ \"Version\": \"2012-10-17\", \"Statement\": [...] }" Further restrict permissions for a session.


9. ? Where to Go Next

  1. AWS STS Documentation – Official API reference.
  2. IAM Best Practices – How to secure IAM roles and policies.
  3. AWS Security Token Service Deep Dive (YouTube) – Video walkthrough of STS use cases.
  4. GitHub Actions OIDC with AWS – Secure CI/CD with STS.


ADVERTISEMENT