Skip to content
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
1 change: 1 addition & 0 deletions docs/globals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Currently, the following resources and properties are being supported:
AccessLogSettings:
Tags:
DefaultRouteSettings:
RouteSettings:
Domain:

SimpleTable:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Resources:
- DynamoDBReadPolicy:
TableName: name

- DynamoDBWritePolicy:
TableName: name

- SESSendBouncePolicy:
IdentityName: name

Expand All @@ -38,6 +41,9 @@ Resources:
- S3CrudPolicy:
BucketName: name

- S3WritePolicy:
BucketName: name

- AMIDescribePolicy: {}

- CloudFormationDescribeStacksPolicy: {}
Expand Down
15 changes: 13 additions & 2 deletions samtranslator/model/api/http_api_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(
auth=None,
cors_configuration=None,
access_log_settings=None,
route_settings=None,
default_route_settings=None,
resource_attributes=None,
passthrough_resource_attributes=None,
Expand Down Expand Up @@ -73,6 +74,7 @@ def __init__(
self.cors_configuration = cors_configuration
self.tags = tags
self.access_log_settings = access_log_settings
self.route_settings = route_settings
self.default_route_settings = default_route_settings
self.resource_attributes = resource_attributes
self.passthrough_resource_attributes = passthrough_resource_attributes
Expand Down Expand Up @@ -195,6 +197,7 @@ def _construct_api_domain(self, http_api):
)
domain_config = dict()
domain.DomainName = self.domain.get("DomainName")
domain.Tags = self.tags
endpoint = self.domain.get("EndpointConfiguration")

if endpoint is None:
Expand Down Expand Up @@ -418,10 +421,15 @@ def _get_authorizers(self, authorizers_config, default_authorizer=None):
self.logical_id, "Authorizer %s must be a dictionary." % (authorizer_name)
)

if "OpenIdConnectUrl" in authorizer:
raise InvalidResourceException(
self.logical_id,
"'OpenIdConnectUrl' is no longer a supported property for authorizer '%s'. Please refer to the AWS SAM documentation."
% (authorizer_name),
)
authorizers[authorizer_name] = ApiGatewayV2Authorizer(
api_logical_id=self.logical_id,
name=authorizer_name,
open_id_connect_url=authorizer.get("OpenIdConnectUrl"),
authorization_scopes=authorizer.get("AuthorizationScopes"),
jwt_configuration=authorizer.get("JwtConfiguration"),
id_source=authorizer.get("IdentitySource"),
Expand Down Expand Up @@ -470,6 +478,7 @@ def _construct_stage(self):
and not self.stage_variables
and not self.access_log_settings
and not self.default_route_settings
and not self.route_settings
):
return

Expand All @@ -489,12 +498,14 @@ def _construct_stage(self):
stage.StageVariables = self.stage_variables
stage.AccessLogSettings = self.access_log_settings
stage.DefaultRouteSettings = self.default_route_settings
stage.Tags = self.tags
stage.AutoDeploy = True
stage.RouteSettings = self.route_settings

return stage

def to_cloudformation(self):
"""Generates CloudFormation resources from a SAM API resource
"""Generates CloudFormation resources from a SAM HTTP API resource

:returns: a tuple containing the HttpApi and Stage for an empty Api.
:rtype: tuple
Expand Down
27 changes: 8 additions & 19 deletions samtranslator/model/apigatewayv2.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class ApiGatewayV2HttpApi(Resource):
"Description": PropertyType(False, is_str()),
"FailOnWarnings": PropertyType(False, is_type(bool)),
"BasePath": PropertyType(False, is_str()),
"Tags": PropertyType(False, list_of(is_type(dict))),
"CorsConfiguration": PropertyType(False, is_type(dict)),
}

