Skip to content

Commit 4724886

Browse files
committed
feat(data_classes): API Gateway V2 IAM and Lambda
Update to support IAM and Lambda authorizer for API Gateway V2 trigger events
1 parent 8d5986a commit 4724886

File tree

4 files changed

+191
-0
lines changed

4 files changed

+191
-0
lines changed

aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,52 @@ def user_agent(self) -> str:
267267
return self["requestContext"]["http"]["userAgent"]
268268

269269

270+
class RequestContextV2AuthorizerIam(DictWrapper):
271+
@property
272+
def access_key(self) -> Optional[str]:
273+
return self.get("accessKey")
274+
275+
@property
276+
def account_id(self) -> Optional[str]:
277+
"""The AWS account ID associated with the request."""
278+
return self.get("accountId")
279+
280+
@property
281+
def caller_id(self) -> Optional[str]:
282+
"""The principal identifier of the caller making the request."""
283+
return self.get("callerId")
284+
285+
@property
286+
def cognito_amr(self) -> Optional[List[str]]:
287+
return self["cognitoIdentity"].get("amr")
288+
289+
@property
290+
def cognito_identity_id(self) -> Optional[str]:
291+
"""The Amazon Cognito identity ID of the caller making the request.
292+
Available only if the request was signed with Amazon Cognito credentials."""
293+
return self["cognitoIdentity"].get("identityId")
294+
295+
@property
296+
def cognito_identity_pool_id(self) -> Optional[str]:
297+
"""The Amazon Cognito identity pool ID of the caller making the request.
298+
Available only if the request was signed with Amazon Cognito credentials."""
299+
return self["cognitoIdentity"].get("identityPoolId")
300+
301+
@property
302+
def principal_org_id(self) -> Optional[str]:
303+
"""The AWS organization ID."""
304+
return self.get("principalOrgId")
305+
306+
@property
307+
def user_arn(self) -> Optional[str]:
308+
"""The Amazon Resource Name (ARN) of the effective user identified after authentication."""
309+
return self.get("userArn")
310+
311+
@property
312+
def user_id(self) -> Optional[str]:
313+
return self.get("userId")
314+
315+
270316
class RequestContextV2Authorizer(DictWrapper):
271317
@property
272318
def jwt_claim(self) -> Dict[str, Any]:
@@ -276,6 +322,15 @@ def jwt_claim(self) -> Dict[str, Any]:
276322
def jwt_scopes(self) -> List[str]:
277323
return self["jwt"]["scopes"]
278324

325+
@property
326+
def get_lambda(self) -> Optional[Dict[str, Any]]:
327+
return self.get("lambda")
328+
329+
@property
330+
def iam(self) -> Optional[RequestContextV2AuthorizerIam]:
331+
iam = self.get("iam")
332+
return None if iam is None else RequestContextV2AuthorizerIam(iam)
333+
279334

