☰ All modules Tier 1 · CLI, SDK and IAM policies GuideCheat sheet ‹ iamlambda ›
Contents
  1. How CLI, SDK and IAM policies appears on DVA-C02
  2. 1. AWS CLI profiles and configuration files
  3. 2. MFA with the CLI and session tokens
  4. 3. CLI credential provider chain
  5. 4. SDK default credential provider chains
  6. 5. Credentials best practices
  7. 6. Using the AWS SDKs in application code
  8. 7. CLI output filtering and pagination
  9. 8. Service quotas and API rate limits
  10. 9. Retries and exponential backoff with jitter
  11. 10. Signing requests with SigV4
  12. 11. Testing permissions with dry run and the policy simulator
  13. 12. Decoding authorization failures
  14. Quick decision rules
  15. Changed vs older material

CLI, SDK and IAM policies — DVA-C02 Mastery Guide

  • Sources: course chapter 07 (AWS CLI, SDK, IAM roles and policies). The course serves as the syllabus only; all wording here is original. IMDS mechanics (token flow, hop limit, enforcement) live in notes/ec2-mastery-guide.md §2 and instance profiles in §1; this guide adds only their CLI and SDK angles.
  • Written 2026-10-12; values checked against AWS docs on 2026-10-12. The marker ⚠️ Changed: <current>. Older material may say <old>. flags a value or behaviour that differs from the course or older practice tests: learn the current value. ⚠️ volatile flags a value AWS has announced will change soon. Every change is listed in Changed vs older material.
  • Tier 1 (highest exam weight), bank target 30 questions. Domains: Security (primary), Development with AWS Services.
  • How to use it: /explain <topic> teaches from these sections (concept → exam facts → developer angle → traps → 3 check questions); /quiz cli-sdk-policies asks bank questions whose source_note links point at the ## N. headings below; /drill cli-sdk-policies fires short recall prompts from notes/cli-sdk-policies-cheat-sheet.md. Suggested loop: read a section and answer its practice questions before opening the answers → /explain what is still unclear → /quiz → /drill.

How CLI, SDK and IAM policies appears on DVA-C02

DVA-C02 assumes you write code and scripts that call AWS. This module covers the plumbing every one of those calls passes through:

Typical question shapes: "the role is attached but the app still acts as an IAM user"; an error code to classify (ThrottlingException vs AccessDenied vs SignatureDoesNotMatch); "the CLI times out listing a bucket"; "check permissions without creating resources"; the MOST secure way to give a laptop, a pipeline or an on-premises server credentials.

Domain map: Security → §2, §3, §4, §5, §10, §11, §12 · Development with AWS Services → §1, §6, §7, §8, §9. Many questions are framed as troubleshooting (§3, §8, §9, §12).

Owned by other modules (cross-referenced, not repeated): IAM users, groups, policy grammar, MFA devices and access-key management, plus the policy simulator, IAM Access Analyzer checks and the access-denied message catalogue (see notes/iam-guide.md §6); STS AssumeRole, cross-account access, writing MFA conditions, policy evaluation logic and iam:PassRole (see notes/advanced-identity-guide.md §9–§11); Secrets Manager and Parameter Store (see notes/security-encryption-guide.md); presigned URL use cases and S3 request rates (see notes/s3-guide.md); IMDSv2 and instance profiles (see notes/ec2-mastery-guide.md §1–§2).

# Topic Why it is on the exam
1 AWS CLI profiles and configuration files Files, profiles and setting precedence decide which account, Region and endpoint a command hits
2 MFA with the CLI and session tokens Long-term keys carry no MFA; get-session-token, mfa_serial and MFA condition keys
3 CLI credential provider chain First match wins: why a stray key beats the instance role
4 SDK default credential provider chains Same idea in code: Java 2.x and boto3 order, container, Lambda and IMDS providers
5 Credentials best practices Roles on AWS, short-term credentials elsewhere; the MOST secure option in every scenario
6 Using the AWS SDKs in application code Region, paginators, waiters, errors, endpoints, current SDK versions
7 CLI output filtering and pagination --page-size vs --max-items, server-side filters vs --query
8 Service quotas and API rate limits Quota vs throttle, Service Quotas, EC2 token buckets, what to do when limits bite
9 Retries and exponential backoff with jitter What to retry, SDK retry modes and settings, idempotency
10 Signing requests with SigV4 Header vs query-string signing, temporary credentials, clock skew, SigV4a
11 Testing permissions with dry run and the policy simulator DryRunOperation vs UnauthorizedOperation; simulating drafts and principals
12 Decoding authorization failures Reading access-denied messages, decode-authorization-message, credential vs permission errors

1. AWS CLI profiles and configuration files

Concept

Exam facts

Developer angle

~/.aws/config with a named profile that sends DynamoDB calls to DynamoDB Local:

[default]
region = eu-west-1
output = json

[profile dev]
region = us-east-2
output = table
services = local-ddb

[services local-ddb]
dynamodb =
  endpoint_url = http://localhost:8000

~/.aws/credentials (format only: prefer short-term credentials, §5):

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws configure --profile dev                  # wizard: key, secret, Region, output
aws configure list --profile dev             # each value and where it came from
aws configure list-profiles
aws configure get region --profile dev
aws configure set output table --profile dev
export AWS_PROFILE=dev                       # default profile for this shell
aws ec2 describe-vpcs --profile prod --region eu-central-1      # per-command override
AWS_ENDPOINT_URL_DYNAMODB=http://localhost:8000 aws dynamodb list-tables
aws configure export-credentials --profile dev --format env     # hand short-term credentials to another tool

