def _construct_api_key(self, usage_plan_logical_id, create_usage_plan, rest_api_stage):
     """
     :param usage_plan_logical_id: String
     :param create_usage_plan: String
     :param rest_api_stage: model.apigateway.ApiGatewayStage stage: the stage of rest api
     :return: api_key model.apigateway.ApiGatewayApiKey resource which is created for the given usage plan
     """
     if create_usage_plan == "SHARED":
         # create an api key resource for all the apis
         api_key_logical_id = "ServerlessApiKey"
         api_key = ApiGatewayApiKey(logical_id=api_key_logical_id, depends_on=[usage_plan_logical_id])
         api_key.Enabled = True
         stage_key = dict()
         stage_key["RestApiId"] = ref(self.logical_id)
         stage_key["StageName"] = ref(rest_api_stage.logical_id)
         if stage_key not in ApiGenerator.stage_keys_shared:
             ApiGenerator.stage_keys_shared.append(stage_key)
         api_key.StageKeys = ApiGenerator.stage_keys_shared
     # for create_usage_plan = "PER_API"
     else:
         # create an api key resource for this api
         api_key_logical_id = self.logical_id + "ApiKey"
         api_key = ApiGatewayApiKey(logical_id=api_key_logical_id, depends_on=[usage_plan_logical_id])
         api_key.Enabled = True
         stage_keys = list()
         stage_key = dict()
         stage_key["RestApiId"] = ref(self.logical_id)
         stage_key["StageName"] = ref(rest_api_stage.logical_id)
         stage_keys.append(stage_key)
         api_key.StageKeys = stage_keys
     return api_key
示例#2
0
class CodeDeployApplication(Resource):
    resource_type = "AWS::CodeDeploy::Application"
    property_types = {
        "ComputePlatform": PropertyType(False, one_of(is_str(), is_type(dict)))
    }

    runtime_attrs = {"name": lambda self: ref(self.logical_id)}
    def _depend_on_lambda_permissions_using_tag(self, bucket, permission):
        """
        Since conditional DependsOn is not supported this undocumented way of
        implicitely  making dependency through tags is used.

        See https://stackoverflow.com/questions/34607476/cloudformation-apply-condition-on-dependson

        It is done by using Ref wrapped in a conditional Fn::If. Using Ref implies a
        dependency, so CloudFormation will automatically wait once it reaches that function, the same
        as if you were using a DependsOn.
        """
        properties = bucket.get('Properties', None)
        if properties is None:
            properties = {}
            bucket['Properties'] = properties
        tags = properties.get('Tags', None)
        if tags is None:
            tags = []
            properties['Tags'] = tags
        dep_tag = {
            'sam:ConditionalDependsOn:' + permission.logical_id: {
                'Fn::If': [
                    permission.resource_attributes[CONDITION],
                    ref(permission.logical_id),
                    'no dependency'
                ]
            }
        }
        properties['Tags'] = tags + get_tag_list(dep_tag)
        return bucket
