Skip to content

feat(data_classes): API Gateway V2 IAM and Lambda #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,56 @@ def user_agent(self) -> str:
return self["requestContext"]["http"]["userAgent"]


class RequestContextV2AuthorizerIam(DictWrapper):
@property
def access_key(self) -> Optional[str]:
"""The IAM user access key associated with the request."""
return self.get("accessKey")

@property
def account_id(self) -> Optional[str]:
"""The AWS account ID associated with the request."""
return self.get("accountId")

@property
def caller_id(self) -> Optional[str]:
"""The principal identifier of the caller making the request."""
return self.get("callerId")

@property
def cognito_amr(self) -> Optional[List[str]]:
"""This represents how the user was authenticated.
AMR stands for Authentication Methods References as per the openid spec"""
return self["cognitoIdentity"].get("amr")

@property
def cognito_identity_id(self) -> Optional[str]:
"""The Amazon Cognito identity ID of the caller making the request.
Available only if the request was signed with Amazon Cognito credentials."""
return self["cognitoIdentity"].get("identityId")

@property
def cognito_identity_pool_id(self) -> Optional[str]:
"""The Amazon Cognito identity pool ID of the caller making the request.
Available only if the request was signed with Amazon Cognito credentials."""
return self["cognitoIdentity"].get("identityPoolId")

@property
def principal_org_id(self) -> Optional[str]:
"""The AWS organization ID."""
return self.get("principalOrgId")

@property
def user_arn(self) -> Optional[str]:
"""The Amazon Resource Name (ARN) of the effective user identified after authentication."""
return self.get("userArn")

@property
def user_id(self) -> Optional[str]:
"""The IAM user ID of the effective user identified after authentication."""
return self.get("userId")


class RequestContextV2Authorizer(DictWrapper):
@property
def jwt_claim(self) -> Dict[str, Any]:
Expand All @@ -276,6 +326,17 @@ def jwt_claim(self) -> Dict[str, Any]:
def jwt_scopes(self) -> List[str]:
return self["jwt"]["scopes"]

@property
def get_lambda(self) -> Optional[Dict[str, Any]]:
"""Lambda authorization context details"""
return self.get("lambda")

@property
def iam(self) -> Optional[RequestContextV2AuthorizerIam]:
"""IAM authorization details used for making the request."""
iam = self.get("iam")
return None if iam is None else RequestContextV2AuthorizerIam(iam)


class RequestContextV2(DictWrapper):
@property
Expand Down
60 changes: 60 additions & 0 deletions tests/events/apiGatewayProxyV2IamEvent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
"cookies": [
"cookie1",
"cookie2"
],
"headers": {
"Header1": "value1",
"Header2": "value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"pathParameters": {
"proxy": "hello/world"
},
"requestContext": {
"routeKey": "$default",
"accountId": "123456789012",
"stage": "$default",
"requestId": "id",
"authorizer": {
"iam": {
"accessKey": "ARIA2ZJZYVUEREEIHAKY",
"accountId": "1234567890",
"callerId": "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials",
"cognitoIdentity": {
"amr" : ["foo"],
"identityId": "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce",
"identityPoolId": "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce"
},
"principalOrgId": "AwsOrgId",
"userArn": "arn:aws:iam::1234567890:user/Admin",
"userId": "AROA2ZJZYVRE7Y3TUXHH6"
}
},
"apiId": "api-id",
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"time": "12/Mar/2020:19:03:58+0000",
"timeEpoch": 1583348638390,
"http": {
"method": "GET",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
}
},
"stageVariables": {
"stageVariable1": "value1",
"stageVariable2": "value2"
},
"body": "{\r\n\t\"a\": 1\r\n}",
"isBase64Encoded": false
}
50 changes: 50 additions & 0 deletions tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
"cookies": [
"cookie1",
"cookie2"
],
"headers": {
"Header1": "value1",
"Header2": "value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"pathParameters": {
"proxy": "hello/world"
},
"requestContext": {
"routeKey": "$default",
"accountId": "123456789012",
"stage": "$default",
"requestId": "id",
"authorizer": {
"lambda": {
"key": "value"
}
},
"apiId": "api-id",
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"time": "12/Mar/2020:19:03:58+0000",
"timeEpoch": 1583348638390,
"http": {
"method": "GET",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
}
},
"stageVariables": {
"stageVariable1": "value1",
"stageVariable2": "value2"
},
"body": "{\r\n\t\"a\": 1\r\n}",
"isBase64Encoded": false
}
26 changes: 26 additions & 0 deletions tests/functional/test_lambda_trigger_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,32 @@ def test_api_gateway_proxy_v2_event():
assert event.stage_variables == event["stageVariables"]


def test_api_gateway_proxy_v2_lambda_authorizer_event():
event = APIGatewayProxyEventV2(load_event("apiGatewayProxyV2LambdaAuthorizerEvent.json"))

request_context = event.request_context
assert request_context is not None
lambda_props = request_context.authorizer.get_lambda
assert lambda_props is not None
assert lambda_props["key"] == "value"


def test_api_gateway_proxy_v2_iam_event():
event = APIGatewayProxyEventV2(load_event("apiGatewayProxyV2IamEvent.json"))

iam = event.request_context.authorizer.iam
assert iam is not None
assert iam.access_key == "ARIA2ZJZYVUEREEIHAKY"
assert iam.account_id == "1234567890"
assert iam.caller_id == "AROA7ZJZYVRE7C3DUXHH6:CognitoIdentityCredentials"
assert iam.cognito_amr == ["foo"]
assert iam.cognito_identity_id == "us-east-1:3f291106-8703-466b-8f2b-3ecee1ca56ce"
assert iam.cognito_identity_pool_id == "us-east-1:4f291106-8703-466b-8f2b-3ecee1ca56ce"
assert iam.principal_org_id == "AwsOrgId"
assert iam.user_arn == "arn:aws:iam::1234567890:user/Admin"
assert iam.user_id == "AROA2ZJZYVRE7Y3TUXHH6"


def test_base_proxy_event_get_query_string_value():
default_value = "default"
set_value = "value"
Expand Down