Traps

Practice questions

  1. A developer runs aws dynamodb list-tables --profile analytics and sees the tables of us-east-2, although the analytics profile in ~/.aws/config contains region = eu-west-1. The developer's shell startup file exports AWS_DEFAULT_REGION=us-east-2. What should the developer do so that the command targets eu-west-1 without editing the shell startup file?

    • A. Rename the section in ~/.aws/config from [profile analytics] to [analytics].
    • B. Add --region eu-west-1 to the command.
    • C. Move the region line into the [analytics] section of ~/.aws/credentials.
    • D. Run aws configure set region eu-west-1 --profile analytics again.
  2. A team wants the AWS CLI and boto3 test scripts on developer laptops to send DynamoDB calls to DynamoDB Local on port 8000, while every other service still reaches AWS, without changing any code. Which TWO configurations meet this requirement? (Select TWO.)

    • A. Export AWS_ENDPOINT_URL_DYNAMODB=http://localhost:8000 in the test shell.
    • B. Export AWS_ENDPOINT_URL=http://localhost:8000 in the test shell.
    • C. Add a [services local-ddb] section with a dynamodb endpoint_url, referenced by services = local-ddb.
    • D. Add --endpoint-url http://localhost:8000 to every aws dynamodb command and endpoint_url= to every boto3 DynamoDB client.
    • E. Export AWS_IGNORE_CONFIGURED_ENDPOINT_URLS=true in the test shell and keep the default endpoints for every other profile.
Answers
  1. B. A command-line option beats the environment variable, which in turn beats the profile's region. A breaks the profile (the profile prefix is required in config); C changes nothing because the environment variable still wins; D rewrites the value that is already there.
  2. A, C. Both are service-specific endpoint settings that leave other services on AWS. B redirects every service; D works only by editing every script, which the requirement rules out; E makes the CLI and SDK ignore configured endpoints.

2. MFA with the CLI and session tokens

Concept

Exam facts

Developer angle

# 1) Find the MFA device identifier of the IAM user
aws iam list-mfa-devices --user-name dev-user --query 'MFADevices[].SerialNumber' --output text

# 2) Trade long-term keys + the current code for 12 h of MFA-backed credentials
read -r AK SK ST <<< "$(aws sts get-session-token \
  --serial-number arn:aws:iam::123456789012:mfa/dev-user-phone \
  --token-code 123456 --duration-seconds 43200 --profile dev-longterm \
  --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' --output text)"

# 3) Store all three values in a separate profile and use it for protected calls
aws configure set aws_access_key_id "$AK" --profile dev-mfa
aws configure set aws_secret_access_key "$SK" --profile dev-mfa
aws configure set aws_session_token "$ST" --profile dev-mfa
aws ec2 stop-instances --instance-ids i-0123456789abcdef0 --profile dev-mfa

A role profile that prompts for the code and caches the role session:

[profile ops-admin]
role_arn = arn:aws:iam::123456789012:role/OpsAdmin
source_profile = dev-longterm
mfa_serial = arn:aws:iam::123456789012:mfa/dev-user-phone
role_session_name = dev-user
duration_seconds = 3600

Running aws s3 ls --profile ops-admin prompts Enter MFA code for arn:aws:iam::123456789012:mfa/dev-user-phone: once; later commands reuse the cached session in ~/.aws/cli/cache until it expires. The matching trust-policy and identity-policy conditions are shown in notes/advanced-identity-guide.md §10.

Traps

