AWS powertools medium security documentation change
Summary
Added documentation for discriminated unions using Pydantic, updated warning about sensitive information in logs (removed CORS mention), added testing guidance for string conversion in events, removed deprecated content, and updated dates
Security assessment
The change removes a warning about relaxed CORS restrictions which could indicate addressing a potential security misconfiguration. This correction prevents developers from being misled about CORS behavior
Diff
diff --git a/powertools/python/latest/core/event_handler/api_gateway.md b/powertools/python/latest/core/event_handler/api_gateway.md index 578c1f98d..a42ce46b9 100644 --- a//powertools/python/latest/core/event_handler/api_gateway.md +++ b//powertools/python/latest/core/event_handler/api_gateway.md @@ -63,0 +64 @@ Metrics + * Discriminated unions @@ -236,0 +238 @@ Table of contents + * Discriminated unions @@ -2875,0 +2878,113 @@ This means Event Handler will look up for a key named `todo`, validate the value +##### Discriminated unions¶ + +You can use Pydantic's `Field(discriminator="...")` with union types to create discriminated unions (also known as tagged unions). This allows the Event Handler to automatically determine which model to use based on a discriminator field in the request body. + +discriminated_unions.py +--- + + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + +| + + + from typing import Literal, Union + + from pydantic import BaseModel, Field + from typing_extensions import Annotated + + from aws_lambda_powertools import Logger, Tracer + from aws_lambda_powertools.event_handler import APIGatewayRestResolver + from aws_lambda_powertools.event_handler.openapi.params import Body + from aws_lambda_powertools.logging import correlation_paths + from aws_lambda_powertools.utilities.typing import LambdaContext + + tracer = Tracer() + logger = Logger() + app = APIGatewayRestResolver(enable_validation=True) + + + class FooAction(BaseModel): + """Action type for foo operations.""" + + action: Literal["foo"] = "foo" + foo_data: str + + + class BarAction(BaseModel): + """Action type for bar operations.""" + + action: Literal["bar"] = "bar" + bar_data: int + + + ActionType = Annotated[Union[FooAction, BarAction], Field(discriminator="action")] # (1)! + + + @app.post("/actions") + @tracer.capture_method + def handle_action(action: Annotated[ActionType, Body(description="Action to perform")]): # (2)! + """Handle different action types using discriminated unions.""" + if isinstance(action, FooAction): + return {"message": f"Handling foo action with data: {action.foo_data}"} + elif isinstance(action, BarAction): + return {"message": f"Handling bar action with data: {action.bar_data}"} + + + @logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP) + @tracer.capture_lambda_handler + def lambda_handler(event: dict, context: LambdaContext) -> dict: + return app.resolve(event, context) + + + 1. `Field(discriminator="action")` tells Pydantic to use the `action` field to determine which model to instantiate + 2. `Body()` annotation tells the Event Handler to parse the request body using the discriminated union + + + @@ -6617 +6732 @@ Danger -This might reveal sensitive information in your logs and relax CORS restrictions, use it sparingly. +This might reveal sensitive information in your logs, use it sparingly. @@ -8824,0 +8940,4 @@ You can test your routes by passing a proxy event request with required params. +Info + +Fields such as headers and query strings are always delivered as strings when events reach Lambda. When testing your Lambda function with local events, we recommend using the sample events available in our [repository](https://github.com/aws-powertools/powertools-lambda-python/tree/develop/tests/events). + @@ -8859,0 +8979,2 @@ assert_rest_api_resolver_response.pyassert_rest_api_response_module.py + 31 + 32 @@ -8887,0 +9009,2 @@ assert_rest_api_resolver_response.pyassert_rest_api_response_module.py + # Always use strings when using query parameters. API Gateway automatically converts them to strings + "queryStringParameters": {"page": "5", "foo": "bar"}, @@ -9397,11 +9520 @@ That said, [Chalice has native integration with Lambda Powertools](https://aws.g -**What happened to`ApiGatewayResolver`?** - -It's been superseded by more explicit resolvers like `APIGatewayRestResolver`, `APIGatewayHttpResolver`, and `ALBResolver`. - -`ApiGatewayResolver` handled multiple types of event resolvers for convenience via `proxy_type` param. However, it made it impossible for static checkers like Mypy and IDEs IntelliSense to know what properties a `current_event` would have due to late bound resolution. - -This provided a suboptimal experience for customers not being able to find all properties available besides common ones between API Gateway REST, HTTP, and ALB - while manually annotating `app.current_event` would work it is not the experience we want to provide to customers. - -`ApiGatewayResolver` will be deprecated in v2 and have appropriate warnings as soon as we have a v2 draft. - -2025-08-19 +2025-09-15