AWS Security ChangesHomeSearch

AWS code-library medium security documentation change

Service: code-library · 2026-05-01 · Security-related medium

File: code-library/latest/ug/bash_2_cloudfront_code_examples.md

Summary

Enhanced security hardening in CloudFront setup script: added input validation, secure permissions, encryption, error handling, and automated cleanup

Security assessment

Changes include: 1) Input validation for AWS account ID, OAC ID, and distribution ID to prevent injection attacks; 2) Secure file permissions (chmod 600/700) for temporary files; 3) Bucket encryption enforcement (AES256); 4) Public access blocking; 5) Secure random ID generation; 6) Redirection of errors to stderr; 7) Removal of sensitive config files during cleanup. These mitigate risks of misconfiguration, data leakage, and unauthorized access.

Diff

diff --git a/code-library/latest/ug/bash_2_cloudfront_code_examples.md b/code-library/latest/ug/bash_2_cloudfront_code_examples.md
index a7bae82d2..b53f110a6 100644
--- a//code-library/latest/ug/bash_2_cloudfront_code_examples.md
+++ b//code-library/latest/ug/bash_2_cloudfront_code_examples.md
@@ -54,0 +55,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    set -euo pipefail
+    
@@ -63 +65 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "ERROR: $1"
+        echo "ERROR: $1" >&2
@@ -65 +67 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$BUCKET_NAME" ]; then
+        if [ -n "${BUCKET_NAME:-}" ]; then
@@ -68 +70 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$OAC_ID" ]; then
+        if [ -n "${OAC_ID:-}" ]; then
@@ -71 +73 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$DISTRIBUTION_ID" ]; then
+        if [ -n "${DISTRIBUTION_ID:-}" ]; then
@@ -84 +86 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$DISTRIBUTION_ID" ]; then
+        if [ -n "${DISTRIBUTION_ID:-}" ]; then
@@ -87,3 +89,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            # Get the current configuration and ETag
-            ETAG=$(aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" --query 'ETag' --output text)
-            if [ $? -ne 0 ]; then
+            # Get the current configuration and ETag in one call
+            DIST_CONFIG=$(aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" 2>/dev/null) || {
@@ -91,4 +92,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            else
-                # Create a modified configuration with Enabled=false
-                aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" | \
-                jq '.DistributionConfig.Enabled = false' > temp_disabled_config.json
+                DIST_CONFIG=""
+            }
@@ -96 +95,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                # Update the distribution to disable it
+            if [ -n "$DIST_CONFIG" ]; then
+                ETAG=$(echo "$DIST_CONFIG" | jq -r '.ETag')
+                
+                # Modify and update distribution in one pipeline
+                if echo "$DIST_CONFIG" | jq '.DistributionConfig.Enabled = false' | \
@@ -99,2 +102,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    --distribution-config file://<(jq '.DistributionConfig' temp_disabled_config.json) \
-                    --if-match "$ETAG"
+                        --distribution-config "$(cat)" \
+                        --if-match "$ETAG" 2>/dev/null; then
@@ -102,3 +104,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                if [ $? -ne 0 ]; then
-                    echo "Failed to disable distribution. Continuing with cleanup..."
-                else
@@ -106 +106,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    aws cloudfront wait distribution-deployed --id "$DISTRIBUTION_ID"
+                    aws cloudfront wait distribution-deployed --id "$DISTRIBUTION_ID" 2>/dev/null || {
+                        echo "Distribution deployment wait timed out. Proceeding with deletion..."
+                    }
@@ -108,4 +110,10 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    # 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
+                    # Get fresh ETag for deletion
+                    DIST_CONFIG=$(aws cloudfront get-distribution-config --id "$DISTRIBUTION_ID" 2>/dev/null) || {
+                        echo "Failed to get updated config. Skipping distribution deletion..."
+                        DIST_CONFIG=""
+                    }
+                    
+                    if [ -n "$DIST_CONFIG" ]; then
+                        ETAG=$(echo "$DIST_CONFIG" | jq -r '.ETag')
+                        aws cloudfront delete-distribution --id "$DISTRIBUTION_ID" --if-match "$ETAG" 2>/dev/null && \
+                            echo "CloudFront distribution deleted." || \
@@ -113,2 +120,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                    else
-                        echo "CloudFront distribution deleted."
@@ -115,0 +122,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+                else
+                    echo "Failed to disable distribution. Continuing with cleanup..."
@@ -120 +128 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$OAC_ID" ]; then
+        if [ -n "${OAC_ID:-}" ]; then
@@ -122,6 +130,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            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
+            OAC_DATA=$(aws cloudfront get-origin-access-control --id "$OAC_ID" 2>/dev/null) || {
+                echo "Failed to get Origin Access Control. You may need to delete it manually."
+                OAC_DATA=""
+            }
+            
+            if [ -n "$OAC_DATA" ]; then
+                OAC_ETAG=$(echo "$OAC_DATA" | jq -r '.ETag')
+                aws cloudfront delete-origin-access-control --id "$OAC_ID" --if-match "$OAC_ETAG" 2>/dev/null && \
+                    echo "Origin Access Control deleted." || \
@@ -129,3 +139,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                else
-                    echo "Origin Access Control deleted."
-                fi
@@ -135 +143 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$BUCKET_NAME" ]; then
+        if [ -n "${BUCKET_NAME:-}" ] && [ "$BUCKET_IS_SHARED" != "true" ]; then
@@ -137,2 +145 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws s3 rm "s3://$BUCKET_NAME" --recursive
-            if [ $? -ne 0 ]; then
+            aws s3 rm "s3://$BUCKET_NAME" --recursive 2>/dev/null || {
@@ -140 +147 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            fi
+            }
@@ -142,2 +149,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws s3 rb "s3://$BUCKET_NAME"
-            if [ $? -ne 0 ]; then
+            aws s3 rb "s3://$BUCKET_NAME" 2>/dev/null && \
+                echo "S3 bucket deleted." || \
@@ -145,3 +151,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            else
-                echo "S3 bucket deleted."
-            fi
@@ -151,2 +155,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        rm -f temp_disabled_config.json
-        rm -rf temp_content
+        rm -f temp_disabled_config.json distribution-config.json bucket-policy.json 2>/dev/null || true
+        rm -rf temp_content 2>/dev/null || true
@@ -155 +159,25 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Generate a random identifier for the bucket name
+    # Trap errors and cleanup
+    trap 'handle_error "Script interrupted"' INT TERM
+    
+    # Validate AWS CLI is available
+    if ! command -v aws &> /dev/null; then
+        handle_error "AWS CLI is not installed or not in PATH"
+    fi
+    
+    # Validate jq is available
+    if ! command -v jq &> /dev/null; then
+        handle_error "jq is not installed or not in PATH"
+    fi
+    
+    # Validate AWS credentials are configured
+    if ! aws sts get-caller-identity &> /dev/null; then
+        handle_error "AWS credentials are not configured or invalid"
+    fi
+    
+    # Initialize variables
+    BUCKET_NAME=""
+    OAC_ID=""
+    DISTRIBUTION_ID=""
+    BUCKET_IS_SHARED=false
+    
+    # Generate a random identifier for the bucket name using secure random
@@ -157 +185,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Check for shared prereq bucket
+    if [ -z "$RANDOM_ID" ]; then
+        handle_error "Failed to generate random identifier"
+    fi
+    
+    # Check for shared prereq bucket and get account ID in parallel calls
@@ -159 +191,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' --output text 2>/dev/null)
+        --query 'Stacks[0].Outputs[?OutputKey==`BucketName`].OutputValue' --output text 2>/dev/null) || PREREQ_BUCKET=""
+    
@@ -170 +203,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create a temporary directory for content
+    # Get AWS account ID early
+    ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
+    if [ $? -ne 0 ]; then
+        handle_error "Failed to get AWS account ID"
+    fi
+    
+    # Validate account ID format
+    if ! [[ "$ACCOUNT_ID" =~ ^[0-9]{12}$ ]]; then
+        handle_error "Invalid AWS account ID format: $ACCOUNT_ID"
+    fi
+    
+    # Create a temporary directory for content with restrictive permissions
@@ -172,0 +217 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    chmod 700 "$TEMP_DIR"
@@ -177 +222,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Step 1: Create an S3 bucket
+    # Step 1: Create an S3 bucket (only if not shared)
+    if [ "$BUCKET_IS_SHARED" != "true" ]; then
@@ -179 +225 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws s3 mb "s3://$BUCKET_NAME"
+        aws s3 mb "s3://$BUCKET_NAME" --region us-east-1
@@ -183,0 +230,19 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        # Batch bucket configuration calls for efficiency
+        aws s3api put-bucket-versioning --bucket "$BUCKET_NAME" --versioning-configuration Status=Enabled &
+        aws s3api put-public-access-block \
+            --bucket "$BUCKET_NAME" \
+            --public-access-block-configuration "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" &
+        aws s3api put-bucket-encryption \
+            --bucket "$BUCKET_NAME" \
+            --server-side-encryption-configuration '{
+                "Rules": [
+                    {
+                        "ApplyServerSideEncryptionByDefault": {
+                            "SSEAlgorithm": "AES256"
+                        }
+                    }