Practice questions

  1. An administrator attached a policy to the ops group that allows ec2:TerminateInstances only when aws:MultiFactorAuthPresent is true. A developer in the group runs aws ec2 terminate-instances with the access keys stored in the default profile and receives UnauthorizedOperation. The developer has a virtual MFA device. What should the developer do without changing the policy?

    • A. Run aws sts get-caller-identity to refresh the MFA status of the default profile.
    • B. Run aws iam enable-mfa-device again for the virtual device, then retry the command.
    • C. Add the device ARN as mfa_serial in the default profile that holds the access keys, then retry the same command.
    • D. Call aws sts get-session-token with the device ARN and a code, then use the returned credentials.
  2. A developer with an IAM user and a virtual MFA device works in two accounts from a laptop. In account A (the developer's own), a bucket policy allows s3:DeleteObject only when aws:MultiFactorAuthPresent is true. In account B, the Deployer role's trust policy requires MFA. The developer wants to type MFA codes as rarely as possible. Which TWO configurations meet these requirements? (Select TWO.)

    • A. For account A, run aws sts get-session-token with --serial-number and --token-code once and store the three returned values in a separate profile.
    • B. For account A, add mfa_serial to the profile that holds the IAM user's access keys.
    • C. For account B, create a profile with role_arn, source_profile and mfa_serial so that the CLI prompts once and caches the role session.
    • D. For account B, append --token-code to every command that must run as Deployer.
    • E. For both accounts, register a FIDO security key and enter its output as the --token-code value.
Answers
  1. D. Only temporary credentials obtained with an MFA code carry aws:MultiFactorAuthPresent = true. A doesn't change the credentials; B fails because the device is already enabled and enabling it again adds no MFA context; C does nothing because mfa_serial applies only to profiles that assume a role.
  2. A, C. Session credentials from get-session-token carry the MFA context that a resource-based condition needs and last up to 36 hours; the role profile prompts once and reuses its cached session. B fails because mfa_serial is ignored without role_arn; D fails because the CLI has no per-command MFA option; E fails because security keys can't be used for MFA-protected API access.

3. CLI credential provider chain

Concept

Exam facts

Developer angle

# Which identity, and from which source?
aws sts get-caller-identity --query Arn --output text
aws configure list
aws s3 ls --debug 2>&1 | grep -i "found credentials"

# Stray keys on an EC2 host? Remove them so the instance profile is used
env | grep '^AWS_'
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

# Assume a second role from the instance role, with no keys on disk
aws configure set role_arn arn:aws:iam::123456789012:role/ReportsWriter --profile reports
aws configure set credential_source Ec2InstanceMetadata --profile reports
aws s3 cp report.csv s3://reports-bucket/2026/ --profile reports

# Force fresh role credentials after the session was revoked
rm -r ~/.aws/cli/cache

Outside EC2, stop the CLI from probing instance metadata before it reports "Unable to locate credentials":

export AWS_EC2_METADATA_DISABLED=true

Traps

Practice questions

  1. A CI runner on an EC2 instance has an instance profile whose role allows only s3:GetObject. A build step runs aws s3 rm s3://artifacts/old/ --recursive and succeeds. aws configure list shows the access key with type env. What explains the result?

    • A. Access keys exported as environment variables are used before the instance profile credentials.
    • B. Instance profile credentials cached in ~/.aws/cli/cache still carry the role's earlier permissions.
    • C. The default profile in ~/.aws/config contains credential_source = Ec2InstanceMetadata.
    • D. A bucket policy grants s3:DeleteObject to the instance role and overrides its identity policy.
  2. A developer laptop has [default] keys in ~/.aws/credentials, a prod profile, and AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY exported for a sandbox IAM user. Which TWO statements about the credentials the AWS CLI uses are correct? (Select TWO.)

    • A. aws s3 ls with no options uses the [default] keys from the credentials file.
    • B. AWS_PROFILE=prod aws s3 ls uses the prod profile's credentials instead of the exported sandbox keys.
    • C. aws s3 ls --profile prod uses the prod profile's credentials instead of the exported sandbox keys.
    • D. aws s3 ls --profile prod fails while access keys are exported.
    • E. aws s3 ls with no options uses the exported sandbox keys.
Answers
  1. A. The env source shows that IAM-user keys from the environment, step 2 of the chain, were used instead of the role (step 10). B is wrong because the CLI caches assume-role credentials there, not instance profile credentials; C would still use the role; D contradicts the evidence that the role wasn't the identity used.
  2. C, E. Environment keys beat every file-based profile, and an explicit --profile on the command line skips them. A ignores that environment variables come before the credentials file; B fails because AWS_PROFILE only selects the profile and the exported keys still win; D is wrong because the two can coexist.

4. SDK default credential provider chains

Concept

Exam facts

Developer angle

import boto3

# Default chain: no keys in code; runs unchanged on a laptop, Lambda, ECS and EC2
s3 = boto3.client("s3", region_name="eu-west-1")

# Pin a named profile for local development
dev = boto3.Session(profile_name="dev")
ddb = dev.client("dynamodb", region_name="eu-west-1")

# Which principal did the chain resolve?
print(boto3.client("sts", region_name="eu-west-1").get_caller_identity()["Arn"])
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.credentials.InstanceProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

public class S3Clients {
    // Same behaviour as passing no provider at all
    static S3Client defaultChain() {
        return S3Client.builder()
                .region(Region.EU_WEST_1)
                .credentialsProvider(DefaultCredentialsProvider.builder().build())
                .build();
    }

    // Ignore everything else on the host and use only the EC2 instance role
    static S3Client instanceRoleOnly() {
        return S3Client.builder()
                .region(Region.EU_WEST_1)
                .credentialsProvider(InstanceProfileCredentialsProvider.create())
                .build();
    }
}
import { S3Client, ListBucketsCommand } from "@aws-sdk/client-s3";
import { fromIni } from "@aws-sdk/credential-providers";

const s3 = new S3Client({ region: "eu-west-1" });                                   // default chain
const devS3 = new S3Client({ region: "eu-west-1", credentials: fromIni({ profile: "dev" }) });
const { Buckets } = await devS3.send(new ListBucketsCommand({}));
console.log(Buckets?.length);

Traps

Practice questions

  1. A Java 2.x service on EC2 must authenticate only with the instance role, even if an operator exports access keys on the host. Which change meets this requirement with the fewest code changes?

    • A. Set AWS_EC2_METADATA_V1_DISABLED=true in the service's environment.
    • B. Pass ProfileCredentialsProvider.create("default") to every client builder.
    • C. Pass InstanceProfileCredentialsProvider.create() to every client builder.
    • D. Start the JVM with the system property aws.profile=instance.
  2. A team runs the same Python (boto3) code on AWS Lambda, on Amazon ECS with AWS Fargate and on Amazon EC2, with no credentials in the code. Which TWO statements describe how boto3 obtains credentials? (Select TWO.)

    • A. On Lambda, it reads the AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN values set from the execution role.
    • B. On ECS, it calls IMDS at 169.254.169.254 before it checks any environment variable.
    • C. On EC2, it reads the instance role from ~/.aws/credentials, which the EC2 launch process writes for the root user at first boot.
    • D. On ECS, it gets the task role's credentials from the endpoint in AWS_CONTAINER_CREDENTIALS_RELATIVE_URI.
    • E. On all three, the code must call sts:AssumeRole before it creates clients.
Answers
  1. C. A pinned instance-profile provider never consults environment variables or profiles. A only blocks the IMDSv1 fallback, so exported keys would still win; B reads the default profile, which is exactly what must be ignored; D names a profile that doesn't exist and still leaves environment keys in front.
  2. A, D. Lambda exposes the execution role through reserved environment variables, and ECS through the container credentials endpoint. B reverses the order (environment and container come before IMDS); C is wrong because EC2 delivers role credentials only through IMDS; E is unnecessary because the default chain does this automatically.

5. Credentials best practices

Concept

Exam facts

Developer angle

~/.aws/config for a developer (IAM Identity Center) and for an on-premises batch server (IAM Roles Anywhere):

[profile dev]
sso_session = corp
sso_account_id = 111122223333
sso_role_name = DeveloperAccess
region = eu-west-1

[sso-session corp]
sso_start_url = https://my-sso-portal.awsapps.com/start
sso_region = eu-west-1
sso_registration_scopes = sso:account:access

[profile onprem-batch]
credential_process = /usr/local/bin/aws_signing_helper credential-process --certificate /etc/pki/batch.pem --private-key /etc/pki/batch.key --trust-anchor-arn arn:aws:rolesanywhere:eu-west-1:111122223333:trust-anchor/TA_ID --profile-arn arn:aws:rolesanywhere:eu-west-1:111122223333:profile/PROFILE_ID --role-arn arn:aws:iam::111122223333:role/BatchUploader
region = eu-west-1
aws sso login --profile dev            # browser sign-in, short-term credentials cached
aws login --profile console-dev        # console credentials (CLI 2.32.0 or later)
aws s3 ls --profile onprem-batch       # the helper trades the X.509 certificate for role credentials

Traps

Practice questions

  1. A company runs a nightly job on on-premises Linux servers that uploads files to Amazon S3. The security team prohibits long-term access keys, and the company already operates an internal certificate authority. Which solution meets the requirement with the LEAST operational overhead?

    • A. Create one IAM user per server and rotate its access keys every 30 days with a scheduled script that updates each server.
    • B. Make the internal CA an IAM Roles Anywhere trust anchor and use its credential helper via credential_process.
    • C. Run aws login on each server every morning and let the job reuse the cached session.
    • D. Store an IAM user's access keys in Secrets Manager and have the job fetch them from Secrets Manager each time it starts.
  2. A new developer needs CLI access to two accounts in the company's AWS Organization. The company uses IAM Identity Center with permission sets. Which TWO steps follow AWS best practices? (Select TWO.)

    • A. Create an IAM user in each account and run aws configure with its access keys.
    • B. Run aws configure sso to create an sso-session and one profile per account and permission set.
    • C. Run aws sso login --profile <name> to obtain short-term credentials before running commands.
    • D. Run aws configure import --csv with the access keys shown in the AWS access portal.
    • E. Paste the portal's temporary keys into ~/.aws/credentials and refresh them by hand each week.
Answers
  1. B. Roles Anywhere trades the existing certificates for temporary role credentials with no keys to manage. A and D still rely on long-term keys; C needs an interactive browser sign-in every day, which an unattended job can't do.
  2. B, C. Identity Center profiles plus aws sso login give each person refreshable short-term credentials. A creates long-term keys; D imports only IAM user CSV files; E is manual and leaves expiring credentials in a plaintext file.

6. Using the AWS SDKs in application code

Concept

Exam facts

Developer angle

import boto3
from botocore.config import Config
from botocore.exceptions import ClientError

cfg = Config(region_name="eu-west-1", connect_timeout=5, read_timeout=10,
             retries={"total_max_attempts": 5, "mode": "standard"})
s3 = boto3.client("s3", config=cfg)

# Paginator instead of handling ContinuationToken yourself
pages = s3.get_paginator("list_objects_v2").paginate(
    Bucket="orders-archive", PaginationConfig={"PageSize": 500})
for key in pages.search("Contents[?Size > `1048576`].Key"):
    print(key)

# Waiter instead of a sleep loop
s3.create_bucket(Bucket="orders-staging-111122223333",
                 CreateBucketConfiguration={"LocationConstraint": "eu-west-1"})
s3.get_waiter("bucket_exists").wait(Bucket="orders-staging-111122223333",
                                    WaiterConfig={"Delay": 5, "MaxAttempts": 20})

try:
    s3.get_object(Bucket="orders-archive", Key="missing.json")
except s3.exceptions.NoSuchKey:
    print("object not found")
except ClientError as err:
    print(err.response["Error"]["Code"], err.response["ResponseMetadata"]["HTTPStatusCode"])

# Local testing against DynamoDB Local
local_ddb = boto3.client("dynamodb", region_name="us-east-1", endpoint_url="http://localhost:8000")

Traps

Practice questions

  1. A boto3 script must process every object in a bucket that holds 40,000 objects, but each list_objects_v2 call returns only 1,000 keys. Which change returns every key with the LEAST custom code?

    • A. Set MaxKeys=40000 on the list_objects_v2 call.
    • B. Call aws s3api list-objects-v2 --no-paginate through subprocess and parse the JSON output in the script.
    • C. Pass PaginationConfig={"MaxItems": 40000} to the existing list_objects_v2 call.
    • D. Iterate over the pages returned by get_paginator("list_objects_v2").paginate(Bucket=...).
  2. A developer is building a Java 2.x service that must run unchanged on a laptop (profile dev), in AWS Lambda and on Amazon EC2, in whichever Region it is deployed. Which TWO practices meet this requirement? (Select TWO.)

    • A. Build clients without a Region so the default Region provider chain resolves it from the environment, profile or IMDS.
    • B. Hard-code Region.US_EAST_1 in every client builder.
    • C. Read access keys from a properties file packaged in the JAR and pass them to StaticCredentialsProvider in every client builder.
    • D. Create one client at startup and call region() on it whenever the target Region changes.
    • E. Build clients without a credentials provider so DefaultCredentialsProvider finds environment, profile or role credentials.
Answers
  1. D. The paginator follows ContinuationToken until the listing ends. A is capped at 1,000 keys per page; B returns only the first page and adds a subprocess; C is a paginator option, not a parameter of list_objects_v2.
  2. A, E. The default Region and credential chains adapt to each environment without code changes. B pins one Region; C embeds long-term keys in the artifact; D fails because built clients are immutable.

7. CLI output filtering and pagination

Concept

Exam facts

Developer angle

# Filter on the server, shape on the client
aws ec2 describe-instances \
  --filters "Name=tag:app,Values=orders" "Name=instance-state-name,Values=running" \
  --query 'Reservations[].Instances[].{Id:InstanceId,Type:InstanceType,AZ:Placement.AvailabilityZone}' \
  --output table

# A huge listing that times out: smaller pages, same result
aws s3api list-objects-v2 --bucket orders-archive --page-size 200 \
  --query 'Contents[].Key' --output text

# Work in batches of 500 and resume later
aws s3api list-objects-v2 --bucket orders-archive --max-items 500 --page-size 500 > batch1.json
NEXT_TOKEN=$(jq -r '.NextToken' batch1.json)
aws s3api list-objects-v2 --bucket orders-archive --max-items 500 --page-size 500 \
  --starting-token "$NEXT_TOKEN"

# Script-friendly: a single value, no pager
aws sts get-caller-identity --query Account --output text --no-cli-pager

# Reusable input file, validated with a dry run first (§11)
aws ec2 run-instances --generate-cli-skeleton input > launch.json
aws ec2 run-instances --cli-input-json file://launch.json --dry-run

Traps

Practice questions

  1. A nightly script runs aws s3api list-objects-v2 against a bucket with two million objects and intermittently fails with a timeout error. The script must still process every object. What should the developer change?

    • A. Add --page-size 200 to the command.
    • B. Add --max-items 200 to the command.
    • C. Add --no-paginate to the command.
    • D. Add --query 'Contents[:200]' to the command.
  2. A developer needs the IDs of running t3.micro instances tagged env=dev as plain text for a shell loop, and wants the EC2 API to return as little data as possible. Which TWO options should the developer use together? (Select TWO.)

    • A. --output table
    • B. --filters "Name=instance-type,Values=t3.micro" "Name=tag:env,Values=dev" "Name=instance-state-name,Values=running"
    • C. --no-paginate
    • D. --query 'Reservations[].Instances[?InstanceType==`t3.micro`].InstanceId' with no server-side filter
    • E. --query 'Reservations[].Instances[].InstanceId' --output text
Answers
  1. A. Smaller pages give each API call a better chance to finish while the CLI still fetches the full list. B and D cut the output to 200 items, so most objects are never processed; C returns only the first page.
  2. B, E. Server-side filters shrink the API response; --query plus text prints only the IDs. A is for humans; C would drop later pages; D filters only after the full response has been transferred.

8. Service quotas and API rate limits

Concept

Exam facts

Developer angle

# Applied value vs AWS default for Standard On-Demand vCPUs
aws service-quotas get-service-quota --service-code ec2 --quota-code L-1216C47A --query 'Quota.Value'
aws service-quotas get-aws-default-service-quota --service-code ec2 --quota-code L-1216C47A --query 'Quota.Value'

# Ask for more and follow the request
aws service-quotas request-service-quota-increase \
  --service-code ec2 --quota-code L-1216C47A --desired-value 256
aws service-quotas list-requested-service-quota-change-history --service-code ec2 \
  --query 'RequestedQuotas[].{Quota:QuotaName,Status:Status,Wanted:DesiredValue}'

# EC2 API throttle quotas (burst = bucket capacity, sustained = refill rate)
aws service-quotas list-service-quotas --service-code ec2 \
  --query "Quotas[?contains(QuotaName, 'DescribeInstances')].[QuotaName,Value]" --output table

Filtered, paginated describes draw from the larger non-mutating bucket:

import boto3

ec2 = boto3.client("ec2", region_name="eu-west-1")
pages = ec2.get_paginator("describe_instances").paginate(
    Filters=[{"Name": "tag:app", "Values": ["orders"]}],
    PaginationConfig={"PageSize": 100})
for page in pages:
    for reservation in page["Reservations"]:
        for instance in reservation["Instances"]:
            print(instance["InstanceId"], instance["State"]["Name"])

Traps

Practice questions

  1. An automation tool calls DescribeInstances once per second without filters or pagination to check about 300 instances, and it often receives RequestLimitExceeded. Which change should the developer make first, without waiting for AWS Support?

    • A. Open an AWS Support case to raise the DescribeInstances bucket refill rate for the account in this Region.
    • B. Call DescribeInstances with filters and pagination and keep the SDK's backoff enabled.
    • C. Request a higher "Running On-Demand Standard instances" quota in Service Quotas.
    • D. Add --no-paginate so the tool makes a single call per cycle.
  2. A deployment pipeline fails in a newly created account with VcpuLimitExceeded when it launches twelve m7i.xlarge instances. Which TWO actions fix the launch and warn the team before the limit is reached again? (Select TWO.)

    • A. Retry the launch with exponential backoff until capacity becomes available.
    • B. Ask AWS Support to raise the RunInstances API refill rate.
    • C. Request an increase of the "Running On-Demand Standard (A, C, D, H, I, M, R, T, Z) instances" quota.
    • D. Create a CloudWatch alarm on the AWS/Usage ResourceCount metric (vCPU, Standard/OnDemand) at 80 % of SERVICE_QUOTA.
    • E. Switch the launch template to IMDSv2-only metadata options.
Answers
  1. B. Filtered, paginated calls use the larger non-mutating bucket, and backoff absorbs the remaining bursts. A needs Support and leaves the wasteful polling in place; C raises an unrelated resource quota; D keeps the calls unpaginated, which is what puts them in the small bucket.
  2. C, D. The vCPU quota is the limit that failed (12 × 4 vCPUs = 48), and a usage alarm warns before the next shortfall. A retries a quota error that won't clear; B targets API throttling, not the vCPU quota; E has no effect on quotas.

9. Retries and exponential backoff with jitter

Concept

Exam facts

Developer angle

~/.aws/config and environment overrides:

[profile batch]
retry_mode = adaptive
max_attempts = 6
export AWS_RETRY_MODE=standard
export AWS_MAX_ATTEMPTS=5
aws dynamodb describe-table --table-name Orders --debug 2>&1 | grep -i retry
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

// One hot table with frequent throttling: let the SDK slow itself down
const ddb = new DynamoDBClient({ region: "eu-west-1", maxAttempts: 5, retryMode: "adaptive" });

Your own loop for a raw HTTPS call without an SDK, with full jitter (for AWS APIs, also treat a 400 whose error code is a throttling code as retryable):

import random
import time

import requests

RETRYABLE_STATUS = {429, 500, 502, 503, 504}

def get_with_backoff(url, max_attempts=5, base=0.5, cap=20.0):
    for attempt in range(max_attempts):
        resp = requests.get(url, timeout=5)
        if resp.status_code not in RETRYABLE_STATUS or attempt == max_attempts - 1:
            return resp
        time.sleep(random.uniform(0, min(cap, base * 2 ** attempt)))  # full jitter

Traps

Practice questions

  1. A Python worker using boto3 writes to a single DynamoDB table and regularly receives ProvisionedThroughputExceededException during bursts. The team wants the SDK to lower its own request rate when throttling occurs, without writing retry code. Which client configuration meets this requirement?

    • A. Config(retries={"mode": "legacy", "max_attempts": 0})
    • B. Config(read_timeout=60, connect_timeout=60)
    • C. AWS_MAX_ATTEMPTS=1 in the worker's environment
    • D. Config(retries={"mode": "adaptive", "total_max_attempts": 5})
  2. A developer calls an AWS service with raw HTTPS requests signed with SigV4, without an SDK. Which TWO error responses should the client retry with exponential backoff and jitter? (Select TWO.)

    • A. HTTP 400 with the error code ThrottlingException
    • B. HTTP 403 with the error code AccessDeniedException
    • C. HTTP 503 with the error code ServiceUnavailable
    • D. HTTP 400 with the error code ValidationException
    • E. HTTP 403 with the error code SignatureDoesNotMatch
Answers
  1. D. Adaptive mode adds client-side rate limiting on top of standard retries, which suits one throttled table. A disables retries; B changes timeouts, not the request rate; C turns retries off entirely.
  2. A, C. Throttling (even with status 400) and a temporarily unavailable service can succeed unchanged after a wait. B and D fail the same way every time until the policy or the request changes; E is a signing or credential error that needs a fix, not a retry.

10. Signing requests with SigV4

Concept

Exam facts

Developer angle

Signing a request to an IAM-authorized API Gateway endpoint (service name execute-api; the caller also needs execute-api:Invoke, see notes/api-gateway-guide.md):

import boto3
import requests
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest

region = "eu-west-1"
url = "https://abc123defg.execute-api.eu-west-1.amazonaws.com/prod/orders"
creds = boto3.Session().get_credentials().get_frozen_credentials()

request = AWSRequest(method="GET", url=url)
SigV4Auth(creds, "execute-api", region).add_auth(request)   # adds Authorization, X-Amz-Date and the token
response = requests.get(url, headers=dict(request.headers), timeout=10)
print(response.status_code)

Presigned URLs (query-string signing done for you):

aws s3 presign s3://orders-archive/invoices/2026-10.pdf --expires-in 3600 --region eu-west-1
import boto3

s3 = boto3.client("s3", region_name="eu-west-1")
url = s3.generate_presigned_url(
    "get_object", Params={"Bucket": "orders-archive", "Key": "invoices/2026-10.pdf"}, ExpiresIn=3600)

Traps

Practice questions

  1. An on-premises service signs requests to an AWS API with its own SigV4 code. Requests that worked yesterday now fail with Signature expired: 20261012T101500Z is now earlier than 20261012T102500Z. Nothing in the code changed. What is the MOST likely cause?

    • A. The IAM user's access key was deactivated during a scheduled key rotation last night.
    • B. The role's permissions policy was edited and no longer allows the action that the service calls.
    • C. The server's clock has drifted outside the allowed time window.
    • D. The target Region now accepts only SigV4a signatures.
  2. A web application assumes an IAM role with sts:AssumeRole using the default session duration and uses those credentials to create S3 presigned GET URLs with ExpiresIn=86400. Users report that the links stop working after about an hour. Which TWO statements are correct? (Select TWO.)

    • A. An ExpiresIn value above 3,600 seconds is silently ignored for SigV4 presigned URLs created by the SDK.
    • B. Switching the URLs to SigV4a removes the dependency on the lifetime of the credentials that signed them.
    • C. Adding an s3:signatureAge condition to the bucket policy extends the validity of every URL to the full 24 hours.
    • D. A presigned URL stops working when the credentials that signed it expire, even if ExpiresIn is longer.
    • E. Requesting a longer role session with DurationSeconds (up to the role's maximum) lets the URLs work longer.
Answers
  1. C. "Signature expired" compares the request timestamp with AWS's clock, so a drifting server clock is the cause. A would fail with a credential error such as InvalidClientTokenId; B would return an access-denied error; D is not how SigV4 works (SigV4a is only for multi-Region requests).
  2. D, E. The URL can't outlive the role session that signed it (1 hour by default), and a longer session extends it. A is wrong because SigV4 allows up to 604,800 s; B doesn't change credential lifetimes; C can only restrict signature age, never extend it.

11. Testing permissions with dry run and the policy simulator

Concept

Exam facts

Question Tool
May this role make this EC2 call, live? --dry-run: DryRunOperation = yes, UnauthorizedOperation = no
May it call S3, DynamoDB or another non-EC2 action? aws iam simulate-principal-policy
Does a draft policy work before it is attached? aws iam simulate-custom-policy with --context-entries
May the caller invoke this Lambda function? aws lambda invoke --invocation-type DryRun

Developer angle

# Would this launch be authorized? Nothing is created.
aws ec2 run-instances --launch-template LaunchTemplateName=web \
  --subnet-id subnet-0123456789abcdef0 --dry-run
# An error occurred (DryRunOperation) when calling the RunInstances operation:
# Request would have succeeded, but DryRun flag is set.

# S3 has no dry run: ask the simulator whether the CI role may write and delete under releases/
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::111122223333:role/ci-deployer \
  --action-names s3:PutObject s3:DeleteObject \
  --resource-arns "arn:aws:s3:::release-bucket/releases/*" \
  --query 'EvaluationResults[].[EvalActionName,EvalDecision]' --output table

The same dry run from boto3:

import boto3
from botocore.exceptions import ClientError

ec2 = boto3.client("ec2", region_name="eu-west-1")
try:
    ec2.stop_instances(InstanceIds=["i-0123456789abcdef0"], DryRun=True)
except ClientError as err:
    code = err.response["Error"]["Code"]
    print("would be allowed" if code == "DryRunOperation" else f"not allowed or invalid: {code}")

Traps

Practice questions

  1. A pipeline step must confirm that its role is authorized to launch instances from the web launch template before the real deployment, without creating resources or incurring cost. Which approach meets this requirement?

    • A. Run aws ec2 run-instances --launch-template LaunchTemplateName=web --dry-run; DryRunOperation means success.
    • B. Run aws ec2 run-instances --launch-template LaunchTemplateName=web and terminate the instance as soon as it starts.
    • C. Run aws ec2 describe-launch-templates --launch-template-names web and check that the template exists.
    • D. Run aws s3 cp with --dryrun against the deployment artifact bucket.
  2. A release script removes old objects with aws s3 rm --recursive and then stops EC2 instances. Before the first production run, the team must confirm that the script's role is allowed to do both, without deleting or stopping anything. Which TWO actions meet this requirement? (Select TWO.)

    • A. Run the aws s3 rm command with --dryrun and check that it lists the objects.
    • B. Run the aws ec2 stop-instances command with --dry-run and expect DryRunOperation.
    • C. Run aws iam simulate-principal-policy for the role with s3:DeleteObject on the objects' ARNs, passing the bucket policy if there is one.
    • D. Run the aws ec2 stop-instances command with --generate-cli-skeleton output.
    • E. Run aws sts decode-authorization-message with the role ARN as the encoded message.
Answers
  1. A. A dry run authorizes the real request without launching anything. B creates a billable instance; C proves the template exists, not that the role may use it; D tests nothing about EC2 permissions.
  2. B, C. The EC2 dry run authorizes the real StopInstances request, and the simulator covers the S3 deletes, which have no dry run. A only prints the planned deletes without any authorization check; D prints an output template; E decodes encoded failure messages, not ARNs.

12. Decoding authorization failures

Concept

Exam facts

Developer angle

aws ec2 stop-instances --instance-ids i-0123456789abcdef0
# An error occurred (UnauthorizedOperation) ... followed by an encoded authorization message

aws sts get-caller-identity --query Arn --output text
aws sts decode-authorization-message --encoded-message "$ENCODED" \
  --query DecodedMessage --output text | python3 -m json.tool

Policy that lets a support role decode messages:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "sts:DecodeAuthorizationMessage",
    "Resource": "*"
  }]
}

