AWS CLI First #2: Multi-Account Profiles, STS AssumeRole & MFA-Enforced Temporary Credentials
Graduate from static access keys to enterprise-grade cloud security. Learn how to configure multi-account profiles, assume IAM roles via AWS STS, enforce MFA on the terminal, and automate profile chaining in ~/.aws/config using a simulated zero-privilege engineer.
AWS with CLI: The Terminal-First Mastery Path
Part of the CLI-first comprehensive learning path from foundational setup to production cloud architectures.
In Part 1: Installation, Root Setup & IAM Admin User Provisioning, we established our terminal environment and generated long-lived access keys for our initial administrator user (cloud-dev-admin).
While static administrator access keys are convenient for initial bootstrapping, in real-world production environments giving developers permanent administrative keys is a critical security vulnerability:
- Permanent Blast Radius: If a developer’s laptop is compromised or a static key is accidentally committed to a repository, attackers retain unexpiring access until an administrator manually revokes it.
- No Automatic Expiration: Static keys never expire on their own.
- No Native MFA Gating: A stolen static access key can be used from any IP address worldwide without triggering a two-factor authentication challenge.
In this guide, we transition to modern cloud security: Dynamic Identity via AWS Security Token Service (STS) and IAM Roles.
By the end of this guide, you will:
- Understand the architectural difference between static keys (
AKIA...) and temporary session tokens (ASIA...). - Master the dual structure of an IAM Role: Trust Policy (Who can assume) vs Permission Policy (What it can do).
- Demystify AWS resource addressing by decoding the Amazon Resource Name (ARN) syntax.
- Simulate an enterprise workflow by provisioning a Zero-Privilege Engineer (
engineer-bob) and an assumed deployment role (CloudStagingDeployer). - Provision Virtual MFA devices from the CLI and enforce
aws:MultiFactorAuthPresentconditions. - Configure Automated Profile Chaining in
~/.aws/configfor seamless, 1-hour cached terminal sessions with interactive MFA prompts.
💰 Estimated Lab Cost
| Component | Usage in Lab | AWS Cost |
|---|---|---|
| AWS STS (AssumeRole API) | Dynamic Token Generation | $0.00 (100% Free) |
| AWS IAM Roles & Trust Policies | Temporary Access Delegation | $0.00 (100% Free) |
| Total Estimated Cost | Complete Hands-On Session | $0.00 (100% Free) |
Core Concept: Static Keys vs Temporary Credentials
Let’s look at the credential prefixes emitted by AWS authentication APIs:
| Credential Type | Prefix | Nature | Lifetime | Stored In |
|---|---|---|---|---|
| Static IAM User Key | AKIA... | Long-lived, permanent | Forever (until revoked) | ~/.aws/credentials |
| Temporary Session Key | ASIA... | Short-lived, dynamic | 15 minutes – 12 hours | Session Token / Memory Cache |
When you use an IAM Role, AWS never issues an AKIA key. Instead, the AWS Security Token Service (STS) issues an ephemeral ASIA access key, a companion secret key, and a cryptographically signed Session Token.
+-----------------------------------------------------------------------------------+
| AWS STS Role Assumption Workflow |
+-----------------------------------------------------------------------------------+
|
1. Base User Auth (AKIA...) + MFA Code |
---------------------------------------->|
v
+------------------------------------+
| AWS Security Token Service (STS) |
| -> Validates caller identity |
| -> Evaluates Role Trust Policy |
| -> Verifies MFA TOTP code |
+------------------------------------+
|
2. Issues Temporary Credentials (ASIA...) |
<----------------------------------------+
- AccessKeyId: ASIAXXXXXXXXXXXXXXXX (Valid for 1 hour)
- SecretAccessKey: wJalrXUtnFEMI/...
- SessionToken: AQoDYXdzEJr1...
Core Concept: The Two Halves of an IAM Role
Unlike an IAM User (which represents a physical person or static service), an IAM Role is an assumed identity with no permanent credentials. Every IAM Role is defined by two distinct policy documents:
+--------------------------------------------------------------------+
| IAM Role |
| |
| [ 1. Trust Policy (AssumeRolePolicyDocument) ] |
| -> Question: "WHO is allowed to assume this role?" |
| -> Example: Trust user 'engineer-bob' + Require active MFA |
| |
| [ 2. Permission Policy (Identity-based Policy) ] |
| -> Question: "WHAT is this role allowed to do once assumed?" |
| -> Example: Manage EC2 instances, read S3 buckets |
+--------------------------------------------------------------------+
- The Trust Policy (
AssumeRolePolicyDocument): Specifies the trusted principals (users, services, or external accounts) permitted to callsts:AssumeRole. - The Permission Policy: Defines the specific AWS API actions and resources the assumed identity can interact with.
Core Concept: IAM Groups vs IAM Roles (The Enterprise Mental Model)
In Part 1, we used an IAM Group (Administrators) to organize users. Now in Part 2, we introduce IAM Roles.
A common question every cloud engineer asks is: “When do I use a Group, and when do I use a Role?”
The fundamental distinction is simple:
- A Group is for ORGANIZING HUMANS (who they are).
- A Role is for GRANTING TEMPORARY HATS (what they are doing right now).
+-----------------------------------------------------------------------------------+
| Group vs Role Architecture Pipeline |
+-----------------------------------------------------------------------------------+
[ Bob ] ---> joins ---> [ 'Developers' Group ]
|
| (Baseline: Self-service password & MFA reset only;
| Zero standing infrastructure privileges)
v
[ 'CloudStagingDeployer' Role ]
|
| (Assumed dynamically with MFA for 1 hour)
v
[ 200 OK: Deploy Staging Infrastructure! ]
Key Differences & Decision Framework:
| Scenario / Requirement | Use Group or Role? | Technical Reason |
|---|---|---|
| Human User Baseline | IAM Group | Organize team members (e.g. Developers) with baseline self-service policies. |
| Infrastructure Modifications | IAM Role | Requires temporary, audited, short-lived STS credentials (ASIA...) with MFA. |
| Server / Compute Access | IAM Role | EC2 instances, ECS tasks, and Lambda functions cannot hold permanent passwords or join groups; they assume roles directly. |
| Cross-Account Access | IAM Role | IAM Groups cannot cross AWS account boundaries; IAM Roles can be assumed across accounts. |
| 3rd-Party SaaS / CI/CD | IAM Role | Platforms like GitHub Actions or Datadog assume roles via OIDC/ExternalId without storing static AWS keys. |
Core Concept: Enterprise Separation of Duties
In production engineering organizations, identity management adheres to a strict Separation of Duties:
+-----------------------------------------------------------------------------------+
| Enterprise Separation of Duties |
+-----------------------------------------------------------------------------------+
[ Platform / SecOps Team ] [ Software Developer ]
(The Cloud Administrators) (The Role Consumer: Bob)
| |
| 1. Provisions 'StagingDeployer' Role |
| 2. Attaches Trust & Permission Docs |
| 3. Shares Role ARN with Developer |
|-------------------------------------->|
| | 4. Adds Profile to ~/.aws/config
| | 5. Assumes Role via CLI with MFA
| | (Zero permanent keys!)
1. In an Enterprise Organization:
- The Platform / SecOps Team (The Gatekeepers): Use Infrastructure as Code (Terraform, AWS CDK) to provision accounts, write trust policies, and attach least-privilege permission boundaries.
- The Software Engineers (The Consumers): Never create their own roles or policies (preventing privilege escalation). They are assigned an unprivileged base identity and a Role ARN, assuming permissions dynamically via MFA.
2. In Our Hands-On Simulation:
Because we are working in our personal AWS environment, we will wear two hats:
- Hat 1 (The Administrator -
cloud-dev-admin): Provisions users, createsCloudStagingDeployer, and configures security policies. - Hat 2 (The Engineer -
engineer-bob): Operates with zero baseline permissions, dynamically assuming the staging role through the CLI.
Core Concept: Decoding the Amazon Resource Name (ARN)
Throughout AWS CLI commands and policies, every resource is addressed by its Amazon Resource Name (ARN):
arn : partition : service : region : account-id : resource-type / resource-id
│ │ │ │ │ │ │
1 2 3 4 5 6 7
The 6 Colon-Separated Fields:
arn: Universal literal prefix.partition: Cloud boundary (awsfor Standard Commercial,aws-cnfor China,aws-us-govfor GovCloud).service: AWS service namespace (iam,sts,s3,ec2,lambda).region: Geographical region (e.g.ap-southeast-1). Left blank (::) for global services like IAM.account-id: The 12-digit AWS Account ID owning the resource (e.g.123456789012).- Note: Root,
cloud-dev-admin, andengineer-boball share the exact same Account ID because they reside in the same account container. - AWS-Managed Policies: Use
awsinstead of an account number (arn:aws:iam::aws:policy/AdministratorAccess). - S3 Buckets: Omit the account ID entirely (
arn:aws:s3:::my-bucket-name) as bucket names are globally unique.
- Note: Root,
resource-type&resource-id: Specific asset path (user/engineer-bob,role/CloudStagingDeployer,mfa/engineer-bob-mfa).
ARN Comparison Reference:
| Entity | Example ARN | Purpose |
|---|---|---|
| Root Identity | arn:aws:iam::123456789012:root | Master account owner |
| Admin User | arn:aws:iam::123456789012:user/cloud-dev-admin | Administrator identity from Part 1 |
| Engineer User | arn:aws:iam::123456789012:user/engineer-bob | Zero-privilege developer user |
| IAM Role | arn:aws:iam::123456789012:role/CloudStagingDeployer | Target role to assume |
| Virtual MFA | arn:aws:iam::123456789012:mfa/engineer-bob-mfa | Virtual TOTP authenticator device |
| Managed Policy | arn:aws:iam::aws:policy/AmazonEC2FullAccess | AWS-maintained permission document |
| Assumed Role Session | arn:aws:sts::123456789012:assumed-role/CloudStagingDeployer/dev-session | Ephemeral session issued by STS |
Phase 1: Provisioning the Zero-Privilege Engineer (engineer-bob)
Let’s begin by acting as the Administrator (cloud-dev-admin) to provision a Developers group and our engineer user: engineer-bob.
Step 1: Create the Developers Group & User via Admin CLI
# 1. Create the Developers IAM Group
aws iam create-group \
--group-name Developers \
--profile cloud-dev-admin
# 2. Create the User
aws iam create-user \
--user-name engineer-bob \
--profile cloud-dev-admin
# 3. Add Bob to the Developers Group
aws iam add-user-to-group \
--user-name engineer-bob \
--group-name Developers \
--profile cloud-dev-admin
Step 2: Generate Access Keys for Bob
aws iam create-access-key \
--user-name engineer-bob \
--profile cloud-dev-admin \
--output json
Output:
{
"AccessKey": {
"UserName": "engineer-bob",
"AccessKeyId": "AKIAEXAMPLEBOBKEYID",
"Status": "Active",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYBOBSECRETKEY",
"CreateDate": "2026-08-28T04:00:00+00:00"
}
}
Step 3: Configure Bob’s Profile Locally
Add Bob’s credentials to your local AWS configuration:
aws configure set aws_access_key_id "AKIAEXAMPLEBOBKEYID" --profile engineer-bob
aws configure set aws_secret_access_key "wJalrXUtnFEMI/K7MDENG/bPxRfiCYBOBSECRETKEY" --profile engineer-bob
aws configure set region "ap-southeast-1" --profile engineer-bob
aws configure set output "json" --profile engineer-bob
Step 4: The “Zero Standing Privilege” Test
Now switch to Bob’s persona. What happens if Bob tries to access AWS resources directly using his static key?
# Attempt to list EC2 instances as Bob
aws ec2 describe-instances --profile engineer-bob
Result: 403 Access Denied!
An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation:
You are not authorized to perform this operation. User: arn:aws:iam::123456789012:user/engineer-bob
is not authorized to perform: ec2:DescribeInstances because no identity-based policy allows the ec2:DescribeInstances action
# Attempt to list S3 buckets as Bob
aws s3 ls --profile engineer-bob
Result: 403 Access Denied!
An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::123456789012:user/engineer-bob is not authorized to perform: s3:ListAllMyBuckets because no identity-based policy allows the s3:ListAllMyBuckets action
This confirms the Zero Standing Privilege model: even if Bob’s static credentials leak, they grant zero direct access to infrastructure.
Phase 2: Creating the CloudStagingDeployer IAM Role
Now, act as the Administrator (cloud-dev-admin) to create the scoped deployment role that Bob is authorized to assume.
Step 1: Retrieve Your Account ID
ACCOUNT_ID=$(aws sts get-caller-identity --profile cloud-dev-admin --query "Account" --output text)
Step 2: Create the Trust Policy JSON
Create staging-trust-policy.json specifying that only engineer-bob can assume this role:
cat <<EOF > staging-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${ACCOUNT_ID}:user/engineer-bob"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
[!WARNING] AWS Architectural Rule: IAM Groups are NOT Principals You might wonder: Can we put
"arn:aws:iam::${ACCOUNT_ID}:group/Developers"inside thePrincipalfield instead of Bob’s individual user ARN? No. In AWS IAM, an IAM Group is a management container for identity policies, but it is never a valid Principal. Trust policies only accept IAM Users, IAM Roles, AWS Account Roots, or AWS Service Principals.
[!TIP] Cross-Account SaaS &
sts:ExternalId(The Confused Deputy Solution): If you create a role intended for a 3rd-party SaaS platform (e.g. Datadog, GitHub Actions, Terraform Cloud) to assume into your account, AWS best practice mandates adding a uniquests:ExternalIdcondition:"Condition": { "StringEquals": { "sts:ExternalId": "my-secret-org-uuid" } }This prevents the Confused Deputy Attack, ensuring another client of that SaaS cannot trick the vendor into assuming your role.
Step 3: Provision the Role via CLI
aws iam create-role \
--role-name CloudStagingDeployer \
--assume-role-policy-document file://staging-trust-policy.json \
--description "Role for deploying staging infrastructure" \
--profile cloud-dev-admin
Verifying & Listing IAM Roles
List IAM roles to confirm the role was created:
# Query specifically for CloudStagingDeployer:
aws iam list-roles \
--query "Roles[?RoleName=='CloudStagingDeployer'].[RoleName, RoleId, Arn]" \
--output table \
--profile cloud-dev-admin
Output:
---------------------------------------------------------------------------------------------------------
| ListRoles |
+----------------------+----------------------+---------------------------------------------------------+
| CloudStagingDeployer| AROA4EXAMPLEUNIQUEID| arn:aws:iam::123456789012:role/CloudStagingDeployer |
+----------------------+----------------------+---------------------------------------------------------+
You can also inspect the full role definition and trust policy at any time with aws iam get-role:
aws iam get-role \
--role-name CloudStagingDeployer \
--profile cloud-dev-admin \
--output json
Step 4: Attach Permission Policies to the Role
Attach scoped permissions to manage EC2 instances and read S3 buckets:
# Attach AmazonEC2FullAccess
aws iam attach-role-policy \
--role-name CloudStagingDeployer \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2FullAccess \
--profile cloud-dev-admin
# Attach AmazonS3ReadOnlyAccess
aws iam attach-role-policy \
--role-name CloudStagingDeployer \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--profile cloud-dev-admin
Verify the attached policies:
aws iam list-attached-role-policies \
--role-name CloudStagingDeployer \
--profile cloud-dev-admin \
--output table
Phase 3: Manual Role Assumption with aws sts assume-role
Now, let’s switch to Bob’s perspective and perform a manual role assumption.
Step 1: Call sts assume-role as Bob
aws sts assume-role \
--role-arn "arn:aws:iam::${ACCOUNT_ID}:role/CloudStagingDeployer" \
--role-session-name "bob-staging-session" \
--duration-seconds 3600 \
--profile engineer-bob
STS JSON Response:
{
"Credentials": {
"AccessKeyId": "ASIA4EXAMPLEKEYID123",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "AQoDYXdzEJr1EXAMPLE...very-long-base64-token...",
"Expiration": "2026-08-28T05:15:00+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA4EXAMPLEUNIQUEID:bob-staging-session",
"Arn": "arn:aws:sts::123456789012:assumed-role/CloudStagingDeployer/bob-staging-session"
}
}
Notice the prefix: ASIA.... This indicates a temporary credential accompanied by a cryptographic SessionToken.
Step 2: Export Temporary Environment Variables & Test
Export these temporary credentials and target region into your current shell session:
export AWS_ACCESS_KEY_ID="ASIA4EXAMPLEKEYID123"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_SESSION_TOKEN="AQoDYXdzEJr1EXAMPLE...very-long-base64-token..."
export AWS_DEFAULT_REGION="ap-southeast-1"
[!NOTE] We also export
AWS_DEFAULT_REGION(e.g.ap-southeast-1) so regional services like EC2 know which data center to query without throwing a(NoRegion): You must specify a regionerror.
Re-run the exact EC2 command that previously failed:
aws ec2 describe-instances --output table
Result: 200 OK! The command succeeds because your active caller identity is now assumed-role/CloudStagingDeployer/bob-staging-session.
To revert back to Bob’s baseline unprivileged identity, unset the session variables:
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_DEFAULT_REGION
Phase 4: Setting Up Virtual MFA for Bob via AWS CLI
In production environments, role assumption should require Multi-Factor Authentication (MFA). Let’s create and enable a Virtual MFA device for engineer-bob directly from the command line.
Step 1: Create the Virtual MFA Device
As the Admin:
aws iam create-virtual-mfa-device \
--virtual-mfa-device-name "engineer-bob-mfa" \
--outfile ./bob-mfa-qr.png \
--bootstrap-method "QRCodePNG" \
--profile cloud-dev-admin
This outputs:
- An MFA device ARN:
arn:aws:iam::123456789012:mfa/engineer-bob-mfa - A QR Code image:
./bob-mfa-qr.png
Open and scan the QR code with your authenticator app (1Password, Google Authenticator, Authy):
# On macOS:
open ./bob-mfa-qr.png
Step 2: Enable the MFA Device for Bob
Submit two consecutive 6-digit TOTP codes (30 seconds apart) to synchronize the device:
MFA_ARN="arn:aws:iam::${ACCOUNT_ID}:mfa/engineer-bob-mfa"
aws iam enable-mfa-device \
--user-name engineer-bob \
--serial-number "$MFA_ARN" \
--authentication-code1 123456 \
--authentication-code2 654321 \
--profile cloud-dev-admin
Delete the QR code image for security:
rm -f ./bob-mfa-qr.png
Verify the active MFA device:
aws iam list-mfa-devices --user-name engineer-bob --profile cloud-dev-admin --output table
[!NOTE] Who Scans and Who Enables MFA in Real Life?
- Who scans the QR code? Bob does. The QR code contains the secret seed that must live inside Bob’s personal authenticator app (on his phone or laptop).
- Why did the Admin run
enable-mfa-device? In our simulation, Bob starts with zero permissions (preventing him from touching IAM). The Admin performs the initial device registration using Bob’s two verification codes.- In Enterprise Production: Organizations either attach a scoped self-service policy (
AllowSelfManageMFA) allowing developers to create and activate their own MFA device (arn:aws:iam::...:mfa/${aws:username}), or enforce MFA centrally through Corporate SSO (Okta / Google Workspace). We will build this exact self-service policy in Part 3!
Phase 5: Hardening the Role Trust Policy with MFA Enforcement
Now, let’s enforce that no one (including Bob) can assume CloudStagingDeployer without presenting a valid MFA token.
Step 1: Update the Trust Policy with Condition
Create mfa-enforced-trust-policy.json:
cat <<EOF > mfa-enforced-trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${ACCOUNT_ID}:user/engineer-bob"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
}
}
}
]
}
EOF
Step 2: Apply the Hardened Policy via CLI
aws iam update-assume-role-policy \
--role-name CloudStagingDeployer \
--policy-document file://mfa-enforced-trust-policy.json \
--profile cloud-dev-admin
Clean up local JSON files:
rm -f staging-trust-policy.json mfa-enforced-trust-policy.json
If Bob attempts to assume the role without an MFA token:
aws sts assume-role \
--role-arn "arn:aws:iam::${ACCOUNT_ID}:role/CloudStagingDeployer" \
--role-session-name "test-session" \
--profile engineer-bob
Result: Access Denied!
An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:iam::123456789012:user/engineer-bob is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::123456789012:role/CloudStagingDeployer
Because the request was sent without an MFA token, the aws:MultiFactorAuthPresent: true condition evaluates to false, causing IAM to block role assumption via an implicit deny.
Step 3: Assume the Role Manually with MFA
To successfully assume the role now, Bob must supply his MFA Device ARN (--serial-number) and his current 6-digit TOTP code (--token-code):
MFA_ARN="arn:aws:iam::${ACCOUNT_ID}:mfa/engineer-bob-mfa"
# Replace 123456 with your current 6-digit code from your authenticator app
aws sts assume-role \
--role-arn "arn:aws:iam::${ACCOUNT_ID}:role/CloudStagingDeployer" \
--role-session-name "bob-mfa-session" \
--serial-number "$MFA_ARN" \
--token-code 123456 \
--profile engineer-bob
STS JSON Response (Success!):
{
"Credentials": {
"AccessKeyId": "ASIA4EXAMPLEKEYID123",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"SessionToken": "AQoDYXdzEJr1EXAMPLE...very-long-base64-token...",
"Expiration": "2026-08-28T05:15:00+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA4EXAMPLEUNIQUEID:bob-mfa-session",
"Arn": "arn:aws:sts::123456789012:assumed-role/CloudStagingDeployer/bob-mfa-session"
}
}
Because STS verified the MFA token, the aws:MultiFactorAuthPresent: true condition evaluates to true and AWS issues temporary ASIA... credentials.
Phase 6: Automated Profile Chaining (Zero-Friction Workflow)
Manually exporting environment variables is tedious. The AWS CLI supports Profile Chaining, which automates the entire STS token exchange, MFA prompt, and credential caching.
Step 1: Configure ~/.aws/config
Open ~/.aws/config and configure Bob’s profile chaining:
[profile engineer-bob]
region = ap-southeast-1
output = json
[profile staging]
role_arn = arn:aws:iam::123456789012:role/CloudStagingDeployer
source_profile = engineer-bob
mfa_serial = arn:aws:iam::123456789012:mfa/engineer-bob-mfa
region = ap-southeast-1
output = table
[!NOTE] Replace
123456789012with your actual AWS Account ID.
Step 2: Execute Commands as the Assumed Role
Now, run any command using --profile staging:
aws ec2 describe-instances --profile staging
The CLI automatically prompts on your terminal:
Enter MFA code for arn:aws:iam::123456789012:mfa/engineer-bob-mfa: 582194
Enter your current 6-digit TOTP code. The command executes seamlessly!
For the next 1 hour, the AWS CLI caches your temporary session token locally. Subsequent commands execute without prompting for MFA until the session expires.
Phase 7: Managing the CLI Credential Cache
Where does the AWS CLI store these temporary session tokens?
Inspect your local cache directory:
ls -la ~/.aws/cli/cache/
You will see SHA-hashed JSON files (e.g. a1b2c3d4e5f6...json).
If you inspect one of these cache files:
cat ~/.aws/cli/cache/*.json | head -n 15
You will see:
{
"Credentials": {
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"SessionToken": "...",
"Expiration": "2026-08-28T05:15:00Z"
},
"ProviderType": "assume-role"
}
How to Force Invalidate / Flush Cached Sessions:
To test MFA prompts or invalidate an active assumed session immediately:
rm -rf ~/.aws/cli/cache/*
Quick Reference: Essential STS & Role CLI Commands
| Action | CLI Command |
|---|---|
| Check Current Identity | aws sts get-caller-identity |
| Create IAM Group | aws iam create-group --group-name <name> |
| Add User to Group | aws iam add-user-to-group --user-name <user> --group-name <group> |
| Assume Role (Manual) | aws sts assume-role --role-arn <arn> --role-session-name <name> |
| Assume Role with MFA | aws sts assume-role --role-arn <arn> --role-session-name <name> --serial-number <mfa-arn> --token-code <code> |
| Create IAM Role | aws iam create-role --role-name <name> --assume-role-policy-document file://trust.json |
| List IAM Roles | aws iam list-roles --output table |
| Get Role Details | aws iam get-role --role-name <name> --output json |
| Update Trust Policy | aws iam update-assume-role-policy --role-name <name> --policy-document file://trust.json |
| Attach Policy to Role | aws iam attach-role-policy --role-name <name> --policy-arn <arn> |
| Create Virtual MFA | aws iam create-virtual-mfa-device --virtual-mfa-device-name <name> --outfile ./qr.png --bootstrap-method QRCodePNG |
| Enable MFA Device | aws iam enable-mfa-device --user-name <user> --serial-number <arn> --authentication-code1 <c1> --authentication-code2 <c2> |
Summary & What’s Next
In this second installment of AWS with CLI, we moved to enterprise-level access security:
- We replaced dangerous static keys with short-lived STS session credentials (
ASIA...). - We demonstrated the Zero Standing Privilege model using
engineer-bob. - We provisioned an IAM Role (
CloudStagingDeployer) and attached scoped permissions via the CLI. - We created a Virtual MFA device and hardened role assumption with the
aws:MultiFactorAuthPresentcondition. - We set up Automated Profile Chaining in
~/.aws/configfor seamless, cached MFA role switching directly on our terminal.
In Part 3, we will dive into Crafting Granular IAM Policies, Boundaries & Service Control Policies via CLI, writing precision JSON policies from scratch and validating them with the IAM Policy Simulator.