From aa2556967a7902acbab2da5fb4fcc856232232a3 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Wed, 15 May 2024 17:50:16 +0200 Subject: [PATCH] fix(parser): handle API Gateway Test UI sourceIp --- packages/parser/src/schemas/apigw.ts | 11 ++- .../events/apiGatewayProxyEventTestUI.json | 81 +++++++++++++++++++ .../parser/tests/unit/schema/apigw.test.ts | 6 ++ packages/parser/tests/unit/schema/utils.ts | 1 + 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 packages/parser/tests/events/apiGatewayProxyEventTestUI.json diff --git a/packages/parser/src/schemas/apigw.ts b/packages/parser/src/schemas/apigw.ts index 6369385e69..ab4e20c6b2 100644 --- a/packages/parser/src/schemas/apigw.ts +++ b/packages/parser/src/schemas/apigw.ts @@ -22,7 +22,16 @@ const APIGatewayEventIdentity = z.object({ cognitoIdentityId: z.string().nullish(), cognitoIdentityPoolId: z.string().nullish(), principalOrgId: z.string().nullish(), - sourceIp: z.string().ip().optional(), + /** + * When invoking the API Gateway REST API using the Test Invoke feature, + * the sourceIp is hardcoded to `test-invoke-source-ip`. This is a stopgap + * solution to allow customers to test their API and have successful parsing. + * + * See aws-powertools/powertools-lambda-python#1562 for more information. + */ + sourceIp: z + .union([z.string().ip(), z.literal('test-invoke-source-ip')]) + .optional(), user: z.string().nullish(), userAgent: z.string().nullish(), userArn: z.string().nullish(), diff --git a/packages/parser/tests/events/apiGatewayProxyEventTestUI.json b/packages/parser/tests/events/apiGatewayProxyEventTestUI.json new file mode 100644 index 0000000000..0b8cbe1e51 --- /dev/null +++ b/packages/parser/tests/events/apiGatewayProxyEventTestUI.json @@ -0,0 +1,81 @@ +{ + "version": "1.0", + "resource": "/my/path", + "path": "/my/path", + "httpMethod": "GET", + "headers": { + "Header1": "value1", + "Header2": "value2", + "Origin": "https://aws.amazon.com" + }, + "multiValueHeaders": { + "Header1": [ + "value1" + ], + "Header2": [ + "value1", + "value2" + ] + }, + "queryStringParameters": { + "parameter1": "value1", + "parameter2": "value" + }, + "multiValueQueryStringParameters": { + "parameter1": [ + "value1", + "value2" + ], + "parameter2": [ + "value" + ] + }, + "requestContext": { + "accountId": "123456789012", + "apiId": "id", + "authorizer": { + "claims": null, + "scopes": null + }, + "domainName": "id.execute-api.us-east-1.amazonaws.com", + "domainPrefix": "id", + "extendedRequestId": "request-id", + "httpMethod": "GET", + "identity": { + "accessKey": null, + "accountId": null, + "caller": null, + "cognitoAuthenticationProvider": null, + "cognitoAuthenticationType": null, + "cognitoIdentityId": null, + "cognitoIdentityPoolId": null, + "principalOrgId": null, + "sourceIp": "test-invoke-source-ip", + "user": null, + "userAgent": "user-agent", + "userArn": null, + "clientCert": { + "clientCertPem": "CERT_CONTENT", + "subjectDN": "www.example.com", + "issuerDN": "Example issuer", + "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", + "validity": { + "notBefore": "May 28 12:30:02 2019 GMT", + "notAfter": "Aug 5 09:36:04 2021 GMT" + } + } + }, + "path": "/my/path", + "protocol": "HTTP/1.1", + "requestId": "id=", + "requestTime": "04/Mar/2020:19:15:17 +0000", + "requestTimeEpoch": 1583349317135, + "resourceId": null, + "resourcePath": "/my/path", + "stage": "$default" + }, + "pathParameters": null, + "stageVariables": null, + "body": "Hello from Lambda!", + "isBase64Encoded": false +} \ No newline at end of file diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index 8b03c9ffbe..802169f313 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -68,6 +68,12 @@ describe('APIGateway ', () => { apiGatewayProxyOtherEvent ); }); + it('should not throw when event has sourceIp as test-invoke-source-ip', () => { + const apiGatewayProxyEventTestUi = TestEvents.apiGatewayProxyEventTestUI; + expect(() => + APIGatewayProxyEventSchema.parse(apiGatewayProxyEventTestUi) + ).not.toThrow(); + }); it('should throw error when event is not a valid proxy event', () => { const event = { resource: '/', diff --git a/packages/parser/tests/unit/schema/utils.ts b/packages/parser/tests/unit/schema/utils.ts index 3a17df8570..03ab950348 100644 --- a/packages/parser/tests/unit/schema/utils.ts +++ b/packages/parser/tests/unit/schema/utils.ts @@ -20,6 +20,7 @@ const filenames = [ 'apiGatewayProxyEventPrincipalId', 'apiGatewayProxyEvent_noVersionAuth', 'apiGatewayProxyOtherEvent', + 'apiGatewayProxyEventTestUI', 'apiGatewayProxyV2Event', 'apiGatewayProxyV2EventPathTrailingSlash', 'apiGatewayProxyV2Event_GET',