A trimmed decoded message (field names as in the STS API reference, values invented):

{
  "allowed": "false",
  "explicitDeny": "true",
  "context": {
    "principal": {"id": "AROAEXAMPLEROLEID:alice", "arn": "arn:aws:sts::111122223333:assumed-role/dev-role/alice"},
    "action": "ec2:StopInstances",
    "resource": "arn:aws:ec2:eu-west-1:111122223333:instance/i-0123456789abcdef0",
    "conditions": [
      {"item": {"key": "ec2:ResourceTag/env", "values": ["prod"]}}
    ]
  }
}

Classifying failures in code before deciding what to fix:

from botocore.exceptions import ClientError, NoCredentialsError

CREDENTIAL_CODES = {"InvalidClientTokenId", "UnrecognizedClientException", "SignatureDoesNotMatch",
                    "ExpiredToken", "ExpiredTokenException", "InvalidAccessKeyId"}
AUTHZ_CODES = {"AccessDenied", "AccessDeniedException", "UnauthorizedOperation"}

def classify(call):
    try:
        return call()
    except NoCredentialsError:
        return "no credentials found in the provider chain"
    except ClientError as err:
        code = err.response["Error"]["Code"]
        if code in CREDENTIAL_CODES:
            return f"credential or signing problem: {code}"
        if code in AUTHZ_CODES:
            return f"authorization problem: {err.response['Error']['Message']}"
        raise