Expand All @@ -24,11 +23,12 @@ class ApiGatewayV2Stage(Resource):
property_types = {
"AccessLogSettings": PropertyType(False, is_type(dict)),
"DefaultRouteSettings": PropertyType(False, is_type(dict)),
"RouteSettings": PropertyType(False, is_type(dict)),
"ClientCertificateId": PropertyType(False, is_str()),
"Description": PropertyType(False, is_str()),
"ApiId": PropertyType(True, is_str()),
"StageName": PropertyType(False, one_of(is_str(), is_type(dict))),
"Tags": PropertyType(False, list_of(is_type(dict))),
"Tags": PropertyType(False, is_type(dict)),
"StageVariables": PropertyType(False, is_type(dict)),
"AutoDeploy": PropertyType(False, is_type(bool)),
}
Expand All @@ -41,7 +41,7 @@ class ApiGatewayV2DomainName(Resource):
property_types = {
"DomainName": PropertyType(True, is_str()),
"DomainNameConfigurations": PropertyType(False, list_of(is_type(dict))),
"Tags": PropertyType(False, list_of(is_type(dict))),
"Tags": PropertyType(False, is_type(dict)),
}


Expand All @@ -57,33 +57,24 @@ class ApiGatewayV2ApiMapping(Resource):

class ApiGatewayV2Authorizer(object):
def __init__(
self,
api_logical_id=None,
name=None,
open_id_connect_url=None,
authorization_scopes=[],
jwt_configuration={},
id_source=None,
self, api_logical_id=None, name=None, authorization_scopes=[], jwt_configuration={}, id_source=None,
):
"""
Creates an authorizer for use in V2 Http Apis
"""
# OIDC uses a connect url, oauth2 doesn't
self.auth_type = "openIdConnect"
if open_id_connect_url is None:
self.auth_type = "oauth2"
# Currently only one type of auth
self.auth_type = "oauth2"

self.api_logical_id = api_logical_id
self.name = name
self.open_id_connect_url = open_id_connect_url
self.authorization_scopes = authorization_scopes

# Validate necessary parameters exist
if not jwt_configuration:
raise InvalidResourceException(api_logical_id, name + " Authorizer must define 'JwtConfiguration'")
raise InvalidResourceException(api_logical_id, name + " Authorizer must define 'JwtConfiguration'.")
self.jwt_configuration = jwt_configuration
if not id_source:
raise InvalidResourceException(api_logical_id, name + " Authorizer must define 'IdentitySource'")
raise InvalidResourceException(api_logical_id, name + " Authorizer must define 'IdentitySource'.")
self.id_source = id_source

def generate_openapi(self):
Expand All @@ -98,6 +89,4 @@ def generate_openapi(self):
"type": "jwt",
},
}
if self.open_id_connect_url:
openapi["x-amazon-apigateway-authorizer"]["openIdConnectUrl"] = self.open_id_connect_url
return openapi
2 changes: 1 addition & 1 deletion samtranslator/model/cognito.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class CognitoUserPool(Resource):
"UsernameAttributes": PropertyType(False, list_of(is_str())),
"UserPoolAddOns": PropertyType(False, list_of(dict)),
"UserPoolName": PropertyType(False, is_str()),
"UserPoolTags": PropertyType(False, is_str()),
"UserPoolTags": PropertyType(False, is_type(dict)),
"VerificationMessageTemplate": PropertyType(False, is_type(dict)),
}

Expand Down
1 change: 1 addition & 0 deletions samtranslator/model/eventsources/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,7 @@ class HttpApi(PushEventSource):
"Stage": PropertyType(False, is_str()),
"Auth": PropertyType(False, is_type(dict)),
"TimeoutInMillis": PropertyType(False, is_type(int)),
"RouteSettings": PropertyType(False, is_type(dict)),
}

def resources_to_link(self, resources):
Expand Down
2 changes: 2 additions & 0 deletions samtranslator/model/sam_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ class SamHttpApi(SamResourceMacro):
"AccessLogSettings": PropertyType(False, is_type(dict)),
"DefaultRouteSettings": PropertyType(False, is_type(dict)),
"Auth": PropertyType(False, is_type(dict)),
"RouteSettings": PropertyType(False, is_type(dict)),
"Domain": PropertyType(False, is_type(dict)),
}

