コード例 #1
0
 def lambda_function(self) -> awslambda.Function:
     """AWS Lambda Function."""
     func = awslambda.Function(
         "LambdaFunction",
         template=self.template,
         Code=self.variables["Code"],
         Handler=self.variables["Entrypoint"].ref,
         Role=GetAtt(self.iam_role, "Arn"),
         Runtime="python3.8",
         Timeout=30,
         MemorySize=128,
         FunctionName=self.context.get_fqn(self.app_name),
     )
     self.add_output(func.title, func.ref())
     self.add_output(f"{func.title}Arn", func.get_att("Arn"))
     return func
コード例 #2
0
ファイル: staticsite.py プロジェクト: jamesloosli/runway
    def add_cloudfront_directory_index_rewrite(self, role):
        # type: (iam.Role) -> awslambda.Function
        """Add an index CloudFront directory index rewrite lambda function to the template.

        Keyword Args:
            role: The index rewrite role resource.

        Return:
            The CloudFront directory index rewrite lambda function resource.

        """
        variables = self.get_variables()
        code_str = ""
        path = os.path.join(
            os.path.dirname(__file__),
            "templates/cf_directory_index_rewrite.template.js",
        )
        with open(path) as file_:
            code_str = file_.read().replace(
                "{{RewriteDirectoryIndex}}", variables["RewriteDirectoryIndex"]
            )

        function = self.template.add_resource(
            awslambda.Function(
                "CFDirectoryIndexRewrite",
                Code=awslambda.Code(ZipFile=code_str),
                DeletionPolicy="Retain",
                Description="Rewrites CF directory HTTP requests to default page",
                Handler="index.handler",
                Role=role.get_att("Arn"),
                Runtime="nodejs10.x",
            )
        )

        self.template.add_output(
            Output(
                "LambdaCFDirectoryIndexRewriteArn",
                Description="Directory Index Rewrite Function Arn",
                Value=function.get_att("Arn"),
            )
        )

        return function
コード例 #3
0
ファイル: staticsite.py プロジェクト: dgreeninger/runway
    def add_cloudfront_directory_index_rewrite(self, role):
        # type: (iam.Role) -> awslambda.Function
        """Add an index CloudFront directory index rewrite lambda function to the template.

        Keyword Args:
            role (dict): The index rewrite role resource

        Return:
            dict: The CloudFront directory index rewrite lambda function resource
        """
        variables = self.get_variables()
        code_str = ''
        path = os.path.join(
            os.path.dirname(__file__),
            'templates/cf_directory_index_rewrite.template.js')
        with open(path) as file_:
            code_str = file_.read().replace('{{RewriteDirectoryIndex}}',
                                            variables["RewriteDirectoryIndex"])

        function = self.template.add_resource(
            awslambda.Function(
                'CFDirectoryIndexRewrite',
                Code=awslambda.Code(ZipFile=code_str),
                DeletionPolicy='Retain',
                Description=
                'Rewrites CF directory HTTP requests to default page',  # noqa
                Handler='index.handler',
                Role=role.get_att('Arn'),
                Runtime='nodejs10.x'))

        self.template.add_output(
            Output('LambdaCFDirectoryIndexRewriteArn',
                   Description='Directory Index Rewrite Function Arn',
                   Value=function.get_att('Arn')))

        return function
