AWS Partner Network (APN) Blog

Building Cross-Account Deployment in GitLab Pipelines Using AWS CDK

By Muni Annachi, DevOps Consultant – AWS
By Mert Simsek, Sr. Cloud Application Architect – AWS
By Ashmeet Singh Pahwa, Security Consultant – AWS
By Darwin Sanoy, Principal Partner Solution Architect – GitLab

GitLab-AWS-Partners-2023
GitLab
Connect with GitLab-1

Many organizations use GitLab as a continuous integration and continuous deployment (CI/CD) platform for their cloud infrastructure and application deployments on Amazon Web Services (AWS).

AWS Cloud Development Kit (AWS CDK) can save time while developing infrastructure as code (IaC) in your preferred language such as Java, JavaScript/TypeScript, or Python. This post provides reference framework for customers to help implement GitLab Pipelines using AWS CDK for a secured and reliable deployment experience across their teams.

We will walk through how to use AWS CDK in GitLab Pipelines, setup deployment architecture with AWS security best practices, and implement deployments into multiple AWS accounts representing development, testing, and production environments.

GitLab is an AWS Specialization Partner and AWS Marketplace Seller that’s a comprehensive DevSecOps platform. What started in 2011 as an open-source project to help one team of programmers collaborate, GitLab is now the platform millions of people use to deliver software faster and more efficiently while strengthening security and compliance.

Solution Overview

In this walkthrough, you are going to learn how to leverage AWS CDK in Gitlab Pipelines to implement cross-account deployments following AWS best practices. We’ll create a Gitlab Pipeline to provision an AWS infrastructure to multiple accounts.

For simplicity, we’re going to use Dev and Prod environments. We use a separate a AWS account as DevOps account to securely access Dev and Prod accounts without creating long-term access keys in deployment environments. A new environment can be added at any point of time with a repeatable approach using the same pattern.

The GitLab Pipeline interacts and authenticates only with a DevOps account to perform deployments into Dev and Prod accounts. In this approach, we don’t need to save credentials for every AWS account and encourage using the best practice of shared accounts for DevOps capabilities.

GitLab-Pipieline-AWS-CDK-1

Figure 1 – CI/CD pipeline architecture.

The solution starts with committing the infrastructure changes into a GitLab repository. Once changes are committed to the repo, GitLab Pipeline will be triggered automatically.

Pipeline then packages and deploys AWS infrastructure into the Dev account. After deployment into the Dev account, the Pipeline waits for manual approval on the GitLab Pipelines interface so it deploys the same infrastructure into the Prod account.

Prerequisites

The prerequisites for following along with this post include:

  • Three AWS accounts—DevOps, Dev, and Prod accounts.
  • Account administrator access to AWS accounts.
  • Node.js and the npm command line interface (CLI).
  • AWS CDK and version 2 of AWS CLI.
  • Access to create new GitLab project (self-managed and SaaS GitLab versions are supported). If you’re using SaaS Model GitLab Project for the first time, you may need to create an account with gitlab.com.
  • Git CLI installed on your computer for cloning the repository.
  • GitLab runner attached to your group (Gitlab SaaS free tier provides 400 free runner minutes).

Create GitLab Project

  • Log in to your GitLab account. On the home page, click on New Project.
  • Click on Import Project.
  • Click on Repository by URL and provide this GitHub repo URL: https://github.com/aws-samples/cross-account-gitlab-pipeline
  • Change other fields on this page such as Project name and Project slug, if required.
  • Go to the cloned repository in GitLab.

Authenticate GitLab with AWS

In this post, we are using AWS Identity and Access Management (IAM) access keys for authenticating into AWS accounts for a non-production workloads. For Production workloads, however, we highly recommend using a more secure solution such as OpenID Connect (OIDC) providers. Visit configure OpenID Connect in AWS to retrieve temporary credentials.

Using OIDC Connect eliminates the use of permanent credentials, and storing a secret improves overall security posture by using temporary credentials.

Authenticate Using IAM Access Keys

  • Create a new IAM user in your DevOps AWS account. In this example, IAM user name is “cicd_gitlab,” and this user needs to have admin access in the AWS account.
  • Capture the access key Id and secret access key generated once the user is created with programmatic access. We’ll use these keys in later steps.

Configure CI/CD Variables

  • Go to Settings in the GitLab project created earlier.
  • Click on CI/CD.
  • Expand Variables section.
  • Add the following keys and their values with Protect variable flag checked:
    • AWS_DEFAULT_REGION – Default region for your AWS account.
    • AWS_ACCESS_KEY_ID – Access key Id of the IAM user in AWS account.
    • AWS_SECRET_ACCESS_KEY – Secret access key of the IAM user in AWS account.
    • DEV_ACCOUNT_ID – 12-digit Dev account Id.
    • PROD_ACCOUNT_ID – 12-digit Prod account Id.

GitLab-Pipieline-AWS-CDK-2

