Skip to content
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

feat: Link APIGW V2 Authorizers to APIGW V2 Api #5625

Merged
merged 10 commits into from
Jul 27, 2023
28 changes: 28 additions & 0 deletions samcli/hook_packages/terraform/hooks/prepare/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,34 @@ class GatewayV2RouteToGatewayV2ApiLocalVariablesLinkingLimitationException(Local
"""


class OneGatewayV2AuthorizerToLambdaFunctionLinkingLimitationException(OneResourceLinkingLimitationException):
"""
Exception specific for Gateway V2 Authorizer linking to more than one Lambda Function
"""


class GatewayV2AuthorizerToLambdaFunctionLocalVariablesLinkingLimitationException(
LocalVariablesLinkingLimitationException
):
"""
Exception specific for Gateway V2 Authorizer linking to Lambda Function using locals.
"""


class OneGatewayV2AuthorizerToGatewayV2ApiLinkingLimitationException(OneResourceLinkingLimitationException):
"""
Exception specific for Gateway V2 Authorizer linking to more than one Gateway V2 API
"""


class GatewayV2AuthorizerToGatewayV2ApiLocalVariablesLinkingLimitationException(
LocalVariablesLinkingLimitationException
):
"""
Exception specific for Gateway V2 Authorizer linking to Gateway V2 API using locals.
"""


class OneGatewayV2ApiToLambdaFunctionLinkingLimitationException(OneResourceLinkingLimitationException):
"""
Exception specific for Gateway V2 API linking to more than one Lambda Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from samcli.lib.utils.resources import AWS_APIGATEWAY_RESTAPI as CFN_AWS_APIGATEWAY_RESTAPI
from samcli.lib.utils.resources import AWS_APIGATEWAY_STAGE as CFN_AWS_APIGATEWAY_STAGE
from samcli.lib.utils.resources import AWS_APIGATEWAY_V2_API as CFN_AWS_APIGATEWAY_V2_API
from samcli.lib.utils.resources import AWS_APIGATEWAY_V2_AUTHORIZER as CFN_AWS_APIGATEWAY_V2_AUTHORIZER
from samcli.lib.utils.resources import AWS_APIGATEWAY_V2_INTEGRATION as CFN_AWS_APIGATEWAY_V2_INTEGRATION
from samcli.lib.utils.resources import AWS_APIGATEWAY_V2_ROUTE as CFN_AWS_APIGATEWAY_V2_ROUTE
from samcli.lib.utils.resources import AWS_APIGATEWAY_V2_STAGE as CFN_AWS_APIGATEWAY_V2_STAGE
Expand All @@ -49,6 +50,7 @@
TF_AWS_API_GATEWAY_V2_ROUTE = "aws_apigatewayv2_route"
TF_AWS_API_GATEWAY_V2_STAGE = "aws_apigatewayv2_stage"
TF_AWS_API_GATEWAY_V2_INTEGRATION = "aws_apigatewayv2_integration"
TF_AWS_API_GATEWAY_V2_AUTHORIZER = "aws_apigatewayv2_authorizer"


def _build_code_property(tf_properties: dict, resource: TFResource) -> Any:
Expand Down Expand Up @@ -412,6 +414,16 @@ def _add_property(cfn_prop, tf_prop):
"PayloadFormatVersion": _get_property_extractor("payload_format_version"),
}

AWS_API_GATEWAY_V2_AUTHORIZER_PROPERTY_BUILDER_MAPPING: PropertyBuilderMapping = {
"ApiId": _get_property_extractor("api_id"),
"AuthorizerType": _get_property_extractor("authorizer_type"),
"AuthorizerUri": _get_property_extractor("authorizer_uri"),
"Name": _get_property_extractor("name"),
"AuthorizerPayloadFormatVersion": _get_property_extractor("authorizer_payload_format_version"),
"IdentitySource": _get_property_extractor("identity_sources"),
"EnableSimpleResponses": _get_property_extractor("enable_simple_responses"),
}

