Skip to content

Commit 0d12466

Browse files
cfbarberobrettstack
authored andcommitted
feat: add ApiKey Auth support (#943)
* Initial work to add ApiKeyRequired support - Implement new translator tests - Add swagger.py unit tests - Update documentation - refactor Auth handling in swagger.py * Fix spacing * undo space changes * Add openapi3 tests * Fix linting errors * Update apikey openapi3 tests with expected output. * Move OpenApi Auth processing- Since the ApiKey setting can be specified just at a Function level, we need to ensure the OpenApi Auth post processing happens even if the API has no explicit Auth Settings
1 parent 7361002 commit 0d12466

34 files changed

+4144
-1411
lines changed

samtranslator/model/api/api_generator.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121
CorsProperties.__new__.__defaults__ = (None, None, _CORS_WILDCARD, None, False)
2222

2323
AuthProperties = namedtuple("_AuthProperties",
24-
["Authorizers", "DefaultAuthorizer", "InvokeRole", "AddDefaultAuthorizerToCorsPreflight"])
25-
AuthProperties.__new__.__defaults__ = (None, None, None, True)
24+
["Authorizers", "DefaultAuthorizer", "InvokeRole", "AddDefaultAuthorizerToCorsPreflight",
25+
"ApiKeyRequired"])
26+
AuthProperties.__new__.__defaults__ = (None, None, None, True, None)
2627

2728
GatewayResponseProperties = ["ResponseParameters", "ResponseTemplates", "StatusCode"]
2829

@@ -115,6 +116,8 @@ def _construct_rest_api(self):
115116
if self.definition_uri:
116117
rest_api.BodyS3Location = self._construct_body_s3_dict()
117118
elif self.definition_body:
119+
# # Post Process OpenApi Auth Settings
120+
self.definition_body = self._openapi_auth_postprocess(self.definition_body)
118121
rest_api.Body = self.definition_body
119122

120123
if self.name:
@@ -308,13 +311,17 @@ def _add_auth(self):
308311
authorizers = self._get_authorizers(auth_properties.Authorizers, auth_properties.DefaultAuthorizer)
309312

310313
if authorizers:
311-
swagger_editor.add_authorizers(authorizers)
314+
swagger_editor.add_authorizers_security_definitions(authorizers)
312315
self._set_default_authorizer(swagger_editor, authorizers, auth_properties.DefaultAuthorizer,
313316
auth_properties.AddDefaultAuthorizerToCorsPreflight)
314317

315-
# Assign the Swagger back to template
318+
if auth_properties.ApiKeyRequired:
319+
swagger_editor.add_apikey_security_definition()
320+
self._set_default_apikey_required(swagger_editor)
316321

317-
self.definition_body = self._openapi_auth_postprocess(swagger_editor.swagger)
322+
# Assign the Swagger back to template
323+
# self.definition_body = self._openapi_auth_postprocess(swagger_editor.swagger)
324+
self.definition_body = swagger_editor.swagger
318325

319326
def _openapi_auth_postprocess(self, definition_body):
320327
"""
@@ -523,6 +530,10 @@ def _set_default_authorizer(self, swagger_editor, authorizers, default_authorize
523530
swagger_editor.set_path_default_authorizer(path, default_authorizer, authorizers=authorizers,
524531
add_default_auth_to_preflight=add_default_auth_to_preflight)
525532

533+
def _set_default_apikey_required(self, swagger_editor):
534+
for path in swagger_editor.iter_on_path():
535+
swagger_editor.set_path_default_apikey_required(path)
536+
526537
def _set_endpoint_configuration(self, rest_api, value):
527538
"""
528539
Sets endpoint configuration property of AWS::ApiGateway::RestApi resource

samtranslator/model/eventsources/push.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ class CloudWatchEvent(PushEventSource):
123123
resource_type = 'CloudWatchEvent'
124124
principal = 'events.amazonaws.com'
125125
property_types = {
126-
'Pattern': PropertyType(False, is_type(dict)),
127-
'Input': PropertyType(False, is_str()),
128-
'InputPath': PropertyType(False, is_str())
126+
'Pattern': PropertyType(False, is_type(dict)),
127+
'Input': PropertyType(False, is_str()),
128+
'InputPath': PropertyType(False, is_str())
129129
}
130130

131131
def to_cloudformation(self, **kwargs):
@@ -539,9 +539,9 @@ def _add_swagger_integration(self, api, function):
539539

540540
if self.Auth:
541541
method_authorizer = self.Auth.get('Authorizer')
542+
api_auth = api.get('Auth')
542543

543544
if method_authorizer:
544-
api_auth = api.get('Auth')
545545
api_authorizers = api_auth and api_auth.get('Authorizers')
546546

547547
if method_authorizer != 'AWS_IAM':
@@ -566,6 +566,16 @@ def _add_swagger_integration(self, api, function):
566566
'is only a valid value when a DefaultAuthorizer on the API is specified.'.format(
567567
method=self.Method, path=self.Path))
568568

569+
apikey_required_setting = self.Auth.get('ApiKeyRequired')
570+
apikey_required_setting_is_false = apikey_required_setting is not None and not apikey_required_setting
571+
if apikey_required_setting_is_false and not api_auth.get('ApiKeyRequired'):
572+
raise InvalidEventException(
573+
self.relative_id,
574+
'Unable to set ApiKeyRequired [False] on API method [{method}] for path [{path}] '
575+
'because the related API does not specify any ApiKeyRequired.'.format(
576+
method=self.Method, path=self.Path))
577+
578+
if method_authorizer or apikey_required_setting is not None:
569579
editor.add_auth_to_method(api=api, path=self.Path, method_name=self.Method, auth=self.Auth)
570580

571581
if self.RequestModel:

0 commit comments

Comments
 (0)