Ejemplo n.º 1
0
 def _generate_restapi(self, resource, template):
     # type: (models.RestAPI, Dict[str, Any]) -> None
     resources = template['Resources']
     resources['RestAPI'] = {
         'Type': 'AWS::Serverless::Api',
         'Properties': {
             'StageName': resource.api_gateway_stage,
             'DefinitionBody': resource.swagger_doc,
         }
     }
     handler_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     api_handler = template['Resources'].pop(handler_cfn_name)
     template['Resources']['APIHandler'] = api_handler
     resources['APIHandlerInvokePermission'] = {
         'Type': 'AWS::Lambda::Permission',
         'Properties': {
             'FunctionName': {
                 'Ref': 'APIHandler'
             },
             'Action': 'lambda:InvokeFunction',
             'Principal': 'apigateway.amazonaws.com',
             'SourceArn': {
                 'Fn::Sub': [
                     ('arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}'
                      ':${RestAPIId}/*'),
                     {
                         'RestAPIId': {
                             'Ref': 'RestAPI'
                         }
                     },
                 ]
             },
         }
     }
     for auth in resource.authorizers:
         auth_cfn_name = to_cfn_resource_name(auth.resource_name)
         resources[auth_cfn_name + 'InvokePermission'] = {
             'Type': 'AWS::Lambda::Permission',
             'Properties': {
                 'FunctionName': {
                     'Fn::GetAtt': [auth_cfn_name, 'Arn']
                 },
                 'Action': 'lambda:InvokeFunction',
                 'Principal': 'apigateway.amazonaws.com',
                 'SourceArn': {
                     'Fn::Sub': [
                         ('arn:aws:execute-api:${AWS::Region}:'
                          '${AWS::AccountId}:${RestAPIId}/*'),
                         {
                             'RestAPIId': {
                                 'Ref': 'RestAPI'
                             }
                         },
                     ]
                 },
             }
         }
     self._inject_restapi_outputs(template)
Ejemplo n.º 2
0
    def _generate_snslambdasubscription(self, resource, template):
        # type: (models.SNSLambdaSubscription, Dict[str, Any]) -> None
        function_cfn_name = to_cfn_resource_name(
            resource.lambda_function.resource_name)
        function_cfn = template['Resources'][function_cfn_name]
        sns_cfn_name = self._register_cfn_resource_name(
            resource.resource_name)

        if resource.topic.startswith('arn:aws:sns:'):
            topic_arn = resource.topic  # type: Union[str, Dict[str, str]]
        else:
            topic_arn = {
                'Fn::Sub': (
                    'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:%s' %
                    resource.topic
                )
            }
        function_cfn['Properties']['Events'] = {
            sns_cfn_name: {
                'Type': 'SNS',
                'Properties': {
                    'Topic': topic_arn,
                }
            }
        }
Ejemplo n.º 3
0
 def _add_websocket_domain_name(self, resource, template):
     # type: (models.WebsocketAPI, Dict[str, Any]) -> None
     if resource.domain_name is None:
         return
     domain_name = resource.domain_name
     cfn_name = to_cfn_resource_name(domain_name.resource_name)
     properties = {
         'DomainName': domain_name.domain_name,
         'DomainNameConfigurations': [
             {'CertificateArn': domain_name.certificate_arn,
              'EndpointType': 'REGIONAL'},
         ]
     }
     if domain_name.tags:
         properties['Tags'] = domain_name.tags
     template['Resources'][cfn_name] = {
         'Type': 'AWS::ApiGatewayV2::DomainName',
         'Properties': properties,
     }
     template['Resources'][cfn_name + 'Mapping'] = {
         'Type': 'AWS::ApiGatewayV2::ApiMapping',
         'Properties': {
             'DomainName': {'Ref': cfn_name},
             'ApiId': {'Ref': 'WebsocketAPI'},
             'ApiMappingKey': domain_name.api_mapping.mount_path,
             'Stage': {'Ref': 'WebsocketAPIStage'},
         }
     }