コード例 #4
0
    def _get_replicated_lambda_remover_lambda(self):
        # type: () -> Dict[str, Any]
        res = {}
        res['role'] = self.template.add_resource(
            iam.Role(
                'ReplicatedLambdaRemoverRole',
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    'lambda.amazonaws.com'),
                Policies=[
                    iam.Policy(PolicyName="LambdaLogCreation",
                               PolicyDocument=PolicyDocument(
                                   Version='2012-10-17',
                                   Statement=[
                                       Statement(
                                           Action=[
                                               awacs.logs.CreateLogGroup,
                                               awacs.logs.CreateLogStream,
                                               awacs.logs.PutLogEvents
                                           ],
                                           Effect=Allow,
                                           Resource=[
                                               Join('', [
                                                   'arn:', Partition,
                                                   ':logs:*:', AccountId,
                                                   ':log-group:/aws/lambda/',
                                                   StackName,
                                                   '-ReplicatedLambdaRemover-*'
                                               ])
                                           ])
                                   ])),
                    iam.Policy(PolicyName="DeleteLambda",
                               PolicyDocument=PolicyDocument(
                                   Version="2012-10-17",
                                   Statement=[
                                       Statement(Action=[
                                           awacs.awslambda.DeleteFunction
                                       ],
                                                 Effect=Allow,
                                                 Resource=self.get_variables()
                                                 ['function_arns'])
                                   ]))
                ],
            ))

        self.template.add_output(
            Output(
                'ReplicatedLambdaRemoverRole',
                Description='The name of the Replicated Lambda Remover Role',
                Value=res['role'].ref()))

        res['function'] = self.template.add_resource(
            awslambda.Function(
                'ReplicatedLambdaRemover',
                Code=awslambda.Code(
                    ZipFile=read_value_from_path('file://' + os.path.join(
                        os.path.dirname(__file__),
                        'templates/replicated_lambda_remover.template.py'))),
                Description=
                "Checks for Replicated Lambdas created during the main stack and "
                "deletes them when they are ready.",
                Handler='index.handler',
                Role=res['role'].get_att('Arn'),
                Runtime='python3.7'))

        self.template.add_output(
            Output('ReplicatedLambdaRemoverArn',
                   Description='The ARN of the Replicated Function',
                   Value=res['function'].get_att('Arn')))

        return res
コード例 #5
0
    def _get_self_destruct(self, replicated_lambda_remover):
        # type: (Dict[str, Union[awslambda.Function, Any]]) -> Dict[str, Any]
        res = {}
        variables = self.get_variables()

        res['role'] = self.template.add_resource(
            iam.Role(
                'SelfDestructRole',
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    'lambda.amazonaws.com'),
                Policies=[
                    iam.Policy(PolicyName="LambdaLogCreation",
                               PolicyDocument=PolicyDocument(
                                   Version='2012-10-17',
                                   Statement=[
                                       Statement(
                                           Action=[
                                               awacs.logs.CreateLogGroup,
                                               awacs.logs.CreateLogStream,
                                               awacs.logs.PutLogEvents
                                           ],
                                           Effect=Allow,
                                           Resource=[
                                               Join('', [
                                                   'arn:', Partition,
                                                   ':logs:*:', AccountId,
                                                   ':log-group:/aws/lambda/',
                                                   StackName, '-SelfDestruct-*'
                                               ])
                                           ])
                                   ])),
                    iam.Policy(
                        PolicyName="DeleteStateMachine",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.states.DeleteStateMachine],
                                    Effect=Allow,
                                    Resource=[
                                        # StateMachine
                                        Join('', [
                                            'arn:', Partition, ':states:',
                                            Region, ':', AccountId,
                                            ':stateMachine:StaticSiteCleanup-',
                                            variables['stack_name']
                                        ])
                                    ])
                            ])),
                    iam.Policy(PolicyName="DeleteRolesAndPolicies",
                               PolicyDocument=PolicyDocument(
                                   Version="2012-10-17",
                                   Statement=[
                                       Statement(
                                           Action=[
                                               awacs.iam.DeleteRolePolicy,
                                               awacs.iam.DeleteRole
                                           ],
                                           Effect=Allow,
                                           Resource=[
                                               Join('', [
                                                   'arn:', Partition, ':iam::',
                                                   AccountId, ':role/',
                                                   StackName, '-*'
                                               ]),
                                           ])
                                   ])),
                    iam.Policy(
                        PolicyName="DeleteLambdas",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.awslambda.DeleteFunction],
                                    Effect=Allow,
                                    Resource=[
                                        Join('', [
                                            'arn:', Partition, ':lambda:',
                                            Region, ':', AccountId,
                                            ':function:%s-SelfDestruct-*' %
                                            (variables['stack_name'])
                                        ]),
                                        replicated_lambda_remover['function'].
                                        get_att('Arn')
                                    ])
                            ])),
                    iam.Policy(
                        PolicyName="DeleteStack",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.cloudformation.DeleteStack],
                                    Effect=Allow,
                                    Resource=[
                                        Join('', [
                                            'arn:', Partition,
                                            ':cloudformation:', Region, ':',
                                            AccountId,
                                            ':stack/%s/*' %
                                            (variables['stack_name'])
                                        ])
                                    ])
                            ]))
                ],
            ))

        self.template.add_output(
            Output('SelfDestructLambdaRole',
                   Description='The name of the Self Destruct Role',
                   Value=res['role'].ref()))

        res['function'] = self.template.add_resource(
            awslambda.Function(
                'SelfDestruct',
                Code=awslambda.Code(ZipFile=read_value_from_path(
                    'file://' +
                    os.path.join(os.path.dirname(__file__),
                                 'templates/self_destruct.template.py'))),
                Description=
                "Issues a Delete Stack command to the Cleanup stack",
                Handler='index.handler',
                Role=res['role'].get_att('Arn'),
                Runtime='python3.7'))

        self.template.add_output(
            Output('SelfDestructLambdaArn',
                   Description='The ARN of the Replicated Function',
                   Value=res['function'].get_att('Arn')))

        return res
コード例 #6
0
    def create_resources(self):
        """Create the resources."""
        template = self.template
        variables = self.get_variables()
        app_name = variables["AppName"].ref

        lambda_iam_role = template.add_resource(
            iam.Role(
                "LambdaRole",
                RoleName=Join("-", [app_name, "lambda-role"]),
                AssumeRolePolicyDocument=Policy(
                    Version="2012-10-17",
                    Statement=[
                        Statement(
                            Effect=Allow,
                            Action=[awacs.sts.AssumeRole],
                            Principal=Principal("Service",
                                                ["lambda.amazonaws.com"]),
                        )
                    ],
                ),
                Path="/service-role/",
                Policies=[
                    iam.Policy(
                        PolicyName=Join("-", [app_name, "lambda-policy"]),
                        PolicyDocument=Policy(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.logs.CreateLogGroup,
                                        awacs.logs.CreateLogStream,
                                        awacs.logs.PutLogEvents,
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":logs:",
                                                Region,
                                                ":",
                                                AccountId,
                                                ":log-group:/aws/lambda/",
                                                app_name,
                                                "-*",
                                            ],
                                        )
                                    ],
                                    Sid="WriteLogs",
                                )
                            ],
                        ),
                    )
                ],
            ))

        lambda_function = template.add_resource(
            awslambda.Function(
                "LambdaFunction",
                Code=variables["Code"],
                Handler=variables["Entrypoint"].ref,
                Role=GetAtt(lambda_iam_role, "Arn"),
                Runtime="python3.6",
                Timeout=30,
                MemorySize=128,
                FunctionName=Join("-", [app_name, "integrationtest"]),
            ))

        template.add_output(
            Output(
                lambda_iam_role.title,
                Description="Lambda Role",
                Export=Export(
                    Sub("${AWS::StackName}-%s" % lambda_iam_role.title)),
                Value=Ref(lambda_iam_role),
            ))
        template.add_output(
            Output(
                lambda_function.title,
                Description="Lambda Function",
                Export=Export(
                    Sub("${AWS::StackName}-%s" % lambda_function.title)),
                Value=GetAtt(lambda_function, "Arn"),
            ))
        template.add_output(
            Output(
                lambda_function.title + "Name",
                Description="Lambda Function Name",
                Export=Export(
                    Sub("${AWS::StackName}-%sName" % lambda_function.title)),
                Value=Ref(lambda_function),
            ))