Traps

Practice questions

  1. A developer's aws ec2 start-instances call fails with UnauthorizedOperation and a long encoded message, although the developer's identity policy allows ec2:StartInstances on all instances. Which action shows whether an explicit deny caused the failure?

    • A. Decode the message locally with base64 --decode, then search the resulting JSON document for a Deny effect.
    • B. Call aws sts get-session-token and retry the command with the new credentials.
    • C. Call aws sts decode-authorization-message with a principal allowed sts:DecodeAuthorizationMessage.
    • D. Rerun the command with --dry-run and read the matched policy statements in the EC2 error output.
  2. A script on a build server fails, and the team must decide whether to change IAM policies or fix the credential setup. Which TWO error codes point to the credential setup rather than to missing permissions? (Select TWO.)

    • A. AccessDeniedException with "because no identity-based policy allows the action"
    • B. InvalidClientTokenId
    • C. UnauthorizedOperation from EC2 with an encoded message
    • D. SignatureDoesNotMatch
    • E. AccessDenied "with an explicit deny in a service control policy"
Answers
  1. C. The STS API decodes the message and reports explicitDeny along with the principal, action, resource and condition values. A fails because only STS can decode it; B changes credentials without explaining the denial; D returns UnauthorizedOperation again and never prints policy statements.
  2. B, D. An unknown key or token and a signature mismatch are credential or signing problems. A, C and E are authorization results that a policy change (or removing a deny) would fix.

