Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
670 lines (664 sloc) 25.8 KB
Description: Create a CodePipeline to include Nested CloudFormation, CodeBuild and Approval steps.
Parameters:
CFNTemplateRepoName:
Type: String
Description: Name of the repo which contains CFN template.
ValidateResourcesRepoName:
Type: String
Description: Name of the repo which contains test script to validate the reosurces.
UATTopic:
Type: String
Description: Name of the SNS topic in same region to send UAT approval notification.
ProdTopic:
Type: String
Description: Name of the SNS topic in same region to send Production approval notification.
ArtifactStoreS3Location:
Type: String
Description: Name of the S3 bucket to store CodePipeline artificat.
Resources:
CodePipelineRole:
Type: "AWS::IAM::Role"
Properties:
RoleName:
Fn::Sub: CodePipelineRole-${AWS::StackName}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "codepipeline.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /
Policies:
-
PolicyName: "CodePipelineNestedCFNAccessPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "s3:DeleteObject"
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:ListBucket"
- "s3:PutObject"
- "s3:GetBucketPolicy"
Resource:
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}/*
-
Effect: "Allow"
Action:
- "sns:Publish"
Resource:
- Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${UATTopic}
- Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ProdTopic}
-
Effect: "Allow"
Action:
- "codecommit:ListBranches"
- "codecommit:ListRepositories"
- "codecommit:BatchGetRepositories"
- "codecommit:Get*"
- "codecommit:GitPull"
- "codecommit:UploadArchive"
Resource:
- Fn::Sub: arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${CFNTemplateRepoName}
- Fn::Sub: arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${ValidateResourcesRepoName}
-
Effect: "Allow"
Action:
- "cloudformation:CreateChangeSet"
- "cloudformation:CreateStack"
- "cloudformation:CreateUploadBucket"
- "cloudformation:DeleteStack"
- "cloudformation:Describe*"
- "cloudformation:List*"
- "cloudformation:UpdateStack"
- "cloudformation:ValidateTemplate"
- "cloudformation:ExecuteChangeSet"
Resource:
- Fn::Sub: arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/Test-${AWS::StackName}*
- Fn::Sub: arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/UAT-${AWS::StackName}*
- Fn::Sub: arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/Prod-${AWS::StackName}*
-
Effect: "Allow"
Action:
- "codebuild:StartBuild"
- "codebuild:BatchGetBuilds"
Resource:
- Fn::Sub: arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/BuildCopyCFN-${AWS::StackName}
- Fn::Sub: arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/ValidateResource-${AWS::StackName}
- Fn::Sub: arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/BuildCopyCFN-${AWS::StackName}:*
- Fn::Sub: arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:build/ValidateResource-${AWS::StackName}:*
-
Effect: "Allow"
Action:
- "iam:PassRole"
Resource:
- Fn::Sub: arn:aws:iam::${AWS::AccountId}:role/CloudFormationRole-${AWS::StackName}
CloudFormationRole:
Type: "AWS::IAM::Role"
Properties:
RoleName:
Fn::Sub: CloudFormationRole-${AWS::StackName}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "cloudformation.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /
Policies:
-
PolicyName: "CloudFormationNestedCFNAccessPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "iam:AddRoleToInstanceProfile"
- "iam:AttachRolePolicy"
- "iam:CreateInstanceProfile"
- "iam:CreatePolicy"
- "iam:CreateRole"
- "iam:DeleteInstanceProfile"
- "iam:DeletePolicy"
- "iam:DeleteRole"
- "iam:DeleteRolePolicy"
- "iam:DetachRolePolicy"
- "iam:GetInstanceProfile"
- "iam:GetPolicy"
- "iam:GetRole"
- "iam:GetRolePolicy"
- "iam:ListAttachedRolePolicies"
- "iam:ListInstanceProfiles"
- "iam:ListInstanceProfilesForRole"
- "iam:ListRolePolicies"
- "iam:ListRoles"
- "iam:PassRole"
- "iam:PutRolePolicy"
- "iam:RemoveRoleFromInstanceProfile"
Resource:
- Fn::Sub: arn:aws:iam::${AWS::AccountId}:role/WebServerIAMRole-*
-
Effect: "Allow"
Action:
- "ec2:Describe*"
- "ec2:CreateSecurityGroup"
- "autoscaling:Describe*"
- "elasticloadbalancing:Describe*"
- "elasticloadbalancing:CreateLoadBalancer"
- "autoscaling:CreateAutoScalingGroup"
- "autoscaling:CreateLaunchConfiguration"
Resource:
- "*"
-
Effect: "Allow"
Action:
- "ec2:AttachNetworkInterface"
- "ec2:AttachVolume"
- "ec2:AuthorizeSecurityGroupIngress"
- "ec2:CreateNetworkInterface"
- "ec2:CreateTags"
- "ec2:CreateVolume"
- "ec2:DeleteSecurityGroup"
- "ec2:DeleteTags"
- "ec2:DeleteVolume"
- "ec2:DetachNetworkInterface"
- "ec2:DetachVolume"
- "ec2:MonitorInstances"
- "ec2:RebootInstances"
- "ec2:ReleaseAddress"
- "ec2:RunInstances"
- "ec2:StartInstances"
- "ec2:StopInstances"
- "ec2:TerminateInstances"
- "ec2:UnmonitorInstances"
Resource:
- Fn::Sub: arn:aws:ec2:${AWS::Region}::image/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:internet-gateway/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:key-pair/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:network-interface/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:subnet/*
- Fn::Sub: arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:volume/*
-
Effect: "Allow"
Action:
- "iam:AddRoleToInstanceProfile"
- "iam:CreateInstanceProfile"
- "iam:DeleteInstanceProfile"
- "iam:GetInstanceProfile"
- "iam:ListInstanceProfiles"
- "iam:ListInstanceProfilesForRole"
- "iam:RemoveRoleFromInstanceProfile"
Resource:
- Fn::Sub: arn:aws:iam::${AWS::AccountId}:instance-profile/Test-${AWS::StackName}-SecurityStack*
- Fn::Sub: arn:aws:iam::${AWS::AccountId}:instance-profile/UAT-${AWS::StackName}-SecurityStack*
- Fn::Sub: arn:aws:iam::${AWS::AccountId}:instance-profile/Prod-${AWS::StackName}-SecurityStack*
-
Effect: "Allow"
Action:
- "rds:AddTagsToResource"
- "rds:CreateDBInstance"
- "rds:CreateDBSecurityGroup"
- "rds:DeleteDBInstance"
- "rds:DeleteDBSecurityGroup"
- "rds:DescribeDBInstances"
- "rds:DescribeDBParameterGroups"
- "rds:DescribeDBParameters"
- "rds:DescribeDBSecurityGroups"
- "rds:DescribeDBSubnetGroups"
- "rds:DescribeOptionGroups"
- "rds:ModifyDBInstance"
- "rds:RebootDBInstance"
- "rds:RemoveTagsFromResource"
Resource:
- Fn::Sub: arn:aws:rds:${AWS::Region}:${AWS::AccountId}:db:*
- Fn::Sub: arn:aws:rds:${AWS::Region}:${AWS::AccountId}:og:*
- Fn::Sub: arn:aws:rds:${AWS::Region}:${AWS::AccountId}:pg:*
- Fn::Sub: arn:aws:rds:${AWS::Region}:${AWS::AccountId}:secgrp:*
- Fn::Sub: arn:aws:rds:${AWS::Region}:${AWS::AccountId}:subgrp:*
-
Effect: "Allow"
Action:
- "elasticloadbalancing:AddTags"
- "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer"
- "elasticloadbalancing:AttachLoadBalancerToSubnets"
- "elasticloadbalancing:ConfigureHealthCheck"
- "elasticloadbalancing:CreateListener"
- "elasticloadbalancing:CreateLoadBalancerListeners"
- "elasticloadbalancing:CreateLoadBalancerPolicy"
- "elasticloadbalancing:DeleteListener"
- "elasticloadbalancing:DeleteLoadBalancer"
- "elasticloadbalancing:DeleteLoadBalancerListeners"
- "elasticloadbalancing:DeleteLoadBalancerPolicy"
- "elasticloadbalancing:DeregisterInstancesFromLoadBalancer"
- "elasticloadbalancing:DetachLoadBalancerFromSubnets"
- "elasticloadbalancing:ModifyListener"
- "elasticloadbalancing:ModifyLoadBalancerAttributes"
- "elasticloadbalancing:RegisterInstancesWithLoadBalancer"
- "elasticloadbalancing:RemoveTags"
- "elasticloadbalancing:SetSecurityGroups"
- "elasticloadbalancing:SetSubnets"
- "elasticloadbalancing:SetLoadBalancerPoliciesOfListener"
- "elasticloadbalancing:EnableAvailabilityZonesForLoadBalancer"
- "elasticloadbalancing:DisableAvailabilityZonesForLoadBalancer"
Resource:
- Fn::Sub: arn:aws:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:loadbalancer/WebELB-*
-
Effect: "Allow"
Action:
- "autoscaling:AttachInstances"
- "autoscaling:AttachLoadBalancers"
- "autoscaling:CreateOrUpdateTags"
- "autoscaling:DeleteAutoScalingGroup"
- "autoscaling:DeleteLaunchConfiguration"
- "autoscaling:DeleteTags"
- "autoscaling:SetDesiredCapacity"
- "autoscaling:SetInstanceHealth"
- "autoscaling:TerminateInstanceInAutoScalingGroup"
- "autoscaling:UpdateAutoScalingGroup"
Resource:
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/Test-${AWS::StackName}-ServerStack-*
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/UAT-${AWS::StackName}-ServerStack-*
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/Prod-${AWS::StackName}-ServerStack-*
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:launchConfiguration:${AWS::AccountId}:*:Test-${AWS::StackName}-ServerStack-*
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:launchConfiguration:${AWS::AccountId}:*:UAT-${AWS::StackName}-ServerStack-*
- Fn::Sub: arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:launchConfiguration:${AWS::AccountId}:*:Prod-${AWS::StackName}-ServerStack-*
-
Effect: "Allow"
Action:
- "s3:GetObject"
- "s3:ListBucket"
Resource:
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}/*
CodeBuildRole:
Type: "AWS::IAM::Role"
Properties:
RoleName:
Fn::Sub: CodeBuildRole-${AWS::StackName}
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "codebuild.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: /service-role/
Policies:
-
PolicyName: "CodeBuildNestedCFNAccessPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "cloudformation:Get*"
- "cloudformation:Describe*"
- "cloudformation:List*"
Resource:
- Fn::Sub: arn:aws:cloudformation:${AWS::Region}:${AWS::AccountId}:stack/Test-${AWS::StackName}*
-
Effect: "Allow"
Action:
- "codecommit:ListBranches"
- "codecommit:ListRepositories"
- "codecommit:BatchGetRepositories"
- "codecommit:Get*"
- "codecommit:GitPull"
Resource:
- Fn::Sub: arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${CFNTemplateRepoName}
- Fn::Sub: arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${ValidateResourcesRepoName}
-
Effect: "Allow"
Action:
- "ec2:Describe*"
- "cloudformation:ValidateTemplate"
- "elasticloadbalancing:Describe*"
- "autoscaling:Describe*"
- "iam:Get*"
- "iam:List*"
- "logs:Describe*"
- "logs:Get*"
- "tag:Get*"
Resource:
- "*"
-
Effect: "Allow"
Action:
- "logs:CreateLogGroup"
- "logs:CreateLogStream"
- "logs:PutLogEvents"
Resource:
- Fn::Sub: arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/codebuild/*
-
Effect: "Allow"
Action:
- "s3:PutObject"
- "s3:GetObject"
- "s3:GetObjectVersion"
- "s3:ListBucket"
Resource:
- Fn::Sub: arn:aws:s3:::codepipeline-${AWS::Region}-*
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}/*
- Fn::Sub: arn:aws:s3:::${ArtifactStoreS3Location}
BuildCopyCFNProject:
Type: AWS::CodeBuild::Project
Properties:
Name:
Fn::Sub: BuildCopyCFN-${AWS::StackName}
Description: Build to validate and copy CFN templates
ServiceRole:
Fn::GetAtt: [ CodeBuildRole, Arn ]
Artifacts:
Type: S3
Location:
Ref: ArtifactStoreS3Location
Name:
Fn::Sub: BuildCopyCFN-${AWS::StackName}
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/nodejs:7.0.0
EnvironmentVariables:
- Name: TEMPLATE_BUCKET
Value:
Ref: ArtifactStoreS3Location
- Name: TEMPLATE_PREFIX
Value: codebuild
Source:
Location:
Fn::Sub: https://git-codecommit.eu-west-1.amazonaws.com/v1/repos/${CFNTemplateRepoName}
Type: CODECOMMIT
TimeoutInMinutes: 15
EncryptionKey:
Fn::Sub: arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3
Tags:
- Key: Name
Value:
Fn::Sub: BuildCopyCFN-${AWS::StackName}
ValidateResourceProject:
Type: AWS::CodeBuild::Project
Properties:
Name:
Fn::Sub: ValidateResource-${AWS::StackName}
Description: Test build to validate the resources created by CFN templates
ServiceRole:
Fn::GetAtt: [ CodeBuildRole, Arn ]
Artifacts:
Type: S3
Location:
Ref: ArtifactStoreS3Location
Name:
Fn::Sub: ValidateResource-${AWS::StackName}
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/python:2.7.12
Source:
Location:
Fn::Sub: https://git-codecommit.eu-west-1.amazonaws.com/v1/repos/${ValidateResourcesRepoName}
Type: CODECOMMIT
TimeoutInMinutes: 15
EncryptionKey:
Fn::Sub: arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/aws/s3
Tags:
- Key: Name
Value:
Fn::Sub: ValidateResource-${AWS::StackName}
DeployPipeline:
Type: "AWS::CodePipeline::Pipeline"
Properties:
Name:
Fn::Sub: ContinuousDeliveryNestedCFN-${AWS::StackName}
RoleArn:
Fn::GetAtt: [ CodePipelineRole, Arn ]
Stages:
-
Name: CFNSource
Actions:
-
Name: CFNTemplateSource
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
OutputArtifacts:
-
Name: CFNTemplateOutput
Configuration:
BranchName: master
RepositoryName:
Ref: CFNTemplateRepoName
RunOrder: 1
-
Name: TestArtifactSource
ActionTypeId:
Category: Source
Owner: AWS
Version: 1
Provider: CodeCommit
OutputArtifacts:
-
Name: TestArtifacts
Configuration:
BranchName: master
RepositoryName:
Ref: ValidateResourcesRepoName
RunOrder: 1
-
Name: Validate
Actions:
-
Name: CodeBuild
InputArtifacts:
- Name: CFNTemplateOutput
ActionTypeId:
Category: Build
Owner: AWS
Version: 1
Provider: CodeBuild
OutputArtifacts:
-
Name: CFNTemplateArtifact
Configuration:
ProjectName:
Ref: BuildCopyCFNProject
RunOrder: 1
-
Name: CreateTestCFNStack
InputArtifacts:
-
Name: CFNTemplateArtifact
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
-
Name: CreatedTestCFNStack
Configuration:
ActionMode: CREATE_UPDATE
RoleArn:
Fn::GetAtt: [ CloudFormationRole, Arn ]
Capabilities: CAPABILITY_NAMED_IAM
StackName:
Fn::Sub: Test-${AWS::StackName}
TemplateConfiguration: CFNTemplateArtifact::config-test.json
TemplatePath: CFNTemplateArtifact::master-stack.yml
RunOrder: 2
-
Name: ValidateTestStack
InputArtifacts:
-
Name: TestArtifacts
ActionTypeId:
Category: Test
Owner: AWS
Version: 1
Provider: CodeBuild
OutputArtifacts:
-
Name: ValidatedTestStack
Configuration:
ProjectName:
Ref: ValidateResourceProject
RunOrder: 3
-
Name: DeleteTestStack
InputArtifacts:
-
Name: ValidatedTestStack
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
-
Name: ProceedToUAT
Configuration:
StackName:
Fn::Sub: Test-${AWS::StackName}
ActionMode: DELETE_ONLY
RoleArn:
Fn::GetAtt: [ CloudFormationRole, Arn ]
RunOrder: 4
-
Name: UAT
Actions:
-
Name: CreateUATChangeSet
InputArtifacts:
-
Name: CFNTemplateArtifact
-
Name: ProceedToUAT
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
-
Name: CreatedUATChangeSet
Configuration:
ActionMode: CHANGE_SET_REPLACE
ChangeSetName: UATCBChangeSet
RoleArn:
Fn::GetAtt: [ CloudFormationRole, Arn ]
Capabilities: CAPABILITY_NAMED_IAM
StackName:
Fn::Sub: UAT-${AWS::StackName}
TemplateConfiguration: CFNTemplateArtifact::config-uat.json
TemplatePath: CFNTemplateArtifact::master-stack.yml
RunOrder: 1
-
Name: ExecuteUATChangeSet
InputArtifacts:
-
Name: CreatedUATChangeSet
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
-
Name: DeployedUAT
Configuration:
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: UATCBChangeSet
StackName:
Fn::Sub: UAT-${AWS::StackName}
RunOrder: 2
-
Name: UATApproval
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
Configuration:
NotificationArn:
Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${UATTopic}
CustomData: Approve once UAT has been completed.
RunOrder: 3
-
Name: Production
Actions:
-
Name: CreateProdChangeSet
InputArtifacts:
-
Name: CFNTemplateArtifact
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
OutputArtifacts:
-
Name: CreatedProdChangeSet
Configuration:
ActionMode: CHANGE_SET_REPLACE
ChangeSetName: ProdCBChangeSet
RoleArn:
Fn::GetAtt: [ CloudFormationRole, Arn ]
Capabilities: CAPABILITY_NAMED_IAM
StackName:
Fn::Sub: Prod-${AWS::StackName}
TemplateConfiguration: CFNTemplateArtifact::config-prod.json
TemplatePath: CFNTemplateArtifact::master-stack.yml
RunOrder: 1
-
Name: ProdApproval
ActionTypeId:
Category: Approval
Owner: AWS
Version: 1
Provider: Manual
Configuration:
NotificationArn:
Fn::Sub: arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ProdTopic}
CustomData: Approve deployment in production.
RunOrder: 2
-
Name: DeployProduction
InputArtifacts:
-
Name: CreatedProdChangeSet
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
Configuration:
ActionMode: CHANGE_SET_EXECUTE
ChangeSetName: ProdCBChangeSet
StackName:
Fn::Sub: Prod-${AWS::StackName}
RunOrder: 3
ArtifactStore:
Type: S3
Location:
Ref: ArtifactStoreS3Location
You can’t perform that action at this time.