Skip to content

Commit 3ed48e7

Browse files
fix(event_sources): add test for Function URL AuthZ (#1421)
Co-authored-by: heitorlessa <[email protected]>
1 parent 9f1555c commit 3ed48e7

File tree

5 files changed

+151
-58
lines changed

5 files changed

+151
-58
lines changed

aws_lambda_powertools/utilities/data_classes/api_gateway_proxy_event.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -123,26 +123,26 @@ def caller_id(self) -> Optional[str]:
123123
"""The principal identifier of the caller making the request."""
124124
return self.get("callerId")
125125

126+
def _cognito_identity(self) -> Dict:
127+
return self.get("cognitoIdentity", {}) or {} # not available in FunctionURL
128+
126129
@property
127130
def cognito_amr(self) -> Optional[List[str]]:
128131
"""This represents how the user was authenticated.
129132
AMR stands for Authentication Methods References as per the openid spec"""
130-
cognito_identity = self["cognitoIdentity"] or {} # not available in FunctionURL
131-
return cognito_identity.get("amr")
133+
return self._cognito_identity().get("amr")
132134

133135
@property
134136
def cognito_identity_id(self) -> Optional[str]:
135137
"""The Amazon Cognito identity ID of the caller making the request.
136138
Available only if the request was signed with Amazon Cognito credentials."""
137-
cognito_identity = self.get("cognitoIdentity") or {} # not available in FunctionURL
138-
return cognito_identity.get("identityId")
139+
return self._cognito_identity().get("identityId")
139140

140141
@property
141142
def cognito_identity_pool_id(self) -> Optional[str]:
142143
"""The Amazon Cognito identity pool ID of the caller making the request.
143144
Available only if the request was signed with Amazon Cognito credentials."""
144-
cognito_identity = self.get("cognitoIdentity") or {} # not available in FunctionURL
145-
return cognito_identity.get("identityPoolId")
145+
return self._cognito_identity().get("identityPoolId")
146146

147147
@property
148148
def principal_org_id(self) -> Optional[str]:
+45-50
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,47 @@
11
{
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": "value1,value2"
13-
},
14-
"queryStringParameters": {
15-
"parameter1": "value1,value2",
16-
"parameter2": "value"
17-
},
18-
"requestContext": {
19-
"accountId": "123456789012",
20-
"apiId": "<urlid>",
21-
"authentication": null,
22-
"authorizer": {
23-
"iam": {
24-
"accessKey": "AKIA...",
25-
"accountId": "111122223333",
26-
"callerId": "AIDA...",
27-
"cognitoIdentity": null,
28-
"principalOrgId": null,
29-
"userArn": "arn:aws:iam::111122223333:user/example-user",
30-
"userId": "AIDA..."
31-
}
32-
},
33-
"domainName": "<url-id>.lambda-url.us-west-2.on.aws",
34-
"domainPrefix": "<url-id>",
35-
"http": {
36-
"method": "POST",
37-
"path": "/my/path",
38-
"protocol": "HTTP/1.1",
39-
"sourceIp": "123.123.123.123",
40-
"userAgent": "agent"
41-
},
42-
"requestId": "id",
43-
"routeKey": "$default",
44-
"stage": "$default",
45-
"time": "12/Mar/2020:19:03:58 +0000",
46-
"timeEpoch": 1583348638390
47-
},
48-
"body": "Hello from client!",
49-
"pathParameters": null,
50-
"isBase64Encoded": false,
51-
"stageVariables": null
2+
"version":"2.0",
3+
"routeKey":"$default",
4+
"rawPath":"/",
5+
"rawQueryString":"",
6+
"headers":{
7+
"sec-fetch-mode":"navigate",
8+
"x-amzn-tls-version":"TLSv1.2",
9+
"sec-fetch-site":"cross-site",
10+
"accept-language":"pt-BR,pt;q=0.9",
11+
"x-forwarded-proto":"https",
12+
"x-forwarded-port":"443",
13+
"x-forwarded-for":"123.123.123.123",
14+
"sec-fetch-user":"?1",
15+
"accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
16+
"x-amzn-tls-cipher-suite":"ECDHE-RSA-AES128-GCM-SHA256",
17+
"sec-ch-ua":"\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"102\", \"Google Chrome\";v=\"102\"",
18+
"sec-ch-ua-mobile":"?0",
19+
"x-amzn-trace-id":"Root=1-62ecd163-5f302e550dcde3b12402207d",
20+
"sec-ch-ua-platform":"\"Linux\"",
21+
"host":"<url-id>.lambda-url.us-east-1.on.aws",
22+
"upgrade-insecure-requests":"1",
23+
"cache-control":"max-age=0",
24+
"accept-encoding":"gzip, deflate, br",
25+
"sec-fetch-dest":"document",
26+
"user-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36"
27+
},
28+
"requestContext":{
29+
"accountId":"anonymous",
30+
"apiId":"<url-id>",
31+
"domainName":"<url-id>.lambda-url.us-east-1.on.aws",
32+
"domainPrefix":"<url-id>",
33+
"http":{
34+
"method":"GET",
35+
"path":"/",
36+
"protocol":"HTTP/1.1",
37+
"sourceIp":"123.123.123.123",
38+
"userAgent":"agent"
39+
},
40+
"requestId":"id",
41+
"routeKey":"$default",
42+
"stage":"$default",
43+
"time":"05/Aug/2022:08:14:39 +0000",
44+
"timeEpoch":1659687279885
45+
},
46+
"isBase64Encoded":false
5247
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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": "value1,value2"
13+
},
14+
"queryStringParameters": {
15+
"parameter1": "value1,value2",
16+
"parameter2": "value"
17+
},
18+
"requestContext": {
19+
"accountId": "123456789012",
20+
"apiId": "<urlid>",
21+
"authentication": null,
22+
"authorizer": {
23+
"iam": {
24+
"accessKey": "AKIA...",
25+
"accountId": "111122223333",
26+
"callerId": "AIDA...",
27+
"cognitoIdentity": null,
28+
"principalOrgId": null,
29+
"userArn": "arn:aws:iam::111122223333:user/example-user",
30+
"userId": "AIDA..."
31+
}
32+
},
33+
"domainName": "<url-id>.lambda-url.us-west-2.on.aws",
34+
"domainPrefix": "<url-id>",
35+
"http": {
36+
"method": "POST",
37+
"path": "/my/path",
38+
"protocol": "HTTP/1.1",
39+
"sourceIp": "123.123.123.123",
40+
"userAgent": "agent"
41+
},
42+
"requestId": "id",
43+
"routeKey": "$default",
44+
"stage": "$default",
45+
"time": "12/Mar/2020:19:03:58 +0000",
46+
"timeEpoch": 1583348638390
47+
},
48+
"body": "Hello from client!",
49+
"pathParameters": null,
50+
"isBase64Encoded": false,
51+
"stageVariables": null
52+
}

