Example #1
0
    def create_integration(self, method_config, lambda_arn):
        """
        Creates an integration object using a single provided ApiGatewayMethodConfig object.
        :param method_config: a single ApiGatewayMethodConfig object
        :param lambda_arn: the ARN of a lambda function to point this integration at.
        :return: a troposphere integration object
        """

        integration = Integration(
            '{0}Integration'.format(method_config.method_name),
            Type='AWS',
            IntegrationHttpMethod=method_config.httpmethod,
            IntegrationResponses=self.integration_responses,
            RequestTemplates=method_config.request.templates,
            Uri=Join('', [
                'arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/',
                lambda_arn, '/invocations'
            ]))

        perm = self.template.add_resource(
            Permission('{0}Permission'.format(integration.title),
                       Action='lambda:InvokeFunction',
                       FunctionName=lambda_arn,
                       Principal='apigateway.amazonaws.com'))

        self.permissions.append(perm)
        # At time of creation of this class, the PassthroughBehavior parameter is not implemented for integrations
        # in troposphere. The below assigns it for now. This can be reworked into the above troposphere object once
        # troposphere is updated.
        integration.resource['PassthroughBehavior'] = "WHEN_NO_TEMPLATES"

        return integration
Example #2
0
        def _lambda_method_obj(resource, suffix):
            resource = self.template.add_resource(resource)

            return self.template.add_resource(
                Method(
                    f"APIGatewayLambdaMatomoEventReceiver{suffix}",
                    DependsOn="LambdaMatomoEventReceiver",
                    RestApiId=Ref(api_gateway),
                    AuthorizationType="NONE",
                    ResourceId=Ref(resource),
                    HttpMethod="ANY",
                    Integration=Integration(
                        Credentials=GetAtt("LambdaExecutionRole", "Arn"),
                        Type="AWS_PROXY",
                        IntegrationHttpMethod="POST",
                        Uri=Join(
                            "",
                            [
                                f"arn:aws:apigateway:{self.region_name}:lambda:path/2015-03-31/functions/",
                                GetAtt("LambdaMatomoEventReceiver", "Arn"),
                                "/invocations",
                            ],
                        ),
                    ),
                ), )
    def create_integration(self, method_config, lambda_arn):
        """
        Creates an integration object using a single provided ApiGatewayMethodConfig object.
        :param method_config: a single ApiGatewayMethodConfig object
        :param lambda_arn: the ARN of a lambda function to point this integration at.
        :return: a troposphere integration object
        """

        integration = Integration(
            '{0}Integration'.format(method_config.method_name),
            Type='AWS',
            IntegrationHttpMethod=method_config.httpmethod,
            IntegrationResponses=self.integration_responses,
            RequestTemplates=method_config.request.templates,
            Uri=Join('',
                     [
                         'arn:aws:apigateway:ap-southeast-2:lambda:path/2015-03-31/functions/',
                         lambda_arn,
                         '/invocations'
                     ]
                     )
        )

        perm = self.template.add_resource(Permission(
            '{0}Permission'.format(integration.title),
            Action='lambda:InvokeFunction',
            FunctionName=lambda_arn,
            Principal='apigateway.amazonaws.com'
        ))

        self.permissions.append(perm)
        # At time of creation of this class, the PassthroughBehavior parameter is not implemented for integrations
        # in troposphere. The below assigns it for now. This can be reworked into the above troposphere object once
        # troposphere is updated.
        integration.resource['PassthroughBehavior'] = "WHEN_NO_TEMPLATES"

        return integration
Example #4
0
 def generate_proxy_method(self, name, auth, uriParams, resource, api):
     return Method(
         name,
         AuthorizationType=auth,
         HttpMethod='ANY',
         Integration=Integration(
             IntegrationHttpMethod='POST',
             Type='AWS_PROXY',
             Uri=Sub(
                 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${FunctionName}/invocations',
                 **uriParams),
         ),
         ResourceId=resource,
         RestApiId=api,
     )
Example #5
0
 def get_integration(self, resource, invoke_lambda_role):
     integration_type = self.get_integration_type(resource)
     if integration_type:
         extra = {}
         if 'parameters' in resource['integration']:
             extra['RequestParameters'] = resource['integration']['parameters']
         return Integration(
             IntegrationResponses=self.get_integration_responses(resource),
             IntegrationHttpMethod=self.get_integration_http_method(resource),
             Type=integration_type,
             Credentials=self.get_integration_credentials(resource, invoke_lambda_role),
             RequestTemplates=self.get_request_templates(resource),
             Uri=self.get_integration_uri(resource),
             **extra
         )
     return troposphere.Ref(troposphere.AWS_NO_VALUE)
