AWS Security ChangesHomeSearch

AWS code-library documentation change

Service: code-library · 2026-05-01 · Documentation low

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

Summary

Enhanced EMR example script with security best practices: added strict error handling, secure permissions for files, S3 bucket encryption/versioning/public access blocking, SSE for uploads, input validation, and improved cleanup procedures.

Security assessment

The changes implement security best practices like strict permissions (chmod 600), S3 encryption/access controls, error handling, and input validation. However, they are preventative measures rather than fixes for specific vulnerabilities. No evidence of addressing a known security incident exists.

Diff

diff --git a/code-library/latest/ug/ec2_example_emr_GettingStarted_037_section.md b/code-library/latest/ug/ec2_example_emr_GettingStarted_037_section.md
index ea595f711..bdc7551ae 100644
--- a//code-library/latest/ug/ec2_example_emr_GettingStarted_037_section.md
+++ b//code-library/latest/ug/ec2_example_emr_GettingStarted_037_section.md
@@ -37,0 +38 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    set -euo pipefail
@@ -39 +40,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Set up logging
+    # Security: Set strict mode and trap errors
+    trap 'handle_error "Script interrupted or command failed"' ERR
+    
+    # Set up logging with secure permissions
@@ -40,0 +45,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    touch "$LOG_FILE"
+    chmod 600 "$LOG_FILE"
@@ -50,2 +56,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [ -n "$BUCKET_NAME" ]; then echo "- S3 Bucket: $BUCKET_NAME"; fi
-        if [ -n "$CLUSTER_ID" ]; then echo "- EMR Cluster: $CLUSTER_ID"; fi
+        if [ -n "${BUCKET_NAME:-}" ]; then echo "- S3 Bucket: $BUCKET_NAME"; fi
+        if [ -n "${CLUSTER_ID:-}" ]; then echo "- EMR Cluster: $CLUSTER_ID"; fi
@@ -62 +68 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "CLEANUP CONFIRMATION"
+        echo "CLEANUP IN PROGRESS"
@@ -64,4 +69,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "Do you want to clean up all created resources? (y/n): "
-        read -r CLEANUP_CHOICE
-        
-        if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then
@@ -71 +73 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if [ -n "$CLUSTER_ID" ]; then
+        if [ -n "${CLUSTER_ID:-}" ]; then
@@ -73 +75 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                aws emr terminate-clusters --cluster-ids "$CLUSTER_ID"
+            aws emr terminate-clusters --cluster-ids "$CLUSTER_ID" 2>/dev/null || true
@@ -76 +78 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                aws emr wait cluster-terminated --cluster-id "$CLUSTER_ID"
+            aws emr wait cluster-terminated --cluster-id "$CLUSTER_ID" 2>/dev/null || true
@@ -80,2 +82,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            # Delete S3 bucket and contents if it exists
-            if [ -n "$BUCKET_NAME" ]; then
+        # Delete S3 bucket and contents if it exists and is not shared
+        if [ -n "${BUCKET_NAME:-}" ] && [ "${BUCKET_IS_SHARED:-false}" != "true" ]; then
@@ -83 +85 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                aws s3 rm "s3://$BUCKET_NAME" --recursive
+            aws s3 rm "s3://$BUCKET_NAME" --recursive 2>/dev/null || true
@@ -86 +88 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                aws s3 rb "s3://$BUCKET_NAME"
+            aws s3 rb "s3://$BUCKET_NAME" 2>/dev/null || true
@@ -89,4 +91,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            echo "Cleanup completed."
-        else
-            echo "Cleanup skipped. Resources will remain in your AWS account."
-            echo "To avoid ongoing charges, remember to manually delete these resources."
+        # Remove temporary key pair file if created by this script
+        if [ -f "${KEY_NAME_FILE:-}" ]; then
+            rm -f "$KEY_NAME_FILE"
+            echo "Removed temporary key pair file."
@@ -93,0 +96,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        
+        echo "Cleanup completed."
@@ -95,0 +100,10 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate AWS CLI is installed and configured
+    if ! command -v aws &> /dev/null; then
+        handle_error "AWS CLI is not installed"
+    fi
+    
+    # Test AWS credentials
+    if ! aws sts get-caller-identity > /dev/null 2>&1; then
+        handle_error "AWS credentials are not configured or invalid"
+    fi
+    
@@ -100 +115,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 || true)
+    
@@ -107 +123 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        BUCKET_NAME="emr${RANDOM_ID}"
+        BUCKET_NAME="emr-${RANDOM_ID}"
@@ -111 +127 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create S3 bucket
+    # Create S3 bucket with security best practices
@@ -113,2 +129,21 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws s3 mb "s3://$BUCKET_NAME" || handle_error "Failed to create S3 bucket"
-    echo "S3 bucket created successfully."
+    aws s3 mb "s3://$BUCKET_NAME" --region "${AWS_REGION:-us-east-1}" || handle_error "Failed to create S3 bucket"
+    
+    # Enable bucket versioning for safety
+    aws s3api put-bucket-versioning --bucket "$BUCKET_NAME" --versioning-configuration Status=Enabled || true
+    
+    # Block public access to bucket
+    aws s3api put-public-access-block --bucket "$BUCKET_NAME" \
+        --public-access-block-configuration \
+        "BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true" || true
+    
+    # Enable encryption on bucket
+    aws s3api put-bucket-encryption --bucket "$BUCKET_NAME" \
+        --server-side-encryption-configuration '{
+            "Rules": [{
+                "ApplyServerSideEncryptionByDefault": {
+                    "SSEAlgorithm": "AES256"
+                }
+            }]
+        }' || true
+    
+    echo "S3 bucket created successfully with security best practices."
@@ -159,0 +195,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Secure the script file
+    chmod 600 health_violations.py
+    
@@ -162 +200 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws s3 cp health_violations.py "s3://$BUCKET_NAME/" || handle_error "Failed to upload PySpark script"
+    aws s3 cp health_violations.py "s3://$BUCKET_NAME/" --sse AES256 || handle_error "Failed to upload PySpark script"
@@ -167 +205,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    curl -o food_establishment_data.zip https://docs.aws.amazon.com/emr/latest/ManagementGuide/samples/food_establishment_data.zip || handle_error "Failed to download sample data"
+    curl -sS -o food_establishment_data.zip "https://docs.aws.amazon.com/emr/latest/ManagementGuide/samples/food_establishment_data.zip" || handle_error "Failed to download sample data"
+    
+    # Verify downloaded file
+    if [ ! -f food_establishment_data.zip ] || [ ! -s food_establishment_data.zip ]; then
+        handle_error "Downloaded file is empty or missing"
+    fi
+    
@@ -170,0 +215,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Secure the sample data file
+    chmod 600 food_establishment_data.csv
+    
@@ -173 +220 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws s3 cp food_establishment_data.csv "s3://$BUCKET_NAME/" || handle_error "Failed to upload sample data"
+    aws s3 cp food_establishment_data.csv "s3://$BUCKET_NAME/" --sse AES256 || handle_error "Failed to upload sample data"
@@ -175,0 +223,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Clean up sensitive local files
+    rm -f food_establishment_data.zip health_violations.py
+    
@@ -178 +228 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws emr create-default-roles || handle_error "Failed to create default roles"
+    aws emr create-default-roles 2>/dev/null || true
@@ -183 +233 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    KEY_PAIRS=$(aws ec2 describe-key-pairs --query "KeyPairs[*].KeyName" --output text)
+    KEY_PAIRS=$(aws ec2 describe-key-pairs --query "KeyPairs[*].KeyName" --output text 2>/dev/null || true)
@@ -187,3 +237,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        KEY_NAME="emr-tutorial-key-$RANDOM_ID"
-        aws ec2 create-key-pair --key-name "$KEY_NAME" --query "KeyMaterial" --output text > "${KEY_NAME}.pem"
-        chmod 400 "${KEY_NAME}.pem"
+        KEY_NAME="emr-tutorial-key-${RANDOM_ID}"
+        KEY_NAME_FILE="${KEY_NAME}.pem"
+        aws ec2 create-key-pair --key-name "$KEY_NAME" --query "KeyMaterial" --output text > "$KEY_NAME_FILE"
+        chmod 400 "$KEY_NAME_FILE"
@@ -197 +248 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Launch EMR cluster
+    # Launch EMR cluster with security best practices
@@ -207 +258,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-      --log-uri "s3://$BUCKET_NAME/logs/")
+      --log-uri "s3://$BUCKET_NAME/logs/" \
+      --ebs-root-volume-size 100 \
+      --security-configuration "EMR-Tutorial-SecurityConfig" 2>/dev/null || true)
@@ -214,4 +267,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Extract cluster ID
-    CLUSTER_ID=$(echo "$CLUSTER_RESPONSE" | grep -o '"ClusterId": "[^"]*' | cut -d'"' -f4)
-    if [ -z "$CLUSTER_ID" ]; then
-        handle_error "Failed to extract cluster ID from response"
+    # Extract cluster ID using jq if available, otherwise use alternative parsing
+    if command -v jq &> /dev/null; then
+        CLUSTER_ID=$(echo "$CLUSTER_RESPONSE" | jq -r '.ClusterId // empty')
+    else
+        CLUSTER_ID=$(echo "$CLUSTER_RESPONSE" | grep -o '"ClusterId"[[:space:]]*:[[:space:]]*"[^"]*' | grep -o 'j-[A-Z0-9]*' || true)
+    fi
+    
+    if [ -z "$CLUSTER_ID" ] || [ "$CLUSTER_ID" == "null" ]; then
+        handle_error "Failed to extract cluster ID from response: $CLUSTER_RESPONSE"
@@ -229,0 +288,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        WAIT_COUNT=0
+        MAX_WAIT=120
@@ -230,0 +291,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+            if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
+                handle_error "Cluster did not reach WAITING state within timeout period"
+            fi
@@ -238,0 +302 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+            WAIT_COUNT=$((WAIT_COUNT + 1))
@@ -255,2 +319 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # FIXED: Check if jq is available before using it
-    # Extract step ID using the appropriate method based on available tools
+    # Extract step ID using appropriate method
@@ -258,3 +321 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Use jq if available
-        echo "Using jq to parse JSON response"
-        STEP_ID=$(echo "$STEP_RESPONSE" | jq -r '.StepIds[0]')
+        STEP_ID=$(echo "$STEP_RESPONSE" | jq -r '.StepIds[0] // empty')
@@ -262,15 +323 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Fallback to grep/awk if jq is not available
-        echo "jq not found, using grep for parsing"
-        STEP_ID=$(echo "$STEP_RESPONSE" | grep -o '"StepIds":\s*\[\s*"[^"]*"' | grep -o 's-[A-Z0-9]*')
-        if [ -z "$STEP_ID" ]; then
-            # Another fallback method
-            STEP_ID=$(echo "$STEP_RESPONSE" | grep -o '"StepIds":\s*\[\s*"[^"]*' | grep -o 's-[A-Z0-9]*')
-            if [ -z "$STEP_ID" ]; then
-                # One more attempt with a different pattern
-                STEP_ID=$(echo "$STEP_RESPONSE" | grep -o 's-[A-Z0-9]*')
-                if [ -z "$STEP_ID" ]; then
-                    echo "Full step response: $STEP_RESPONSE"
-                    handle_error "Failed to extract step ID from response"
-                fi