AWS Security ChangesHomeSearch

AWS code-library documentation change

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

File: code-library/latest/ug/api-gateway_example_api_gateway_GettingStarted_087_section.md

Summary

Updated API Gateway/Lambda tutorial with enhanced security practices: added input validation, error handling, input sanitization, safer IAM role management, Python 3.11 runtime, and proper JSON responses.

Security assessment

The changes implement security best practices like input validation and sanitization to prevent injection attacks, proper error handling to avoid information leakage, and secure resource management. However, there's no evidence of addressing a specific vulnerability or documenting new security features.

Diff

diff --git a/code-library/latest/ug/api-gateway_example_api_gateway_GettingStarted_087_section.md b/code-library/latest/ug/api-gateway_example_api_gateway_GettingStarted_087_section.md
index 63a016a35..a5a65fb58 100644
--- a//code-library/latest/ug/api-gateway_example_api_gateway_GettingStarted_087_section.md
+++ b//code-library/latest/ug/api-gateway_example_api_gateway_GettingStarted_087_section.md
@@ -40,0 +41,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    set -euo pipefail
+    
@@ -52,0 +55,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    # Validate inputs
+    if [[ -z "$ACCOUNT_ID" ]] || [[ -z "$REGION" ]]; then
+        echo "Error: Failed to retrieve AWS account information" >&2
+        exit 1
+    fi
+    
@@ -55 +63 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create Lambda function code
+    # Create Lambda function code with input validation
@@ -57,0 +66 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    import logging
@@ -59,4 +68,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    def lambda_handler(event, context):
-        print(event)
-        
-        greeter = 'World'
+    logger = logging.getLogger()
+    logger.setLevel(logging.INFO)
@@ -63,0 +71 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    def lambda_handler(event, context):
@@ -65,5 +73 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if (event['queryStringParameters']) and (event['queryStringParameters']['greeter']) and (
-                    event['queryStringParameters']['greeter'] is not None):
-                greeter = event['queryStringParameters']['greeter']
-        except KeyError:
-            print('No greeter')
+            logger.info("Received event: %s", json.dumps(event))
@@ -71,6 +75 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        try:
-            if (event['multiValueHeaders']) and (event['multiValueHeaders']['greeter']) and (
-                    event['multiValueHeaders']['greeter'] is not None):
-                greeter = " and ".join(event['multiValueHeaders']['greeter'])
-        except KeyError:
-            print('No greeter')
+            greeter = 'World'
@@ -77,0 +77,24 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+            # Safely retrieve greeter from query string parameters
+            query_params = event.get('queryStringParameters') or {}
+            if isinstance(query_params, dict) and 'greeter' in query_params:
+                greeter_value = query_params.get('greeter')
+                if isinstance(greeter_value, str) and greeter_value:
+                    greeter = greeter_value
+            
+            # Safely retrieve greeter from multi-value headers
+            multi_headers = event.get('multiValueHeaders') or {}
+            if isinstance(multi_headers, dict) and 'greeter' in multi_headers:
+                greeter_list = multi_headers.get('greeter', [])
+                if isinstance(greeter_list, list) and greeter_list:
+                    greeter = " and ".join(str(g) for g in greeter_list if g)
+            
+            # Safely retrieve greeter from headers
+            headers = event.get('headers') or {}
+            if isinstance(headers, dict) and 'greeter' in headers:
+                greeter_value = headers.get('greeter')
+                if isinstance(greeter_value, str) and greeter_value:
+                    greeter = greeter_value
+            
+            # Safely retrieve greeter from body
+            body = event.get('body')
+            if body and isinstance(body, str):
@@ -79,15 +102,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            if (event['headers']) and (event['headers']['greeter']) and (
-                    event['headers']['greeter'] is not None):
-                greeter = event['headers']['greeter']
-        except KeyError:
-            print('No greeter')
-        
-        if (event['body']) and (event['body'] is not None):
-            body = json.loads(event['body'])
-            try:
-                if (body['greeter']) and (body['greeter'] is not None):
-                    greeter = body['greeter']
-            except KeyError:
-                print('No greeter')
-        
-        res = {
+                    body_dict = json.loads(body)
+                    if isinstance(body_dict, dict) and 'greeter' in body_dict:
+                        greeter_value = body_dict.get('greeter')
+                        if isinstance(greeter_value, str) and greeter_value:
+                            greeter = greeter_value
+                except (json.JSONDecodeError, ValueError) as e:
+                    logger.warning("Failed to parse body: %s", str(e))
+            
+            # Sanitize greeter to prevent injection
+            greeter = greeter.replace('"', '\\"').replace("'", "\\'")
+            
+            response = {
@@ -96 +116 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-                "Content-Type": "*/*"
+                    "Content-Type": "application/json"
@@ -98 +118 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-            "body": "Hello, " + greeter + "!"
+                "body": json.dumps({"message": f"Hello, {greeter}!"})
@@ -101 +121,12 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        return res
+            logger.info("Response: %s", json.dumps(response))
+            return response
+            
+        except Exception as e:
+            logger.error("Unexpected error: %s", str(e), exc_info=True)
+            return {
+                "statusCode": 500,
+                "headers": {
+                    "Content-Type": "application/json"
+                },
+                "body": json.dumps({"error": "Internal server error"})
+            }
@@ -105 +136,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    zip function.zip lambda_function.py
+    zip -q function.zip lambda_function.py || {
+        echo "Error: Failed to create function.zip" >&2
+        exit 1
+    }
@@ -125 +159 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create IAM role
+    # Create IAM role with error handling
@@ -128 +162,5 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --assume-role-policy-document file://trust-policy.json
+        --assume-role-policy-document file://trust-policy.json \
+        --description "Temporary role for Lambda execution" || {
+        echo "Error: Failed to create IAM role" >&2
+        exit 1
+    }
@@ -133 +171,4 @@ 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"
+        --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" || {
+        echo "Error: Failed to attach IAM policy" >&2
+        exit 1
+    }
@@ -140 +181 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create Lambda function
+    # Create Lambda function with Python 3.11 (more recent runtime)
@@ -143 +184 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --runtime python3.9 \
+        --runtime python3.11 \
@@ -146 +187,7 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --zip-file fileb://function.zip
+        --zip-file fileb://function.zip \
+        --timeout 30 \
+        --memory-size 128 \
+        --environment "Variables={LOG_LEVEL=INFO}" || {
+        echo "Error: Failed to create Lambda function" >&2
+        exit 1
+    }
@@ -150,2 +197,2 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create REST API
-    aws apigateway create-rest-api \
+    # Create REST API with minimum logging
+    API_RESPONSE=$(aws apigateway create-rest-api \
@@ -153 +200,3 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --endpoint-configuration types=REGIONAL
+        --endpoint-configuration types=REGIONAL \
+        --description "API for Lambda proxy integration tutorial" \
+        --output json)
@@ -155,2 +204,6 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Get API ID
-    API_ID=$(aws apigateway get-rest-apis --query "items[?name=='$API_NAME'].id" --output text)
+    API_ID=$(echo "$API_RESPONSE" | grep -o '"id": "[^"]*"' | head -1 | cut -d'"' -f4)
+    
+    if [[ -z "$API_ID" ]]; then
+        echo "Error: Failed to create API Gateway" >&2
+        exit 1
+    fi
@@ -165 +218,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --path-part helloworld
+        --path-part helloworld || {
+        echo "Error: Failed to create resource" >&2
+        exit 1
+    }
@@ -170 +226 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-    # Create ANY method
+    # Create ANY method with no authorization (intentional for tutorial)
@@ -175 +231,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --authorization-type NONE
+        --authorization-type NONE || {
+        echo "Error: Failed to create method" >&2
+        exit 1
+    }
@@ -186 +245,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --uri "$LAMBDA_URI"
+        --uri "$LAMBDA_URI" || {
+        echo "Error: Failed to create integration" >&2
+        exit 1
+    }
@@ -188,0 +251 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
+    STATEMENT_ID="apigateway-invoke-$(openssl rand -hex 4)"
@@ -193 +256 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --statement-id "apigateway-invoke-$(openssl rand -hex 4)" \
+        --statement-id "$STATEMENT_ID" \
@@ -196 +259,4 @@ There's more on GitHub. Find the complete example and learn how to set up and ru
-        --source-arn "$SOURCE_ARN"