Ejemplo n.º 4
0
    def _generate_snslambdasubscription(self, resource, template):
        # type: (models.SNSLambdaSubscription, Dict[str, Any]) -> None
        function_cfn_name = to_cfn_resource_name(
            resource.lambda_function.resource_name)
        function_cfn = template['Resources'][function_cfn_name]
        sns_cfn_name = self._register_cfn_resource_name(
            resource.resource_name)

        if resource.topic.startswith('arn:aws:sns:'):
            topic_arn = resource.topic  # type: Union[str, Dict[str, str]]
        else:
            topic_arn = {
                'Fn::Sub': (
                    'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:%s' %
                    resource.topic
                )
            }
        function_cfn['Properties']['Events'] = {
            sns_cfn_name: {
                'Type': 'SNS',
                'Properties': {
                    'Topic': topic_arn,
                }
            }
        }
Ejemplo n.º 5
0
 def _generate_restapi(self, resource, template):
     # type: (models.RestAPI, Dict[str, Any]) -> None
     resources = template['Resources']
     resources['RestAPI'] = {
         'Type': 'AWS::Serverless::Api',
         'Properties': {
             'StageName': resource.api_gateway_stage,
             'DefinitionBody': resource.swagger_doc,
         }
     }
     handler_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     api_handler = template['Resources'].pop(handler_cfn_name)
     template['Resources']['APIHandler'] = api_handler
     resources['APIHandlerInvokePermission'] = {
         'Type': 'AWS::Lambda::Permission',
         'Properties': {
             'FunctionName': {'Ref': 'APIHandler'},
             'Action': 'lambda:InvokeFunction',
             'Principal': 'apigateway.amazonaws.com',
             'SourceArn': {
                 'Fn::Sub': [
                     ('arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}'
                      ':${RestAPIId}/*'),
                     {'RestAPIId': {'Ref': 'RestAPI'}},
                 ]
             },
         }
     }
     for auth in resource.authorizers:
         auth_cfn_name = to_cfn_resource_name(auth.resource_name)
         resources[auth_cfn_name + 'InvokePermission'] = {
             'Type': 'AWS::Lambda::Permission',
             'Properties': {
                 'FunctionName': {'Fn::GetAtt': [auth_cfn_name, 'Arn']},
                 'Action': 'lambda:InvokeFunction',
                 'Principal': 'apigateway.amazonaws.com',
                 'SourceArn': {
                     'Fn::Sub': [
                         ('arn:aws:execute-api:${AWS::Region}:'
                          '${AWS::AccountId}:${RestAPIId}/*'),
                         {'RestAPIId': {'Ref': 'RestAPI'}},
                     ]
                 },
             }
         }
     self._inject_restapi_outputs(template)
Ejemplo n.º 6
0
 def _auth_uri(self, authorizer):
     # type: (ChaliceAuthorizer) -> Any
     return {
         'Fn::Sub':
         ('arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31'
          '/functions/${%s.Arn}/invocations' %
          to_cfn_resource_name(authorizer.name))
     }
Ejemplo n.º 7
0
def test_to_cfn_resource_name_properties(name):
    try:
        result = utils.to_cfn_resource_name(name)
    except ValueError:
        # This is acceptable, the function raises ValueError
        # on bad input.
        pass
    else:
        assert re.search('[^A-Za-z0-9]', result) is None
Ejemplo n.º 8
0
 def _auth_uri(self, authorizer):
     # type: (ChaliceAuthorizer) -> Any
     return {
         'Fn::Sub': (
             'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31'
             '/functions/${%s.Arn}/invocations' % to_cfn_resource_name(
                 authorizer.name)
         )
     }
Ejemplo n.º 9
0
def test_to_cfn_resource_name_properties(name):
    try:
        result = utils.to_cfn_resource_name(name)
    except ValueError:
        # This is acceptable, the function raises ValueError
        # on bad input.
        pass
    else:
        assert re.search('[^A-Za-z0-9]', result) is None
Ejemplo n.º 10
0
 def _register_cfn_resource_name(self, name):
     # type: (str) -> str
     cfn_name = to_cfn_resource_name(name)
     if cfn_name in self._seen_names:
         raise DuplicateResourceNameError(
             'A duplicate resource name was generated for '
             'the SAM template: %s' % cfn_name, )
     self._seen_names.add(cfn_name)
     return cfn_name
Ejemplo n.º 11
0
 def _register_cfn_resource_name(self, name):
     # type: (str) -> str
     cfn_name = to_cfn_resource_name(name)
     if cfn_name in self._seen_names:
         raise DuplicateResourceNameError(
             'A duplicate resource name was generated for '
             'the SAM template: %s' % cfn_name,
         )
     self._seen_names.add(cfn_name)
     return cfn_name
