# AWS CLI Cheat Sheet — Configuration & IAM

> **Tool:** AWS CLI v2
> **Category:** Cloud CLIs
> **Verified against:** aws-cli/2.33.6, flags verified via `aws <cmd> help`, 2026-08-21
> **Official docs:** https://docs.aws.amazon.com/cli/

Setting up profiles, switching accounts, and the IAM commands you actually reach for day to day — users, roles, policies, and assuming roles across accounts.

## Configuring a profile

```bash
aws configure --profile myprofile               # interactive: access key, secret, region, output format
aws configure set region us-east-1 --profile myprofile
aws configure set output json --profile myprofile
aws configure sso --profile myprofile            # set up an IAM Identity Center (SSO) profile instead
```

## Listing and switching profiles

```bash
aws configure list-profiles                      # every profile defined in ~/.aws/config and ~/.aws/credentials
aws configure list --profile myprofile            # show resolved config + where each value came from
export AWS_PROFILE=myprofile                      # switch the active profile for the current shell
aws sts get-caller-identity                        # confirm which identity/account the active profile resolves to
```

`aws configure list`'s output tells you *where* a value is coming from (env var, config file, credential file, or IAM instance role) — invaluable when a command is silently using the wrong account and you can't tell why.

## Assuming a role (cross-account access)

```bash
aws sts assume-role \
  --role-arn arn:aws:iam::111122223333:role/DeployRole \
  --role-session-name my-session \
  --duration-seconds 3600
```

This prints temporary `AccessKeyId`/`SecretAccessKey`/`SessionToken` credentials to stdout — export them as env vars, or configure a profile block with `role_arn` + `source_profile` in `~/.aws/config` so the CLI assumes the role automatically on every call for that profile.

## Managing IAM users

```bash
aws iam list-users
aws iam create-user --user-name jane
aws iam get-user --user-name jane
aws iam delete-user --user-name jane
aws iam create-access-key --user-name jane        # generates a new access key pair for that user
aws iam list-access-keys --user-name jane
```

## Managing IAM roles

```bash
aws iam list-roles
aws iam create-role \
  --role-name MyServiceRole \
  --assume-role-policy-document file://trust-policy.json
aws iam get-role --role-name MyServiceRole
aws iam delete-role --role-name MyServiceRole
```

`--assume-role-policy-document` is the *trust policy* — who is allowed to assume this role — not the permissions the role grants. Permissions come from a separate policy attached with `attach-role-policy`.

## Attaching and inspecting policies

```bash
aws iam attach-role-policy --role-name MyServiceRole --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
aws iam attach-user-policy --user-name jane --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
aws iam list-attached-role-policies --role-name MyServiceRole
aws iam list-attached-user-policies --user-name jane
aws iam detach-role-policy --role-name MyServiceRole --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
```

## Filtering output with --query and --output

```bash
aws iam list-users --query 'Users[].UserName' --output text
aws iam list-roles --query "Roles[?contains(RoleName, 'Deploy')].RoleName" --output table
```

`--query` uses JMESPath against the JSON response — it runs client-side after the API call, so it doesn't reduce API load, only the output you see. `--output` controls the rendering format: `json` (default), `text`, `table`, or `yaml`.

## Managing IAM groups

```bash
aws iam create-group --group-name Developers
aws iam add-user-to-group --group-name Developers --user-name jane
aws iam list-groups-for-user --user-name jane
aws iam attach-group-policy --group-name Developers --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess
```

Attaching a policy to a group grants it to every current and future member — cheaper to maintain at scale than attaching the same policy to each user individually.

## Managing policy documents and versions

```bash
aws iam create-policy --policy-name MyAppPolicy --policy-document file://policy.json
aws iam list-policy-versions --policy-arn arn:aws:iam::111122223333:policy/MyAppPolicy
aws iam create-policy-version --policy-arn arn:aws:iam::111122223333:policy/MyAppPolicy --policy-document file://policy-v2.json --set-as-default
aws iam get-policy --policy-arn arn:aws:iam::111122223333:policy/MyAppPolicy
```

A managed policy keeps up to 5 versions. `create-policy-version` doesn't overwrite — it adds a new version and, only with `--set-as-default`, makes it the one actually in effect. Once you hit 5 versions, delete an old one with `delete-policy-version` before creating another.

## Rotating access keys

```bash
aws iam create-access-key --user-name jane                       # create a second, parallel key
aws iam update-access-key --user-name jane --access-key-id AKIA... --status Inactive
aws iam delete-access-key --user-name jane --access-key-id AKIA...
```

Standard rotation is create-new → update apps to use it → deactivate the old one (not delete) → confirm nothing broke → delete. `update-access-key --status Inactive` is reversible; `delete-access-key` is not.

## MFA — enrolling a device and using it for temporary credentials

```bash
aws iam enable-mfa-device --user-name jane --serial-number arn:aws:iam::111122223333:mfa/jane --authentication-code1 123456 --authentication-code2 789012
aws iam list-mfa-devices --user-name jane

aws sts get-session-token --serial-number arn:aws:iam::111122223333:mfa/jane --token-code 123456 --duration-seconds 3600
```

`enable-mfa-device` needs two *consecutive* codes from the device (`--authentication-code1`/`2`) to prove it's correctly synced, not one. `get-session-token` is what actually enforces MFA for subsequent calls — it returns temporary credentials that carry an MFA-authenticated flag, which some IAM policies require via a `aws:MultiFactorAuthPresent` condition.