class LambdaFunction(Resource):
    resource_type = 'AWS::Lambda::Function'
    property_types = {
        'Code': PropertyType(True, is_type(dict)),
        'DeadLetterConfig': PropertyType(False, is_type(dict)),
        'Description': PropertyType(False, is_str()),
        'FunctionName': PropertyType(False, is_str()),
        'Handler': PropertyType(True, is_str()),
        'MemorySize': PropertyType(False, is_type(int)),
        'Role': PropertyType(False, is_str()),
        'Runtime': PropertyType(False, is_str()),
        'Timeout': PropertyType(False, is_type(int)),
        'VpcConfig': PropertyType(False, is_type(dict)),
        'Environment': PropertyType(False, is_type(dict)),
        'Tags': PropertyType(False, list_of(is_type(dict))),
        'TracingConfig': PropertyType(False, is_type(dict)),
        'KmsKeyArn': PropertyType(False, one_of(is_type(dict), is_str())),
        'Layers': PropertyType(False, list_of(one_of(is_str(),
                                                     is_type(dict)))),
        'ReservedConcurrentExecutions': PropertyType(False, any_type())
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
class S3Bucket(Resource):
    resource_type = 'AWS::S3::Bucket'
    property_types = {
        'AccessControl': PropertyType(False, any_type()),
        'AccelerateConfiguration': PropertyType(False, any_type()),
        'AnalyticsConfigurations': PropertyType(False, any_type()),
        'BucketEncryption': PropertyType(False, any_type()),
        'BucketName': PropertyType(False, is_str()),
        'CorsConfiguration': PropertyType(False, any_type()),
        'InventoryConfigurations': PropertyType(False, any_type()),
        'LifecycleConfiguration': PropertyType(False, any_type()),
        'LoggingConfiguration': PropertyType(False, any_type()),
        'MetricsConfigurations': PropertyType(False, any_type()),
        'NotificationConfiguration': PropertyType(False, is_type(dict)),
        'PublicAccessBlockConfiguration': PropertyType(False, is_type(dict)),
        'ReplicationConfiguration': PropertyType(False, any_type()),
        'Tags': PropertyType(False, is_type(list)),
        'VersioningConfiguration': PropertyType(False, any_type()),
        'WebsiteConfiguration': PropertyType(False, any_type()),
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
示例#6
0
class CognitoUserPool(Resource):
    resource_type = "AWS::Cognito::UserPool"
    property_types = {
        "AdminCreateUserConfig": PropertyType(False, is_type(dict)),
        "AliasAttributes": PropertyType(False, list_of(is_str())),
        "AutoVerifiedAttributes": PropertyType(False, list_of(is_str())),
        "DeviceConfiguration": PropertyType(False, is_type(dict)),
        "EmailConfiguration": PropertyType(False, is_type(dict)),
        "EmailVerificationMessage": PropertyType(False, is_str()),
        "EmailVerificationSubject": PropertyType(False, is_str()),
        "LambdaConfig": PropertyType(False, is_type(dict)),
        "MfaConfiguration": PropertyType(False, is_str()),
        "Policies": PropertyType(False, is_type(dict)),
        "Schema": PropertyType(False, list_of(dict)),
        "SmsAuthenticationMessage": PropertyType(False, is_str()),
        "SmsConfiguration": PropertyType(False, list_of(dict)),
        "SmsVerificationMessage": PropertyType(False, is_str()),
        "UsernameAttributes": PropertyType(False, list_of(is_str())),
        "UserPoolAddOns": PropertyType(False, list_of(dict)),
        "UserPoolName": PropertyType(False, is_str()),
        "UserPoolTags": PropertyType(False, is_type(dict)),
        "VerificationMessageTemplate": PropertyType(False, is_type(dict)),
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn"),
        "provider_name":
        lambda self: fnGetAtt(self.logical_id, "ProviderName"),
        "provider_url": lambda self: fnGetAtt(self.logical_id, "ProviderURL"),
    }
    def _construct_stage(self, deployment, swagger):
        """Constructs and returns the ApiGateway Stage.

        :param model.apigateway.ApiGatewayDeployment deployment: the Deployment for this Stage
        :returns: the Stage to which this SAM Api corresponds
        :rtype: model.apigateway.ApiGatewayStage
        """

        # If StageName is some intrinsic function, then don't prefix the Stage's logical ID
        # This will NOT create duplicates because we allow only ONE stage per API resource
        stage_name_prefix = self.stage_name if isinstance(self.stage_name, string_types) else ""

        stage = ApiGatewayStage(self.logical_id + stage_name_prefix + 'Stage')
        stage.RestApiId = ref(self.logical_id)
        stage.update_deployment_ref(deployment.logical_id)
        stage.StageName = self.stage_name
        stage.CacheClusterEnabled = self.cache_cluster_enabled
        stage.CacheClusterSize = self.cache_cluster_size
        stage.Variables = self.variables
        stage.MethodSettings = self.method_settings

        if swagger is not None:
            deployment.make_auto_deployable(stage, swagger)

        return stage
    def _construct_stage(self):
        """Constructs and returns the ApiGatewayV2 Stage.

        :returns: the Stage to which this SAM Api corresponds
        :rtype: model.apigatewayv2.ApiGatewayV2Stage
        """

        # If there are no special configurations, don't create a stage and use the default
        if not self.stage_name and not self.stage_variables and not self.access_log_settings:
            return

        # If StageName is some intrinsic function, then don't prefix the Stage's logical ID
        # This will NOT create duplicates because we allow only ONE stage per API resource
        stage_name_prefix = self.stage_name if isinstance(self.stage_name, string_types) else ""
        if stage_name_prefix.isalnum():
            stage_logical_id = self.logical_id + stage_name_prefix + "Stage"
        elif stage_name_prefix == DefaultStageName:
            stage_logical_id = self.logical_id + "ApiGatewayDefaultStage"
        else:
            generator = logical_id_generator.LogicalIdGenerator(self.logical_id + "Stage", stage_name_prefix)
            stage_logical_id = generator.gen()
        stage = ApiGatewayV2Stage(stage_logical_id, attributes=self.passthrough_resource_attributes)
        stage.ApiId = ref(self.logical_id)
        stage.StageName = self.stage_name
        stage.StageVariables = self.stage_variables
        stage.AccessLogSettings = self.access_log_settings
        stage.AutoDeploy = True

        if self.tags is not None:
            stage.Tags = get_tag_list(self.tags)

        return stage
示例#9
0
class ApiGatewayDeployment(Resource):
    resource_type = 'AWS::ApiGateway::Deployment'
    property_types = {
        'Description': PropertyType(False, is_str()),
        'RestApiId': PropertyType(True, is_str()),
        'StageDescription': PropertyType(False, is_type(dict)),
        'StageName': PropertyType(False, is_str())
    }

    runtime_attrs = {
        "deployment_id": lambda self: ref(self.logical_id),
    }

    def make_auto_deployable(self, stage, swagger=None):
        """
        Sets up the resource such that it will triggers a re-deployment when Swagger changes

        :param swagger: Dictionary containing the Swagger definition of the API
        """
        if not swagger:
            return

        # CloudFormation does NOT redeploy the API unless it has a new deployment resource
        # that points to latest RestApi resource. Append a hash of Swagger Body location to
        # redeploy only when the API data changes. First 10 characters of hash is good enough
        # to prevent redeployment when API has not changed

        # NOTE: `str(swagger)` is for backwards compatibility. Changing it to a JSON or something will break compat
        generator = logical_id_generator.LogicalIdGenerator(
            self.logical_id, str(swagger))
        self.logical_id = generator.gen()
        hash = generator.get_hash(length=40)  # Get the full hash
        self.Description = "RestApi deployment id: {}".format(hash)
        stage.update_deployment_ref(self.logical_id)
示例#10
0
    def _depend_on_lambda_permissions_using_tag(self, bucket, permission):
        """
        Since conditional DependsOn is not supported this undocumented way of
        implicitely  making dependency through tags is used.

        See https://stackoverflow.com/questions/34607476/cloudformation-apply-condition-on-dependson

        It is done by using Ref wrapped in a conditional Fn::If. Using Ref implies a
        dependency, so CloudFormation will automatically wait once it reaches that function, the same
        as if you were using a DependsOn.
        """
        properties = bucket.get('Properties', None)
        if properties is None:
            properties = {}
            bucket['Properties'] = properties
        tags = properties.get('Tags', None)
        if tags is None:
            tags = []
            properties['Tags'] = tags
        dep_tag = {
            'sam:ConditionalDependsOn:' + permission.logical_id: {
                'Fn::If': [
                    permission.resource_attributes[CONDITION],
                    ref(permission.logical_id),
                    'no dependency'
                ]
            }
        }
        properties['Tags'] = tags + get_tag_list(dep_tag)
        return bucket
示例#11
0
class SQSQueue(Resource):
    resource_type = 'AWS::SQS::Queue'
    property_types = {}
    runtime_attrs = {
        "queue_url": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn"),
    }
示例#12
0
class S3Bucket(Resource):
    resource_type = "AWS::S3::Bucket"
    property_types = {
        "AccessControl": PropertyType(False, any_type()),
        "AccelerateConfiguration": PropertyType(False, any_type()),
        "AnalyticsConfigurations": PropertyType(False, any_type()),
        "BucketEncryption": PropertyType(False, any_type()),
        "BucketName": PropertyType(False, is_str()),
        "CorsConfiguration": PropertyType(False, any_type()),
        "InventoryConfigurations": PropertyType(False, any_type()),
        "LifecycleConfiguration": PropertyType(False, any_type()),
        "LoggingConfiguration": PropertyType(False, any_type()),
        "MetricsConfigurations": PropertyType(False, any_type()),
        "NotificationConfiguration": PropertyType(False, is_type(dict)),
        "PublicAccessBlockConfiguration": PropertyType(False, is_type(dict)),
        "ReplicationConfiguration": PropertyType(False, any_type()),
        "Tags": PropertyType(False, is_type(list)),
        "VersioningConfiguration": PropertyType(False, any_type()),
        "WebsiteConfiguration": PropertyType(False, any_type()),
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
示例#13
0
class DynamoDBTable(Resource):
    resource_type = 'AWS::DynamoDB::Table'
    property_types = {
        'AttributeDefinitions':
        PropertyType(True, list_of(is_type(dict))),
        'GlobalSecondaryIndexes':
        PropertyType(False, list_of(is_type(dict))),
        'KeySchema':
        PropertyType(False, list_of(is_type(dict))),
        'LocalSecondaryIndexes':
        PropertyType(False, list_of(is_type(dict))),
        'ProvisionedThroughput':
        PropertyType(False,
                     dict_of(is_str(), one_of(is_type(int), is_type(dict)))),
        'StreamSpecification':
        PropertyType(False, is_type(dict)),
        'TableName':
        PropertyType(False, one_of(is_str(), is_type(dict))),
        'Tags':
        PropertyType(False, list_of(is_type(dict))),
        'SSESpecification':
        PropertyType(False, is_type(dict)),
        'BillingMode':
        PropertyType(False, is_str())
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn"),
        "stream_arn": lambda self: fnGetAtt(self.logical_id, "StreamArn")
    }
示例#14
0
    def _construct_stage(self, deployment, swagger):
        """Constructs and returns the ApiGateway Stage.

        :param model.apigateway.ApiGatewayDeployment deployment: the Deployment for this Stage
        :returns: the Stage to which this SAM Api corresponds
        :rtype: model.apigateway.ApiGatewayStage
        """

        # If StageName is some intrinsic function, then don't prefix the Stage's logical ID
        # This will NOT create duplicates because we allow only ONE stage per API resource
        stage_name_prefix = self.stage_name if isinstance(
            self.stage_name, string_types) else ""

        stage = ApiGatewayStage(self.logical_id + stage_name_prefix + 'Stage')
        stage.RestApiId = ref(self.logical_id)
        stage.update_deployment_ref(deployment.logical_id)
        stage.StageName = self.stage_name
        stage.CacheClusterEnabled = self.cache_cluster_enabled
        stage.CacheClusterSize = self.cache_cluster_size
        stage.Variables = self.variables
        stage.MethodSettings = self.method_settings
        stage.AccessLogSetting = self.access_log_setting

        if swagger is not None:
            deployment.make_auto_deployable(stage, swagger)

        return stage
示例#15
0
    def to_cloudformation(self, **kwargs):
        function = kwargs.get('function')

        if not function:
            raise TypeError("Missing required keyword argument: function")

        resources = []

        resource = 'rule/${RuleName}'

        partition = ArnGenerator.get_partition_name()
        source_arn = fnSub(
            ArnGenerator.generate_arn(partition=partition,
                                      service='iot',
                                      resource=resource),
            {'RuleName': ref(self.logical_id)})
        source_account = fnSub('${AWS::AccountId}')

        resources.append(
            self._construct_permission(function,
                                       source_arn=source_arn,
                                       source_account=source_account))
        resources.append(self._construct_iot_rule(function))

        return resources
class CognitoUserPool(Resource):
    resource_type = 'AWS::Cognito::UserPool'
    property_types = {
        'AdminCreateUserConfig': PropertyType(False, is_type(dict)),
        'AliasAttributes': PropertyType(False, list_of(is_str())),
        'AutoVerifiedAttributes': PropertyType(False, list_of(is_str())),
        'DeviceConfiguration': PropertyType(False, is_type(dict)),
        'EmailConfiguration': PropertyType(False, is_type(dict)),
        'EmailVerificationMessage': PropertyType(False, is_str()),
        'EmailVerificationSubject': PropertyType(False, is_str()),
        'LambdaConfig': PropertyType(False, is_type(dict)),
        'MfaConfiguration': PropertyType(False, is_str()),
        'Policies': PropertyType(False, is_type(dict)),
        'Schema': PropertyType(False, list_of(dict)),
        'SmsAuthenticationMessage': PropertyType(False, is_str()),
        'SmsConfiguration': PropertyType(False, list_of(dict)),
        'SmsVerificationMessage': PropertyType(False, is_str()),
        'UsernameAttributes': PropertyType(False, list_of(is_str())),
        'UserPoolAddOns': PropertyType(False, list_of(dict)),
        'UserPoolName': PropertyType(False, is_str()),
        'UserPoolTags': PropertyType(False, is_str()),
        'VerificationMessageTemplate': PropertyType(False, is_type(dict))
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn"),
        "provider_name":
        lambda self: fnGetAtt(self.logical_id, "ProviderName"),
        "provider_url": lambda self: fnGetAtt(self.logical_id, "ProviderURL")
    }
    def gen_skeleton():
        """
        Method to make an empty swagger file, with just some basic structure. Just enough to pass validator.

        :return dict: Dictionary of a skeleton swagger document
        """
        return {"openapi": "3.0.1", "info": {"version": "1.0", "title": ref("AWS::StackName")}, "paths": {}}
示例#18
0
class LambdaFunction(Resource):
    resource_type = "AWS::Lambda::Function"
    property_types = {
        "Code": PropertyType(True, is_type(dict)),
        "PackageType": PropertyType(False, is_str()),
        "DeadLetterConfig": PropertyType(False, is_type(dict)),
        "Description": PropertyType(False, is_str()),
        "FunctionName": PropertyType(False, is_str()),
        "Handler": PropertyType(False, is_str()),
        "MemorySize": PropertyType(False, is_type(int)),
        "Role": PropertyType(False, is_str()),
        "Runtime": PropertyType(False, is_str()),
        "Timeout": PropertyType(False, is_type(int)),
        "VpcConfig": PropertyType(False, is_type(dict)),
        "Environment": PropertyType(False, is_type(dict)),
        "Tags": PropertyType(False, list_of(is_type(dict))),
        "TracingConfig": PropertyType(False, is_type(dict)),
        "KmsKeyArn": PropertyType(False, one_of(is_type(dict), is_str())),
        "Layers": PropertyType(False, list_of(one_of(is_str(),
                                                     is_type(dict)))),
        "ReservedConcurrentExecutions": PropertyType(False, any_type()),
        "FileSystemConfigs": PropertyType(False, list_of(is_type(dict))),
        "CodeSigningConfigArn": PropertyType(False, is_str()),
        "ImageConfig": PropertyType(False, is_type(dict)),
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
示例#19
0
class IotTopicRule(Resource):
    resource_type = 'AWS::IoT::TopicRule'
    property_types = {'TopicRulePayload': PropertyType(False, is_type(dict))}

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
示例#20
0
class ApiGatewayDeployment(Resource):
    _X_HASH_DELIMITER = "||"

    resource_type = "AWS::ApiGateway::Deployment"
    property_types = {
        "Description": PropertyType(False, is_str()),
        "RestApiId": PropertyType(True, is_str()),
        "StageDescription": PropertyType(False, is_type(dict)),
        "StageName": PropertyType(False, is_str()),
    }

    runtime_attrs = {"deployment_id": lambda self: ref(self.logical_id)}

    def make_auto_deployable(self,
                             stage,
                             openapi_version=None,
                             swagger=None,
                             domain=None,
                             redeploy_restapi_parameters=None):
        """
        Sets up the resource such that it will trigger a re-deployment when Swagger changes
        or the openapi version changes or a domain resource changes.

        :param swagger: Dictionary containing the Swagger definition of the API
        :param openapi_version: string containing value of OpenApiVersion flag in the template
        :param domain: Dictionary containing the custom domain configuration for the API
        :param redeploy_restapi_parameters: Dictionary containing the properties for which rest api will be redeployed
        """
        if not swagger:
            return

        # CloudFormation does NOT redeploy the API unless it has a new deployment resource
        # that points to latest RestApi resource. Append a hash of Swagger Body location to
        # redeploy only when the API data changes. First 10 characters of hash is good enough
        # to prevent redeployment when API has not changed

        # NOTE: `str(swagger)` is for backwards compatibility. Changing it to a JSON or something will break compat
        hash_input = [str(swagger)]
        if openapi_version:
            hash_input.append(str(openapi_version))
        if domain:
            hash_input.append(json.dumps(domain))
        if redeploy_restapi_parameters:
            function_names = redeploy_restapi_parameters.get("function_names")
        else:
            function_names = None
        # The deployment logical id is <api logicalId> + "Deployment"
        # The keyword "Deployment" is removed and all the function names associated with api is obtained
        if function_names and function_names.get(self.logical_id[:-10], None):
            hash_input.append(function_names.get(self.logical_id[:-10], ""))
        data = self._X_HASH_DELIMITER.join(hash_input)
        generator = logical_id_generator.LogicalIdGenerator(
            self.logical_id, data)
        self.logical_id = generator.gen()
        digest = generator.get_hash(length=40)  # Get the full hash
        self.Description = "RestApi deployment id: {}".format(digest)
        stage.update_deployment_ref(self.logical_id)
class LambdaAlias(Resource):
    resource_type = 'AWS::Lambda::Alias'
    property_types = {
        'Description': PropertyType(False, is_str()),
        'Name': PropertyType(False, is_str()),
        'FunctionName': PropertyType(True, one_of(is_str(), is_type(dict))),
        'FunctionVersion': PropertyType(True, one_of(is_str(), is_type(dict)))
    }

    runtime_attrs = {"arn": lambda self: ref(self.logical_id)}
示例#22
0
 def to_dict(self):
     """
     :return: a dict that can be used as part of a cloudformation template
     """
     dict_with_nones = self._asdict()
     codedeploy_lambda_alias_update_dict = dict(
         (k, v) for k, v in dict_with_nones.items()
         if v != ref(None) and v is not None)
     return {
         "CodeDeployLambdaAliasUpdate": codedeploy_lambda_alias_update_dict
     }
示例#23
0
class ApiGatewayUsagePlan(Resource):
    resource_type = "AWS::ApiGateway::UsagePlan"
    property_types = {
        "ApiStages": PropertyType(False, is_type(list)),
        "Description": PropertyType(False, is_str()),
        "Quota": PropertyType(False, is_type(dict)),
        "Tags": PropertyType(False, list_of(dict)),
        "Throttle": PropertyType(False, is_type(dict)),
        "UsagePlanName": PropertyType(False, is_str()),
    }
    runtime_attrs = {"usage_plan_id": lambda self: ref(self.logical_id)}
示例#24
0
class LambdaEventSourceMapping(Resource):
    resource_type = 'AWS::Lambda::EventSourceMapping'
    property_types = {
        'BatchSize': PropertyType(False, is_type(int)),
        'Enabled': PropertyType(False, is_type(bool)),
        'EventSourceArn': PropertyType(True, is_str()),
        'FunctionName': PropertyType(True, is_str()),
        'StartingPosition': PropertyType(True, is_str())
    }

    runtime_attrs = {"name": lambda self: ref(self.logical_id)}
示例#25
0
class LambdaAlias(Resource):
    resource_type = "AWS::Lambda::Alias"
    property_types = {
        "Description": PropertyType(False, is_str()),
        "Name": PropertyType(False, is_str()),
        "FunctionName": PropertyType(True, one_of(is_str(), is_type(dict))),
        "FunctionVersion": PropertyType(True, one_of(is_str(), is_type(dict))),
        "ProvisionedConcurrencyConfig": PropertyType(False, is_type(dict)),
    }

    runtime_attrs = {"arn": lambda self: ref(self.logical_id)}
示例#26
0
class IAMRole(Resource):
    resource_type = "AWS::IAM::Role"
    property_types = {
        "AssumeRolePolicyDocument": PropertyType(True, is_type(dict)),
        "ManagedPolicyArns": PropertyType(False, is_type(list)),
        "Path": PropertyType(False, is_str()),
        "Policies": PropertyType(False, is_type(list)),
        "PermissionsBoundary": PropertyType(False, is_str()),
        "Tags": PropertyType(False, list_of(is_type(dict))),
    }

    runtime_attrs = {"name": lambda self: ref(self.logical_id), "arn": lambda self: fnGetAtt(self.logical_id, "Arn")}
class LambdaVersion(Resource):
    resource_type = 'AWS::Lambda::Version'
    property_types = {
        'CodeSha256': PropertyType(False, is_str()),
        'Description': PropertyType(False, is_str()),
        'FunctionName': PropertyType(True, one_of(is_str(), is_type(dict)))
    }

    runtime_attrs = {
        "arn": lambda self: ref(self.logical_id),
        "version": lambda self: fnGetAtt(self.logical_id, "Version")
    }
示例#28
0
class SubscriptionFilter(Resource):
    resource_type = "AWS::Logs::SubscriptionFilter"
    property_types = {
        "LogGroupName": PropertyType(True, is_str()),
        "FilterPattern": PropertyType(True, is_str()),
        "DestinationArn": PropertyType(True, is_str()),
    }

    runtime_attrs = {
        "name": lambda self: ref(self.logical_id),
        "arn": lambda self: fnGetAtt(self.logical_id, "Arn")
    }
示例#29
0
class NestedStack(Resource):
    resource_type = 'AWS::CloudFormation::Stack'
    # TODO: support passthrough parameters for stacks (Conditions, etc)
    property_types = {
        'TemplateURL': PropertyType(True, is_str()),
        'Parameters': PropertyType(False, is_type(dict)),
        'NotificationArns': PropertyType(False, list_of(is_str())),
        'Tags': PropertyType(False, list_of(is_type(dict))),
        'TimeoutInMinutes': PropertyType(False, is_type(int))
    }

    runtime_attrs = {"stack_id": lambda self: ref(self.logical_id)}
    def _construct_usage_plan_key(self, usage_plan_logical_id, create_usage_plan, api_key):
        """
        :param usage_plan_logical_id: String
        :param create_usage_plan: String
        :param api_key: model.apigateway.ApiGatewayApiKey resource
        :return: model.apigateway.ApiGatewayUsagePlanKey resource that contains the mapping between usage plan and api key
        """
        if create_usage_plan == "SHARED":
            # create a mapping between api key and the usage plan
            usage_plan_key_logical_id = "ServerlessUsagePlanKey"
        # for create_usage_plan = "PER_API"
        else:
            # create a mapping between api key and the usage plan
            usage_plan_key_logical_id = self.logical_id + "UsagePlanKey"

        usage_plan_key = ApiGatewayUsagePlanKey(logical_id=usage_plan_key_logical_id, depends_on=[api_key.logical_id])
        usage_plan_key.KeyId = ref(api_key.logical_id)
        usage_plan_key.KeyType = "API_KEY"
        usage_plan_key.UsagePlanId = ref(usage_plan_logical_id)

        return usage_plan_key
示例#31
0
class ApiGatewayV2HttpApi(Resource):
    resource_type = "AWS::ApiGatewayV2::Api"
    property_types = {
        "Body": PropertyType(False, is_type(dict)),
        "BodyS3Location": PropertyType(False, is_type(dict)),
        "Description": PropertyType(False, is_str()),
        "FailOnWarnings": PropertyType(False, is_type(bool)),
        "BasePath": PropertyType(False, is_str()),
        "CorsConfiguration": PropertyType(False, is_type(dict)),
    }

    runtime_attrs = {"http_api_id": lambda self: ref(self.logical_id)}
示例#32
0
    def _construct_basepath_mappings(self, basepaths, http_api):
        basepath_resource_list = []

        if basepaths is None:
            basepath_mapping = ApiGatewayV2ApiMapping(
                self.logical_id + "ApiMapping", attributes=self.passthrough_resource_attributes
            )
            basepath_mapping.DomainName = ref(self.domain.get("ApiDomainName"))
            basepath_mapping.ApiId = ref(http_api.logical_id)
            basepath_mapping.Stage = ref(http_api.logical_id + ".Stage")
            basepath_resource_list.extend([basepath_mapping])
        else:
            for path in basepaths:
                # search for invalid characters in the path and raise error if there are
                invalid_regex = r"[^0-9a-zA-Z\/\-\_]+"
                if re.search(invalid_regex, path) is not None:
                    raise InvalidResourceException(self.logical_id, "Invalid Basepath name provided.")
                # ignore leading and trailing `/` in the path name
                m = re.search(r"[a-zA-Z0-9]+[\-\_]?[a-zA-Z0-9]+", path)
                path = m.string[m.start(0) : m.end(0)]
                if path is None:
                    raise InvalidResourceException(self.logical_id, "Invalid Basepath name provided.")
                logical_id = "{}{}{}".format(self.logical_id, re.sub(r"[\-\_]+", "", path), "ApiMapping")
                basepath_mapping = ApiGatewayV2ApiMapping(logical_id, attributes=self.passthrough_resource_attributes)
                basepath_mapping.DomainName = ref(self.domain.get("ApiDomainName"))
                basepath_mapping.ApiId = ref(http_api.logical_id)
                basepath_mapping.Stage = ref(http_api.logical_id + ".Stage")
                basepath_mapping.ApiMappingKey = path
                basepath_resource_list.extend([basepath_mapping])
        return basepath_resource_list
示例#33
0
    def gen_skeleton():
        """
        Method to make an empty swagger file, with just some basic structure. Just enough to pass validator.

        :return dict: Dictionary of a skeleton swagger document
        """
        return {
            'swagger': '2.0',
            'info': {
                'version': '1.0',
                'title': ref('AWS::StackName')
            },
            'paths': {
            }
        }
    def to_cloudformation(self, **kwargs):
        """Returns the Lambda Permission resource allowing S3 to invoke the function this event source triggers.

        :param dict kwargs: S3 bucket resource
        :returns: a list of vanilla CloudFormation Resources, to which this S3 event expands
        :rtype: list
        """
        function = kwargs.get('function')

        if not function:
            raise TypeError("Missing required keyword argument: function")

        if 'bucket' not in kwargs or kwargs['bucket'] is None:
            raise TypeError("Missing required keyword argument: bucket")

        if 'bucket_id' not in kwargs or kwargs['bucket_id'] is None:
            raise TypeError("Missing required keyword argument: bucket_id")

        bucket = kwargs['bucket']
        bucket_id = kwargs['bucket_id']

        resources = []

        source_account = ref('AWS::AccountId')
        permission = self._construct_permission(function, source_account=source_account)
        if CONDITION in permission.resource_attributes:
            self._depend_on_lambda_permissions_using_tag(bucket, permission)
        else:
            self._depend_on_lambda_permissions(bucket, permission)
        resources.append(permission)

        # NOTE: `bucket` here is a dictionary representing the S3 Bucket resource in your SAM template. If there are
        # multiple S3 Events attached to the same bucket, we will update the Bucket resource with notification
        # configuration for each event. This is the reason why we continue to use existing bucket dict and append onto
        # it.
        #
        # NOTE: There is some fragile logic here where we will append multiple resources to output
        #   SAM template but de-dupe them when merging into output CFN template. This is scary because the order of
        #   merging is literally "last one wins", which works fine because we linearly loop through the template once.
        #   The de-dupe happens inside `samtranslator.translator.Translator.translate` method when merging results of
        #   to_cloudformation() to output template.
        self._inject_notification_configuration(function, bucket)
        resources.append(S3Bucket.from_dict(bucket_id, bucket))

        return resources
示例#35
0
    def to_cloudformation(self, **kwargs):
        function = kwargs.get('function')

        if not function:
            raise TypeError("Missing required keyword argument: function")

        resources = []

        resource = 'rule/${RuleName}'

        partition = ArnGenerator.get_partition_name()
        source_arn = fnSub(ArnGenerator.generate_arn(partition=partition, service='iot', resource=resource),
                           {'RuleName': ref(self.logical_id)})
        source_account = fnSub('${AWS::AccountId}')

        resources.append(self._construct_permission(function, source_arn=source_arn,
                                                    source_account=source_account))
        resources.append(self._construct_iot_rule(function))

        return resources
 def update_deployment_ref(self, deployment_logical_id):
     self.DeploymentId = ref(deployment_logical_id)