![Build a CI/CD pipeline for CloudFormation and Cross-Account.](https://assets.community.aws/a/2dB6d3v5DwH8OLRsUU6Iv5jZ2Dk/1-pn.webp)
Build a CI/CD pipeline for CloudFormation and Cross-Account.
Step-by-step guide on creating a CI/CD for AWS CloudFormation StackSets with CodeCommit, CodeBuild, CodePipeline and S3 to Multi-Account deployments.
Published Mar 4, 2024
A CI/CD pipeline for AWS CloudFormation StackSets facilitates automated infrastructure deployment across multiple accounts. This pipeline streamlines managing and updating CloudFormation templates, ensuring consistency and compliance throughout the organization's AWS accounts. By automating the deployment process, teams can efficiently propagate changes, manage updates, and enforce best practices, promoting scalability, security, and operational efficiency.
I want to share a guide on how you can deploy and update your infrastructure on AWS with a CI/CD pipeline, AWS CloudFormation StackSets, and from an account (master or delegated account) to multiple accounts.
If your organization has several AWS accounts, I recommend that the deployment and updating of the infrastructure be done from an account that it delegates and belongs to the organization or from its master account (Root) to the other accounts that they have according to its purpose (production, development, test, etc.) In addition, I recommend using native AWS services such as CodeCommit (private Git repository), CodeBuild (continuous integration service), CodePipeline (continuous delivery service), and CloudFormation (Infrastructure as Code).
- AWS CloudFormation templates should be stored in a Git repository on CodeCommit to perform workflows that include code revisions and modifications, pull requests, and merge branches.
- The CodePipeline service should be used for the CI/CD pipeline and to automate the environment deployment process.
- The templates will be uploaded to a bucket in S3 so the CloudFormation stacks in the destination accounts can access them.
- AWS CloudFormation (Stack Set) service will be used in the central account ID:111111111111 to provision and manage the resources in the target accounts: dev-ID:222222222222, prod-ID:333333333333
- CodeBuild service must be used to perform a test and thus be able to check the availability of the deployed environment.
![CI/CD flow Figure 1](https://assets.community.aws/a/2dB8zeTGtDBFAdXpwPCdNGkEwZ0/1-pn.webp)
I make available some AWS CloudFormation templates that I created for this DEMO. You can get them from the following repository on GitHub:
There is a root template called kloudpepper-ROOT.yml, which is used to define the parameters that will be inserted in the infrastructure to be deployed and, in turn, calls the other separate templates by types of resources or services. The templates are made this way to have an organization when modifying values or data in that particular resource. I explain it better in the previous article:
Also, you're going to look at a JSON file called parameters-test.json. This file contains the parameters used in the environment to be deployed. For example, the CIDR of the VPC, the name of the environment, if it is a production or non-production environment type, and others. We will carry out the DEMO simulation of a non-productive environment.
Finally, the buildspec.yml file, which we will use to define a set of build commands in CodeBuild and check that the environment was deployed correctly.
1. In a delegated or root account, you must create an S3 bucket to deposit the templates and other files used to deploy the infrastructure on AWS and configure the CI/CD pipeline. To better understand, refer to Figure 1 and look at the pipeline. To create the Bucket, you must put the exact name you defined for the environment. This step is essential since, in the templates, there is a parameter that refers to this name. Therefore, they can't put different names on the templates' parameters and the Bucket's name.
Example:
![Buket's name Figure 2](https://assets.community.aws/a/2dBBuE9QlyLsVyzheUMhbEztvOs/2-pn.webp)
2. Insert the following policy in the Bucket created. You have to change the IDs
111111111111
and 222222222222
with the correct IDs that you have in your accounts. Also, you must modify the Resource value to the correct ARN (Bucket's ARN):3. It's necessary to create two (2) roles to delegate the administration permissions of the destination accounts to the account where the CI/CD pipeline will be configured (Cross-Account IAM Role). AWS has created two (2) CloudFormation templates to create the roles and permissions in the accounts. I share the templates in the Git repository.
3.1 In the delegate or main (Root) account, you can execute the following template in AWS CloudFormation:
Note: You don't have to insert parameters.
3.2 On the target accounts, execute the following template in AWS CloudFormation:
https://github.com/kloudpepper/IaC/blob/main/CloudFormation/extras/AWSCloudFormationStackSetExecutionRole.yml
https://github.com/kloudpepper/IaC/blob/main/CloudFormation/extras/AWSCloudFormationStackSetExecutionRole.yml
When you execute this template in AWS CloudFormation, it will insert the ID of the parent or delegate account (Root).
![Figure 3](https://assets.community.aws/a/2dBMWwNmhCuKFCDtJfk9iVZCu7P/3-pn.webp)
4. Create a CodeCommit repository:
I would like to configure the repository with approval rules and branches to control the template modifications. However, we won't be making those settings for this demo. Create the repository in CodeCommit and upload the templates found on GitHub:
![Figure 4](https://assets.community.aws/a/2dDZHyTHb6XeOil9JWALBqjbmNx/4-pn.webp)
![Figure 5](https://assets.community.aws/a/2dDZMINlHtIhioCVXY6OvTGQoMp/5-pn.webp)
5. Create a building project in CodeBuild and add the following parameters:
![Figure 6](https://assets.community.aws/a/2dDa9kANPDoqyRKiqhdkjMItKR2/6-pn.webp)
![Figure 7](https://assets.community.aws/a/2dDZzidlrxVdDxrppaDWZmHXgp4/7-pn.webp)
![Figure 8](https://assets.community.aws/a/2dDaW4vgTZl4W1U48XP1ZoWM6yC/8-pn.webp)
![Figure 9](https://assets.community.aws/a/2dDaZ9IGQQNt8O0KcC0DnfDMTtd/9-pn.webp)
![Figure 10](https://assets.community.aws/a/2dDabkd7HQqfIShavj1ZtYAlD5R/10-p.webp)
![Figure 11](https://assets.community.aws/a/2dDae90FKskT1Rr86LCBwTRMLfd/11-p.webp)
![Figure 12](https://assets.community.aws/a/2dDagYVjm12BelNW5hommr2pqeM/12-p.webp)
![Figure 13](https://assets.community.aws/a/2dDaifixznNsDeErqo1bnACcwbt/13-p.webp)
5.1 When you finish creating the project, a role is automatically created for execution. It's necessary to enter the project and find this role. A policy must then be inserted to assume the role of the target account. Follow the next steps:
![Figure 14](https://assets.community.aws/a/2dDalXiGwG2ma9COLwbyQzJM8tX/14-p.webp)
![Figure 15](https://assets.community.aws/a/2dDanrgRJEEUMgkjMjgKlgNksDZ/15-p.webp)
5.2 Create the following inline policy inside the role. Replace
222222222222
ID with the valid destination account ID:![Figure 16](https://assets.community.aws/a/2dDece8iLfP5UYtON9nnq5dJIGi/16-p.webp)
6. Create a pipeline in CodePipeline and add the following parameters:
![Figure 17](https://assets.community.aws/a/2dDqLFkD6QV2xP1uYqSrfHpsRCg/17-p.webp)
![Figure 18](https://assets.community.aws/a/2dDqP3XgbX6MUeL4ZMxV5kOvvn1/18-p.webp)
![Figure 19](https://assets.community.aws/a/2dDqRnqACflDZu6GWIm3PLnG2eJ/19-p.webp)
![Figure 20](https://assets.community.aws/a/2dDqfLN4dYD88AERpfyU5RPIFSu/20-p.webp)
![Figure 21](https://assets.community.aws/a/2dDqoEH46Xlbpl60eMPUAiwKW4K/21-p.webp)
6.1 Once you finish configuring the pipeline, it will automatically start executing. You must stop the execution so you can continue configuring the pipeline:
![Figure 22](https://assets.community.aws/a/2dDqwNT9L7GsbWdfO2uYuLRVRrj/22-p.webp)
![Figure 23](https://assets.community.aws/a/2dDrPEGP5xYpURB66Kto0AzJtep/23-p.webp)
6.2 Edit the pipeline:
![Figure 24](https://assets.community.aws/a/2dDrZdYXTGh1QkfeOTXoN2MfjH1/24-p.webp)
6.3 After the Source stage, add a new stage and enter a name:
![Figure 25](https://assets.community.aws/a/2dDriveKeu8980EPKixPEIjuXLA/25-p.webp)
![Figure 26](https://assets.community.aws/a/2dDrrZ5GKbrHLeq1eKRLdM9M9xk/26-p.webp)
6.4 Add an action in the Upload_S3 stage:
![Figure 27](https://assets.community.aws/a/2dDryTrdJ5Dqp313oo56QPAUoRY/27-p.webp)
6.5 Add the following parameters in the Upload_S3 action:
![Figure 28](https://assets.community.aws/a/2dDs8fvnxKORFpTVubvg1PsgITJ/28-p.webp)
![Figure 29](https://assets.community.aws/a/2dDsEdDN3q2YLzXBxSXCAupBLzM/29-p.webp)
6.6 Once you save the configuration in the Upload_S3 action, you have to save the stage:
![Figure 30](https://assets.community.aws/a/2dDsNYPV6j8ocjvOMDT6zxfkGxw/30-p.webp)
6.7 After the Deploy stage, add a new stage and enter a name:
![Figure 31](https://assets.community.aws/a/2dDsZqNgfPsc4HA63L5tzXuxhbk/31-p.webp)
![Figure 32](https://assets.community.aws/a/2dDsdgsypDKxoofJ1jyhrk4OMRS/32-p.webp)
6.8 Add an action in the Test stage:
![Figure 33](https://assets.community.aws/a/2dDsmwaArPkmQVAdMX8HV3We4Fq/33-p.webp)
6.9 Add the following parameters to the Test action:
![Figure 34](https://assets.community.aws/a/2dDt4TwTJCG4D5N896jCD46C4Nt/34-p.webp)
![Figure 35](https://assets.community.aws/a/2dDt8jlWlxvQq8XEf7HMYPNdlUO/35-p.webp)
6.10 Once you save the configuration in the Test action, you have to save the stage:
![Figure 36](https://assets.community.aws/a/2dDtSfbZN6CU1qdMZmEtH2snLND/36-p.webp)
6.11 Finally, save the pipeline:
![Figure 37](https://assets.community.aws/a/2dDtaT68LIAUzF9lybWPNZqzz9p/37-p.webp)
6.12 Disable EventBridge rule (optional):
Remember that we configured the pipeline so that CloudWatch Events automatically runs the pipeline every time there is a change in the CodeCommit repository. If you need to turn off this automatic process, you can go to EventBridge and disable the rule.
![Figure 38](https://assets.community.aws/a/2dDuMJvdjL3qXvFPdRabLMt31N5/38-p.webp)
1. Once you have created the pipeline in CodePipeline, go to the Release change button and execute it:
![Figure 39](https://assets.community.aws/a/2dDv6UKMyzu9DGW7r0nOxM9TrFk/39-p.webp)
1.2 Wait for the execution to finish and check the stages:
![Figure 40](https://assets.community.aws/a/2dDyzdWFF9bFsvhoL4IVrcVDIzK/40-p.webp)
![Figure 41](https://assets.community.aws/a/2dDz35wZZT1Rf6Pwueac7k63yCe/41-p.webp)
![Figure 42](https://assets.community.aws/a/2dDz5JwJApk6nN81DSLk2DZbvy9/42-p.webp)
![Figure 43](https://assets.community.aws/a/2dDz7hKkxRjf0Cx2oJR3JYIvwfg/43-p.webp)
1.3 In the master or delegate account, check the StackSets Operations:
![Figure 44](https://assets.community.aws/a/2dDz9wJ56fnam92MM00EsKto1lY/44-p.webp)
1.4 Finally, in the destination account, check the nested stacks:
![Figure 45](https://assets.community.aws/a/2dDzM0JXPGhSlMt3V2dIMYpkGUR/45-p.webp)
I hope that this article will be of great help to you. A big hug, and see you soon.
Thank you!