tests/functional/data_classes/test_lambda_function_url.py

+46
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,51 @@ def test_lambda_function_url_event():
88
assert event.version == "2.0"
99
assert event.route_key == "$default"
1010

11+
assert event.path == "/"
12+
assert event.raw_query_string == ""
13+
14+
assert event.cookies is None
15+
16+
headers = event.headers
17+
assert len(headers) == 20
18+
19+
assert event.query_string_parameters is None
20+
21+
assert event.is_base64_encoded is False
22+
assert event.body is None
23+
assert event.path_parameters is None
24+
assert event.stage_variables is None
25+
assert event.http_method == "GET"
26+
27+
request_context = event.request_context
28+
29+
assert request_context.account_id == "anonymous"
30+
assert request_context.api_id is not None
31+
assert request_context.domain_name == "<url-id>.lambda-url.us-east-1.on.aws"
32+
assert request_context.domain_prefix == "<url-id>"
33+
assert request_context.request_id == "id"
34+
assert request_context.route_key == "$default"
35+
assert request_context.stage == "$default"
36+
assert request_context.time is not None
37+
assert request_context.time_epoch == 1659687279885
38+
assert request_context.authentication is None
39+
40+
http = request_context.http
41+
assert http.method == "GET"
42+
assert http.path == "/"
43+
assert http.protocol == "HTTP/1.1"
44+
assert http.source_ip == "123.123.123.123"
45+
assert http.user_agent == "agent"
46+
47+
assert request_context.authorizer is None
48+
49+
50+
def test_lambda_function_url_event_iam():
51+
event = LambdaFunctionUrlEvent(load_event("lambdaFunctionUrlIAMEvent.json"))
52+
53+
assert event.version == "2.0"
54+
assert event.route_key == "$default"
55+
1156
assert event.path == "/my/path"
1257
assert event.raw_query_string == "parameter1=value1&parameter1=value2&parameter2=value"
1358

@@ -60,6 +105,7 @@ def test_lambda_function_url_event():
60105
assert iam.access_key is not None
61106
assert iam.account_id == "111122223333"
62107
assert iam.caller_id is not None
108+
assert iam.cognito_amr is None
63109
assert iam.cognito_identity_id is None
64110
assert iam.cognito_identity_pool_id is None
65111
assert iam.principal_org_id is None

tests/functional/event_handler/test_lambda_function_url.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def foo():
1515
return Response(200, content_types.TEXT_HTML, "foo")
1616

1717
# WHEN calling the event handler
18-
result = app(load_event("lambdaFunctionUrlEvent.json"), {})
18+
result = app(load_event("lambdaFunctionUrlIAMEvent.json"), {})
1919

2020
# THEN process event correctly
2121
# AND set the current_event type as LambdaFunctionUrlEvent
@@ -33,7 +33,7 @@ def foo():
3333
raise RuntimeError()
3434

3535
# WHEN calling the event handler
36-
result = app(load_event("lambdaFunctionUrlEvent.json"), {})
36+
result = app(load_event("lambdaFunctionUrlIAMEvent.json"), {})
3737

3838
# THEN process event correctly
3939
# AND return 404 because the event doesn't match any known route

0 commit comments

Comments
 (0)