AWS Security ChangesHomeSearch

AWS code-library medium security documentation change

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

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

Summary

Enhanced security practices in CloudWatch dashboard example script: added strict file permissions, input validation, error handling, resource cleanup automation, and security hardening measures.

Security assessment

Changes implement security best practices: 1) Set secure file permissions (chmod 600/700) for logs/temp files to prevent unauthorized access. 2) Added input validation for AWS region format to prevent injection attacks. 3) Implemented strict error handling (set -euo pipefail) to fail safely. 4) Escaped special characters in JSON generation to prevent injection vulnerabilities. 5) Automated cleanup of temporary resources to prevent sensitive data leakage. 6) Added AWS CLI installation check to prevent runtime failures.

Diff

diff --git a/code-library/latest/ug/iam_example_cloudwatch_GettingStarted_031_section.md b/code-library/latest/ug/iam_example_cloudwatch_GettingStarted_031_section.md
index 325d5d3c4..5a9d5fc52 100644
--- a//code-library/latest/ug/iam_example_cloudwatch_GettingStarted_031_section.md
+++ b//code-library/latest/ug/iam_example_cloudwatch_GettingStarted_031_section.md
@@ -40,2 +40,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"
@@ -45,0 +47,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
+    
@@ -48 +53,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
@@ -55,2 +61 @@ 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..."
@@ -58 +62,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then
@@ -60,4 +64,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"
@@ -64,0 +70,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."
@@ -67,0 +76,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
+    
@@ -70,2 +83 @@ 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
@@ -75,2 +87,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 "")
@@ -82,0 +95,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
+    
@@ -85 +102,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 "")
+    
@@ -89 +107 @@ 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
@@ -90,0 +109,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
@@ -93 +113 @@ 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'
@@ -104,2 +124,11 @@ 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
+        
+        # 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"}]}'
@@ -107,3 +136 @@ 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 \
+        if ! ROLE_ARN=$(aws iam create-role \
@@ -111 +138 @@ 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" \
@@ -113,3 +140 @@ 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
@@ -123 +148 @@ 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 \
@@ -125,4 +150,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
@@ -133,2 +156,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 \
@@ -139,3 +162,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
@@ -144,2 +166,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
@@ -152 +174 @@ 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
@@ -156 +178 @@ 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
@@ -158 +179,0 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        rm -rf "$TEMP_DIR"
@@ -165,0 +187,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+        FUNCTION_NAME=""
+        ROLE_NAME=""
@@ -171,2 +194,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
@@ -189 +219 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -206 +236 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -223 +253 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "region": "$REGION",
+            "region": "$REGION_ESCAPED",
@@ -239,2 +269,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"
@@ -248,3 +278,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
@@ -252,2 +283,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
@@ -256 +290 @@ 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
@@ -259,2 +293,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
@@ -266 +300 @@ 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
@@ -273,0 +308,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")
+    
@@ -276,4 +313 @@ 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