There are more AWS SDK examples available in the AWS Doc SDK Examples
CloudFront examples using AWS CLI with Bash script
The following code examples show you how to perform actions and implement common scenarios by using the AWS Command Line Interface with Bash script with CloudFront.
Scenarios are code examples that show you how to accomplish specific tasks by calling multiple functions within a service or combined with other AWS services.
Each example includes a link to the complete source code, where you can find instructions on how to set up and run the code in context.
Topics
Scenarios
The following code example shows how to:
Create an Amazon S3 bucket
Upload content to the bucket
Create a CloudFront distribution with OAC
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # CloudFront Getting Started Tutorial Script # This script creates an S3 bucket, uploads sample content, creates a CloudFront distribution with OAC, # and demonstrates how to access content through CloudFront. # Set up logging LOG_FILE="cloudfront-tutorial.log" exec > >(tee -a "$LOG_FILE") 2>&1 echo "Starting CloudFront Getting Started Tutorial at $(date)" # Function to handle errors handle_error() { echo "ERROR: $1" echo "Resources created before error:" if [ -n "$BUCKET_NAME" ]; then echo "- S3 Bucket: $BUCKET_NAME" fi if [ -n "$OAC_ID" ]; then echo "- CloudFront Origin Access Control: $OAC_ID" fi if [ -n "$DISTRIBUTION_ID" ]; then echo "- CloudFront Distribution: $DISTRIBUTION_ID" fi echo "Attempting to clean up resources..." cleanup exit 1 } # Function to clean up resources cleanup() { echo "Cleaning up resources..." if [ -n "$DISTRIBUTION_ID" ]; then echo "Disabling CloudFront distribution $DISTRIBUTION_ID..." # Get the current configuration and ETag ETAG=$(aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" --query 'ETag' --output text) if [ $? -ne 0 ]; then echo "Failed to get distribution config. Continuing with cleanup..." else # Create a modified configuration with Enabled=false aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" | \ jq '.DistributionConfig.Enabled = false' > temp_disabled_config.json # Update the distribution to disable it aws cloudfront update-distribution \ --id "$DISTRIBUTION_ID" \ --distribution-config file://<(jq '.DistributionConfig' temp_disabled_config.json) \ --if-match "$ETAG" if [ $? -ne 0 ]; then echo "Failed to disable distribution. Continuing with cleanup..." else echo "Waiting for distribution to be disabled (this may take several minutes)..." aws cloudfront wait distribution-deployed --id "$DISTRIBUTION_ID" # Delete the distribution ETAG=$(aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" --query 'ETag' --output text) aws cloudfront delete-distribution --id "$DISTRIBUTION_ID" --if-match "$ETAG" if [ $? -ne 0 ]; then echo "Failed to delete distribution. You may need to delete it manually." else echo "CloudFront distribution deleted." fi fi fi fi if [ -n "$OAC_ID" ]; then echo "Deleting Origin Access Control $OAC_ID..." OAC_ETAG=$(aws cloudfront get-origin-access-control --id "$OAC_ID" --query 'ETag' --output text 2>/dev/null) if [ $? -ne 0 ]; then echo "Failed to get Origin Access Control ETag. You may need to delete it manually." else aws cloudfront delete-origin-access-control --id "$OAC_ID" --if-match "$OAC_ETAG" if [ $? -ne 0 ]; then echo "Failed to delete Origin Access Control. You may need to delete it manually." else echo "Origin Access Control deleted." fi fi fi if [ -n "$BUCKET_NAME" ]; then echo "Deleting S3 bucket $BUCKET_NAME and its contents..." aws s3 rm "s3://$BUCKET_NAME" --recursive if [ $? -ne 0 ]; then echo "Failed to remove bucket contents. Continuing with bucket deletion..." fi aws s3 rb "s3://$BUCKET_NAME" if [ $? -ne 0 ]; then echo "Failed to delete bucket. You may need to delete it manually." else echo "S3 bucket deleted." fi fi # Clean up temporary files rm -f temp_disabled_config.json rm -rf temp_content } # Generate a random identifier for the bucket name RANDOM_ID=$(openssl rand -hex 6) BUCKET_NAME="cloudfront-${RANDOM_ID}" echo "Using bucket name: $BUCKET_NAME" # Create a temporary directory for content TEMP_DIR="temp_content" mkdir -p "$TEMP_DIR/css" if [ $? -ne 0 ]; then handle_error "Failed to create temporary directory" fi # Step 1: Create an S3 bucket echo "Creating S3 bucket: $BUCKET_NAME" aws s3 mb "s3://$BUCKET_NAME" if [ $? -ne 0 ]; then handle_error "Failed to create S3 bucket" fi # Step 2: Create sample content echo "Creating sample content..." cat > "$TEMP_DIR/index.html" << 'EOF' <!DOCTYPE html> <html> <head> <title>Hello World</title> <link rel="stylesheet" type="text/css" href="css/styles.css"> </head> <body> <h1>Hello world!</h1> </body> </html> EOF cat > "$TEMP_DIR/css/styles.css" << 'EOF' body { font-family: Arial, sans-serif; margin: 40px; background-color: #f5f5f5; } h1 { color: #333; text-align: center; } EOF # Step 3: Upload content to the S3 bucket echo "Uploading content to S3 bucket..." aws s3 cp "$TEMP_DIR/" "s3://$BUCKET_NAME/" --recursive if [ $? -ne 0 ]; then handle_error "Failed to upload content to S3 bucket" fi # Step 4: Create Origin Access Control echo "Creating Origin Access Control..." OAC_RESPONSE=$(aws cloudfront create-origin-access-control \ --origin-access-control-config Name="oac-for-$BUCKET_NAME",SigningProtocol=sigv4,SigningBehavior=always,OriginAccessControlOriginType=s3) if [ $? -ne 0 ]; then handle_error "Failed to create Origin Access Control" fi OAC_ID=$(echo "$OAC_RESPONSE" | jq -r '.OriginAccessControl.Id') echo "Created Origin Access Control with ID: $OAC_ID" # Step 5: Create CloudFront distribution echo "Creating CloudFront distribution..." # Get AWS account ID for bucket policy ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) if [ $? -ne 0 ]; then handle_error "Failed to get AWS account ID" fi # Create distribution configuration cat > distribution-config.json << EOF { "CallerReference": "cli-tutorial-$(date +%s)", "Origins": { "Quantity": 1, "Items": [ { "Id": "S3-$BUCKET_NAME", "DomainName": "$BUCKET_NAME.s3.amazonaws.com", "S3OriginConfig": { "OriginAccessIdentity": "" }, "OriginAccessControlId": "$OAC_ID" } ] }, "DefaultCacheBehavior": { "TargetOriginId": "S3-$BUCKET_NAME", "ViewerProtocolPolicy": "redirect-to-https", "AllowedMethods": { "Quantity": 2, "Items": ["GET", "HEAD"], "CachedMethods": { "Quantity": 2, "Items": ["GET", "HEAD"] } }, "DefaultTTL": 86400, "MinTTL": 0, "MaxTTL": 31536000, "Compress": true, "ForwardedValues": { "QueryString": false, "Cookies": { "Forward": "none" } } }, "Comment": "CloudFront distribution for tutorial", "Enabled": true, "WebACLId": "" } EOF DIST_RESPONSE=$(aws cloudfront create-distribution --distribution-config file://distribution-config.json) if [ $? -ne 0 ]; then handle_error "Failed to create CloudFront distribution" fi DISTRIBUTION_ID=$(echo "$DIST_RESPONSE" | jq -r '.Distribution.Id') DOMAIN_NAME=$(echo "$DIST_RESPONSE" | jq -r '.Distribution.DomainName') echo "Created CloudFront distribution with ID: $DISTRIBUTION_ID" echo "CloudFront domain name: $DOMAIN_NAME" # Step 6: Update S3 bucket policy echo "Updating S3 bucket policy..." cat > bucket-policy.json << EOF { "Version":"2012-10-17", "Statement": [ { "Sid": "AllowCloudFrontServicePrincipal", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::$BUCKET_NAME/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::$ACCOUNT_ID:distribution/$DISTRIBUTION_ID" } } } ] } EOF aws s3api put-bucket-policy --bucket "$BUCKET_NAME" --policy file://bucket-policy.json if [ $? -ne 0 ]; then handle_error "Failed to update S3 bucket policy" fi # Step 7: Wait for distribution to deploy echo "Waiting for CloudFront distribution to deploy (this may take 5-10 minutes)..." aws cloudfront wait distribution-deployed --id "$DISTRIBUTION_ID" if [ $? -ne 0 ]; then echo "Warning: Distribution deployment wait timed out. The distribution may still be deploying." else echo "CloudFront distribution is now deployed." fi # Step 8: Display access information echo "" echo "===== CloudFront Distribution Setup Complete =====" echo "You can access your content at: https://$DOMAIN_NAME/index.html" echo "" echo "Resources created:" echo "- S3 Bucket: $BUCKET_NAME" echo "- CloudFront Origin Access Control: $OAC_ID" echo "- CloudFront Distribution: $DISTRIBUTION_ID" echo "" # Ask user if they want to clean up resources read -p "Do you want to clean up all resources created by this script? (y/n): " CLEANUP_RESPONSE if [[ "$CLEANUP_RESPONSE" =~ ^[Yy] ]]; then cleanup echo "All resources have been cleaned up." else echo "Resources will not be cleaned up. You can manually delete them later." echo "To access your content, visit: https://$DOMAIN_NAME/index.html" fi echo "Tutorial completed at $(date)"-
For API details, see the following topics in AWS CLI Command Reference.
-
The following code example shows how to:
Create a web ACL
Add a string match rule
Add managed rules
Configure logging
Clean up resources
- AWS CLI with Bash script
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials
repository. #!/bin/bash # AWS WAF Getting Started Script # This script creates a Web ACL with a string match rule and AWS Managed Rules, # associates it with a CloudFront distribution, and then cleans up all resources. # Set up logging LOG_FILE="waf-tutorial.log" exec > >(tee -a "$LOG_FILE") 2>&1 echo "===================================================" echo "AWS WAF Getting Started Tutorial" echo "===================================================" echo "This script will create AWS WAF resources and associate" echo "them with a CloudFront distribution." echo "" # Maximum number of retries for operations MAX_RETRIES=3 # Function to handle errors handle_error() { echo "ERROR: $1" echo "Check the log file for details: $LOG_FILE" cleanup_resources exit 1 } # Function to check command success check_command() { if echo "$1" | grep -i "error" > /dev/null; then handle_error "$2: $1" fi } # Function to clean up resources cleanup_resources() { echo "" echo "===================================================" echo "CLEANING UP RESOURCES" echo "===================================================" if [ -n "$DISTRIBUTION_ID" ] && [ -n "$WEB_ACL_ARN" ]; then echo "Disassociating Web ACL from CloudFront distribution..." DISASSOCIATE_RESULT=$(aws wafv2 disassociate-web-acl \ --resource-arn "arn:aws:cloudfront::$(aws sts get-caller-identity --query Account --output text):distribution/$DISTRIBUTION_ID" \ --region us-east-1 2>&1) if echo "$DISASSOCIATE_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to disassociate Web ACL: $DISASSOCIATE_RESULT" else echo "Web ACL disassociated successfully." fi fi if [ -n "$WEB_ACL_ID" ] && [ -n "$WEB_ACL_NAME" ]; then echo "Deleting Web ACL..." # Get the latest lock token before deletion GET_RESULT=$(aws wafv2 get-web-acl \ --name "$WEB_ACL_NAME" \ --scope CLOUDFRONT \ --id "$WEB_ACL_ID" \ --region us-east-1 2>&1) if echo "$GET_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to get Web ACL for deletion: $GET_RESULT" echo "You may need to manually delete the Web ACL using the AWS Console." else LATEST_TOKEN=$(echo "$GET_RESULT" | grep -o '"LockToken": "[^"]*' | cut -d'"' -f4) if [ -n "$LATEST_TOKEN" ]; then DELETE_RESULT=$(aws wafv2 delete-web-acl \ --name "$WEB_ACL_NAME" \ --scope CLOUDFRONT \ --id "$WEB_ACL_ID" \ --lock-token "$LATEST_TOKEN" \ --region us-east-1 2>&1) if echo "$DELETE_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to delete Web ACL: $DELETE_RESULT" echo "You may need to manually delete the Web ACL using the AWS Console." else echo "Web ACL deleted successfully." fi else echo "Warning: Could not extract lock token for deletion. You may need to manually delete the Web ACL." fi fi fi echo "Cleanup process completed." } # Generate a random identifier for resource names RANDOM_ID=$(openssl rand -hex 4) WEB_ACL_NAME="MyWebACL-${RANDOM_ID}" METRIC_NAME="MyWebACLMetrics-${RANDOM_ID}" echo "Using Web ACL name: $WEB_ACL_NAME" # Step 1: Create a Web ACL echo "" echo "===================================================" echo "STEP 1: Creating Web ACL" echo "===================================================" CREATE_RESULT=$(aws wafv2 create-web-acl \ --name "$WEB_ACL_NAME" \ --scope "CLOUDFRONT" \ --default-action Allow={} \ --visibility-config "SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=$METRIC_NAME" \ --region us-east-1 2>&1) check_command "$CREATE_RESULT" "Failed to create Web ACL" # Extract Web ACL ID, ARN, and Lock Token from the Summary object WEB_ACL_ID=$(echo "$CREATE_RESULT" | grep -o '"Id": "[^"]*' | cut -d'"' -f4) WEB_ACL_ARN=$(echo "$CREATE_RESULT" | grep -o '"ARN": "[^"]*' | cut -d'"' -f4) LOCK_TOKEN=$(echo "$CREATE_RESULT" | grep -o '"LockToken": "[^"]*' | cut -d'"' -f4) if [ -z "$WEB_ACL_ID" ]; then handle_error "Failed to extract Web ACL ID" fi if [ -z "$LOCK_TOKEN" ]; then handle_error "Failed to extract Lock Token" fi echo "Web ACL created successfully with ID: $WEB_ACL_ID" echo "Lock Token: $LOCK_TOKEN" # Step 2: Add a String Match Rule echo "" echo "===================================================" echo "STEP 2: Adding String Match Rule" echo "===================================================" # Try to update with retries for ((i=1; i<=MAX_RETRIES; i++)); do echo "Attempt $i to add string match rule..." # Get the latest lock token before updating GET_RESULT=$(aws wafv2 get-web-acl \ --name "$WEB_ACL_NAME" \ --scope CLOUDFRONT \ --id "$WEB_ACL_ID" \ --region us-east-1 2>&1) if echo "$GET_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to get Web ACL for update: $GET_RESULT" if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to get Web ACL after $MAX_RETRIES attempts" fi sleep 2 continue fi LATEST_TOKEN=$(echo "$GET_RESULT" | grep -o '"LockToken": "[^"]*' | cut -d'"' -f4) if [ -z "$LATEST_TOKEN" ]; then echo "Warning: Could not extract lock token for update" if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to extract lock token after $MAX_RETRIES attempts" fi sleep 2 continue fi echo "Using lock token: $LATEST_TOKEN" UPDATE_RESULT=$(aws wafv2 update-web-acl \ --name "$WEB_ACL_NAME" \ --scope "CLOUDFRONT" \ --id "$WEB_ACL_ID" \ --lock-token "$LATEST_TOKEN" \ --default-action Allow={} \ --rules '[{ "Name": "UserAgentRule", "Priority": 0, "Statement": { "ByteMatchStatement": { "SearchString": "MyAgent", "FieldToMatch": { "SingleHeader": { "Name": "user-agent" } }, "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ], "PositionalConstraint": "EXACTLY" } }, "Action": { "Count": {} }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "UserAgentRuleMetric" } }]' \ --visibility-config "SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=$METRIC_NAME" \ --region us-east-1 2>&1) if echo "$UPDATE_RESULT" | grep -i "WAFOptimisticLockException" > /dev/null; then echo "Optimistic lock exception encountered. Will retry with new lock token." if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to add string match rule after $MAX_RETRIES attempts: $UPDATE_RESULT" fi sleep 2 continue elif echo "$UPDATE_RESULT" | grep -i "error" > /dev/null; then handle_error "Failed to add string match rule: $UPDATE_RESULT" else # Success echo "String match rule added successfully." break fi done # Step 3: Add AWS Managed Rules echo "" echo "===================================================" echo "STEP 3: Adding AWS Managed Rules" echo "===================================================" # Try to update with retries for ((i=1; i<=MAX_RETRIES; i++)); do echo "Attempt $i to add AWS Managed Rules..." # Get the latest lock token before updating GET_RESULT=$(aws wafv2 get-web-acl \ --name "$WEB_ACL_NAME" \ --scope CLOUDFRONT \ --id "$WEB_ACL_ID" \ --region us-east-1 2>&1) if echo "$GET_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to get Web ACL for update: $GET_RESULT" if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to get Web ACL after $MAX_RETRIES attempts" fi sleep 2 continue fi LATEST_TOKEN=$(echo "$GET_RESULT" | grep -o '"LockToken": "[^"]*' | cut -d'"' -f4) if [ -z "$LATEST_TOKEN" ]; then echo "Warning: Could not extract lock token for update" if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to extract lock token after $MAX_RETRIES attempts" fi sleep 2 continue fi echo "Using lock token: $LATEST_TOKEN" UPDATE_RESULT=$(aws wafv2 update-web-acl \ --name "$WEB_ACL_NAME" \ --scope "CLOUDFRONT" \ --id "$WEB_ACL_ID" \ --lock-token "$LATEST_TOKEN" \ --default-action Allow={} \ --rules '[{ "Name": "UserAgentRule", "Priority": 0, "Statement": { "ByteMatchStatement": { "SearchString": "MyAgent", "FieldToMatch": { "SingleHeader": { "Name": "user-agent" } }, "TextTransformations": [ { "Priority": 0, "Type": "NONE" } ], "PositionalConstraint": "EXACTLY" } }, "Action": { "Count": {} }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "UserAgentRuleMetric" } }, { "Name": "AWS-AWSManagedRulesCommonRuleSet", "Priority": 1, "Statement": { "ManagedRuleGroupStatement": { "VendorName": "AWS", "Name": "AWSManagedRulesCommonRuleSet", "ExcludedRules": [] } }, "OverrideAction": { "Count": {} }, "VisibilityConfig": { "SampledRequestsEnabled": true, "CloudWatchMetricsEnabled": true, "MetricName": "AWS-AWSManagedRulesCommonRuleSet" } }]' \ --visibility-config "SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=$METRIC_NAME" \ --region us-east-1 2>&1) if echo "$UPDATE_RESULT" | grep -i "WAFOptimisticLockException" > /dev/null; then echo "Optimistic lock exception encountered. Will retry with new lock token." if [ "$i" -eq "$MAX_RETRIES" ]; then handle_error "Failed to add AWS Managed Rules after $MAX_RETRIES attempts: $UPDATE_RESULT" fi sleep 2 continue elif echo "$UPDATE_RESULT" | grep -i "error" > /dev/null; then handle_error "Failed to add AWS Managed Rules: $UPDATE_RESULT" else # Success echo "AWS Managed Rules added successfully." break fi done # Step 4: List CloudFront distributions echo "" echo "===================================================" echo "STEP 4: Listing CloudFront Distributions" echo "===================================================" CF_RESULT=$(aws cloudfront list-distributions --query "DistributionList.Items[*].{Id:Id,DomainName:DomainName}" --output table 2>&1) if echo "$CF_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to list CloudFront distributions: $CF_RESULT" echo "Continuing without CloudFront association." else echo "$CF_RESULT" # Ask user to select a CloudFront distribution echo "" echo "===================================================" echo "STEP 5: Associate Web ACL with CloudFront Distribution" echo "===================================================" echo "Enter the ID of the CloudFront distribution to associate with the Web ACL:" echo "(If you don't have a CloudFront distribution, press Enter to skip this step)" read -r DISTRIBUTION_ID if [ -n "$DISTRIBUTION_ID" ]; then ASSOCIATE_RESULT=$(aws wafv2 associate-web-acl \ --web-acl-arn "$WEB_ACL_ARN" \ --resource-arn "arn:aws:cloudfront::$(aws sts get-caller-identity --query Account --output text):distribution/$DISTRIBUTION_ID" \ --region us-east-1 2>&1) if echo "$ASSOCIATE_RESULT" | grep -i "error" > /dev/null; then echo "Warning: Failed to associate Web ACL with CloudFront distribution: $ASSOCIATE_RESULT" echo "Continuing without CloudFront association." DISTRIBUTION_ID="" else echo "Web ACL associated with CloudFront distribution successfully." fi else echo "Skipping association with CloudFront distribution." fi fi # Display summary of created resources echo "" echo "===================================================" echo "RESOURCE SUMMARY" echo "===================================================" echo "Web ACL Name: $WEB_ACL_NAME" echo "Web ACL ID: $WEB_ACL_ID" echo "Web ACL ARN: $WEB_ACL_ARN" if [ -n "$DISTRIBUTION_ID" ]; then echo "Associated CloudFront Distribution: $DISTRIBUTION_ID" fi echo "" # Ask user if they want to clean up resources echo "===================================================" echo "CLEANUP CONFIRMATION" echo "===================================================" echo "Do you want to clean up all created resources? (y/n): " read -r CLEANUP_CHOICE if [[ "$CLEANUP_CHOICE" =~ ^[Yy] ]]; then cleanup_resources else echo "" echo "Resources have NOT been cleaned up. You can manually clean them up later." echo "To clean up resources manually, run the following commands:" if [ -n "$DISTRIBUTION_ID" ]; then echo "aws wafv2 disassociate-web-acl --resource-arn \"arn:aws:cloudfront::$(aws sts get-caller-identity --query Account --output text):distribution/$DISTRIBUTION_ID\" --region us-east-1" fi echo "aws wafv2 delete-web-acl --name \"$WEB_ACL_NAME\" --scope CLOUDFRONT --id \"$WEB_ACL_ID\" --lock-token \"<get-latest-token>\" --region us-east-1" echo "" echo "To get the latest lock token, run:" echo "aws wafv2 get-web-acl --name \"$WEB_ACL_NAME\" --scope CLOUDFRONT --id \"$WEB_ACL_ID\" --region us-east-1" fi echo "" echo "===================================================" echo "Tutorial completed!" echo "===================================================" echo "Log file: $LOG_FILE"-
For API details, see the following topics in AWS CLI Command Reference.
-