Ejemplo n.º 12
0
 def _add_auth_handlers(self, resources, config, code_uri):
     # type: (Dict[str, Any], Config, str) -> None
     for auth_config in config.chalice_app.builtin_auth_handlers:
         auth_resource_name = to_cfn_resource_name(auth_config.name)
         new_config = config.scope(chalice_stage=config.chalice_stage,
                                   function_name=auth_config.name)
         resources[auth_resource_name] = self._generate_serverless_function(
             new_config, code_uri, auth_config.handler_string, 'authorizer')
         resources[auth_resource_name + 'InvokePermission'] = \
             self._generate_lambda_permission(auth_resource_name)
Ejemplo n.º 13
0
 def _generate_deployment_alarms(self, resource, template):
     # type: (models.LambdaFunction, Dict[str, Any]) -> List[str]
     deploy_preference = resource.deployment_preference
     alarm_resources = []
     if isinstance(deploy_preference, models.SimpleDeploymentPreference):
         resources = template['Resources']
         function_name = to_cfn_resource_name(resource.resource_name)
         for alarm in deploy_preference.alarms:
             target = 'LatestVersion' if alarm.with_version else 'Alias'
             cfn_resource_name = to_cfn_resource_name(
                 function_name + target + 'ErrorOccurredAlarm')
             dimensions = [{
                 'Name': 'Resource',
                 'Value': {
                     'Fn::Sub': "${APIHandler}:" +
                                deploy_preference.auto_publish_alias
                 }
             }, {
                 'Name': 'FunctionName',
                 'Value': {'Ref': 'APIHandler'}
             }]
             if alarm.with_version:
                 dimensions.append({
                     'Name': 'ExecutedVersion',
                     'Value': {'Fn::GetAtt': ['APIHandler.Version', 'Version']}
                 })
             resources[cfn_resource_name] = {
                 'Type': 'AWS::CloudWatch::Alarm',
                 'Properties': {
                     'AlarmDescription': 'Lambda Function Error > 0',
                     'ComparisonOperator': 'GreaterThanThreshold',
                     'Dimensions': dimensions,
                     'EvaluationPeriods': 2,
                     'MetricName': 'Errors',
                     'Namespace': 'AWS/Lambda',
                     'Period': 60,
                     'Statistic': 'Sum',
                     'Threshold': 0
                 }
             }
             alarm_resources.append(cfn_resource_name)
     return alarm_resources
Ejemplo n.º 14
0
 def _add_iam_role(self, resource, cfn_resource):
     # type: (models.LambdaFunction, Dict[str, Any]) -> None
     role = resource.role
     if isinstance(role, models.ManagedIAMRole):
         cfn_resource['Properties']['Role'] = {
             'Fn::GetAtt':
             [to_cfn_resource_name(role.resource_name), 'Arn'],
         }
     else:
         # resource is a PreCreatedIAMRole
         cfn_resource['Properties']['Role'] = role.role_arn
Ejemplo n.º 15
0
 def _add_iam_role(self, resource, cfn_resource):
     # type: (models.LambdaFunction, Dict[str, Any]) -> None
     role = resource.role
     if isinstance(role, models.ManagedIAMRole):
         cfn_resource['Properties']['Role'] = {
             'Fn::GetAtt': [
                 to_cfn_resource_name(role.resource_name), 'Arn'
             ],
         }
     else:
         # resource is a PreCreatedIAMRole
         cfn_resource['Properties']['Role'] = role.role_arn
Ejemplo n.º 16
0
 def _generate_scheduledevent(self, resource, template):
     # type: (models.ScheduledEvent, Dict[str, Any]) -> None
     function_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     function_cfn = template['Resources'][function_cfn_name]
     event_cfn_name = self._register_cfn_resource_name(
         resource.resource_name)
     function_cfn['Properties']['Events'] = {
         event_cfn_name: {
             'Type': 'Schedule',
             'Properties': {
                 'Schedule': resource.schedule_expression,
             }
         }
     }
Ejemplo n.º 17
0
 def _generate_scheduledevent(self, resource, template):
     # type: (models.ScheduledEvent, Dict[str, Any]) -> None
     function_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     function_cfn = template['Resources'][function_cfn_name]
     event_cfn_name = self._register_cfn_resource_name(
         resource.resource_name)
     function_cfn['Properties']['Events'] = {
         event_cfn_name: {
             'Type': 'Schedule',
             'Properties': {
                 'Schedule': resource.schedule_expression,
             }
         }
     }
