You have setup CodePipeline for continuous integration and continuous delivery. You are using CloudFormation to deploy the resources. Whenever there is change in property of one of these resources, CloudFormation shows one of the below behaviour to make the change to the resource in the stack-

>>Update with no interruption: Your resource is updated in place without any disruption to normal use.

>>Update with some interruption: Your resource is still the same resource, but there will be some downtime as the update is applied.

>>Replacement: An entirely new resource is created to replace your existing resource. Recreating the resource generates a new physical ID. AWS CloudFormation then deletes the old resource.

You can prevent stack resources from being unintentionally updated or deleted during a stack update by using a stack policy. A stack policy is a JSON document that defines the update actions that can be performed on designated resources.

After you set a stack policy, all of the resources in the stack are protected by default. To allow updates on specific resources, you specify an explicit Allow statement for those resources in your stack policy. You can define only one stack policy per stack, but, you can protect multiple resources within a single policy. A stack policy applies to all AWS CloudFormation users who attempt to update the stack. You can’t associate different stack policies with different users.

You can find more details on How to protect resources in CloudFormation Stack from being Deleted or Replaced using Stack Policy

 

In this article we will see how CodePipeline can be used to execute this stack policy every time new Stack is Created.

I have the project source code in GitHub. The CodeBuild will produce the build artifact from GitHub. The Stack Policy JSON file is saved in S3 bucket (in zip format). This way the access to change stack policy will be with limited users. This S3 bucket will be configured as second source in CodePipeline.

Build stage will provide build output artifact and then in Deploy stage (using CloudFormation) the Stack will be created and the Stack policy will be applied.

 

Steps:

>>Create CodePipeline using the below JSON script-

 

{
    "pipeline": {
        "name": "Clipipelinestack",
        "roleArn": "arn:aws:iam::103414563212260:role/service-role/AWSCodePipelineServiceRole-ap-southeast-2-stackpolicy",
        "artifactStore": {
            "type": "S3",
            "location": "codepipeline-ap-southeast-2-76344657653255"
        },
        "stages": [
            {
                "name": "Source",
                "actions": [
                    {
                        "name": "Source1",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "ThirdParty",
                            "provider": "GitHub",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "Branch": "MultiProjectTest",
                            "OAuthToken": "*********",
                            "Owner": "TestSoftware",
                            "PollForSourceChanges": "false",
                            "Repo": "raaviblog.test"
                        },
                        "outputArtifacts": [
                            {
                                "name": "MobileApp"
                            }
                        ],
                        "inputArtifacts": []
                    },
					{
                        "name": "Source2",
                        "actionTypeId": {
                            "category": "Source",
                            "owner": "AWS",
                            "provider": "S3",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "S3Bucket": "stackpolicytest",
                            "S3ObjectKey": "stack_policy.zip"
                        },
                        "outputArtifacts": [
                            {
                                "name": "StackApp"
                            }
                        ],
                        "inputArtifacts": []
                    }
                ]
            },
            {
                "name": "Build",
                "actions": [
                    {
                        "name": "Build",
                        "actionTypeId": {
                            "category": "Build",
                            "owner": "AWS",
                            "provider": "CodeBuild",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ProjectName": "TestProject",
			    "PrimarySource": "MobileApp"
                        },
                        "outputArtifacts": [
                            {
                                "name": "MobileAppBuild"
                            }
                        ],
                        "inputArtifacts": [
                            {
                                "name": "MobileApp"
                            }
                        ]
                    }
                ]
            },
            {
                "name": "Deploy",
                "actions": [
                    {
                        "name": "Applystackpolicy",
                        "actionTypeId": {
                            "category": "Deploy",
                            "owner": "AWS",
                            "provider": "CloudFormation",
                            "version": "1"
                        },
                        "runOrder": 1,
                        "configuration": {
                            "ActionMode": "CREATE_UPDATE",
                            "Capabilities": "CAPABILITY_NAMED_IAM,CAPABILITY_AUTO_EXPAND",
                            "ParameterOverrides": "",
                            "RoleArn": "arn:aws:iam::103414563212260:role/codepipelinecloudformationrole",
                            "StackName": "teststack",
                            "TemplateConfiguration": "StackApp::stack_policy.json",
                            "TemplatePath": "MobileAppBuild::serverless.template.json"
                        },
                        "outputArtifacts": [],
                        "inputArtifacts": [
                            {
                                "name": "StackApp"
                            },
                            {
                                "name": "MobileAppBuild"
                            }
                        ]
                    }
                ]
            }
        ],
        "version": 1
    }
}

 

Script Details-

>> Clipipelinestack: CodePipeline with this name will be created. It will have 2 sources, 1 build stage and 1 deploy stage created.

>>AWSCodePipelineServiceRole-ap-southeast-2-stackpolicy: This is an IAM ARN for a service role.

>>codepipeline-ap-southeast-2-76344657653255: The name of the Amazon S3 bucket automatically generated for you the first time you create a pipeline using the console, such as codepipeline-us-east-2-1234567890, or any Amazon S3 bucket you provision for this purpose.

>>Source: This will have all source stages in it. No need to change the name.

>>Source1: The name of first source stage. Provide name as you like.

>>GitHub:The first source provider is GitHub.

>>OAuthToken: Provide OAuth token for the GitHub project.

>>MobileApp: This will be the output artifact name from Source1. It will be saved in S3 bucket – codepipeline-ap-southeast-2-76344657653255

>>Source2: The name of second source stage. Provide name as you like.

>>S3: The first source provider is S3 bucket.

>>stackpolicytest: The stack policy in zip format is saved in this bucket.

>>StackApp: This is the output artifact name from Source2. It will be saved in S3 bucket – codepipeline-ap-southeast-2-76344657653255

>>Build: This will have Build stages. No need to change the name.

>>CodeBuild: AWS Codebuild is the provider. This will have MobileApp as input artifact and MobileAppBuild as output artifact. The CodeBuild will use project TestProject to create the build artifact.

>>Deploy: This is Deploy Stage and provider  CloudFormation will start creating the resource based on the resource template “MobileAppBuild::serverless.template.json” provided.

>>TemplateConfiguration: Provide the stack policy template here. StackApp::stack_policy.json

>>CREATE_UPDATE: This action will create the stack and apply the stack policy.

>>Deploy stage will use “StackApp” and “MobileAppBuild” as input artifacts.

 

Execute the JSON script using AWS CLI-

aws codepipeline create-pipeline --cli-input-json file://C:\personal\aws\codepipelinecli_deploy.json

 

This way you can use the CodePipeline to automate the application of the stack policy to protect the stack created.

Note: You can not apply this stack policy using “CHANGE_SET_REPLACE” action. Create Change set will not apply the stack policy.