Quick decision rules

Profiles, MFA and the credential chain (§1–§5)

SDK usage, CLI output and quotas (§6–§8)

Retries, signing and permission testing (§9–§12)

Changed vs older material

Learn the Current column; older practice material may still show the Course / older material value. Confirmed rows are copied to notes/current-facts.md.

Topic Course / older material Current (verified 2026-10-12) Source
§1, §6 · Default Region when none is configured us-east-1 is chosen by default No default: set the Region in code, AWS_REGION (boto3 and CLI v1 read only AWS_DEFAULT_REGION, not AWS_REGION) or the profile; the CLI fails with "You must specify a region", boto3 raises NoRegionError, Java 2.x client creation fails AWS docs
§1 · AWS CLI version 1 v1 (installed with pip) treated as current Maintenance mode since 2026-07-15 (critical bug and security fixes only, no new services, APIs or Regions); end of support 2027-07-15; use v2 AWS blog
§3 · AWS CLI v2 credential precedence 6 sources: command line, environment, credentials file, config file, container, instance profile 10 sources: options → environment → assume role → web identity → IAM Identity Center → credentials file → credential_process → config file → container → EC2 instance profile AWS docs
§4 · SDK for Java default credential chain Java 1.x: aws.accessKeyId / aws.secretKey, 5 steps Java 2.x DefaultCredentialsProvider: aws.accessKeyId / aws.secretAccessKey / aws.sessionToken → environment → web identity → shared profile (SSO, role, console login, process, keys) → ECS container → instance profile; Java 1.x is end of support AWS docs
§5 · Credentials for CLI/SDK use outside AWS Environment variables or named profiles with IAM user access keys Short-term credentials: aws login (CLI 2.32.0+, refreshed every 15 min for up to 12 h), IAM Identity Center, IAM Roles Anywhere, OIDC federation; long-term keys "Not recommended" AWS docs
§6 · Official AWS SDKs Java, .NET, Node.js, PHP, Python, Go, Ruby, C++ Also JavaScript v3 (Node.js and browsers), Kotlin, Rust, Swift, SAP ABAP and the Tools for PowerShell; Java 1.x, JavaScript v2, Go v1 and .NET 3.x are end of support AWS docs
§8 · EC2 DescribeInstances request rate 100 calls per second Token bucket per account and Region: without filters or pagination 50 burst / 10 per s; filtered or paginated (non-mutating bucket) 100 / 20 per s; throttled calls get RequestLimitExceeded AWS docs
§8 · Running On-Demand Standard instances quota 1,152 vCPUs AWS default 5 vCPUs (L-1216C47A); the applied value varies by account and EC2 raises it automatically with usage or on request AWS docs
§9 · Which errors to retry Retry 5xx and throttling; never retry a 4xx Retry transient and throttling errors, including throttles with a 4xx status (ThrottlingException 400, 429) and an HTTP 400 RequestTimeout; don't retry other 4xx such as AccessDeniedException or ValidationException AWS docs
§9 · SDK default retry behaviour ⚠️ volatile Per-SDK legacy defaults (boto3 and CLI v1: legacy, 5 attempts; DynamoDB 10) Updated behaviour is opt-in (AWS_NEW_RETRIES_2026=true) and, per AWS, the default from November 2026: standard mode everywhere, 3 attempts (DynamoDB 4), base delay 50 ms transient / 1,000 ms throttling, 20 s cap, 500-token retry quota (14 per transient, 5 per throttling retry) AWS docs · AWS blog