RESOURCE_TRANSLATOR_MAPPING: Dict[str, ResourceTranslator] = {
TF_AWS_LAMBDA_FUNCTION: ResourceTranslator(CFN_AWS_LAMBDA_FUNCTION, AWS_LAMBDA_FUNCTION_PROPERTY_BUILDER_MAPPING),
TF_AWS_LAMBDA_LAYER_VERSION: ResourceTranslator(
Expand Down Expand Up @@ -450,4 +462,7 @@ def _add_property(cfn_prop, tf_prop):
TF_AWS_API_GATEWAY_V2_INTEGRATION: ResourceTranslator(
CFN_AWS_APIGATEWAY_V2_INTEGRATION, AWS_API_GATEWAY_V2_INTEGRATION_PROPERTY_BUILDER_MAPPING
),
TF_AWS_API_GATEWAY_V2_AUTHORIZER: ResourceTranslator(
CFN_AWS_APIGATEWAY_V2_AUTHORIZER, AWS_API_GATEWAY_V2_AUTHORIZER_PROPERTY_BUILDER_MAPPING
),
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
GatewayResourceToApiGatewayMethodLocalVariablesLinkingLimitationException,
GatewayResourceToGatewayRestApiLocalVariablesLinkingLimitationException,
GatewayV2ApiToLambdaFunctionLocalVariablesLinkingLimitationException,
GatewayV2AuthorizerToGatewayV2ApiLocalVariablesLinkingLimitationException,
GatewayV2AuthorizerToLambdaFunctionLocalVariablesLinkingLimitationException,
GatewayV2IntegrationToGatewayV2ApiLocalVariablesLinkingLimitationException,
GatewayV2IntegrationToLambdaFunctionLocalVariablesLinkingLimitationException,
GatewayV2RouteToGatewayV2ApiLocalVariablesLinkingLimitationException,
Expand All @@ -33,6 +35,8 @@
OneGatewayResourceToApiGatewayMethodLinkingLimitationException,
OneGatewayResourceToRestApiLinkingLimitationException,
OneGatewayV2ApiToLambdaFunctionLinkingLimitationException,
OneGatewayV2AuthorizerToGatewayV2ApiLinkingLimitationException,
OneGatewayV2AuthorizerToLambdaFunctionLinkingLimitationException,
OneGatewayV2IntegrationToGatewayV2ApiLinkingLimitationException,
OneGatewayV2IntegrationToLambdaFunctionLinkingLimitationException,
OneGatewayV2RouteToGatewayV2ApiLinkingLimitationException,
Expand Down Expand Up @@ -2008,6 +2012,79 @@ def _link_gateway_v2_route_to_api(
ResourceLinker(resource_linking_pair).link_resources()


def _link_gateway_v2_authorizer_to_lambda_function(
authorizer_config_resources: Dict[str, TFResource],
authorizer_cfn_resources: Dict[str, List],
lamda_function_resources: Dict[str, Dict],
) -> None:
"""
Iterate through all the resources and link the corresponding V2 Authorizer to each Lambda Function

Parameters
----------
authorizer_config_resources: Dict[str, TFResource]
Dictionary of configuration Authorizer resources
authorizer_cfn_resources: Dict[str, List]
Dictionary containing resolved configuration address of CFN Authorizer resources
lamda_function_resources: Dict[str, Dict]
Dictionary of Terraform Lambda Function resources (not configuration resources). The dictionary's key is the
calculated logical id for each resource
"""
exceptions = ResourcePairExceptions(
multiple_resource_linking_exception=OneGatewayV2AuthorizerToLambdaFunctionLinkingLimitationException,
local_variable_linking_exception=GatewayV2AuthorizerToLambdaFunctionLocalVariablesLinkingLimitationException,
)
resource_linking_pair = ResourceLinkingPair(
source_resource_cfn_resource=authorizer_cfn_resources,
source_resource_tf_config=authorizer_config_resources,
destination_resource_tf=lamda_function_resources,
tf_destination_attribute_name="invoke_arn",
terraform_link_field_name="authorizer_uri",
cfn_link_field_name="AuthorizerUri",
terraform_resource_type_prefix=LAMBDA_FUNCTION_RESOURCE_ADDRESS_PREFIX,
cfn_resource_update_call_back_function=_link_gateway_authorizer_to_lambda_function_call_back,
linking_exceptions=exceptions,
)
ResourceLinker(resource_linking_pair).link_resources()


def _link_gateway_v2_authorizer_to_api(
v2_authorizer_config_resources: Dict[str, TFResource],
v2_authorizer_config_address_cfn_resources_map: Dict[str, List],
api_resources: Dict[str, Dict],
) -> None:
"""
Iterate through all the resources and link the corresponding
Gateway V2 Authorizer resources to each Gateway V2 Api

Parameters
----------
v2_authorizer_config_resources: Dict[str, TFResource]
Dictionary of configuration Gateway V2 Authorizers
v2_authorizer_config_address_cfn_resources_map: Dict[str, List]
Dictionary containing resolved configuration addresses matched up to the cfn Gateway V2 Authorizer
api_resources: Dict[str, Dict]
Dictionary of all Terraform Gateway V2 Api resources (not configuration resources).
The dictionary's key is the calculated logical id for each resource.
"""
exceptions = ResourcePairExceptions(
multiple_resource_linking_exception=OneGatewayV2AuthorizerToGatewayV2ApiLinkingLimitationException,
local_variable_linking_exception=GatewayV2AuthorizerToGatewayV2ApiLocalVariablesLinkingLimitationException,
)
resource_linking_pair = ResourceLinkingPair(
source_resource_cfn_resource=v2_authorizer_config_address_cfn_resources_map,
source_resource_tf_config=v2_authorizer_config_resources,
destination_resource_tf=api_resources,
tf_destination_attribute_name="id",
terraform_link_field_name="api_id",
cfn_link_field_name="ApiId",
terraform_resource_type_prefix=API_GATEWAY_V2_API_RESOURCE_ADDRESS_PREFIX,
cfn_resource_update_call_back_function=_link_gateway_v2_resource_to_api_callback,
linking_exceptions=exceptions,
)
ResourceLinker(resource_linking_pair).link_resources()


def _link_gateway_v2_api_to_function_callback(
gateway_v2_api_cfn_resource: Dict, referenced_function_resource_values: List[ReferenceType]
) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,22 @@ def __init__(self):

class ApiGatewayV2IntegrationProperties(ResourceProperties):
"""
Contains the collection logic of the required properties for linking the aws_api_gateway_v2_authorizer resources.
Contains the collection logic of the required properties for linking the aws_api_gateway_v2_integration resources.
"""

def __init__(self):
super(ApiGatewayV2IntegrationProperties, self).__init__()


class ApiGatewayV2AuthorizerProperties(ResourceProperties):
"""
Contains the collection logic of the required properties for linking the aws_api_gateway_v2_authorizer resources.
"""

def __init__(self):
super(ApiGatewayV2AuthorizerProperties, self).__init__()


class ApiGatewayV2StageProperties(ResourceProperties):
"""
Contains the collection logic of the required properties for linking the aws_api_gateway_v2_stage resources.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
TF_AWS_API_GATEWAY_REST_API,
TF_AWS_API_GATEWAY_STAGE,
TF_AWS_API_GATEWAY_V2_API,
TF_AWS_API_GATEWAY_V2_AUTHORIZER,
TF_AWS_API_GATEWAY_V2_INTEGRATION,
TF_AWS_API_GATEWAY_V2_ROUTE,
TF_AWS_API_GATEWAY_V2_STAGE,
Expand All @@ -29,6 +30,8 @@
_link_gateway_resources_to_gateway_rest_apis,
_link_gateway_stage_to_rest_api,
_link_gateway_v2_api_to_function,
_link_gateway_v2_authorizer_to_api,
_link_gateway_v2_authorizer_to_lambda_function,
_link_gateway_v2_integration_to_api,
_link_gateway_v2_integration_to_lambda_function,
_link_gateway_v2_route_to_api,
Expand Down Expand Up @@ -120,6 +123,16 @@
dest=TF_AWS_API_GATEWAY_V2_API,
linking_func=_link_gateway_v2_route_to_api,
),
LinkingPairCaller(
source=TF_AWS_API_GATEWAY_V2_AUTHORIZER,
dest=TF_AWS_LAMBDA_FUNCTION,
linking_func=_link_gateway_v2_authorizer_to_lambda_function,
),
LinkingPairCaller(
source=TF_AWS_API_GATEWAY_V2_AUTHORIZER,
dest=TF_AWS_API_GATEWAY_V2_API,
linking_func=_link_gateway_v2_authorizer_to_api,
),
LinkingPairCaller(
source=TF_AWS_API_GATEWAY_V2_API,
dest=TF_AWS_LAMBDA_FUNCTION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
TF_AWS_API_GATEWAY_REST_API,
TF_AWS_API_GATEWAY_STAGE,
TF_AWS_API_GATEWAY_V2_API,
TF_AWS_API_GATEWAY_V2_AUTHORIZER,
TF_AWS_API_GATEWAY_V2_INTEGRATION,
TF_AWS_API_GATEWAY_V2_ROUTE,
TF_AWS_API_GATEWAY_V2_STAGE,
Expand All @@ -23,6 +24,7 @@
ApiGatewayRestApiProperties,
ApiGatewayStageProperties,
ApiGatewayV2ApiProperties,
ApiGatewayV2AuthorizerProperties,
ApiGatewayV2IntegrationProperties,
ApiGatewayV2RouteProperties,
ApiGatewayV2StageProperties,
Expand Down Expand Up @@ -60,5 +62,6 @@ def get_resource_property_mapping() -> Dict[str, ResourceProperties]:
TF_AWS_API_GATEWAY_V2_ROUTE: ApiGatewayV2RouteProperties(),
TF_AWS_API_GATEWAY_V2_INTEGRATION: ApiGatewayV2IntegrationProperties(),
TF_AWS_API_GATEWAY_V2_API: ApiGatewayV2ApiProperties(),
TF_AWS_API_GATEWAY_V2_AUTHORIZER: ApiGatewayV2AuthorizerProperties(),
TF_AWS_API_GATEWAY_V2_STAGE: ApiGatewayV2StageProperties(),
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from samcli.hook_packages.terraform.hooks.prepare.translate import AWS_PROVIDER_NAME, NULL_RESOURCE_PROVIDER_NAME
from samcli.lib.utils.resources import (
AWS_APIGATEWAY_V2_AUTHORIZER,
AWS_LAMBDA_FUNCTION as CFN_AWS_LAMBDA_FUNCTION,
AWS_LAMBDA_LAYERVERSION,
AWS_APIGATEWAY_RESOURCE,
Expand Down Expand Up @@ -61,6 +62,7 @@ def setUp(self) -> None:
self.apigwv2_route_name = "my_apigwv2_route"
self.apigwv2_stage_name = "my_apigwv2_stage"
self.apigwv2_integration_name = "my_apigwv2_integration"
self.apigwv2_authorizer_name = "my_authorizer_v2"

self.tf_function_common_properties: dict = {
"function_name": self.zip_function_name,
Expand Down Expand Up @@ -941,6 +943,44 @@ def setUp(self) -> None:
"Metadata": {"SamResourceId": f"aws_apigatewayv2_integration.{self.apigwv2_integration_name}"},
}

self.tf_apigwv2_authorizer_common_attributes: dict = {
"type": "aws_apigatewayv2_authorizer",
"provider_name": AWS_PROVIDER_NAME,
}

self.tf_apigwv2_authorizer_properties: dict = {
"api_id": "aws_apigatewayv2_api.my_api.id",
"authorizer_type": "REQUEST",
"authorizer_uri": "aws_lambda_function.authorizerv2.invoke_arn",
"name": self.apigwv2_authorizer_name,
"authorizer_payload_format_version": "2.0",
"identity_sources": ["$request.header.hello"],
"enable_simple_responses": False,
}

self.expected_cfn_apigwv2_authorizer_properties: dict = {
"ApiId": "aws_apigatewayv2_api.my_api.id",
"AuthorizerType": "REQUEST",
"AuthorizerUri": "aws_lambda_function.authorizerv2.invoke_arn",
"Name": self.apigwv2_authorizer_name,
"AuthorizerPayloadFormatVersion": "2.0",
"IdentitySource": ["$request.header.hello"],
"EnableSimpleResponses": False,
}

self.tf_apigwv2_authorizer_resource: dict = {
**self.tf_apigwv2_authorizer_common_attributes,
"values": self.tf_apigwv2_authorizer_properties,
"address": f"aws_apigatewayv2_authorizer.{self.apigwv2_authorizer_name}",
"name": self.apigwv2_authorizer_name,
}

self.expected_cfn_apigwv2_authorizer: dict = {
"Type": AWS_APIGATEWAY_V2_AUTHORIZER,
"Properties": self.expected_cfn_apigwv2_authorizer_properties,
"Metadata": {"SamResourceId": f"aws_apigatewayv2_authorizer.{self.apigwv2_authorizer_name}"},
}

self.tf_json_with_root_module_only: dict = {
"planned_values": {
"root_module": {
Expand All @@ -961,6 +1001,7 @@ def setUp(self) -> None:
self.tf_apigwv2_route_resource,
self.tf_apigwv2_stage_resource,
self.tf_apigwv2_integration_resource,
self.tf_apigwv2_authorizer_resource,
]
}
}
Expand All @@ -982,9 +1023,9 @@ def setUp(self) -> None:
f"AwsApigatewayv2RouteMyApigwv2Route{self.mock_logical_id_hash}": self.expected_cfn_apigwv2_route,
f"AwsApigatewayv2StageMyApigwv2Stage{self.mock_logical_id_hash}": self.expected_cfn_apigwv2_stage,
f"AwsApigatewayv2IntegrationMyApigwv2Integration{self.mock_logical_id_hash}": self.expected_cfn_apigwv2_integration,
f"AwsApigatewayv2AuthorizerMyAuthorizerV2{self.mock_logical_id_hash}": self.expected_cfn_apigwv2_authorizer,
},
}

self.tf_json_with_root_module_with_sam_metadata_resources: dict = {
"planned_values": {
"root_module": {
Expand Down
Loading