280335
class RequestContextV2(DictWrapper):
281336
@property
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "$default",
4+
"rawPath": "/my/path",
5+
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
6+
"cookies": [
7+
"cookie1",
8+
"cookie2"
9+
],
10+
"headers": {
11+
"Header1": "value1",
12+
"Header2": "value2"
13+
},
14+
"queryStringParameters": {
15+
"parameter1": "value1,value2",
16+
"parameter2": "value"
17+
},
18+
"pathParameters": {
19+
"proxy": "hello/world"
20+
},
21+
"requestContext": {
22+
"routeKey": "$default",
23+
"accountId": "123456789012",
24+
"stage": "$default",
25+
"requestId": "id",
26+
"authorizer": {
27+
"iam": {
28+
"accessKey": "ARIA2ZJZYVUEREEIHAKY",
29+
"accountId": "1234567890",
30+
"callerId": "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials",
31+
"cognitoIdentity": {
32+
"amr" : ["foo"],
33+
"identityId": "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce",
34+
"identityPoolId": "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce"
35+
},
36+
"principalOrgId": "AwsOrgId",
37+
"userArn": "arn:aws:iam::1234567890:user/Admin",
38+
"userId": "AROA2ZJZYVRE7Y3TUXHH6"
39+
}
40+
},
41+
"apiId": "api-id",
42+
"domainName": "id.execute-api.us-east-1.amazonaws.com",
43+
"domainPrefix": "id",
44+
"time": "12/Mar/2020:19:03:58+0000",
45+
"timeEpoch": 1583348638390,
46+
"http": {
47+
"method": "GET",
48+
"path": "/my/path",
49+
"protocol": "HTTP/1.1",
50+
"sourceIp": "IP",
51+
"userAgent": "agent"
52+
}
53+
},
54+
"stageVariables": {
55+
"stageVariable1": "value1",
56+
"stageVariable2": "value2"
57+
},
58+
"body": "{\r\n\t\"a\": 1\r\n}",
59+
"isBase64Encoded": false
60+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
{
2+
"version": "2.0",
3+
"routeKey": "$default",
4+
"rawPath": "/my/path",
5+
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
6+
"cookies": [
7+
"cookie1",
8+
"cookie2"
9+
],
10+
"headers": {
11+
"Header1": "value1",
12+
"Header2": "value2"
13+
},
14+
"queryStringParameters": {
15+
"parameter1": "value1,value2",
16+
"parameter2": "value"
17+
},
18+
"pathParameters": {
19+
"proxy": "hello/world"
20+
},
21+
"requestContext": {
22+
"routeKey": "$default",
23+
"accountId": "123456789012",
24+
"stage": "$default",
25+
"requestId": "id",
26+
"authorizer": {
27+
"lambda": {
28+
"key": "value"
29+
}
30+
},
31+
"apiId": "api-id",
32+
"domainName": "id.execute-api.us-east-1.amazonaws.com",
33+
"domainPrefix": "id",
34+
"time": "12/Mar/2020:19:03:58+0000",
35+
"timeEpoch": 1583348638390,
36+
"http": {
37+
"method": "GET",
38+
"path": "/my/path",
39+
"protocol": "HTTP/1.1",
40+
"sourceIp": "IP",
41+
"userAgent": "agent"
42+
}
43+
},
44+
"stageVariables": {
45+
"stageVariable1": "value1",
46+
"stageVariable2": "value2"
47+
},
48+
"body": "{\r\n\t\"a\": 1\r\n}",
49+
"isBase64Encoded": false
50+
}

tests/functional/test_lambda_trigger_events.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,32 @@ def test_api_gateway_proxy_v2_event():
639639
assert event.stage_variables == event["stageVariables"]
640640

641641

642+
def test_api_gateway_proxy_v2_lambda_authorizer_event():
643+
event = APIGatewayProxyEventV2(load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json"))
644+
645+
request_context = event.request_context
646+
assert request_context is not None
647+
lambda_props = request_context.authorizer.get_lambda
648+
assert lambda_props is not None
649+
assert lambda_props["key"] == "value"
650+
651+
652+
def test_api_gateway_proxy_v2_iam_event():
653+
event = APIGatewayProxyEventV2(load_event("apiGatewayProxyV2IamEvent.json"))
654+
655+
iam = event.request_context.authorizer.iam
656+
assert iam is not None
657+
assert iam.access_key == "ARIA2ZJZYVUEREEIHAKY"
658+
assert iam.account_id == "1234567890"
659+
assert iam.caller_id == "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials"
660+
assert iam.cognito_amr == ["foo"]
661+
assert iam.cognito_identity_id == "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce"
662+
assert iam.cognito_identity_pool_id == "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce"
663+
assert iam.principal_org_id == "AwsOrgId"
664+
assert iam.user_arn == "arn:aws:iam::1234567890:user/Admin"
665+
assert iam.user_id == "AROA2ZJZYVRE7Y3TUXHH6"
666+
667+
642668
def test_base_proxy_event_get_query_string_value():
643669
default_value = "default"
644670
set_value = "value"

0 commit comments

Comments
 (0)