Ejemplo n.º 18
0
 def _generate_cloudwatchevent(self, resource, template):
     # type: (models.CloudWatchEvent, Dict[str, Any]) -> None
     function_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     function_cfn = template['Resources'][function_cfn_name]
     event_cfn_name = self._register_cfn_resource_name(
         resource.resource_name)
     function_cfn['Properties']['Events'] = {
         event_cfn_name: {
             'Type': 'CloudWatchEvent',
             'Properties': {
                 # For api calls we need serialized string form, for
                 # SAM Templates we need datastructures.
                 'Pattern': json.loads(resource.event_pattern)
             }
         }
     }
Ejemplo n.º 19
0
 def _generate_api_function_events(self, app):
     # type: (Chalice) -> Dict[str, Any]
     events = {}
     for methods in app.routes.values():
         for http_method, view in methods.items():
             key_name = to_cfn_resource_name(view.view_name +
                                             http_method.lower())
             events[key_name] = {
                 'Type': 'Api',
                 'Properties': {
                     'Path': view.uri_pattern,
                     'RestApiId': {
                         'Ref': 'RestAPI'
                     },
                     'Method': http_method.lower(),
                 }
             }
     return events
Ejemplo n.º 20
0
 def _generate_sqseventsource(self, resource, template):
     # type: (models.SQSEventSource, Dict[str, Any]) -> None
     function_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     function_cfn = template['Resources'][function_cfn_name]
     sns_cfn_name = self._register_cfn_resource_name(resource.resource_name)
     function_cfn['Properties']['Events'] = {
         sns_cfn_name: {
             'Type': 'SQS',
             'Properties': {
                 'Queue': {
                     'Fn::Sub':
                     ('arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:%s' %
                      resource.queue)
                 },
                 'BatchSize': resource.batch_size,
             }
         }
     }
Ejemplo n.º 21
0
 def _generate_sqseventsource(self, resource, template):
     # type: (models.SQSEventSource, Dict[str, Any]) -> None
     function_cfn_name = to_cfn_resource_name(
         resource.lambda_function.resource_name)
     function_cfn = template['Resources'][function_cfn_name]
     sns_cfn_name = self._register_cfn_resource_name(
         resource.resource_name)
     function_cfn['Properties']['Events'] = {
         sns_cfn_name: {
             'Type': 'SQS',
             'Properties': {
                 'Queue': {
                     'Fn::Sub': (
                         'arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:%s' %
                         resource.queue
                     )
                 },
                 'BatchSize': resource.batch_size,
             }
         }
     }
Ejemplo n.º 22
0
 def _add_domain_name(self, resource, template):
     # type: (models.RestAPI, Dict[str, Any]) -> None
     if resource.domain_name is None:
         return
     domain_name = resource.domain_name
     endpoint_type = resource.endpoint_type
     cfn_name = to_cfn_resource_name(domain_name.resource_name)
     properties = {
         'DomainName': domain_name.domain_name,
         'EndpointConfiguration': {
             'Types': [endpoint_type],
         }
     }  # type: Dict[str, Any]
     if endpoint_type == 'EDGE':
         properties['CertificateArn'] = domain_name.certificate_arn
     else:
         properties['RegionalCertificateArn'] = domain_name.certificate_arn
     if domain_name.tls_version is not None:
         properties['SecurityPolicy'] = domain_name.tls_version.value
     if domain_name.tags:
         properties['Tags'] = [
             {'Key': key, 'Value': value}
             for key, value in sorted(domain_name.tags.items())
         ]
     template['Resources'][cfn_name] = {
         'Type': 'AWS::ApiGateway::DomainName',
         'Properties': properties
     }
     template['Resources'][cfn_name + 'Mapping'] = {
         'Type': 'AWS::ApiGateway::BasePathMapping',
         'Properties': {
             'DomainName': {'Ref': 'ApiGatewayCustomDomain'},
             'RestApiId': {'Ref': 'RestAPI'},
             'BasePath': domain_name.api_mapping.mount_path,
             'Stage': {'Ref': 'RestAPI.Stage'},
         }
     }
Ejemplo n.º 23
0
def test_to_cfn_resource_name(name, cfn_name):
    assert utils.to_cfn_resource_name(name) == cfn_name
Ejemplo n.º 24
0
def test_to_cfn_resource_name(name, cfn_name):
    assert utils.to_cfn_resource_name(name) == cfn_name