Figure 2 – Gitlab CI/CD variables setup.

Bootstrap AWS Accounts

Bootstrapping is the process of provisioning resources for the AWS CDK before you can deploy stacks into an AWS account. You can bootstrap AWS accounts via AWS CLI and CDK toolkit.

Open a shell terminal for configuring Dev account access keys. Run the below command to bootstrap the application on the Dev account and wait for the bootstrap to complete. While bootstrapping the Dev account, establish trust between the DevOps and Dev accounts using the –trust parameter in CDK command, so the DevOps account can deploy the infrastructure to Dev account. This eliminates the need for saving Dev account credentials in GitLab.

Note that if you want to use only two accounts (Dev and Prod), use Dev account number instead of DevOps account number in the –trust parameter.

cdk bootstrap aws://{Dev_AWS_ACCOUNT}/{Dev_AWS_REGION} --trust {DevOps_AWS_ACCOUNT} --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess

Perform the same steps as above in the Prod account. Open a shell terminal for configuring Prod account access keys. Run the below command to bootstrap the Prod account and wait for the bootstrap to complete.

cdk bootstrap aws://{PROD_AWS_ACCOUNT}/{PROD_AWS_REGION} --trust {DevOps_AWS_ACCOUNT} --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess

Create and Run GitLab Pipeline

  • In this post, we have a sample serverless app built with AWS Lambda. We’ll be deploying the app as a CDK stack into the Dev and Prod accounts with GitLab Pipelines. Refer to lib/cross-account-gitlab-stack.ts in the GitLab repository for CDK stack details.
  • Below is the snippet of CDK code we’re going to deploy.
 const lambdaFunction = new lambda.Function(this, 'Handler', {
      code: new lambda.AssetCode('lambda'),
      handler: 'index.handler',
      runtime: lambda.Runtime.NODEJS_18_X,
      role: lambdaRole
    });
    lambdaRole.attachInlinePolicy(new iam.Policy(this, 'lambda-policy', {
      statements: [new iam.PolicyStatement({
        actions: ['s3:GetObject'],
        resources: [sample_bucket.bucketArn+"/someprefix"],
      }),
      new iam.PolicyStatement({
        actions: ['s3:ListBucket'],
        resources: [sample_bucket.bucketArn],
      })],
    }));
  • In the repo, you’ll see a file named .gitlab-ci.yml which defines the GitLab Pipeline and various stages as seen below.
image: node:18-alpine
cache:
  paths:
  - node_modules/
stages:
- build
- deploy-test
- deploy-prod
build-job:
  stage: build
  script:
  - echo "Compiling the code..."
  - npm install
  - npm run build
  - echo "Compile complete."
deploy-dev-infra:
  stage: deploy-test
  variables:
    CDK_DEPLOY_ACCOUNT: $DEV_ACCOUNT_ID
    CDK_DEPLOY_REGION: $AWS_DEFAULT_REGION
  before_script:
  - npm install -g aws-cdk@latest
  - cdk --version
  script:
  - npx cdk synth
  - cdk diff
  - cdk deploy --require-approval never
deploy-prod-infra:
  stage: deploy-prod
  variables:
    CDK_DEPLOY_ACCOUNT: $PROD_ACCOUNT_ID
    CDK_DEPLOY_REGION: $AWS_DEFAULT_REGION
  before_script:
  - npm install -g aws-cdk@latest
  - cdk --version
  script:
  - npx cdk synth
  - cdk diff
  - cdk deploy --require-approval never
  rules:
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    when: manual

Verify Pipeline Execution and Deployment

  • When the CDK bootstrap and above variable definition are completed, you should see a GitLab Pipeline kicked off automatically. You may see that the first pipeline run fails; re-run the same pipeline.
  • Pipeline deploys the stack to the Dev account in the deploy-test-infra stage.
  • Pipeline pauses before Prod account deployment and waits for manual approval.
  • Click the Play icon on the deploy-prod-infra stage.
  • Pipeline resumes deployment to Prod account. This approach can be used for validating changes in the Dev environment before approving deployment in Prod.
  • Verify the logs for each stage and see the pipeline to completion successfully.

GitLab-Pipieline-AWS-CDK-3

Figure 3 – GitLab Pipeline stages.

Conclusion

In this post, we walked through how to use GitLab Pipelines for CI/CD purposes. Using this approach can save you time on searching and provide a reference solution for customers implementing cross-account GitLab Pipeline setup and examples aligned with AWS best practices.

You can also learn more about GitLab in AWS Marketplace.

.
GitLab-APN-Blog-Connect-2023
.


GitLab – AWS Partner Spotlight

GitLab is an AWS Partner and comprehensive DevSecOps platform. What started in 2011 as an open-source project to help one team of programmers collaborate, GitLab is now the platform millions of people use to deliver software faster and more efficiently while strengthening security and compliance.

Contact GitLab | Partner Overview | AWS Marketplace