-
-
Save sashatu/0e1241443583bc9018de4cce6cc626f3 to your computer and use it in GitHub Desktop.
CloudFormation Template to deploy a CI/CD Pipeline for Terraform on AWS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AWSTemplateFormatVersion: 2010-09-09 | |
Description: Create an AWS-native IaC Pipeline for Terraform deployments. | |
Make sure that the Stack name is distinct across all AWS Regions for this account. | |
Parameters: | |
ExistingGitHubConnection: | |
Type: String | |
Description: Provide an existing GitHub Connection ARN or leave blank to create a new one | |
GitHubRepo: | |
Type: String | |
Description: Name of GitHub Repo to be used by the pipeline (user_name/repo_name) | |
GitHubBranch: | |
Type: String | |
Description: Name of GitHub Branch to be used by the pipeline | |
Default: main | |
BuildImageName: | |
Type: String | |
Description: Docker image for build projects - Ubuntu is recommended | |
Default: aws/codebuild/standard:7.0 | |
TerraformVersion: | |
Type: String | |
Description: Version of Terraform to be used by the pipeline | |
Default: 1.4.6 | |
Conditions: | |
NewGitHubConnection: !Equals | |
- "" | |
- !Ref ExistingGitHubConnection | |
Resources: | |
GitHubConnection: | |
Type: 'AWS::CodeStarConnections::Connection' | |
Properties: | |
ConnectionName: !If [NewGitHubConnection, !Sub "${AWS::StackName}-${AWS::AccountId}-github", !Sub "${AWS::StackName}-to_be_deleted"] | |
ProviderType: GitHub | |
PipelineBucket: | |
Type: 'AWS::S3::Bucket' | |
Properties: | |
BucketName: !Sub ${AWS::StackName}-${AWS::AccountId}-codepipeline | |
TerraformStateBucket: | |
Type: 'AWS::S3::Bucket' | |
Properties: | |
BucketName: !Sub ${AWS::StackName}-${AWS::AccountId}-tfstate | |
TerraformLockTable: | |
Type: AWS::DynamoDB::Table | |
Properties: | |
TableName: !Sub ${AWS::StackName}-${AWS::AccountId}-tflock | |
BillingMode: PAY_PER_REQUEST | |
AttributeDefinitions: | |
- | |
AttributeName: "LockID" | |
AttributeType: "S" | |
KeySchema: | |
- | |
AttributeName: "LockID" | |
KeyType: "HASH" | |
PipelineServiceRole: | |
Type: AWS::IAM::Role | |
Properties: | |
RoleName: !Sub ${AWS::StackName}-pipeline-service-role | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: sts:AssumeRole | |
Principal: | |
Service: | |
- codepipeline.amazonaws.com | |
- codebuild.amazonaws.com | |
Policies: | |
- PolicyName: !Sub ${AWS::StackName}-CodePipelineInlinePolicy | |
PolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Sid: UseGitHubConnection | |
Resource: '*' | |
Effect: Allow | |
Action: | |
- codestar-connections:UseConnection | |
- Sid: CodeBuildPermissions | |
Resource: '*' | |
Effect: Allow | |
Action: | |
- codebuild:StartBuild | |
- codebuild:BatchGetBuilds | |
- sns:Publish | |
- Sid: CloudWatchLogs | |
Resource: '*' | |
Effect: Allow | |
Action: | |
- logs:CreateLogGroup | |
- logs:CreateLogStream | |
- logs:PutLogEvents | |
- Sid: AccessPipelineBucket | |
Effect: Allow | |
Action: | |
- s3:Get* | |
- s3:ListBucket | |
Resource: | |
- !Sub arn:aws:s3:::${PipelineBucket} | |
- Sid: AccessPipelineBucketObjects | |
Effect: Allow | |
Action: | |
- s3:PutObject* | |
- s3:GetObject* | |
Resource: | |
- !Sub arn:aws:s3:::${PipelineBucket}/* | |
ProjectServiceRole: | |
Type: AWS::IAM::Role | |
Properties: | |
RoleName: !Sub ${AWS::StackName}-codebuild-role | |
AssumeRolePolicyDocument: | |
Version: '2012-10-17' | |
Statement: | |
- Effect: Allow | |
Action: sts:AssumeRole | |
Principal: | |
Service: | |
- codebuild.amazonaws.com | |
ManagedPolicyArns: | |
- arn:aws:iam::aws:policy/AdministratorAccess | |
TerraformPlanProject: | |
Type: AWS::CodeBuild::Project | |
Properties: | |
Name: !Sub ${AWS::StackName}-terraform-plan | |
Artifacts: | |
Type: CODEPIPELINE | |
Environment: | |
ComputeType: BUILD_GENERAL1_SMALL | |
Type: LINUX_CONTAINER | |
Image: !Ref BuildImageName | |
ServiceRole: !GetAtt ProjectServiceRole.Arn | |
LogsConfig: | |
CloudWatchLogs: | |
Status: ENABLED | |
Source: | |
Type: CODEPIPELINE | |
BuildSpec: !Sub | | |
version: 0.2 | |
env: | |
exported-variables: | |
- BuildID | |
- BuildTag | |
phases: | |
install: | |
commands: | |
- "curl -s https://releases.hashicorp.com/terraform/${TerraformVersion}/terraform_${TerraformVersion}_linux_amd64.zip -o terraform.zip" | |
- "unzip terraform.zip -d /usr/local/bin" | |
- "chmod 755 /usr/local/bin/terraform" | |
- "rm terraform.zip" | |
pre_build: | |
commands: | |
- terraform init -input=false -backend-config="bucket=${TerraformStateBucket}" -backend-config="key=${AWS::StackName}.tfstate" -backend-config="dynamodb_table=${TerraformLockTable}" -backend-config="region=${AWS::Region}" | |
build: | |
commands: | |
- terraform plan -lock=true -input=false -out=${AWS::StackName}-terraform.tfplan -no-color | |
artifacts: | |
name: TerraformPlan | |
files: | |
- ${AWS::StackName}-terraform.tfplan | |
TerraformApplyProject: | |
Type: AWS::CodeBuild::Project | |
Properties: | |
Name: !Sub ${AWS::StackName}-terraform-apply | |
Artifacts: | |
Type: CODEPIPELINE | |
Environment: | |
ComputeType: BUILD_GENERAL1_SMALL | |
Type: LINUX_CONTAINER | |
Image: !Ref BuildImageName | |
ServiceRole: !GetAtt ProjectServiceRole.Arn | |
LogsConfig: | |
CloudWatchLogs: | |
Status: ENABLED | |
Source: | |
Type: CODEPIPELINE | |
BuildSpec: !Sub | | |
version: 0.2 | |
env: | |
exported-variables: | |
- BuildID | |
- BuildTag | |
phases: | |
install: | |
commands: | |
- "curl -s https://releases.hashicorp.com/terraform/${TerraformVersion}/terraform_${TerraformVersion}_linux_amd64.zip -o terraform.zip" | |
- "unzip terraform.zip -d /usr/local/bin" | |
- "chmod 755 /usr/local/bin/terraform" | |
- "rm terraform.zip" | |
pre_build: | |
commands: | |
- terraform init -input=false -backend-config="bucket=${TerraformStateBucket}" -backend-config="key=${AWS::StackName}.tfstate" -backend-config="dynamodb_table=${TerraformLockTable}" -backend-config="region=${AWS::Region}" | |
build: | |
commands: | |
- cp $CODEBUILD_SRC_DIR_TerraformPlan/${AWS::StackName}-terraform.tfplan . | |
- terraform apply ${AWS::StackName}-terraform.tfplan | |
IaCPipeline: | |
Type: AWS::CodePipeline::Pipeline | |
Properties: | |
RoleArn: !GetAtt PipelineServiceRole.Arn | |
Name: !Sub ${AWS::StackName}-pipeline | |
ArtifactStores: | |
- Region: !Ref AWS::Region | |
ArtifactStore: | |
Type: S3 | |
Location: !Sub ${PipelineBucket} | |
Stages: | |
- Name: Get-GitHub-Source | |
Actions: | |
- Name: GitHub | |
RunOrder: 1 | |
ActionTypeId: | |
Category: Source | |
Provider: CodeStarSourceConnection | |
Owner: AWS | |
Version: '1' | |
Namespace: GitHubSource | |
OutputArtifacts: | |
- Name: GitHubCode | |
Configuration: | |
ConnectionArn: !If [NewGitHubConnection, !Ref GitHubConnection, !Ref ExistingGitHubConnection] | |
FullRepositoryId: !Ref GitHubRepo | |
BranchName: !Ref GitHubBranch | |
OutputArtifactFormat: CODE_ZIP | |
DetectChanges: true | |
- Name: Create-Terraform-Plan | |
Actions: | |
- Name: terraform_plan | |
RunOrder: 1 | |
Namespace: TFPlan | |
InputArtifacts: | |
- Name: GitHubCode | |
OutputArtifacts: | |
- Name: TerraformPlan | |
ActionTypeId: | |
Category: Build | |
Provider: CodeBuild | |
Owner: AWS | |
Version: '1' | |
Configuration: | |
ProjectName: !Ref TerraformPlanProject | |
- Name: Approve-Terraform-Plan | |
Actions: | |
- Name: review-plan | |
RunOrder: 1 | |
ActionTypeId: | |
Category: Approval | |
Provider: Manual | |
Owner: AWS | |
Version: '1' | |
- Name: Apply-Terraform-Plan | |
Actions: | |
- Name: terraform-apply | |
RunOrder: 1 | |
Namespace: TFApply | |
InputArtifacts: | |
- Name: GitHubCode | |
- Name: TerraformPlan | |
ActionTypeId: | |
Category: Build | |
Provider: CodeBuild | |
Owner: AWS | |
Version: '1' | |
Configuration: | |
ProjectName: !Ref TerraformApplyProject | |
PrimarySource: GitHubCode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment