AWS CodePipeline with a Cross-Account CodeCommit Repository
Deploy resources using AWS CodePipeline from CodeCommit repository from another AWS account.
If you are using an approach wherein you want to deploy DEV, UAT, PROD, QA etc. application environments from single CodeCommit repository from another AWS account based on the CodeCommit branches using CodePipeline, you are on the right place.
For the sake of the explanation, let’s consider that you have two different AWS accounts: Account DEV for your dev environment and Account PROD for your prod application environment. DEV AWS account is where your CodeCommit repository sits and you deploy your dev environment using the CodePipeline in this account which gets triggered based on the “dev” branch. When the changes are deployed in the DEV account and they are tested by someone who confirms them to be deployed on prod, you need to merge the changes to master branch which should automatically deploy those changes to your PROD AWS account. I am assuming that you have already configured the CodePipeline in your PROD Account. In addition, I am also assuming that your CodeCommit repository has two branches named “dev” and “prod”
Let’s get started with the steps that need to be in place to configure this:
You must create an AWS Customer Managed Encryption Key since you cannot edit AWS managed kms’s key policy, add the key to the pipeline in PROD account, set up policies and roles to enable cross account access. See the steps below in PROD account:
- Create an AWS KMS Encryption Key (Follow the steps if you need assistance in creating KMS key https://docs.aws.amazon.com/codepipeline/latest/userguide/pipelines-create-cross-account.html).
- Please make sure you add your CodePipeline service role ARN to the KMS Key Policy in the “Key users” section.
- Go to S3, select the S3 bucket where the pipeline artifacts are stored. if you cannot find the S3 pipeline artifacts bucket, then you can describe your pipeline using the following command which will return your pipeline details in JSON format.
aws codepipeline get-pipeline — name name-of-your-pipeline
- Go to S3 Artifact Bucket → Permissions → Add the following Bucket Policy
{
“Version”: “2012–10–17”,
“Id”: “PolicyForKMSAccess”,
“Statement”: [
{
“Sid”: “DenyUnencryptedObjects”,
“Effect”: “Deny”,
“Principal”: “*”,
“Action”: “s3:PutObject”,
“Resource”: “arn:aws:s3:::NAME-OF-THE-BUCKET/*”,
“Condition”: {
“StringNotEquals”: {
“s3:x-amz-server-side-encryption”: “aws:kms”
}
}
},
{
“Sid”: “AllowAccessFromDevAccount”,
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::DEV-AWS-ACCOUNT_ID:root”
},
“Action”: [
“s3:Get*”,
“s3:Put*”
],
“Resource”: “arn:aws:s3:::NAME-OF-THE-BUCKET/*”
},
{
“Sid”: “AllowListObjects”,
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::DEV-AWS-ACCOUNT_ID:root”
},
“Action”: “s3:ListBucket”,
“Resource”: “arn:aws:s3:::NAME-OF-THE-BUCKET”
}
]
}
- Add the following policy to your CodePipeline service role so it can get access to assume role on DEV account.
{
“Version”: “2012–10–17”,
“Statement”: {
“Effect”: “Allow”,
“Action”: “sts:AssumeRole”,
“Resource”: [
“arn:aws:iam::DEV_AWS_ACCOUNT_ID:role/*
]
}
}
- Create “Event Bus” in PROD account to receive the codecommit events from DEV account when master branch receives updates. Go to CloudWatch → Event Buses under Events section → Add Permission → Enter DEV AWS Account Id → Add.
- Create a CloudWatch Event Rule in PROD account to trigger the pipeline on master branch of the CodeCommit in DEV account. Go to CloudWatch → Rules → Create Rule → Click “Edit” under Event Pattern Preview, Paste the following pattern:
{
“detail-type”: [
“CodeCommit Repository State Change”
],
“resources”: [
“arn:aws:codecommit:REGION:DEV-AWS-ACCOUNT-ID:REPO-NAME-IN-DEV-ACCOUNT”
],
“source”: [
“aws.codecommit”
],
“detail”: {
“referenceType”: [
“branch”
],
“event”: [
“referenceCreated”,
“referenceUpdated”
],
“referenceName”: [
“master”
]
}
}
Add PROD Account’s CodePipeline ARN as a target of this rule and click “Next”. Enter an appropriate name for the rule and Create.
That’s all you need to do in your PROD AWS account to make it work.
Now, we need to set up DEV account to allow the PROD pipeline’s artifact bucket to extract the CodeCommit repository when the merge/push happens. Follow the steps below:
- Create an IAM Policy that lets PROD account to access the CodeCommit resources and also the KMS key so it can encrypt them with the same key as the rest of your CodePipeline. Here is the policy:
{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“s3:GetObject*”,
“s3:PutObject”,
“s3:PutObjectAcl”,
“codecommit:ListBranches”,
“codecommit:ListRepositories”
],
“Resource”: [
“arn:aws:s3:::YOUR_BUCKET_NAME_IN_PROD_FOR_CODE_PIPELINE_ARTIFACTS/*”
]
},
{
“Effect”: “Allow”,
“Action”: [
“kms:DescribeKey”,
“kms:GenerateDataKey*”,
“kms:Encrypt”,
“kms:ReEncrypt*”,
“kms:Decrypt”
],
“Resource”: [
“arn:aws:kms:YOUR_KMS_ARN_FROM_PROD_ACCOUNT”
]
}
]
}
- Create a role for cross account access and attach the above policy as well as the AWSCodeCommitFullAccess policy. Establish the trust relationship with the PROD AWS Account by adding the following policy in Trust Relationship of your role.
{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::PROD_AWS_ACCOUNT_ID:root”
},
“Action”: “sts:AssumeRole”
}
]
}
That’s all about the configuration of DEV account.
Final Step
Now, you will have to get your CodePipeline in PROD account to assume the role in the Source Stage to extract the code and dump it in the S3 bucket for all of your next stages. You can’t do this bit from AWS console, because once the CodePipeline is created, you cannot edit it from Console you can only edit the details using AWS CLI. Run the following command from CLI.
aws codepipeline get-pipeline — name NameOfPipeline > pipeline.json
The above step will save the pipeline’s configuration in pipeline.json file. Edit the file as follows:
{
“pipeline”: {
“roleArn”: “arn:aws:iam::*********:role/*************”,
“stages”: [
{
“name”: “Source”,
“actions”: [
{
“inputArtifacts”: [],
“name”: “SourceCode”,
“actionTypeId”: {
“category”: “Source”,
“owner”: “AWS”,
“version”: “1”,
“provider”: “CodeCommit”
},
“outputArtifacts”: [
{
“name”: “Source”
}
],
“configuration”: {
“PollForSourceChanges”: “false”,
“BranchName”: “master”,
“RepositoryName”: “YOUR-REPOSITORY-NAME-IN-DEV”
},
“runOrder”: 1,
“roleArn”: “arn:aws:iam::DEV-ACCOUNT-ID:role/ROLE_NAME_WITH_CROSS_ACCOUNT_POLICY_FROM_DEV_ACCOUNT”
}
]
},
“artifactStore”: {
“type”: “S3”,
“location”: “YOUR_BUCKET_NAME”,
“encryptionKey”: {
“id”: “arn:aws:kms:YOUR_KMS_KEY_ARN”,
“type”: “KMS”
}
},
“name”: “*******************”,
“version”: 19
}
}
For more details, please visit https://cloudfornoobs.com/aws-codepipeline-with-cross-account-codecommit-repo/
You can test the pipeline by pushing some changes to “master” branch or merging the master branch with dev. I hope this helps.
Feel free to comment if there are any questions.