コード例 #7
0
    def _get_replicated_lambda_remover_lambda(self):
        # type: () -> Dict[str, Any]
        res = {}
        variables = self.get_variables()
        res["role"] = self.template.add_resource(
            iam.Role(
                "ReplicatedLambdaRemoverRole",
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    "lambda.amazonaws.com"
                ),
                PermissionsBoundary=(
                    variables["RoleBoundaryArn"]
                    if self.role_boundary_specified
                    else NoValue
                ),
                Policies=[
                    iam.Policy(
                        PolicyName="LambdaLogCreation",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.logs.CreateLogGroup,
                                        awacs.logs.CreateLogStream,
                                        awacs.logs.PutLogEvents,
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":logs:*:",
                                                AccountId,
                                                ":log-group:/aws/lambda/",
                                                StackName,
                                                "-ReplicatedLambdaRemover-*",
                                            ],
                                        )
                                    ],
                                )
                            ],
                        ),
                    ),
                    iam.Policy(
                        PolicyName="DeleteLambda",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.awslambda.DeleteFunction],
                                    Effect=Allow,
                                    Resource=self.get_variables()["function_arns"],
                                )
                            ],
                        ),
                    ),
                ],
            )
        )

        self.template.add_output(
            Output(
                "ReplicatedLambdaRemoverRole",
                Description="The name of the Replicated Lambda Remover Role",
                Value=res["role"].ref(),
            )
        )

        res["function"] = self.template.add_resource(
            awslambda.Function(
                "ReplicatedLambdaRemover",
                Code=awslambda.Code(
                    ZipFile=read_value_from_path(
                        "file://"
                        + os.path.join(
                            os.path.dirname(__file__),
                            "templates/replicated_lambda_remover.template.py",
                        )
                    )
                ),
                Description="Checks for Replicated Lambdas created during the main stack and "
                "deletes them when they are ready.",
                Handler="index.handler",
                Role=res["role"].get_att("Arn"),
                Runtime="python3.7",
            )
        )

        self.template.add_output(
            Output(
                "ReplicatedLambdaRemoverArn",
                Description="The ARN of the Replicated Function",
                Value=res["function"].get_att("Arn"),
            )
        )

        return res
