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_cloudwatch_code_examples.md

Summary

Enhanced security practices in CloudWatch dashboard script: added strict error handling, secure file permissions, input validation, resource cleanup automation, sensitive data sanitization in logs, and unique resource naming.

Security assessment

Changes implement security best practices: 1) Added 'chmod 600' for log files and 'chmod 700' for temp directories to prevent unauthorized access. 2) Implemented input validation for AWS region format and JSON syntax to prevent injection attacks. 3) Added sensitive data sanitization in logs (redacting ARNs/secrets). 4) Automated resource cleanup to prevent persistent resources. 5) Set restrictive umask (0077) and used shred for secure file deletion. These address security risks like credential leaks, insecure temp files, and resource persistence.

Diff

diff --git a/code-library/latest/ug/bash_2_cloudwatch_code_examples.md b/code-library/latest/ug/bash_2_cloudwatch_code_examples.md
index bd962f7b2..5aa77484c 100644
--- a//code-library/latest/ug/bash_2_cloudwatch_code_examples.md
+++ b//code-library/latest/ug/bash_2_cloudwatch_code_examples.md
@@ -54,2 +54,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Set up logging
-    LOG_FILE="cloudwatch-dashboard-script.log"
+    # Set up logging with secure permissions
+    LOG_FILE="${HOME}/.cloudwatch-dashboard-script.log"
+    touch "$LOG_FILE" && chmod 600 "$LOG_FILE"
@@ -59,0 +61,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security: Set strict error handling
+    set -euo pipefail
+    trap 'handle_error "Script failed at line $LINENO"' ERR
+    
@@ -62 +67,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "ERROR: $1"
+        local error_msg="${1:-Unknown error}"
+        echo "ERROR: $error_msg" >&2
@@ -69,2 +75 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        echo "An error occurred. Do you want to clean up the created resources? (y/n): "
-        read -r CLEANUP_CHOICE
+        echo "An error occurred. Proceeding with automatic cleanup..."
@@ -72 +76,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then
@@ -74,4 +78,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard
-            echo "Cleanup complete."
-        else
-            echo "Resources were not cleaned up. You can manually delete them later."
+        aws cloudwatch delete-dashboards --dashboard-names LambdaMetricsDashboard 2>/dev/null || true
+        
+        # Clean up temporary files
+        if [ -n "${TEMP_DIR:-}" ] && [ -d "$TEMP_DIR" ]; then
+            rm -rf "$TEMP_DIR"
@@ -78,0 +84,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        rm -f dashboard-body.json
+        
+        echo "Cleanup complete."
@@ -81,0 +90,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Security: Validate AWS CLI is installed
+    if ! command -v aws &> /dev/null; then
+        handle_error "AWS CLI is not installed. Please install it and try again."
+    fi
+    
@@ -84,2 +97 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    aws sts get-caller-identity > /dev/null 2>&1
-    if [ $? -ne 0 ]; then
+    if ! aws sts get-caller-identity > /dev/null 2>&1; then
@@ -89,2 +101,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Get the current region
-    REGION=$(aws configure get region)
+    # Get the current region securely
+    REGION=$(aws configure get region 2>/dev/null || echo "")
@@ -96,0 +109,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate region format
+    if ! [[ "$REGION" =~ ^[a-z]{2}-[a-z]+-[0-9]{1}$ ]]; then
+        handle_error "Invalid AWS region format: $REGION"
+    fi
+    
@@ -99 +116,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    LAMBDA_FUNCTIONS=$(aws lambda list-functions --query "Functions[*].FunctionName" --output text)
+    LAMBDA_FUNCTIONS=$(aws lambda list-functions --region "$REGION" --query "Functions[*].FunctionName" --output text 2>/dev/null || echo "")
+    
@@ -103 +121 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Create a temporary directory for Lambda function code
+        # Create a temporary directory for Lambda function code with secure permissions
@@ -104,0 +123,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        chmod 700 "$TEMP_DIR"
+        trap 'rm -rf "$TEMP_DIR"' EXIT
@@ -107 +127 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        cat > "$TEMP_DIR/index.js" << EOF
+        cat > "$TEMP_DIR/index.js" << 'EOF'
@@ -118,2 +138,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        cd "$TEMP_DIR" || handle_error "Failed to change to temporary directory"
-        zip -q function.zip index.js
+        if ! cd "$TEMP_DIR"; then
+            handle_error "Failed to change to temporary directory"
+        fi
+        
+        if ! zip -q function.zip index.js; then
+            handle_error "Failed to create zip file"
+        fi
@@ -121,3 +146,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Create a role for the Lambda function
-        ROLE_NAME="LambdaDashboardTestRole"
-        ROLE_ARN=$(aws iam create-role \
+        # Create a role for the Lambda function with restricted trust policy
+        ROLE_NAME="LambdaDashboardTestRole-$(date +%s)"
+        TRUST_POLICY='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}'
+        
+        if ! ROLE_ARN=$(aws iam create-role \
@@ -125 +152 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]}' \
+            --assume-role-policy-document "$TRUST_POLICY" \
@@ -127,3 +154 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --output text)
-        
-        if [ $? -ne 0 ]; then
+            --output text 2>/dev/null); then
@@ -137 +162 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        aws iam attach-role-policy \
+        if ! aws iam attach-role-policy \
@@ -139,4 +164,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-        
-        if [ $? -ne 0 ]; then
-            aws iam delete-role --role-name "$ROLE_NAME"
+            --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"; then
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -147,2 +170,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        FUNCTION_NAME="DashboardTestFunction"
-        aws lambda create-function \
+        FUNCTION_NAME="DashboardTestFunction-$(date +%s)"
+        if ! aws lambda create-function \
@@ -153,3 +176,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            --zip-file fileb://function.zip
-        
-        if [ $? -ne 0 ]; then
+            --zip-file fileb://function.zip \
+            --region "$REGION" > /dev/null 2>&1; then
@@ -158,2 +180,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-            aws iam delete-role --role-name "$ROLE_NAME"
+                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -166 +188 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null > /dev/null
+            aws lambda invoke --function-name "$FUNCTION_NAME" --payload '{}' /dev/null --region "$REGION" > /dev/null 2>&1 || true
@@ -170 +192 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        # Clean up temporary directory
+        # Go back to original directory
@@ -172 +193,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        rm -rf "$TEMP_DIR"
@@ -179,0 +201,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        FUNCTION_NAME=""
+        ROLE_NAME=""
@@ -185,2 +208,9 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create a JSON file for the dashboard body
-    cat > dashboard-body.json << EOF
+    # Create a JSON file for the dashboard body with secure permissions
+    DASHBOARD_JSON="dashboard-body-$$.json"
+    touch "$DASHBOARD_JSON" && chmod 600 "$DASHBOARD_JSON"
+    
+    # Escape special characters in region and function name for JSON
+    REGION_ESCAPED=$(printf '%s\n' "$REGION" | sed 's:[\/&]:\\&:g')
+    FUNCTION_ESCAPED=$(printf '%s\n' "$DEFAULT_FUNCTION" | sed 's:[\/&]:\\&:g')
+    
+    cat > "$DASHBOARD_JSON" << EOF
@@ -203 +233 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -220 +250 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -237 +267 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -253,2 +283,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-              "value": "$DEFAULT_FUNCTION",
-              "label": "$DEFAULT_FUNCTION"
+              "value": "$FUNCTION_ESCAPED",
+              "label": "$FUNCTION_ESCAPED"
@@ -262,3 +292,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create the dashboard using the JSON file
-    DASHBOARD_RESULT=$(aws cloudwatch put-dashboard --dashboard-name LambdaMetricsDashboard --dashboard-body file://dashboard-body.json)
-    DASHBOARD_EXIT_CODE=$?
+    # Validate JSON before sending
+    if ! jq empty "$DASHBOARD_JSON" 2>/dev/null; then
+        handle_error "Invalid JSON generated for dashboard"
+    fi
@@ -266,2 +297,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Check if there was a fatal error
-    if [ $DASHBOARD_EXIT_CODE -ne 0 ]; then
+    # Create the dashboard using the JSON file
+    if ! DASHBOARD_RESULT=$(aws cloudwatch put-dashboard \
+        --dashboard-name "LambdaMetricsDashboard-$(date +%s)" \
+        --dashboard-body file://"$DASHBOARD_JSON" \
+        --region "$REGION" 2>&1); then
@@ -270 +304 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            aws lambda delete-function --function-name "$FUNCTION_NAME"
+            aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$REGION" 2>/dev/null || true
@@ -273,2 +307,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
-            aws iam delete-role --role-name "$ROLE_NAME"
+                --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>/dev/null || true
+            aws iam delete-role --role-name "$ROLE_NAME" 2>/dev/null || true
@@ -280 +314 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    if [[ "$DASHBOARD_RESULT" == *"DashboardValidationMessages"* ]]; then
+    if echo "$DASHBOARD_RESULT" | grep -q "DashboardValidationMessages"; then
@@ -287,0 +322,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Extract dashboard name from result
+    DASHBOARD_NAME=$(echo "$DASHBOARD_RESULT" | grep -oP '"DashboardName"\s*:\s*"\K[^"]+' || echo "LambdaMetricsDashboard")
+    
@@ -290,4 +327 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name LambdaMetricsDashboard)
-    DASHBOARD_INFO_EXIT_CODE=$?
-    
-    if [ $DASHBOARD_INFO_EXIT_CODE -ne 0 ]; then
+    if ! DASHBOARD_INFO=$(aws cloudwatch get-dashboard --dashboard-name "$DASHBOARD_NAME" --region "$REGION" 2>&1); then