Skip to content
Stelligent
  • Services
    • Road Map
    • Automate
    • Secure
    • 30-Day Pipeline
    • CI in AWS
  • Resources
    • DevOps on AWS Solutions
    • Tools We Use
    • Glossary
  • Industries
    • Financial Services
    • Government
    • Healthcare & Life Sciences
  • Case Studies
  • White Papers
  • Blog
  • Careers
  • About
    • Mphasis Acquisition
    • News & Events
  • Contact
Stelligent
  • Services
    • Road Map
    • Automate
    • Secure
    • 30-Day Pipeline
    • CI in AWS
  • Resources
    • DevOps on AWS Solutions
    • Tools We Use
    • Glossary
  • Industries
    • Financial Services
    • Government
    • Healthcare & Life Sciences
  • Case Studies
  • White Papers
  • Blog
  • Careers
  • About
    • Mphasis Acquisition
    • News & Events
  • Contact
Automation, AWS, CodePipeline, DevOps, Infrastructure

Create a Cross-Account Pipeline in AWS CloudFormation

Stelligent Amazon Pollycast
Voiced by Amazon Polly

When creating pipelines in AWS CodePipeline, you may want to make these pipelines available to other AWS accounts. When doing this, you’ll likely want to make these pipelines read only. A typical use case is that you want consistency for certain types of pipelines across an enterprise by providing a view of these pipelines to other accounts. Doing this involves the use of CodePipeline and AWS Identity and Access Management (IAM). Moreover, if you’re like us, you’ll want to automate the provisioning of this in AWS CloudFormation.
In this post, I describe how to automate the provisioning of cross-account access to pipelines in AWS CodePipeline using IAM. All of the examples in this post are coded in one CloudFormation template: codepipeline-cross-account-pipeline.json. Instructions for running this template are provided at the end of this post.

Create a Simple CodePipeline Stack