コード例 #8
0
    def _get_self_destruct(self, replicated_lambda_remover):
        # type: (Dict[str, Union[awslambda.Function, Any]]) -> Dict[str, Any]
        res = {}
        variables = self.get_variables()

        res["role"] = self.template.add_resource(
            iam.Role(
                "SelfDestructRole",
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    "lambda.amazonaws.com"
                ),
                PermissionsBoundary=(
                    variables["RoleBoundaryArn"]
                    if self.role_boundary_specified
                    else NoValue
                ),
                Policies=[
                    iam.Policy(
                        PolicyName="LambdaLogCreation",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.logs.CreateLogGroup,
                                        awacs.logs.CreateLogStream,
                                        awacs.logs.PutLogEvents,
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":logs:*:",
                                                AccountId,
                                                ":log-group:/aws/lambda/",
                                                StackName,
                                                "-SelfDestruct-*",
                                            ],
                                        )
                                    ],
                                )
                            ],
                        ),
                    ),
                    iam.Policy(
                        PolicyName="DeleteStateMachine",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.states.DeleteStateMachine],
                                    Effect=Allow,
                                    Resource=[
                                        # StateMachine
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":states:",
                                                Region,
                                                ":",
                                                AccountId,
                                                ":stateMachine:StaticSiteCleanup-",
                                                variables["stack_name"],
                                            ],
                                        )
                                    ],
                                )
                            ],
                        ),
                    ),
                    iam.Policy(
                        PolicyName="DeleteRolesAndPolicies",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.iam.DeleteRolePolicy,
                                        awacs.iam.DeleteRole,
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":iam::",
                                                AccountId,
                                                ":role/",
                                                StackName,
                                                "-*",
                                            ],
                                        ),
                                    ],
                                )
                            ],
                        ),
                    ),
                    iam.Policy(
                        PolicyName="DeleteLambdas",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.awslambda.DeleteFunction],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":lambda:",
                                                Region,
                                                ":",
                                                AccountId,
                                                ":function:%s-SelfDestruct-*"
                                                % (variables["stack_name"]),
                                            ],
                                        ),
                                        replicated_lambda_remover["function"].get_att(
                                            "Arn"
                                        ),
                                    ],
                                )
                            ],
                        ),
                    ),
                    iam.Policy(
                        PolicyName="DeleteStack",
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.cloudformation.DeleteStack],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":cloudformation:",
                                                Region,
                                                ":",
                                                AccountId,
                                                ":stack/%s/*"
                                                % (variables["stack_name"]),
                                            ],
                                        )
                                    ],
                                )
                            ],
                        ),
                    ),
                ],
            )
        )

        self.template.add_output(
            Output(
                "SelfDestructLambdaRole",
                Description="The name of the Self Destruct Role",
                Value=res["role"].ref(),
            )
        )

        res["function"] = self.template.add_resource(
            awslambda.Function(
                "SelfDestruct",
                Code=awslambda.Code(
                    ZipFile=read_value_from_path(
                        "file://"
                        + os.path.join(
                            os.path.dirname(__file__),
                            "templates/self_destruct.template.py",
                        )
                    )
                ),
                Description="Issues a Delete Stack command to the Cleanup stack",
                Handler="index.handler",
                Role=res["role"].get_att("Arn"),
                Runtime="python3.7",
            )
        )

        self.template.add_output(
            Output(
                "SelfDestructLambdaArn",
                Description="The ARN of the Replicated Function",
                Value=res["function"].get_att("Arn"),
            )
        )

        return res
コード例 #9
0
ファイル: lambda_function.py プロジェクト: voodooGQ/runway
    def create_resources(self):
        """Create the resources."""
        template = self.template
        variables = self.get_variables()
        app_name = variables['AppName'].ref

        lambda_iam_role = template.add_resource(
            iam.Role(
                'LambdaRole',
                RoleName=Join('-',
                              [app_name,
                               'lambda-role']),
                AssumeRolePolicyDocument=Policy(
                    Version='2012-10-17',
                    Statement=[
                        Statement(
                            Effect=Allow,
                            Action=[awacs.sts.AssumeRole],
                            Principal=Principal('Service',
                                                ['lambda.amazonaws.com'])
                        )
                    ]
                ),
                Path='/service-role/',
                Policies=[
                    iam.Policy(
                        PolicyName=Join('-',
                                        [app_name,
                                         'lambda-policy']),
                        PolicyDocument=Policy(
                            Version='2012-10-17',
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.logs.CreateLogGroup,
                                        awacs.logs.CreateLogStream,
                                        awacs.logs.PutLogEvents
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join('', [
                                            'arn:',
                                            Partition,
                                            ':logs:',
                                            Region,
                                            ':',
                                            AccountId,
                                            ':log-group:/aws/lambda/',
                                            app_name,
                                            '-*'])
                                    ],
                                    Sid='WriteLogs'
                                )
                            ]
                        )
                    )
                ]
            )
        )

        lambda_function = template.add_resource(
            awslambda.Function(
                'LambdaFunction',
                Code=variables['Code'],
                Handler=variables['Entrypoint'].ref,
                Role=GetAtt(lambda_iam_role, 'Arn'),
                Runtime='python3.6',
                Timeout=30,
                MemorySize=128,
                FunctionName=Join('-', [app_name,
                                        'integrationtest'])
            )
        )

        template.add_output(
            Output(
                lambda_iam_role.title,
                Description='Lambda Role',
                Export=Export(Sub(
                    '${AWS::StackName}-%s' % lambda_iam_role.title
                )),
                Value=Ref(lambda_iam_role)
            )
        )
        template.add_output(
            Output(
                lambda_function.title,
                Description='Lambda Function',
                Export=Export(Sub(
                    '${AWS::StackName}-%s' % lambda_function.title
                )),
                Value=GetAtt(lambda_function, 'Arn')
            )
        )
        template.add_output(
            Output(
                lambda_function.title + 'Name',
                Description='Lambda Function Name',
                Export=Export(Sub(
                    '${AWS::StackName}-%sName' % lambda_function.title
                )),
                Value=Ref(lambda_function)
            )
        )
