Cli_sdks
Chapter 4: AWS CLI and SDKs
Section titled “Chapter 4: AWS CLI and SDKs”Mastering Programmatic Access to AWS Services
Section titled “Mastering Programmatic Access to AWS Services”4.1 Overview
Section titled “4.1 Overview”The AWS CLI and SDKs enable programmatic access to AWS services, essential for DevOps automation and infrastructure management.
AWS Programmatic Access Options+------------------------------------------------------------------+| || +------------------------+ || | AWS Programmatic | || | Access | || +------------------------+ || | || +--------------------+--------------------+ || | | | || v v v || +----------+ +----------+ +----------+ || | AWS CLI | | SDKs | | APIs | || | | | | | | || | - Command| | - Python | | - REST | || | Line | | - Java | | - HTTP | || | - Shell | | - Node.js| | calls | || | Scripts| | - Go | | | || | | | - .NET | | | || +----------+ +----------+ +----------+ || |+------------------------------------------------------------------+4.2 AWS CLI Installation & Configuration
Section titled “4.2 AWS CLI Installation & Configuration”Installation Methods
Section titled “Installation Methods” AWS CLI Installation+------------------------------------------------------------------+| || Method 1: Official Installer || +----------------------------------------------------------+ || | # Linux/macOS | || | curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ || | -o "awscliv2.zip" | || | unzip awscliv2.zip | || | sudo ./aws/install | || +----------------------------------------------------------+ || || Method 2: Package Manager || +----------------------------------------------------------+ || | # macOS (Homebrew) | || | brew install awscli | || | | || | # Ubuntu/Debian | || | sudo apt-get install awscli | || | | || | # Windows (Chocolatey) | || | choco install awscli | || +----------------------------------------------------------+ || || Method 3: Python pip || +----------------------------------------------------------+ || | pip install awscli | || | pip install --upgrade awscli | || +----------------------------------------------------------+ || || Verify Installation: || +----------------------------------------------------------+ || | $ aws --version | || | aws-cli/2.15.0 Python/3.11.6 Linux/6.1.0 botocore/2.25.0 | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Configuration Methods
Section titled “Configuration Methods” AWS CLI Configuration+------------------------------------------------------------------+| || Method 1: Interactive Configuration (aws configure) || +----------------------------------------------------------+ || | $ aws configure | || | AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE | || | AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/... | || | Default region name [None]: us-east-1 | || | Default output format [None]: json | || +----------------------------------------------------------+ || || Method 2: Environment Variables || +----------------------------------------------------------+ || | export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE | || | export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/... | || | export AWS_DEFAULT_REGION=us-east-1 | || | export AWS_DEFAULT_OUTPUT=json | || +----------------------------------------------------------+ || || Method 3: Credentials File || +----------------------------------------------------------+ || | # ~/.aws/credentials | || | [default] | || | aws_access_key_id = AKIAIOSFODNN7EXAMPLE | || | aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/... | || | | || | [production] | || | aws_access_key_id = AKIAI44QH8DHBEXAMPLE | || | aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/... | || +----------------------------------------------------------+ || || Method 4: Config File || +----------------------------------------------------------+ || | # ~/.aws/config | || | [default] | || | region = us-east-1 | || | output = json | || | | || | [profile production] | || | region = us-west-2 | || | output = table | || | role_arn = arn:aws:iam::123456789012:role/AdminRole | || | source_profile = default | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Configuration Precedence
Section titled “Configuration Precedence” Credential Precedence Order+------------------------------------------------------------------+| || 1. Highest Priority || +----------------------------------------------------------+ || | Command line options (--profile, --region) | || +----------------------------------------------------------+ || | || v || 2. Environment Variables || +----------------------------------------------------------+ || | AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc. | || +----------------------------------------------------------+ || | || v || 3. Assume Role Credentials || +----------------------------------------------------------+ || | From aws configure set or environment | || +----------------------------------------------------------+ || | || v || 4. Credentials File (~/.aws/credentials) || +----------------------------------------------------------+ || | [default] profile | || +----------------------------------------------------------+ || | || v || 5. Config File (~/.aws/config) || +----------------------------------------------------------+ || | Profile settings | || +----------------------------------------------------------+ || | || v || 6. Container Credentials (EC2/ECS) || +----------------------------------------------------------+ || | IAM role for EC2 instance or ECS task | || +----------------------------------------------------------+ || | || v || 7. Instance Profile Credentials || +----------------------------------------------------------+ || | EC2 instance metadata | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+4.3 AWS CLI Command Structure
Section titled “4.3 AWS CLI Command Structure”Basic Command Syntax
Section titled “Basic Command Syntax” AWS CLI Command Structure+------------------------------------------------------------------+| || aws <service> <operation> [parameters] [options] || || +----------------------------------------------------------+ || | Component | Description | Example | || | --------------|--------------------------|---------------| || | aws | CLI command prefix | aws | || | <service> | AWS service name | ec2, s3, iam | || | <operation> | Action to perform | describe-instances || | [parameters] | Required arguments | --instance-ids || | [options] | Optional flags | --region, --output || +----------------------------------------------------------+ || || Examples: || +----------------------------------------------------------+ || | # List EC2 instances | || | aws ec2 describe-instances | || | | || | # List S3 buckets | || | aws s3 ls | || | | || | # Get specific EC2 instance | || | aws ec2 describe-instances --instance-ids i-1234567890 | || | | || | # Use specific profile | || | aws s3 ls --profile production | || | | || | # Change output format | || | aws ec2 describe-instances --output table | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Parameter Types
Section titled “Parameter Types” AWS CLI Parameter Types+------------------------------------------------------------------+| || 1. Simple Values || +----------------------------------------------------------+ || | --instance-type t2.micro | || | --region us-east-1 | || +----------------------------------------------------------+ || || 2. List Values || +----------------------------------------------------------+ || | --instance-ids i-1234567890 i-0987654321 | || | --security-group-ids sg-123456 sg-789012 | || +----------------------------------------------------------+ || || 3. Key-Value Pairs || +----------------------------------------------------------+ || | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=MyInstance}]' || +----------------------------------------------------------+ || || 4. JSON Structures || +----------------------------------------------------------+ || | --cli-input-json file://instance-config.json | || | | || | # Inline JSON | || | --filters '[{"Name":"instance-type","Values":["t2.micro"]}]' || +----------------------------------------------------------+ || || 5. Shorthand Syntax || +----------------------------------------------------------+ || | # Key=value format | || | --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":100}}]' || +----------------------------------------------------------+ || |+------------------------------------------------------------------+4.4 Output Formats
Section titled “4.4 Output Formats”Available Output Formats
Section titled “Available Output Formats” AWS CLI Output Formats+------------------------------------------------------------------+| || 1. JSON (Default) || +----------------------------------------------------------+ || | $ aws ec2 describe-instances --output json | || | { | || | "Reservations": [ | || | { | || | "Instances": [ | || | { | || | "InstanceId": "i-1234567890", | || | "InstanceType": "t2.micro", | || | "State": { | || | "Name": "running" | || | } | || | } | || | ] | || | } | || | ] | || | } | || +----------------------------------------------------------+ || || 2. Table || +----------------------------------------------------------+ || | $ aws ec2 describe-instances --output table | || | ------------------------------------------------ | || | | DescribeInstances | | || | ------------------------------------------------ | || | ||InstanceId ||InstanceType||State ||| | || | ||i-1234567890 ||t2.micro ||running ||| | || | ||i-0987654321 ||t2.small ||stopped ||| | || | ------------------------------------------------ | || +----------------------------------------------------------+ || || 3. Text || +----------------------------------------------------------+ || | $ aws ec2 describe-instances --output text | || | RESERVATIONS r-1234567890 123456789012 | || | INSTANCES i-1234567890 t2.micro running | || +----------------------------------------------------------+ || || 4. YAML || +----------------------------------------------------------+ || | $ aws ec2 describe-instances --output yaml | || | Reservations: | || | - Instances: | || | - InstanceId: i-1234567890 | || | InstanceType: t2.micro | || | State: | || | Name: running | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Query with JMESPath
Section titled “Query with JMESPath” AWS CLI Query Examples+------------------------------------------------------------------+| || Basic Queries: || +----------------------------------------------------------+ || | # Get all instance IDs | || | aws ec2 describe-instances \ | || | --query 'Reservations[*].Instances[*].InstanceId' | || | # Output: ["i-1234567890", "i-0987654321"] | || +----------------------------------------------------------+ || || Filter Queries: || +----------------------------------------------------------+ || | # Get only running instances | || | aws ec2 describe-instances \ | || | --query 'Reservations[*].Instances[?State.Name==`running`].InstanceId' || +----------------------------------------------------------+ || || Nested Queries: || +----------------------------------------------------------+ || | # Get instance ID and type | || | aws ec2 describe-instances \ | || | --query 'Reservations[*].Instances[*].[InstanceId,InstanceType]' || | # Output: [["i-1234567890", "t2.micro"], ...] | || +----------------------------------------------------------+ || || Custom Output: || +----------------------------------------------------------+ || | # Format with custom names | || | aws ec2 describe-instances \ | || | --query 'Reservations[*].Instances[*].{ID:InstanceId,Type:InstanceType,State:State.Name}' || | # Output: | || | # [ | || | # { "ID": "i-1234567890", "Type": "t2.micro", "State": "running" } || | # ] | || +----------------------------------------------------------+ || || Sort and Limit: || +----------------------------------------------------------+ || | # Sort by launch time, get first 5 | || | aws ec2 describe-instances \ | || | --query 'sort_by(Reservations[*].Instances[*],&LaunchTime)[:5].InstanceId' || +----------------------------------------------------------+ || |+------------------------------------------------------------------+4.5 AWS SDKs Overview
Section titled “4.5 AWS SDKs Overview”Available SDKs
Section titled “Available SDKs” AWS SDKs Comparison+------------------------------------------------------------------+| || SDK | Language | Package Name | Use Case || ---------------|------------|-----------------|---------------|| AWS SDK for | Python | boto3 | Scripting, || Python | | | Automation || ---------------|------------|-----------------|---------------|| AWS SDK for | JavaScript | @aws-sdk/* | Node.js apps, || JavaScript | (Node.js) | | Web apps || ---------------|------------|-----------------|---------------|| AWS SDK for | Java | aws-java-sdk | Enterprise || Java | | | applications || ---------------|------------|-----------------|---------------|| AWS SDK for | Go | github.com/ | Microservices,|| Go | | aws/aws-sdk-go | CLI tools || ---------------|------------|-----------------|---------------|| AWS SDK for | .NET | AWSSDK.* | Windows apps, || .NET | | | Azure hybrid || ---------------|------------|-----------------|---------------|| AWS SDK for | Ruby | aws-sdk | Rails apps, || Ruby | | | Automation || ---------------|------------|-----------------|---------------|| AWS SDK for | PHP | aws/aws-sdk-php | Web apps, || PHP | | | CMS || ---------------|------------|-----------------|---------------|| AWS SDK for | C++ | aws-sdk-cpp | Game dev, || C++ | | | Embedded |+------------------------------------------------------------------+4.6 AWS SDK for Python (boto3)
Section titled “4.6 AWS SDK for Python (boto3)”Installation and Setup
Section titled “Installation and Setup”# Installationpip install boto3
# Basic Usageimport boto3
# Create client (low-level service access)s3_client = boto3.client('s3')
# Create resource (high-level object-oriented access)s3_resource = boto3.resource('s3')
# Specify regionec2 = boto3.client('ec2', region_name='us-west-2')
# Use specific profilesession = boto3.Session(profile_name='production')s3 = session.client('s3')Client vs Resource
Section titled “Client vs Resource” boto3 Client vs Resource+------------------------------------------------------------------+| || Client (Low-Level) || +----------------------------------------------------------+ || | - Maps 1:1 with AWS API operations | || | - Returns dictionary responses | || | - More control over parameters | || | - Handles pagination manually | || | | || | # Example | || | client = boto3.client('s3') | || | response = client.list_buckets() | || | for bucket in response['Buckets']: | || | print(bucket['Name']) | || +----------------------------------------------------------+ || || Resource (High-Level) || +----------------------------------------------------------+ || | - Object-oriented interface | || | - Returns resource objects | || | - Automatic pagination | || | - Simpler syntax | || | | || | # Example | || | s3 = boto3.resource('s3') | || | for bucket in s3.buckets.all(): | || | print(bucket.name) | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+Common boto3 Patterns
Section titled “Common boto3 Patterns”import boto3from botocore.exceptions import ClientError
# ============================================================# Pattern 1: Error Handling# ============================================================def get_object_safe(bucket, key): s3 = boto3.client('s3') try: response = s3.get_object(Bucket=bucket, Key=key) return response['Body'].read() except ClientError as e: error_code = e.response['Error']['Code'] if error_code == 'NoSuchKey': print(f"Object {key} not found") elif error_code == 'AccessDenied': print("Access denied") else: print(f"Error: {e}") return None
# ============================================================# Pattern 2: Pagination# ============================================================def list_all_instances(): ec2 = boto3.client('ec2') instances = [] paginator = ec2.get_paginator('describe_instances')
for page in paginator.paginate(): for reservation in page['Reservations']: for instance in reservation['Instances']: instances.append(instance)
return instances
# ============================================================# Pattern 3: Waiters# ============================================================def wait_for_instance(instance_id): ec2 = boto3.client('ec2') waiter = ec2.get_waiter('instance_running')
try: waiter.wait(InstanceIds=[instance_id]) print(f"Instance {instance_id} is now running") except Exception as e: print(f"Error waiting for instance: {e}")
# ============================================================# Pattern 4: Resource Operations# ============================================================def manage_s3_objects(): s3 = boto3.resource('s3')
# Create bucket bucket = s3.create_bucket(Bucket='my-new-bucket')
# Upload file bucket.upload_file('local-file.txt', 'remote-key.txt')
# Download file bucket.download_file('remote-key.txt', 'downloaded-file.txt')
# Delete objects bucket.Object('remote-key.txt').delete()
# ============================================================# Pattern 5: Assume Role# ============================================================def assume_role(role_arn, session_name): sts = boto3.client('sts')
response = sts.assume_role( RoleArn=role_arn, RoleSessionName=session_name )
# Create session with temporary credentials session = boto3.Session( aws_access_key_id=response['Credentials']['AccessKeyId'], aws_secret_access_key=response['Credentials']['SecretAccessKey'], aws_session_token=response['Credentials']['SessionToken'] )
return session4.7 AWS SDK for JavaScript (Node.js)
Section titled “4.7 AWS SDK for JavaScript (Node.js)”Installation and Setup
Section titled “Installation and Setup”// Installation// npm install @aws-sdk/client-ec2 @aws-sdk/client-s3
// ES Modules (recommended)import { S3Client, ListBucketsCommand } from '@aws-sdk/client-s3';import { EC2Client, DescribeInstancesCommand } from '@aws-sdk/client-ec2';
// Create clientconst s3Client = new S3Client({ region: 'us-east-1' });
// CommonJSconst { S3Client, ListBucketsCommand } = require('@aws-sdk/client-s3');Common Patterns
Section titled “Common Patterns”import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';import { EC2Client, DescribeInstancesCommand, StartInstancesCommand } from '@aws-sdk/client-ec2';
// ============================================================// Pattern 1: Basic Operations// ============================================================async function listBuckets() { const client = new S3Client({ region: 'us-east-1' });
try { const command = new ListBucketsCommand({}); const response = await client.send(command);
response.Buckets.forEach(bucket => { console.log(bucket.Name); }); } catch (error) { console.error('Error:', error); }}
// ============================================================// Pattern 2: S3 Upload/Download// ============================================================async function uploadToS3(bucket, key, body) { const client = new S3Client({ region: 'us-east-1' });
const command = new PutObjectCommand({ Bucket: bucket, Key: key, Body: body });
try { const response = await client.send(command); console.log('Upload successful:', response); } catch (error) { console.error('Upload failed:', error); }}
async function downloadFromS3(bucket, key) { const client = new S3Client({ region: 'us-east-1' });
const command = new GetObjectCommand({ Bucket: bucket, Key: key });
try { const response = await client.send(command); const body = await response.Body.transformToString(); return body; } catch (error) { console.error('Download failed:', error); return null; }}
// ============================================================// Pattern 3: EC2 Operations// ============================================================async function listInstances() { const client = new EC2Client({ region: 'us-east-1' });
const command = new DescribeInstancesCommand({});
try { const response = await client.send(command);
response.Reservations.forEach(reservation => { reservation.Instances.forEach(instance => { console.log(`Instance: ${instance.InstanceId}, State: ${instance.State.Name}`); }); }); } catch (error) { console.error('Error:', error); }}
// ============================================================// Pattern 4: Pagination// ============================================================import { paginateListObjects } from '@aws-sdk/client-s3';
async function listAllObjects(bucket) { const client = new S3Client({ region: 'us-east-1' }); const objects = [];
const paginator = paginateListObjects({ client }, { Bucket: bucket });
for await (const page of paginator) { if (page.Contents) { objects.push(...page.Contents); } }
return objects;}
// ============================================================// Pattern 5: Waiters// ============================================================import { waitUntilInstanceRunning } from '@aws-sdk/client-ec2';
async function startAndWaitForInstance(instanceId) { const client = new EC2Client({ region: 'us-east-1' });
// Start instance await client.send(new StartInstancesCommand({ InstanceIds: [instanceId] }));
// Wait for running state await waitUntilInstanceRunning({ client }, { InstanceIds: [instanceId] });
console.log(`Instance ${instanceId} is now running`);}4.8 AWS SDK for Go
Section titled “4.8 AWS SDK for Go”Installation and Setup
Section titled “Installation and Setup”// Installation// go get github.com/aws/aws-sdk-go-v2// go get github.com/aws/aws-sdk-go-v2/config// go get github.com/aws/aws-sdk-go-v2/service/s3// go get github.com/aws/aws-sdk-go-v2/service/ec2
package main
import ( "context" "fmt" "log"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/ec2")
func main() { // Load configuration cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { log.Fatalf("unable to load SDK config, %v", err) }
// Create clients s3Client := s3.NewFromConfig(cfg) ec2Client := ec2.NewFromConfig(cfg)
// Use clients... _ = s3Client _ = ec2Client}Common Patterns
Section titled “Common Patterns”package main
import ( "context" "fmt" "log" "io"
"github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/ec2/types")
// ============================================================// Pattern 1: S3 Operations// ============================================================func listBuckets() { cfg, _ := config.LoadDefaultConfig(context.TODO()) client := s3.NewFromConfig(cfg)
result, err := client.ListBuckets(context.TODO(), &s3.ListBucketsInput{}) if err != nil { log.Fatal(err) }
for _, bucket := range result.Buckets { fmt.Printf("Bucket: %s\n", *bucket.Name) }}
func uploadToS3(bucket, key string, body io.Reader) error { cfg, _ := config.LoadDefaultConfig(context.TODO()) client := s3.NewFromConfig(cfg)
_, err := client.PutObject(context.TODO(), &s3.PutObjectInput{ Bucket: aws.String(bucket), Key: aws.String(key), Body: body, })
return err}
// ============================================================// Pattern 2: EC2 Operations// ============================================================func listInstances() { cfg, _ := config.LoadDefaultConfig(context.TODO()) client := ec2.NewFromConfig(cfg)
result, err := client.DescribeInstances(context.TODO(), &ec2.DescribeInstancesInput{}) if err != nil { log.Fatal(err) }
for _, reservation := range result.Reservations { for _, instance := range reservation.Instances { fmt.Printf("Instance: %s, State: %s\n", *instance.InstanceId, instance.State.Name) } }}
func startInstance(instanceID string) error { cfg, _ := config.LoadDefaultConfig(context.TODO()) client := ec2.NewFromConfig(cfg)
_, err := client.StartInstances(context.TODO(), &ec2.StartInstancesInput{ InstanceIds: []string{instanceID}, })
return err}
// ============================================================// Pattern 3: Pagination// ============================================================func listAllObjects(bucket string) error { cfg, _ := config.LoadDefaultConfig(context.TODO()) client := s3.NewFromConfig(cfg)
paginator := s3.NewListObjectsV2Paginator(client, &s3.ListObjectsV2Input{ Bucket: aws.String(bucket), })
for paginator.HasMorePages() { page, err := paginator.NextPage(context.TODO()) if err != nil { return err }
for _, obj := range page.Contents { fmt.Printf("Object: %s (%d bytes)\n", *obj.Key, obj.Size) } }
return nil}
// ============================================================// Pattern 4: Error Handling// ============================================================import ( "github.com/aws/aws-sdk-go-v2/service/s3/types" "errors")
func handleS3Errors(err error) { var noSuchKey *types.NoSuchKey var accessDenied *types.AccessDenied
switch { case errors.As(err, &noSuchKey): fmt.Println("Object not found") case errors.As(err, &accessDenied): fmt.Println("Access denied") default: fmt.Printf("Error: %v\n", err) }}4.9 CLI Automation Scripts
Section titled “4.9 CLI Automation Scripts”Shell Script Examples
Section titled “Shell Script Examples”#!/bin/bash# ============================================================# Script: Backup S3 Bucket# ============================================================
SOURCE_BUCKET="my-source-bucket"DEST_BUCKET="my-backup-bucket"DATE=$(date +%Y-%m-%d)
# Sync bucketsaws s3 sync s3://$SOURCE_BUCKET s3://$DEST_BUCKET/$DATE/ \ --storage-class STANDARD_IA \ --quiet
echo "Backup completed: s3://$DEST_BUCKET/$DATE/"
# ============================================================# Script: EC2 Instance Management# ============================================================
# Start instances with specific tagaws ec2 start-instances \ --instance-ids $(aws ec2 describe-instances \ --filters "Name=tag:Environment,Values=development" \ "Name=instance-state-name,Values=stopped" \ --query "Reservations[*].Instances[*].InstanceId" \ --output text)
# Stop instances at end of dayaws ec2 stop-instances \ --instance-ids $(aws ec2 describe-instances \ --filters "Name=tag:AutoStop,Values=true" \ "Name=instance-state-name,Values=running" \ --query "Reservations[*].Instances[*].InstanceId" \ --output text)
# ============================================================# Script: Clean Up Old Snapshots# ============================================================
RETENTION_DAYS=30
# Get snapshots older than retention periodOLD_SNAPSHOTS=$(aws ec2 describe-snapshots \ --owner-ids self \ --query "Snapshots[?StartTime<='$(date -d "-$RETENTION_DAYS days" +%Y-%m-%d)'].SnapshotId" \ --output text)
# Delete old snapshotsfor snapshot in $OLD_SNAPSHOTS; do echo "Deleting snapshot: $snapshot" aws ec2 delete-snapshot --snapshot-id $snapshotdone
# ============================================================# Script: Rotate Access Keys# ============================================================
USERNAME="dev-user"
# Create new access keyNEW_KEY=$(aws iam create-access-key \ --user-name $USERNAME \ --query 'AccessKey.[AccessKeyId,SecretAccessKey]' \ --output text)
ACCESS_KEY_ID=$(echo $NEW_KEY | awk '{print $1}')SECRET_KEY=$(echo $NEW_KEY | awk '{print $2}')
echo "New Access Key: $ACCESS_KEY_ID"echo "New Secret Key: $SECRET_KEY"
# List old keysOLD_KEYS=$(aws iam list-access-keys \ --user-name $USERNAME \ --query "AccessKeyMetadata[?AccessKeyId!='$ACCESS_KEY_ID'].AccessKeyId" \ --output text)
# Delete old keysfor key in $OLD_KEYS; do echo "Deleting old key: $key" aws iam delete-access-key \ --user-name $USERNAME \ --access-key-id $keydone4.10 Best Practices
Section titled “4.10 Best Practices” AWS CLI/SDK Best Practices+------------------------------------------------------------------+| || 1. Credential Management || +----------------------------------------------------------+ || | - Use IAM roles instead of access keys where possible | || | - Rotate access keys regularly | || | - Use named profiles for different accounts | || | - Never hardcode credentials in code | || +----------------------------------------------------------+ || || 2. Error Handling || +----------------------------------------------------------+ || | - Always implement retry logic | || | - Use exponential backoff | || | - Handle specific error codes | || | - Log errors for debugging | || +----------------------------------------------------------+ || || 3. Performance || +----------------------------------------------------------+ || | - Use pagination for large result sets | || | - Use waiters instead of polling | || | - Use concurrent requests where appropriate | || | - Cache frequently accessed data | || +----------------------------------------------------------+ || || 4. Security || +----------------------------------------------------------+ || | - Use least privilege IAM policies | || | - Enable CloudTrail for API auditing | || | - Use VPC endpoints for private connectivity | || | - Encrypt sensitive data in transit | || +----------------------------------------------------------+ || |+------------------------------------------------------------------+4.11 Exam Tips
Section titled “4.11 Exam Tips”- Credential Precedence: Know the order of credential sources
- Output Formats: JSON, table, text, yaml - know when to use each
- JMESPath Queries: Understand query syntax for filtering output
- Client vs Resource: boto3 client is low-level, resource is high-level
- Pagination: Use paginators for large result sets
- Waiters: Use waiters to wait for resource state changes
- Error Handling: Implement retry with exponential backoff
- Profiles: Use named profiles for multi-account access
Next Chapter
Section titled “Next Chapter”Chapter 5: AWS Well-Architected Framework
Last Updated: February 2026