The first code fragment you see here is the beginning of the CodePipeline definition using the AWS::CodePipeline::Pipeline type. To expedite the example, I’m using the Lambda-based pipeline that we described in the Mocking AWS CodePipeline pipelines with Lambda post. For simplicity, I’m defining two stages: Source and Commit.

    "CodePipelineStack":{
      "Type":"AWS::CodePipeline::Pipeline",
      "DependsOn":[
        "CodePipelineLambdaDummy"
      ],
      "Properties":{
        "RoleArn":{
          "Fn::Join":[
            "",
            [
              "arn:aws:iam::",
              {
                "Ref":"AWS::AccountId"
              },
              ":role/AWS-CodePipeline-Service"
            ]
          ]
        },
        "Stages":[
          {
            "Name":"Source",
            "Actions":[
              {
                "InputArtifacts":[
                ],
                "Name":"Source",
                "ActionTypeId":{
                  "Category":"Source",
                  "Owner":"AWS",
                  "Version":"1",
                  "Provider":"S3"
                },
                "OutputArtifacts":[
                  {
                    "Name":"MyApp"
                  }
                ],
                "Configuration":{
                  "S3Bucket":{
                    "Ref":"S3Bucket"
                  },
                  "S3ObjectKey":{
                    "Ref":"S3Key"
                  }
                },
                "RunOrder":1
              }
            ]
          },
...

Create an IAM Role

Here, I’m creating an IAM Role that references a user-based parameter containing the AWS account id of the account for which we want to share access to the pipeline(s) we’re defining in this AWS account. This way the other AWS account can assume the role defined in the account that’s defining the IAM role and for which this CloudFormation stack is being launched.

    "CrossAccountPipelineViewersRole":{
      "Type":"AWS::IAM::Role",
      "Properties":{
        "AssumeRolePolicyDocument":{
          "Version":"2012-10-17",
          "Statement":[
            {
              "Effect":"Allow",
              "Principal":{
                "AWS":{
                  "Fn::Join":[
                    "",
                    [
                      "arn:aws:iam::",
                      {
                        "Ref":"PipelineAWSAccountId"
                      },
                      ":root"
                    ]
                  ]
                }
              },
              "Action":"sts:AssumeRole"
            }
          ]
        },
        "Path":"/"
      }
    },
...

Create an IAM Policy

When defining the IAM policy, I set dependencies on the CodePipeline stack and the IAM role using the DependsOn attribute. By defining these dependencies, I can reference the role and stack in the IAM Policy.
You can see the limits I’m defining in the Allow Actions of the PolicyDocument of this definition. This is based on the example from Configure Cross-Account Access to a Pipeline. The Resource attribute defines the limits to the specific pipelines in CodePipeline for which we’ll provide access.

    "CrossAccountPipelineViewersPolicy":{
      "Type":"AWS::IAM::Policy",
      "DependsOn":[
        "CodePipelineStack",
        "CrossAccountPipelineViewersRole"
      ],
      "Properties":{
        "PolicyName":"CrossAccountPipelineViewersPolicy",
        "Roles":[
          {
            "Ref":"CrossAccountPipelineViewersRole"
          }
        ],
        "PolicyDocument":{
          "Version":"2012-10-17",
          "Statement":[
            {
              "Effect":"Allow",
              "Action":[
                "codepipeline:GetPipeline",
                "codepipeline:GetPipelineState",
                "codepipeline:ListActionTypes",
                "codepipeline:ListPipelines",
                "iam:ListRoles",
                "s3:GetBucketPolicy",
                "s3:GetObject",
                "s3:ListAllMyBuckets",
                "s3:ListBucket",
                "codedeploy:GetApplication",
                "codedeploy:GetDeploymentGroup",
                "codedeploy:ListApplications",
                "codedeploy:ListDeploymentGroups",
                "elasticbeanstalk:DescribeApplications",
                "elasticbeanstalk:DescribeEnvironments",
                "lambda:GetFunctionConfiguration",
                "lambda:ListFunctions"
              ],
              "Resource":[
                "*"
              ]
            }
          ]
        }
      }
    },
...

Create a CodePipeline URL Output in CloudFormation

While not directly related to limiting access permissions, I’ve found the code fragment below to be useful when defining my CloudFormation stacks for CodePipeline. It’s a CloudFormation Output that defines the URL for CodePipeline. It’s useful as a way to quickly jump to the pipeline in CodePipeline once the CloudFormation stack is complete.

    "CodePipelineURL":{
      "Value":{
        "Fn::Join":[
          "",
          [
            "https://console.aws.amazon.com/codepipeline/home?region=",
            {
              "Ref":"AWS::Region"
            },
            "#/view/",
            {
              "Ref":"CodePipelineStack"
            }
          ]
        ]
      }
    },

Launch the CloudFormation Stack

To launch the CloudFormation stack, click on the Launch Stack button below and enter the AWS account id for which you want to provide access through the AssumeRole functionality. It’ll take a few minutes to launch.

Launch Stack

To run the same from the command line, here’s a command-line example. Likewise, you’ll need to enter a parameter values for the PipelineAWSAccountId parameter key.

aws cloudformation create-stack --stack-name CrossAccountPipeline
--template-url https://s3.amazonaws.com/stelligent-public/cloudformation-templates/github/cross-account-pipeline/codepipeline-cross-account-pipeline.json
 --region us-east-1 --disable-rollback --capabilities="CAPABILITY_IAM"
--parameters ParameterKey=PipelineAWSAccountId,ParameterValue=YOURAWSACCTID

Access Pipeline Resources from other AWS Account

Once your CloudFormation has launched, go to the IAM role that was generated as part of the stack. It’ll be called something CrossAccountPipelineViewersUniqueID where the UniqueId is a generated value. For easier access, just click on the CrossAcccountIAMRole Output link in the CloudFormation stack.
From here, copy the link provided and login to your other AWS account for which you have access with the copied link.
cross-account-pipeline-iam-role
Then go to CodePipeline. You should see any pipelines for which you have access in the other account.
cross-account-pipeline-2
 

Limiting cross-account access to specific pipelines

Ideally, you’ll also want to limit access to specific pipelines. To do this, you should be able to configure the ARN(s) in the Resource attribute associated with the IAM Policy. So far, I haven’t been able to get this to work, so if anyone finds a solution to this problem, let me know. The way I attempted to get this to work was to define the resource as you see in the code fragment below (it does not work).

"Resource":[
  {
    "Fn::Join":[
      "",
      [
        "arn:aws:codepipeline:",
        {
          "Ref":"AWS::Region"
        },
          ":",
        {
          "Ref":"AWS::AccountId"
        },
          ":",
        {
          "Ref":"CodePipelineStack"
        }
      ]
    ]
  }
]

 

Resources

  • Source code for Cross-Account CodePipeline: codepipeline-cross-account-pipeline.json
  • Configure Cross-Account Access to a Pipeline
  • How to Enable Cross-Account Access to the AWS Management Console
  • Mocking AWS CodePipeline pipelines with Lambda
  • Switching to an IAM Role (AWS Command Line Interface)
March 21, 2016aws, CloudFormation, continuous delivery, cross-account, devops, Lambda

Published by Paul Duvall

CTO at Stelligent. We do Continuous Delivery in Amazon Web Services. Author of Continuous Integration book and DevOps in AWS LiveLessons. View all posts by Paul Duvall

Post navigation

Previous Previous post: Serverless Delivery: Architecture (Part 1)
Next Next post: Serverless Delivery: Bootstrapping the Pipeline (Part 2)

Automation For The People

  • DevOps Culture: Building Confidence in Delivery January 15, 2019
  • Measuring DevOps Success with Four Key Metrics December 21, 2018
  • DevOps on AWS Radio: Containers on AWS with Casey Lee (Ep. 21) December 18, 2018
  • AWS re:Invent 2018 DevOps re:Cap December 12, 2018
  • DevOps on AWS Radio: DevOps Philosophies with James Martin at 3M HIS (Ep. 20) November 15, 2018

Stelligent

 

© Copyright 2018 Stelligent. All Rights Reserved.

info@stelligent.com | Blog | Mphasis | Terms of Use | Privacy Statement

Proudly powered by WordPress / Theme: Shoreditch by Automattic.