AWS Security ChangesHomeSearch

AWS cloudformation-cli documentation change

Service: cloudformation-cli · 2025-03-23 · Documentation low

File: cloudformation-cli/latest/hooks-userguide/lambda-hooks-create-lambda-function.md

Summary

Added Python implementation examples for Lambda Hooks alongside existing Node.js examples, including improved error handling and safe dictionary access patterns

Security assessment

Changes demonstrate secure coding practices like safe dictionary value access (dict.get()), proper HTTP error handling, and JSON parsing error handling. While these improve code safety, there's no evidence they address a specific disclosed vulnerability.

Diff

diff --git a/cloudformation-cli/latest/hooks-userguide/lambda-hooks-create-lambda-function.md b/cloudformation-cli/latest/hooks-userguide/lambda-hooks-create-lambda-function.md
index 0bf7eeb1c..69aa2b58a 100644
--- a/cloudformation-cli/latest/hooks-userguide/lambda-hooks-create-lambda-function.md
+++ b/cloudformation-cli/latest/hooks-userguide/lambda-hooks-create-lambda-function.md
@@ -351 +351,4 @@ To see all of the properties available for the resource type, see [AWS::DynamoDB
-The following example Lambda Hook targets `Node.js`. This is a simple function that fails any resource update to DynamoDB, which tries to set the `ReadCapacity` of `ProvisionedThroughput` to something larger than 10. If the Hook succeeds, the message, "ReadCapacity is correctly configured," will display to the caller. If the request fails validation, the Hook will fail with the status, "ReadCapacity cannot be more than 10."
+The following is a simple function that fails any resource update to DynamoDB, which tries to set the `ReadCapacity` of `ProvisionedThroughput` to something larger than 10. If the Hook succeeds, the message, "ReadCapacity is correctly configured," will display to the caller. If the request fails validation, the Hook will fail with the status, "ReadCapacity cannot be more than 10."
+
+Node.js
+    
@@ -373,0 +377,31 @@ The following example Lambda Hook targets `Node.js`. This is a simple function t
+Python
+    
+    
+    
+    import json
+                                
+    def lambda_handler(event, context):
+        # Using dict.get() for safe access to nested dictionary values
+        request_data = event.get('requestData', {})
+        target_model = request_data.get('targetModel', {})
+        target_name = request_data.get('targetName', '')
+        
+        response = {
+            "hookStatus": "SUCCESS",
+            "message": "ReadCapacity is correctly configured.",
+            "clientRequestToken": event.get('clientRequestToken')
+        }
+        
+        if target_name == "AWS::DynamoDB::Table":
+            # Safely navigate nested dictionary
+            resource_properties = target_model.get('resourceProperties', {})
+            provisioned_throughput = resource_properties.get('ProvisionedThroughput', {})
+            read_capacity = provisioned_throughput.get('ReadCapacityUnits')
+            
+            if read_capacity and read_capacity > 10:
+                response['hookStatus'] = "FAILED"
+                response['errorCode'] = "NonCompliant"
+                response['message'] = "ReadCapacity must be cannot be more than 10."
+        
+        return response
+
@@ -562 +596,4 @@ This is an example `payload` of the `requestData`:
-The following example Lambda Hook is targeting `Node.js`. It's a simple function that downloads the stack operation payload, parses the template JSON, and returns `SUCCESS`.
+The following example is a simple function that downloads the stack operation payload, parses the template JSON, and returns `SUCCESS`.
+
+Node.js
+    
@@ -593,0 +631,45 @@ The following example Lambda Hook is targeting `Node.js`. It's a simple function
+Python
+    
+
+To use Python, you'll need to import the `requests` library. To do this, you'll need to include the library in your deployment package when creating your Lambda function. For more information, see [Creating a .zip deployment package with dependencies](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies) in the _AWS Lambda Developer Guide_.
+    
+    
+    import json
+    import requests
+    
+    def lamnbda_handler(event, context):
+        # Safely access nested dictionary values
+        request_data = event.get('requestData', {})
+        target_type = request_data.get('targetType')
+        payload_url = request_data.get('payload')
+        
+        response = {
+            "hookStatus": "SUCCESS",
+            "message": "Stack update is compliant",
+            "clientRequestToken": event.get('clientRequestToken')
+        }
+        
+        try:
+            # Fetch the payload
+            template_hook_payload_request = requests.get(payload_url)
+            template_hook_payload_request.raise_for_status()  # Raise an exception for bad responses
+            template_hook_payload = template_hook_payload_request.json()
+            
+            if 'template' in template_hook_payload:
+                # Do something with the template template_hook_payload['template']
+                # JSON or YAML
+                pass
+            
+            if 'previousTemplate' in template_hook_payload:
+                # Do something with the template template_hook_payload['previousTemplate']
+                # JSON or YAML
+                pass
+    
+        except Exception as error:
+            print(error)
+            response['hookStatus'] = "FAILED"
+            response['message'] = "Failed to evaluate stack operation."
+            response['errorCode'] = "InternalFailure"
+        
+        return response
+
@@ -852 +934,4 @@ This is an example `payload` of the `requestData.payload`:
-The following example Lambda Hook is targeting `Node.js`. It's a simple function that downloads the change set operation payload, loops through each change, and then prints out the before and after properties before it returns a `SUCCESS`.
+The following example is a simple function that downloads the change set operation payload, loops through each change, and then prints out the before and after properties before it returns a `SUCCESS`.
+
+Node.js
+    
@@ -887,0 +973,51 @@ The following example Lambda Hook is targeting `Node.js`. It's a simple function
+Python
+    
+
+To use Python, you'll need to import the `requests` library. To do this, you'll need to include the library in your deployment package when creating your Lambda function. For more information, see [Creating a .zip deployment package with dependencies](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies) in the _AWS Lambda Developer Guide_.
+    
+    
+    import json
+    import requests
+    
+    def lambda_handler(event, context):
+        payload_url = event.get('requestData', {}).get('payload')
+        response = {
+            "hookStatus": "SUCCESS",
+            "message": "Change set changes are compliant",
+            "clientRequestToken": event.get('clientRequestToken')
+        }
+    
+        try:
+            change_set_hook_payload_request = requests.get(payload_url)
+            change_set_hook_payload_request.raise_for_status()  # Raises an HTTPError for bad responses
+            change_set_hook_payload = change_set_hook_payload_request.json()
+            
+            changes = change_set_hook_payload.get('changedResources', [])
+            
+            for change in changes:
+                before_context = {}
+                after_context = {}
+                
+                if change.get('beforeContext'):
+                    before_context = json.loads(change['beforeContext'])
+                
+                if change.get('afterContext'):
+                    after_context = json.loads(change['afterContext'])
+                
+                print(before_context)
+                print(after_context)
+                # Evaluate Change here
+    
+        except requests.RequestException as error:
+            print(error)
+            response['hookStatus'] = "FAILED"
+            response['message'] = "Failed to evaluate change set operation."
+            response['errorCode'] = "InternalFailure"
+        except json.JSONDecodeError as error:
+            print(error)
+            response['hookStatus'] = "FAILED"
+            response['message'] = "Failed to parse JSON payload."
+            response['errorCode'] = "InternalFailure"
+    
+        return response
+