コード例 #10
0
ファイル: buildpipeline.py プロジェクト: twitty-onica/runway
    def create_template(self):
        """Create template (main function called by Stacker)."""
        template = self.template
        variables = self.get_variables()
        template.set_version("2010-09-09")
        template.set_description("App - Build Pipeline")

        # Resources
        boundary_arn = Join(
            "",
            [
                "arn:",
                Partition,
                ":iam::",
                AccountId,
                ":policy/",
                variables["RolePermissionsBoundaryName"].ref,
            ],
        )

        # Repo image limit is 1000 by default; this lambda function will prune
        # old images
        image_param_path = Join("", ["/", variables["AppPrefix"].ref, "/current-hash"])
        image_param_arn = Join(
            "",
            [
                "arn:",
                Partition,
                ":ssm:",
                Region,
                ":",
                AccountId,
                ":parameter",
                image_param_path,
            ],
        )
        ecr_repo_arn = Join(
            "",
            [
                "arn:",
                Partition,
                ":ecr:",
                Region,
                ":",
                AccountId,
                ":repository/",
                variables["EcrRepoName"].ref,
            ],
        )
        cleanuplambdarole = template.add_resource(
            iam.Role(
                "CleanupLambdaRole",
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    "lambda.amazonaws.com"
                ),
                ManagedPolicyArns=[IAM_ARN_PREFIX + "AWSLambdaBasicExecutionRole"],
                PermissionsBoundary=boundary_arn,
                Policies=[
                    iam.Policy(
                        PolicyName=Join(
                            "", [variables["AppPrefix"].ref, "-ecrcleanup"]
                        ),
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.ssm.GetParameter],
                                    Effect=Allow,
                                    Resource=[image_param_arn],
                                ),
                                Statement(
                                    Action=[
                                        awacs.ecr.DescribeImages,
                                        awacs.ecr.BatchDeleteImage,
                                    ],
                                    Effect=Allow,
                                    Resource=[ecr_repo_arn],
                                ),
                            ],
                        ),
                    )
                ],
            )
        )
        cleanupfunction = template.add_resource(
            awslambda.Function(
                "CleanupFunction",
                Description="Cleanup stale ECR images",
                Code=awslambda.Code(ZipFile=variables["ECRCleanupLambdaFunction"]),
                Environment=awslambda.Environment(
                    Variables={
                        "ECR_REPO_NAME": variables["EcrRepoName"].ref,
                        "SSM_PARAM": image_param_path,
                    }
                ),
                Handler="index.handler",
                Role=cleanuplambdarole.get_att("Arn"),
                Runtime="python3.6",
                Timeout=120,
            )
        )
        cleanuprule = template.add_resource(
            events.Rule(
                "CleanupRule",
                Description="Regularly invoke CleanupFunction",
                ScheduleExpression="rate(7 days)",
                State="ENABLED",
                Targets=[
                    events.Target(
                        Arn=cleanupfunction.get_att("Arn"), Id="CleanupFunction"
                    )
                ],
            )
        )
        template.add_resource(
            awslambda.Permission(
                "AllowCWLambdaInvocation",
                FunctionName=cleanupfunction.ref(),
                Action=awacs.awslambda.InvokeFunction.JSONrepr(),
                Principal="events.amazonaws.com",
                SourceArn=cleanuprule.get_att("Arn"),
            )
        )

        appsource = template.add_resource(
            codecommit.Repository(
                "AppSource",
                RepositoryName=Join("-", [variables["AppPrefix"].ref, "source"]),
            )
        )
        for i in ["Name", "Arn"]:
            template.add_output(
                Output(
                    "AppRepo%s" % i,
                    Description="%s of app source repo" % i,
                    Value=appsource.get_att(i),
                )
            )

        bucket = template.add_resource(
            s3.Bucket(
                "Bucket",
                AccessControl=s3.Private,
                LifecycleConfiguration=s3.LifecycleConfiguration(
                    Rules=[
                        s3.LifecycleRule(
                            NoncurrentVersionExpirationInDays=90, Status="Enabled"
                        )
                    ]
                ),
                VersioningConfiguration=s3.VersioningConfiguration(Status="Enabled"),
            )
        )
        template.add_output(
            Output(
                "PipelineBucketName",
                Description="Name of pipeline bucket",
                Value=bucket.ref(),
            )
        )

        # This list must be kept in sync between the CodeBuild project and its
        # role
        build_name = Join("", [variables["AppPrefix"].ref, "-build"])

        build_role = template.add_resource(
            iam.Role(
                "BuildRole",
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    "codebuild.amazonaws.com"
                ),
                PermissionsBoundary=boundary_arn,
                Policies=[
                    iam.Policy(
                        PolicyName=Join("", [build_name, "-policy"]),
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[awacs.s3.GetObject],
                                    Effect=Allow,
                                    Resource=[Join("", [bucket.get_att("Arn"), "/*"])],
                                ),
                                Statement(
                                    Action=[awacs.ecr.GetAuthorizationToken],
                                    Effect=Allow,
                                    Resource=["*"],
                                ),
                                Statement(
                                    Action=[
                                        awacs.ecr.BatchCheckLayerAvailability,
                                        awacs.ecr.BatchGetImage,
                                        awacs.ecr.CompleteLayerUpload,
                                        awacs.ecr.DescribeImages,
                                        awacs.ecr.GetDownloadUrlForLayer,
                                        awacs.ecr.InitiateLayerUpload,
                                        awacs.ecr.PutImage,
                                        awacs.ecr.UploadLayerPart,
                                    ],
                                    Effect=Allow,
                                    Resource=[ecr_repo_arn],
                                ),
                                Statement(
                                    Action=[
                                        awacs.ssm.GetParameter,
                                        awacs.ssm.PutParameter,
                                    ],
                                    Effect=Allow,
                                    Resource=[image_param_arn],
                                ),
                                Statement(
                                    Action=[
                                        awacs.logs.CreateLogGroup,
                                        awacs.logs.CreateLogStream,
                                        awacs.logs.PutLogEvents,
                                    ],
                                    Effect=Allow,
                                    Resource=[
                                        Join(
                                            "",
                                            [
                                                "arn:",
                                                Partition,
                                                ":logs:",
                                                Region,
                                                ":",
                                                AccountId,
                                                ":log-group:/aws/codebuild/",
                                                build_name,
                                            ]
                                            + x,
                                        )
                                        for x in [[":*"], [":*/*"]]
                                    ],
                                ),
                            ],
                        ),
                    )
                ],
            )
        )

        buildproject = template.add_resource(
            codebuild.Project(
                "BuildProject",
                Artifacts=codebuild.Artifacts(Type="CODEPIPELINE"),
                Environment=codebuild.Environment(
                    ComputeType="BUILD_GENERAL1_SMALL",
                    EnvironmentVariables=[
                        codebuild.EnvironmentVariable(
                            Name="AWS_DEFAULT_REGION", Type="PLAINTEXT", Value=Region
                        ),
                        codebuild.EnvironmentVariable(
                            Name="AWS_ACCOUNT_ID", Type="PLAINTEXT", Value=AccountId
                        ),
                        codebuild.EnvironmentVariable(
                            Name="IMAGE_REPO_NAME",
                            Type="PLAINTEXT",
                            Value=variables["EcrRepoName"].ref,
                        ),
                    ],
                    Image="aws/codebuild/docker:18.09.0",
                    Type="LINUX_CONTAINER",
                ),
                Name=build_name,
                ServiceRole=build_role.get_att("Arn"),
                Source=codebuild.Source(
                    Type="CODEPIPELINE", BuildSpec=variables["BuildProjectBuildSpec"]
                ),
            )
        )

        pipelinerole = template.add_resource(
            iam.Role(
                "PipelineRole",
                AssumeRolePolicyDocument=make_simple_assume_policy(
                    "codepipeline.amazonaws.com"
                ),
                PermissionsBoundary=boundary_arn,
                Policies=[
                    iam.Policy(
                        PolicyName=Join("", [build_name, "-pipeline-policy"]),
                        PolicyDocument=PolicyDocument(
                            Version="2012-10-17",
                            Statement=[
                                Statement(
                                    Action=[
                                        awacs.codecommit.GetBranch,
                                        awacs.codecommit.GetCommit,
                                        awacs.codecommit.UploadArchive,
                                        awacs.codecommit.GetUploadArchiveStatus,  # noqa
                                        awacs.codecommit.CancelUploadArchive,
                                    ],  # noqa
                                    Effect=Allow,
                                    Resource=[appsource.get_att("Arn")],
                                ),
                                Statement(
                                    Action=[awacs.s3.GetBucketVersioning],
                                    Effect=Allow,
                                    Resource=[bucket.get_att("Arn")],
                                ),
                                Statement(
                                    Action=[awacs.s3.GetObject, awacs.s3.PutObject],
                                    Effect=Allow,
                                    Resource=[Join("", [bucket.get_att("Arn"), "/*"])],
                                ),
                                Statement(
                                    Action=[
                                        awacs.codebuild.BatchGetBuilds,
                                        awacs.codebuild.StartBuild,
                                    ],
                                    Effect=Allow,
                                    Resource=[buildproject.get_att("Arn")],
                                ),
                            ],
                        ),
                    )
                ],
            )
        )

        template.add_resource(
            codepipeline.Pipeline(
                "Pipeline",
                ArtifactStore=codepipeline.ArtifactStore(
                    Location=bucket.ref(), Type="S3"
                ),
                Name=build_name,
                RoleArn=pipelinerole.get_att("Arn"),
                Stages=[
                    codepipeline.Stages(
                        Name="Source",
                        Actions=[
                            codepipeline.Actions(
                                Name="CodeCommit",
                                ActionTypeId=codepipeline.ActionTypeId(
                                    Category="Source",
                                    Owner="AWS",
                                    Provider="CodeCommit",
                                    Version="1",
                                ),
                                Configuration={
                                    "RepositoryName": appsource.get_att("Name"),  # noqa
                                    "BranchName": "master",
                                },
                                OutputArtifacts=[
                                    codepipeline.OutputArtifacts(Name="CodeCommitRepo")
                                ],
                            ),
                        ],
                    ),
                    codepipeline.Stages(
                        Name="Build",
                        Actions=[
                            codepipeline.Actions(
                                Name="Build",
                                ActionTypeId=codepipeline.ActionTypeId(
                                    Category="Build",
                                    Owner="AWS",
                                    Provider="CodeBuild",
                                    Version="1",
                                ),
                                Configuration={"ProjectName": buildproject.ref()},
                                InputArtifacts=[
                                    codepipeline.InputArtifacts(Name="CodeCommitRepo")
                                ],
                            )
                        ],
                    ),
                ],
            )
        )