Expand Down Expand Up @@ -910,6 +911,7 @@ def to_cloudformation(self, **kwargs):
auth=self.Auth,
cors_configuration=self.CorsConfiguration,
access_log_settings=self.AccessLogSettings,
route_settings=self.RouteSettings,
default_route_settings=self.DefaultRouteSettings,
resource_attributes=self.resource_attributes,
passthrough_resource_attributes=self.get_passthrough_resource_attributes(),
Expand Down
13 changes: 12 additions & 1 deletion samtranslator/plugins/api/implicit_api_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,10 @@ def _add_api_to_swagger(self, event_id, event_properties, template):
if isinstance(api_id, dict) or not template.get(api_id):
raise InvalidEventException(
event_id,
"RestApiId must be a valid reference to an 'AWS::Serverless::Api' resource " "in same template",
self.api_id_property
+ " must be a valid reference to an '"
+ self._get_api_resource_type_name()
+ "' resource in same template.",
)

# Make sure Swagger is valid
Expand Down Expand Up @@ -343,3 +346,11 @@ def _generate_implicit_api_resource(self):
raise NotImplementedError(
"Method _setup_api_properties() must be implemented in a " "subclass of ImplicitApiPlugin"
)

def _get_api_resource_type_name(self):
"""
Returns the type of API resource
"""
raise NotImplementedError(
"Method _setup_api_properties() must be implemented in a " "subclass of ImplicitApiPlugin"
)
43 changes: 43 additions & 0 deletions samtranslator/plugins/api/implicit_http_api_plugin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import six

from samtranslator.model.intrinsics import make_conditional
from samtranslator.model.naming import GeneratedLogicalId
from samtranslator.plugins.api.implicit_api_plugin import ImplicitApiPlugin
from samtranslator.public.open_api import OpenApiEditor
Expand Down Expand Up @@ -88,6 +89,8 @@ def _process_api_events(self, function, api_events, template, condition=None):
method_conditions[method] = condition

self._add_api_to_swagger(logicalId, event_properties, template)
if "RouteSettings" in event_properties:
self._add_route_settings_to_api(logicalId, event_properties, template, condition)
api_events[logicalId] = event

# We could have made changes to the Events structure. Write it back to function
Expand Down Expand Up @@ -116,6 +119,46 @@ def _get_api_definition_from_editor(self, editor):
"""
return editor.openapi

def _get_api_resource_type_name(self):
"""
Returns the type of API resource
"""
return "AWS::Serverless::HttpApi"

def _add_route_settings_to_api(self, event_id, event_properties, template, condition):
"""
Adds the RouteSettings for this path/method from the given event to the RouteSettings configuration
on the AWS::Serverless::HttpApi that this refers to.

:param string event_id: LogicalId of the event
:param dict event_properties: Properties of the event
:param SamTemplate template: SAM Template to search for Serverless::HttpApi resources
:param string condition: Condition on this HttpApi event (if any)
"""

api_id = self._get_api_id(event_properties)
resource = template.get(api_id)

path = event_properties["Path"]
method = event_properties["Method"]

# Route should be in format "METHOD /path" or just "/path" if the ANY method is used
route = "{} {}".format(method.upper(), path)
if method == OpenApiEditor._X_ANY_METHOD:
route = path

# Handle Resource-level conditions if necessary
api_route_settings = resource.properties.get("RouteSettings", {})
event_route_settings = event_properties.get("RouteSettings", {})
if condition:
event_route_settings = make_conditional(condition, event_properties.get("RouteSettings", {}))

# Merge event-level and api-level RouteSettings properties
api_route_settings.setdefault(route, {})
api_route_settings[route].update(event_route_settings)
resource.properties["RouteSettings"] = api_route_settings
template.set(api_id, resource)


class ImplicitHttpApiResource(SamResource):
"""
Expand Down
6 changes: 6 additions & 0 deletions samtranslator/plugins/api/implicit_rest_api_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ def _get_api_definition_from_editor(self, editor):
"""
return editor.swagger

def _get_api_resource_type_name(self):
"""
Returns the type of API resource
"""
return "AWS::Serverless::Api"


class ImplicitApiResource(SamResource):
"""
Expand Down
1 change: 1 addition & 0 deletions samtranslator/plugins/globals/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Globals(object):
"CorsConfiguration",
"DefaultRouteSettings",
"Domain",
"RouteSettings",
],
SamResourceType.SimpleTable.value: ["SSESpecification"],
}
Expand Down
Loading