Example #6
0
def add_method_to_apigateway(t: Template, lambda_function: Function,
                             apigwlambda_role: Role, rest_api: RestApi,
                             resource: Resource, method_type: str):
    return t.add_resource(
        Method(
            f'Method{lambda_function.name}',
            DependsOn=lambda_function,
            RestApiId=Ref(rest_api),
            AuthorizationType="NONE",
            ResourceId=Ref(resource),
            HttpMethod=method_type,
            Integration=Integration(
                Credentials=GetAtt(apigwlambda_role, "Arn"),
                Type="AWS",
                IntegrationHttpMethod='POST',
                IntegrationResponses=[IntegrationResponse(StatusCode='200')],
                Uri=Join("", [
                    "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/",
                    GetAtt(lambda_function, "Arn"), "/invocations"
                ])),
            MethodResponses=[MethodResponse("CatResponse", StatusCode='200')]))
Example #7
0
    ))

# Create a Lambda API method for the Lambda resource
method = t.add_resource(
    Method(
        "LambdaMethod",
        DependsOn='FoobarFunction',
        RestApiId=Ref(rest_api),
        AuthorizationType="NONE",
        ResourceId=Ref(resource),
        HttpMethod="GET",
        Integration=Integration(
            Credentials=GetAtt("LambdaExecutionRole", "Arn"),
            Type="AWS",
            IntegrationHttpMethod='POST',
            IntegrationResponses=[IntegrationResponse(StatusCode='200')],
            Uri=Join("", [
                "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/",
                GetAtt("FoobarFunction", "Arn"), "/invocations"
            ])),
        MethodResponses=[MethodResponse("CatResponse", StatusCode='200')]))

# Create a deployment
stage_name = 'v1'

deployment = t.add_resource(
    Deployment(
        "%sDeployment" % stage_name,
        DependsOn="LambdaMethod",
        RestApiId=Ref(rest_api),
    ))
Example #8
0
             RestApiId=Ref(rest_api),
             PathPart="subscribe",
             ParentId=GetAtt("EmailListApi", "RootResourceId")))

subscribe_method = t.add_resource(
    Method("subscribeMethod",
           DependsOn="EmailSubscribeFunction",
           RestApiId=Ref(rest_api),
           AuthorizationType="NONE",
           ResourceId=Ref(subscribe_resource),
           HttpMethod="POST",
           Integration=Integration(
               Type="AWS",
               IntegrationHttpMethod="POST",
               IntegrationResponses=[IntegrationResponse(StatusCode="200")],
               Uri=Join("", [
                   "arn:aws:apigateway:",
                   Ref('AWS::Region'), ":lambda:path/2015-03-31/functions/",
                   GetAtt(EmailSubscribeFunction, "Arn"), "/invocations"
               ])),
           MethodResponses=[MethodResponse("CatResponse", StatusCode="200")]))

# /unsubscribe
unsubscribe_resource = t.add_resource(
    Resource("unsubscribeResource",
             RestApiId=Ref(rest_api),
             PathPart="unsubscribe",
             ParentId=GetAtt("EmailListApi", "RootResourceId")))

unsubscribe_method = t.add_resource(
    Method("unsubscribeMethod",
    def initiate_api_gateway_creation(self):
        self.template.set_version('2010-09-09')
        self.template.set_description('Creates a API Gateway which is '
                                      'used to get data from dynamoDB.')

        role = self.template.add_resource(
            Role('RootRole',
                 RoleName="monty-cloud-api-role",
                 Path='/',
                 AssumeRolePolicyDocument={
                     "Version":
                     "2012-10-17",
                     "Statement": [{
                         "Action": ["sts:AssumeRole"],
                         "Effect": "Allow",
                         "Principal": {
                             "Service": [
                                 "apigateway.amazonaws.com",
                                 "lambda.amazonaws.com",
                                 "dynamodb.amazonaws.com"
                             ]
                         }
                     }]
                 }))

        self.template.add_resource(
            ManagedPolicy(
                'RolePolicies',
                ManagedPolicyName='api-gw-policy',
                Description='This policy is used for the DynamoDB table ',
                PolicyDocument={
                    "Version":
                    "2012-10-17",
                    "Statement": [{
                        "Action": ["dynamodb:*", "lambda:*", "s3:*"],
                        "Resource": [
                            "arn:aws:dynamodb:*:*:table/*",
                            "arn:aws:lambda:*:*:function:*"
                        ],
                        "Effect":
                        "Allow"
                    }]
                },
                Roles=[Ref(role)]))

        name = self.template.add_resource(
            RestApi('restApiName',
                    Name='monty-cloud-get-api',
                    Description='Monty Cloud API Gateway',
                    EndpointConfiguration=EndpointConfiguration(
                        Types=['REGIONAL'])))

        self.template.add_resource(
            Permission("lambdaApiGatewayInvoke",
                       Action="lambda:InvokeFunction",
                       FunctionName="arn:aws:lambda:{}:{}:function:"
                       "get_data".format(self.region, self.account_number),
                       Principal="apigateway.amazonaws.com",
                       SourceArn="arn:aws:execute-api:{}:{}:*/*"
                       "/GET/get-details".format(self.region,
                                                 self.account_number)))

        get_api_resource = self.template.add_resource(
            Resource('restApiGetDetailsResource',
                     RestApiId=Ref(name),
                     ParentId=GetAtt(name, 'RootResourceId'),
                     PathPart='get-details',
                     DependsOn=name))

        get_api_method = self.template.add_resource(
            Method('restApiGetDetailsMethod',
                   AuthorizationType='None',
                   ApiKeyRequired=False,
                   HttpMethod='GET',
                   ResourceId=Ref(get_api_resource),
                   RestApiId=Ref(name),
                   Integration=Integration(Type='AWS_PROXY',
                                           IntegrationHttpMethod='POST',
                                           Uri=self.uri.format(
                                               self.region, self.region,
                                               self.account_number),
                                           Credentials=GetAtt(role, "Arn")),
                   MethodResponses=[
                       MethodResponse(
                           StatusCode='200',
                           ResponseModels={'application/json': 'Empty'})
                   ],
                   DependsOn=get_api_resource))

        deployment = self.template.add_resource(
            Deployment('restApiDeployment',
                       RestApiId=Ref(name),
                       DependsOn=[get_api_method]))

        self.template.add_resource(
            Stage('restApiStage',
                  DeploymentId=Ref(deployment),
                  Description='Prod Stage',
                  MethodSettings=[
                      MethodSetting(ResourcePath='/get-details',
                                    HttpMethod='GET')
                  ],
                  RestApiId=Ref(name),
                  StageName='prod'))

        return self.template.to_yaml()
Example #10
0
    def add_api_gateway(self, apigateway_name):
        self.log.info('Adding API Gateway %s' % apigateway_name)
        assert (self.lambda_function is not None)
        # define all value used by api gateway
        lambda_method_name = '%sLambdaMethod' % apigateway_name
        lambda_permission_name = '%sLambdaPermission' % apigateway_name
        resource_name = '%sResource' % apigateway_name
        deployment_name = '%sDeployment' % self.stage_name
        apikey_name = '%sApiKey' % apigateway_name

        # start creating api gateway template
        self.apigateway = RestApi(apigateway_name, Name=apigateway_name)
        self.template.add_resource(self.apigateway)

        resource = Resource(resource_name,
                            RestApiId=Ref(self.apigateway),
                            PathPart='{proxy+}',
                            ParentId=GetAtt(apigateway_name, 'RootResourceId'))
        self.template.add_resource(resource)

        permission = Permission(lambda_permission_name,
                                Action='lambda:invokeFunction',
                                FunctionName=GetAtt(self.lambda_function,
                                                    'Arn'),
                                Principal='apigateway.amazonaws.com',
                                SourceArn=Join("", [
                                    'arn:aws:execute-api:',
                                    Ref('AWS::Region'), ':',
                                    Ref('AWS::AccountId'), ':',
                                    Ref(self.apigateway), '/*'
                                ]))
        self.template.add_resource(permission)

        method = Method(
            lambda_method_name,
            DependsOn=lambda_permission_name,
            RestApiId=Ref(self.apigateway),
            ResourceId=Ref(resource),
            HttpMethod='ANY',
            AuthorizationType='NONE',
            Integration=Integration(
                Type='AWS_PROXY',
                IntegrationHttpMethod='POST',
                Uri=Join("", [
                    'arn:aws:apigateway:',
                    Ref('AWS::Region'), ':lambda:path/2015-03-31/functions/',
                    GetAtt(self.lambda_function, 'Arn'), '/invocations'
                ])),
            MethodResponses=[MethodResponse(StatusCode='200')])
        self.template.add_resource(method)

        # create a deployment
        deployment = Deployment(deployment_name,
                                DependsOn=lambda_method_name,
                                RestApiId=Ref(self.apigateway))
        self.template.add_resource(deployment)

        stage = Stage('%sStage' % self.stage_name,
                      StageName=self.stage_name,
                      RestApiId=Ref(self.apigateway),
                      DeploymentId=Ref(deployment))
        self.template.add_resource(stage)

        key = ApiKey(apikey_name,
                     StageKeys=[
                         StageKey(RestApiId=Ref(self.apigateway),
                                  StageName=Ref(stage))
                     ])
        self.template.add_resource(key)
    PathPart="civ6",
    ParentId=GetAtt("Civ6NotifGW", "RootResourceId"),
)

Civ6Notif_PostMethod = Method(
    "Civ6NotifPostMethod",
    DependsOn='Civ6NotifFunction',
    RestApiId=Ref(Civ6Notif_GW),
    AuthorizationType="NONE",
    ResourceId=Ref(Civ6Notif_GW_Resource),
    HttpMethod="POST",
    Integration=Integration(
        Credentials=GetAtt("Civ6NotifLambdaExecutionRole", "Arn"),
        Type="AWS",
        IntegrationHttpMethod='POST',
        IntegrationResponses=[IntegrationResponse(StatusCode='200')],
        Uri=Join("", [
            "arn:aws:apigateway:",
            Ref("AWS::Region"), ":lambda:path/2015-03-31/functions/",
            GetAtt("Civ6NotifFunction", "Arn"), "/invocations"
        ])),
    MethodResponses=[MethodResponse("CatResponse", StatusCode='200')])

stage_name = "prod"

Civ6Notif_GW_Deployment = Deployment(f'{stage_name}Deployment',
                                     RestApiId=Ref(Civ6Notif_GW),
                                     DependsOn="Civ6NotifPostMethod")

Civ6Notif_GW_Stage = Stage(f'{stage_name}Stage',
                           StageName=stage_name,
                           RestApiId=Ref(Civ6Notif_GW),
    ParentId=GetAtt("ApiGateway", "RootResourceId"),
))

