Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Commit of codepipeline cross account deployment example
- Loading branch information
Showing
6 changed files
with
500 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# AWS Code Pipeline to Cross Account Deployments | ||
--- | ||
AWS Code Pipeline is a powerful CI/DC tool that can perform deployments across AWS accounts. | ||
Sadly however the current available documentation/examples for doing this are complete rubbish. | ||
|
||
This is half a reference to myself on getting this working and a resource for others attempting to do this. | ||
![Diagram showing proposed architecture](doc-images/diagram.png) | ||
In this example we have 1 account that runs the pipeline, gets the code, performs the build. The another account that we deploy into. In this example we only have one account, but fairly easily this could be expanded to many accounts. | ||
|
||
--- | ||
### Getting this working | ||
|
||
At time of writing there is **ZERO** support in the AWS Console for doing this with code pipeline. | ||
Options are CLI and cloudformation, here I'm using yml based cloudformation templates. | ||
|
||
*warning, in some places I've used overly board permissions (ie admin * * ) which is bad! Please tune these to match the services your using and deploying to.* | ||
|
||
The templates are broken into two folders and should be deployed in the older listed here | ||
#### 1. Deploy Account: | ||
contains templates that need to be used in the following order | ||
1. *kms-cross-account.yml* - creates the KMS key and allows access from the Production account | ||
2. *code-build.yml* - sets up the codebuild job and exports the name via CFN export - you will need to customise this to your application build | ||
3. *code-pipeline.yml* - Sets up the code pipeline job itself (it won't work yet however) | ||
|
||
#### 2. Production Account: (actually all and any other accounts we want to deploy into) | ||
1. *iam-codepipeline-cross-account-deploy.yml* - Sets up two IAM roles, one for codepipleine to access from the deploy account and another thats used to run the cloudformation deploy. | ||
|
||
#### 3 One more thing | ||
Yes I said its all CF. Well its mostly CF, because this bit won't work with CF unless I create you a new bucket and well that's probably not ideal. | ||
|
||
You need to add a cross account bucket policy to your S3 bucket (the artifact store). | ||
|
||
The JSON below shows that bucket policy, Replace **YOURBUCKETNAMEHERE** with your artifact bucket name and **ProductionAccountNumber** with the number of your Production account. | ||
|
||
Obviously if you had multiple accounts that you were going to deploy into, make sure each one of them is represented here. | ||
|
||
```JSON | ||
{ | ||
"Version": "2012-10-17", | ||
"Id": "SSEAndSSLPolicy", | ||
"Statement": [ | ||
{ | ||
"Sid": "DenyUnEncryptedObjectUploads", | ||
"Effect": "Deny", | ||
"Principal": "*", | ||
"Action": "s3:PutObject", | ||
"Resource": "arn:aws:s3:::YOURBUCKETNAMEHERE/*", | ||
"Condition": { | ||
"StringNotEquals": { | ||
"s3:x-amz-server-side-encryption": "aws:kms" | ||
} | ||
} | ||
}, | ||
{ | ||
"Sid": "DenyInsecureConnections", | ||
"Effect": "Deny", | ||
"Principal": "*", | ||
"Action": "s3:*", | ||
"Resource": "arn:aws:s3:::YOURBUCKETNAMEHERE/*", | ||
"Condition": { | ||
"Bool": { | ||
"aws:SecureTransport": "false" | ||
} | ||
} | ||
}, | ||
{ | ||
"Sid": "", | ||
"Effect": "Allow", | ||
"Principal": { | ||
"AWS": "arn:aws:iam::ProductionAccountNumber:root" | ||
}, | ||
"Action": [ | ||
"s3:Get*", | ||
"s3:Put*" | ||
], | ||
"Resource": "arn:aws:s3:::YOURBUCKETNAMEHERE/*" | ||
}, | ||
{ | ||
"Sid": "", | ||
"Effect": "Allow", | ||
"Principal": { | ||
"AWS": "arn:aws:iam::ProductionAccountNumber:root" | ||
}, | ||
"Action": "s3:ListBucket", | ||
"Resource": "arn:aws:s3:::YOURBUCKETNAMEHERE" | ||
} | ||
] | ||
} | ||
``` | ||
|
||
--- | ||
|
||
### Other resources | ||
At the time of writing 2018-01-27 I'd found the following resources from AWS: | ||
|
||
* https://github.com/awslabs/aws-refarch-cross-account-pipeline - This is actually helpful except there are errors in their templates and it won't deploy (I found issues with their KMS template specifically). Some of the templates also treat the account id as a number, which is great except when your acc id starts with a 0 like several of my accounts do! Its also overly complicated, its a good reference. I do wish they had a better diagram for how the roles worked, because that's the hard part. | ||
|
||
* https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-create-cross-account.html - The official documentation. Its SO dense, no diagrams, I don't consider myself a beginner and frankly this document wasn't readable by me. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
AWSTemplateFormatVersion: "2010-09-09" | ||
Description: "code-build-services" | ||
|
||
Parameters: | ||
DockerImage: | ||
Type: String | ||
Description: The docker repo path to build image | ||
Default: node:6 | ||
|
||
KMSKeyArn: | ||
Description: ARN of the KMS key | ||
Type: String | ||
Default: 'arn:aws:kms:us-east-1:011111122222:key/606723ff-6e07-4f7a-b3b8-7e5b51aa2a28' | ||
|
||
|
||
Resources: | ||
CodeBuildProject: | ||
Type: AWS::CodeBuild::Project | ||
Properties: | ||
Name: !Ref AWS::StackName | ||
ServiceRole: !Ref CodeBuildRole | ||
EncryptionKey: !Ref KMSKeyArn | ||
Source: | ||
Type: CODEPIPELINE | ||
BuildSpec: | ||
!Sub | | ||
version: 0.2 | ||
phases: | ||
install: | ||
commands: | ||
- npm -g install yarn | ||
- 'echo "//registry.npmjs.org/:_authToken=${!NPM_TOKEN}" > ~/.npmrc' | ||
pre_build: | ||
commands: | ||
- yarn | ||
build: | ||
commands: | ||
- yarn build | ||
artifacts: | ||
files: | ||
- build/* | ||
discard-paths: yes | ||
|
||
Artifacts: | ||
Type: CODEPIPELINE | ||
Environment: | ||
Type: LINUX_CONTAINER | ||
ComputeType: BUILD_GENERAL1_SMALL | ||
Image: !Ref DockerImage | ||
|
||
TimeoutInMinutes: 15 | ||
|
||
|
||
CodeBuildRole: | ||
Type: AWS::IAM::Role | ||
Properties: | ||
AssumeRolePolicyDocument: | ||
Statement: | ||
- Action: ['sts:AssumeRole'] | ||
Effect: Allow | ||
Principal: | ||
Service: [codebuild.amazonaws.com] | ||
Version: '2012-10-17' | ||
Path: / | ||
Policies: | ||
- PolicyName: CodeBuildAccess | ||
PolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Action: | ||
- '*' | ||
Effect: Allow | ||
Resource: '*' | ||
|
||
|
||
Outputs: | ||
|
||
CodeBuild: | ||
Description: "FN export value for other " | ||
Value: !Ref AWS::StackName | ||
Export: | ||
Name: 'code-build-xaccount-export' |
157 changes: 157 additions & 0 deletions
157
code-pipeline-cross-account/deploy-account/code-pipeline.yml
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
AWSTemplateFormatVersion: "2010-09-09" | ||
Description: "Code pipeline Example Cross Account" | ||
|
||
Parameters: | ||
|
||
RepoName: | ||
Description: "Name of the repo to clone" | ||
Type: String | ||
Default: 'Test2' | ||
|
||
CodePipeLineBucket: | ||
Description: "The S3 bucket to use for codepipeline - bucket must already exist - example: codepipeline-us-east-1-773922028333" | ||
Type: String | ||
Default: 'codepipeline-us-east-1-011111122222' | ||
|
||
BranchName: | ||
Description: "The git branch to operate from" | ||
Type: String | ||
Default: 'master' | ||
|
||
ProdAccNumber: | ||
Description: "The account number of the account to perform the deployment into" | ||
Type: String | ||
Default: '33333322222' | ||
|
||
KMSKeyArn: | ||
Description: ARN of the KMS key to use | ||
Type: String | ||
Default: 'arn:aws:kms:us-east-1:011111122222:key/606723cf-6e08-4f7a-b4b8-7e5b50ee2a28' | ||
|
||
|
||
Resources: | ||
AppPipeline: | ||
Type: "AWS::CodePipeline::Pipeline" | ||
Properties: | ||
Name: !Ref AWS::StackName | ||
RoleArn: !GetAtt CodePipeLineRole.Arn | ||
Stages: | ||
- | ||
Name: Source | ||
Actions: | ||
- | ||
Name: Source | ||
ActionTypeId: | ||
Category: Source | ||
Owner: AWS | ||
Version: 1 | ||
Provider: CodeCommit | ||
OutputArtifacts: | ||
- | ||
Name: SourceCode | ||
Configuration: | ||
PollForSourceChanges: true | ||
BranchName: master | ||
RepositoryName: !Ref RepoName | ||
RunOrder: 1 | ||
- | ||
Name: BuildVersions | ||
Actions: | ||
- | ||
Name: CallCodeBuild | ||
ActionTypeId: | ||
Category: Build | ||
Owner: AWS | ||
Version: 1 | ||
Provider: CodeBuild | ||
InputArtifacts: | ||
- | ||
Name: SourceCode | ||
OutputArtifacts: | ||
- | ||
Name: DeployableArtifact | ||
Configuration: | ||
ProjectName: !ImportValue code-build-xaccount-export # | ||
# ^name of the code build job (this is deployed separately and we import from cloudformation export vals | ||
RunOrder: 1 | ||
|
||
- | ||
Name: DeployProd # Add addtional accounts by cloning this and calling it something else (like DeployStg) | ||
Actions: # Don't forget the additional account number parameter either | ||
- | ||
Name: cfnCreateChangeSet | ||
RoleArn: !Sub 'arn:aws:iam::${ProdAccNumber}:role/CodePipeline-Cross-Account-Role-Access' | ||
InputArtifacts: | ||
- | ||
Name: DeployableArtifact | ||
ActionTypeId: | ||
Category: Deploy | ||
Owner: AWS | ||
Version: 1 | ||
Provider: CloudFormation | ||
Configuration: | ||
ActionMode: CHANGE_SET_REPLACE | ||
Capabilities: CAPABILITY_IAM | ||
ChangeSetName: 'myawesomestack2-changeset' | ||
RoleArn: !Sub 'arn:aws:iam::${ProdAccNumber}:role/CodePipeline-cloudformation-deploy-role' | ||
StackName: 'myawesomestack2' | ||
TemplatePath: DeployableArtifact::template.json | ||
RunOrder: 1 | ||
- | ||
Name: cfnExecuteChangeSet | ||
RoleArn: arn:aws:iam::945437139977:role/CP-Cross-Account-Access | ||
ActionTypeId: | ||
Category: Deploy | ||
Owner: AWS | ||
Version: 1 | ||
Provider: CloudFormation | ||
Configuration: | ||
ActionMode: CHANGE_SET_EXECUTE | ||
ChangeSetName: 'myawesomestack2-changeset' | ||
StackName: 'myawesomestack2' | ||
RoleArn: !Sub 'arn:aws:iam::${ProdAccNumber}:role/CodePipeline-cloudformation-deploy-role' | ||
RunOrder: 2 | ||
|
||
|
||
ArtifactStore: | ||
Type: S3 | ||
Location: !Ref CodePipeLineBucket | ||
EncryptionKey: | ||
Id: !Ref KMSKeyArn | ||
Type: KMS | ||
|
||
CodePipeLineRole: | ||
Type: "AWS::IAM::Role" | ||
Properties: | ||
AssumeRolePolicyDocument: | ||
Version: "2012-10-17" | ||
Statement: | ||
- | ||
Effect: "Allow" | ||
Principal: | ||
Service: | ||
- "codepipeline.amazonaws.com" | ||
Action: | ||
- "sts:AssumeRole" | ||
Path: "/" | ||
Policies: | ||
- | ||
PolicyName: "code-pipeline-access" | ||
PolicyDocument: | ||
Version: "2012-10-17" | ||
Statement: | ||
- | ||
Effect: "Allow" | ||
Action: | ||
- "*" | ||
Resource: "*" | ||
|
||
Outputs: | ||
|
||
StackName: | ||
Description: "Stack Name" | ||
Value: !Ref AWS::StackName | ||
|
||
CodePipeLineJob: | ||
Description: "Name of the code pipeline job created" | ||
Value: !Ref AppPipeline |
50 changes: 50 additions & 0 deletions
50
code-pipeline-cross-account/deploy-account/kms-cross-account.yml
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
AWSTemplateFormatVersion: '2010-09-09' | ||
Description: Creates a KMS key and grants access to another account for access | ||
Parameters: | ||
|
||
ProductionAccount: | ||
Description: AWS Account Number for production | ||
Type: String | ||
Default: 33333322222 | ||
|
||
Resources: | ||
KMSKey: | ||
Type: AWS::KMS::Key | ||
Properties: | ||
Description: Used by Assumed Roles in Dev/Test/Prod accounts to Encrypt/Decrypt code | ||
EnableKeyRotation: true | ||
KeyPolicy: | ||
Version: "2012-10-17" | ||
Id: !Ref AWS::StackName | ||
Statement: | ||
- | ||
Sid: Allows admin of the key | ||
Effect: Allow | ||
Principal: | ||
AWS: !Sub arn:aws:iam::${AWS::AccountId}:root | ||
Action: | ||
- kms:* | ||
Resource: "*" | ||
- | ||
Sid: Allow use of key in another account | ||
Effect: Allow | ||
Principal: | ||
AWS: | ||
- !Sub arn:aws:iam::${ProductionAccount}:root | ||
# If adding additional accounts put them just in here! and add the parameter up the top! | ||
Action: | ||
- kms:Encrypt | ||
- kms:Decrypt | ||
- kms:ReEncrypt* | ||
- kms:GenerateDataKey* | ||
- kms:DescribeKey | ||
Resource: "*" | ||
KMSAlias: | ||
Type: AWS::KMS::Alias | ||
Properties: | ||
AliasName: alias/codepipeline-crossaccount-key | ||
TargetKeyId: !Ref KMSKey | ||
|
||
Outputs: | ||
KMSKeyArn: | ||
Value: !GetAtt [KMSKey,Arn] |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.