From 73be358d3d28134f286140692012467840216f15 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Tue, 9 Sep 2025 09:36:07 +0100 Subject: [PATCH] Fix IPV6 problem --- .../utilities/parser/functions.py | 10 +++++++++- tests/unit/parser/_pydantic/test_apigw.py | 14 ++++++++++++++ tests/unit/parser/_pydantic/test_apigwv2.py | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/parser/functions.py b/aws_lambda_powertools/utilities/parser/functions.py index c133df96868..e5c9c345714 100644 --- a/aws_lambda_powertools/utilities/parser/functions.py +++ b/aws_lambda_powertools/utilities/parser/functions.py @@ -101,7 +101,15 @@ def _validate_source_ip(value): IPvAnyNetwork(value) except ValueError: try: - ip_part = value.split(":")[0] + # Handle IPv6 with port: [IPv6]:port + if value.startswith("[") and "]:" in value: + ip_part = value.split("]:")[0][1:] # Remove "[" and get IP part + elif ":" in value and value.count(":") <= 1: + ip_part = value.split(":")[0] + else: + # If it"s not in IP:port format, validate as-is + ip_part = value + IPvAnyNetwork(ip_part) except (ValueError, IndexError) as e: raise ValueError(f"Invalid IP address in sourceIp: {ip_part}") from e diff --git a/tests/unit/parser/_pydantic/test_apigw.py b/tests/unit/parser/_pydantic/test_apigw.py index 4222efa10b2..be613c97245 100644 --- a/tests/unit/parser/_pydantic/test_apigw.py +++ b/tests/unit/parser/_pydantic/test_apigw.py @@ -120,6 +120,20 @@ def test_apigw_event_and_source_ip_with_random_string(): APIGatewayProxyEventModel(**raw_event) +def test_apigw_event_and_source_ip_ipv6(): + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["requestContext"]["identity"]["sourceIp"] = "fe80::1ff:fe23:4567:890a" + + APIGatewayProxyEventModel(**raw_event) + + +def test_apigw_event_and_source_ip_ipv6_with_port(): + raw_event = load_event("apiGatewayProxyEvent.json") + raw_event["requestContext"]["identity"]["sourceIp"] = "[fe80::1ff:fe23:4567:890a]:12345" + + APIGatewayProxyEventModel(**raw_event) + + def test_apigw_event_with_invalid_websocket_request(): # GIVEN an event with an eventType != MESSAGE and has a messageId event = { diff --git a/tests/unit/parser/_pydantic/test_apigwv2.py b/tests/unit/parser/_pydantic/test_apigwv2.py index 7db8d92ff2a..a9c7a3ef9e1 100644 --- a/tests/unit/parser/_pydantic/test_apigwv2.py +++ b/tests/unit/parser/_pydantic/test_apigwv2.py @@ -89,6 +89,20 @@ def test_apigw_v2_event_and_source_ip_with_random_string(): APIGatewayProxyEventV2Model(**raw_event) +def test_apigw_v2_event_and_source_ip_ipv6(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event["requestContext"]["http"]["sourceIp"] = "fe80::1ff:fe23:4567:890a" + + APIGatewayProxyEventV2Model(**raw_event) + + +def test_apigw_v2_event_and_source_ip_ipv6_with_port(): + raw_event = load_event("apiGatewayProxyV2Event.json") + raw_event["requestContext"]["http"]["sourceIp"] = "[fe80::1ff:fe23:4567:890a]:12345" + + APIGatewayProxyEventV2Model(**raw_event) + + def test_api_gateway_proxy_v2_event_lambda_authorizer(): raw_event = load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json") parsed_event: APIGatewayProxyEventV2Model = APIGatewayProxyEventV2Model(**raw_event)