# create a Lambda API method for the Lambda resource
method = t.add_resource(Method(
    "MethodConvert",
    DependsOn="Lambda",  # The Lambda Ref
    RestApiId=Ref(rest_api),
    AuthorizationType="NONE",
    ResourceId=Ref(resource),
    HttpMethod="POST",
    Integration=Integration(
        Credentials=GetAtt("LambdaExecutionRole", "Arn"),
        Type="AWS_PROXY",
        IntegrationHttpMethod='POST',
        Uri=Join("", [
            "arn:aws:apigateway:" + args.region + ":lambda:path/2015-03-31/functions/",
            GetAtt("Lambda", "Arn"),
            "/invocations"
        ])
    ),
))

# allow the API Gateway to invoke Lambda
permission = t.add_resource(Permission(
    "Permission",
    Action="lambda:InvokeFunction",
    FunctionName=GetAtt("Lambda", "Arn"),
    Principal="apigateway.amazonaws.com",
    SourceArn=Join("", [
        "arn:aws:execute-api:" + args.region + ":",
        Ref("AWS::AccountId"),
Example #13
0
            ParentId=Ref(method + "Date"),
        ))

    # Create a Lambda API method for the Lambda resource
    method = t.add_resource(
        Method(
            "CrimeDataAPIMethod" + method,
            DependsOn='CrimeDataAPIFunction',
            RestApiId=Ref(rest_api),
            AuthorizationType="NONE",
            ResourceId=Ref(query),
            HttpMethod="GET",
            Integration=Integration(
                Credentials=GetAtt("CrimeDataExecutionRole", "Arn"),
                Type="AWS_PROXY",
                IntegrationHttpMethod='POST',
                Uri=Join("", [
                    "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/",
                    GetAtt("CrimeDataAPIFunction", "Arn"), "/invocations"
                ])),
        ))

# Allow the gateway to invoke Lambda
permission = t.add_resource(
    Permission("CrimeDataAPILambdaPermission",
               Action="lambda:InvokeFunction",
               FunctionName=GetAtt("CrimeDataAPIFunction", "Arn"),
               Principal="apigateway.amazonaws.com",
               SourceArn=Join("", [
                   "arn:aws:execute-api:",
                   Ref("AWS::Region"), ":",
                   Ref("AWS::AccountId"), ":",
Example #14
0
        ResourceId=Ref(resource),
        HttpMethod="GET",
        MethodResponses=[
            MethodResponse("CatResponse",
                           StatusCode='200',
                           ResponseModels={'application/json': 'Empty'})
        ],
        Integration=Integration(
            Credentials=GetAtt("LambdaExecutionRole", "Arn"),
            PassthroughBehavior='WHEN_NO_MATCH',
            Type="AWS",
            IntegrationHttpMethod='POST',
            IntegrationResponses=[
                IntegrationResponse(
                    StatusCode='200',
                    ResponseTemplates={'application/json': ''},
                )
            ],
            Uri=Join("", [
                "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/",
                GetAtt("function", "Arn"), "/invocations"
            ]),
            RequestTemplates={'application/json': '{"statusCode": 200}'},
        ),
    ))

deployment = t.add_resource(
    Deployment(
        "%sDeployment" % stage_name,
        DependsOn="optionsmethod",
        RestApiId=Ref(rest_api),
Example #15
0
health_method = template.add_resource(Method(
    "HealthMethod",
    ApiKeyRequired=True,
    RestApiId=Ref(api_gateway),
    AuthorizationType="NONE",
    ResourceId=Ref(health_resource),
    HttpMethod="GET",
    OperationName='mock',
    Integration=Integration(
        Type='MOCK',
        IntegrationResponses=[IntegrationResponse(
            ResponseTemplates={
                'application/json': "{\"message\": \"OK\"}"
            },
            StatusCode='200'
        )],
        PassthroughBehavior='WHEN_NO_TEMPLATES',
        RequestTemplates={
            'application/json': "{\"statusCode\": 200, \"message\": \"OK\"}"
        },
    ),
    MethodResponses=[
        MethodResponse(
            'HealthResponse',
            ResponseModels={
                'application/json': Ref(health_model),
            },
            StatusCode='200',
        )
    ],
    def get_framework_template(self):

        from troposphere import (
            GetAtt,
            Ref,
            Sub,
            Tags,
            Template,
        )

        from troposphere.apigateway import (
            BasePathMapping,
            Deployment,
            DomainName,
            Integration,
            IntegrationResponse,
            Method,
            MethodResponse,
            Resource,
            RestApi,
            Stage,
        )

        from troposphere.ec2 import (
            VPCEndpoint, )

        from troposphere.s3 import (
            Bucket,
            BucketPolicy,
            VersioningConfiguration,
        )

        t = Template()

        ###############
        # API Gateway #
        ###############

        api = t.add_resource(
            RestApi(
                'ApiGateway',
                Name=self.args.stack + 'Api',
                Description=
                'API for portal and redirects for the Cornell AppStream Service',
            ))

        ####################
        # Redirect Methods #
        ####################

        stack_url = "'https://shibidp.cit.cornell.edu/idp/profile/SAML2/Unsolicited/SSO?providerId=urn:amazon:webservices&target=https://appstream2.{region}.aws.amazon.com/saml?accountId={account}%26stack={stack}'"
        stack_link = '<li><a href="./{redirect_nal}">{redirect}</a></li>'

        methods = []
        stack_links = ''
        for redirect in sorted(self.config['Redirects'].keys()):
            redirect_info = self.config['Redirects'][redirect]
            redirect_nal = re.sub('\W+', '', redirect)
            redirect_url = stack_url.format(account=redirect_info['account'],
                                            region=redirect_info['region'],
                                            stack=redirect_info['stack'])
            methods.append('ApiGatewayRedirect' + redirect_nal)
            stack_links += stack_link.format(redirect=redirect,
                                             redirect_nal=redirect_nal)

            resource = t.add_resource(
                Resource(
                    'ApiGatewayResource' + redirect_nal,
                    ParentId=GetAtt(api, 'RootResourceId'),
                    PathPart=redirect_nal,
                    RestApiId=Ref(api),
                ))

            method = t.add_resource(
                Method(
                    'ApiGatewayRedirect' + redirect_nal,
                    AuthorizationType='None',
                    HttpMethod='ANY',
                    Integration=Integration(
                        Type='MOCK',
                        IntegrationResponses=[
                            IntegrationResponse(
                                ResponseParameters={
                                    'method.response.header.Location':
                                    redirect_url,
                                },
                                ResponseTemplates={
                                    'application/json': '{"redirect": 302}'
                                },
                                StatusCode='302',
                            ),
                        ],
                        RequestTemplates={
                            'application/json': '{"statusCode":200}'
                        },
                    ),
                    MethodResponses=[
                        MethodResponse(
                            ResponseParameters={
                                'method.response.header.Location': True,
                            },
                            StatusCode='302',
                        ),
                    ],
                    ResourceId=Ref(resource),
                    RestApiId=Ref(api),
                ))

        ###########################
        # API Gateway Root Method #
        ###########################

        with open('./include/root_integration_template.html',
                  'r') as rootTemplateHTML:
            rootTemplate = rootTemplateHTML.read()

        root_method = t.add_resource(
            Method(
                'ApiGatewayRootMethod',
                AuthorizationType='None',
                HttpMethod='ANY',
                Integration=Integration(
                    Type='MOCK',
                    IntegrationResponses=[
                        IntegrationResponse(
                            ResponseParameters={
                                'method.response.header.Content-Type':
                                "'text/html'",
                            },
                            ResponseTemplates={
                                'text/html':
                                rootTemplate.format(stack_links=stack_links),
                            },
                            StatusCode='200',
                        ),
                    ],
                    RequestTemplates={
                        'application/json': '{"statusCode":200}'
                    },
                ),
                MethodResponses=[
                    MethodResponse(
                        ResponseParameters={
                            'method.response.header.Content-Type': True,
                        },
                        StatusCode='200',
                    ),
                ],
                ResourceId=GetAtt(api, 'RootResourceId'),
                RestApiId=Ref(api),
            ))

        #####################
        # API Gateway Stage #
        #####################

        api_deployment = t.add_resource(
            Deployment(
                'ApiGatewayDeployment' + self.run_time,
                Description=
                'Deployment for API portal and redirects for the Cornell AppStream Service',
                RestApiId=Ref(api),
                DependsOn=methods + ['ApiGatewayRootMethod'],
            ))

        api_stage = t.add_resource(
            Stage(
                'ApiGatewayStage',
                DeploymentId=Ref(api_deployment),
                Description=
                'Stage for API portal and redirects for the Cornell AppStream Service',
                RestApiId=Ref(api),
                StageName='apps',
            ))

        ######################
        # API Gateway Domain #
        ######################

        api_domain = t.add_resource(
            DomainName(
                'ApiGatewayDomain',
                CertificateArn=self.config['ACM_ARN'],
                DomainName=self.config['DomainName'],
            ))

        api_domain_mapping = t.add_resource(
            BasePathMapping(
                'ApiGatewayDomainMapping',
                DomainName=Ref(api_domain),
                RestApiId=Ref(api),
                Stage=Ref(api_stage),
            ))

        ###################
        # VPC S3 Endpoint #
        ###################

        s3_endpoint = t.add_resource(
            VPCEndpoint(
                'S3VPCEndpoint',
                ServiceName=Sub('com.amazonaws.${AWS::Region}.s3'),
                VpcId=self.config['VPC'],
                RouteTableIds=self.config['RouteTables'],
            ))

        ####################
        # S3 Bucket Policy #
        ####################

        sub_args = {
            'bucket_name': self.config['Bucket'],
            'vpc_id': self.config['VPC']
        }
        with open('./include/bucket_policy.json', 'r') as bucketPolicyJSON:
            bucket_policy_document = bucketPolicyJSON.read()

        bucket_policy = t.add_resource(
            BucketPolicy(
                'FrameworkBucketPolicy',
                Bucket=self.config['Bucket'],
                PolicyDocument=Sub(bucket_policy_document, **sub_args),
            ))

        with open('./cloudformation/framework.json', 'w') as frameworkTemplate:
            frameworkTemplate.write(t.to_json())

        return t