Featured image of post Bitbucket OIDC Integration with AWS ECR

Bitbucket OIDC Integration with AWS ECR

Introduction

We previously talked about OIDC integration with AWS using GitHub Actions. We will now see how to do a similar integration with BitBucket Pipelines. Namely, we want to push a container image to AWS ECR and then use that image in future pipelines.

AWS IAM Identity Providers

We have to configure the Bitbucket OpenID Connect provider in AWS IAM. Use the following to create a new OpenID Connect provider:

  • Provider URL: api.bitbucket.org/2.0/workspaces/<YOUR-WORKSPACE-NAME>/pipelines-config/identity/oidc
  • Audience: ari:cloud:bitbucket::workspace/<YOUR-WORKSPACE-ID>

Now that the provider is configured, we can set up the IAM role for the Bitbucket OIDC provider and use it in our pipelines.

AWS OIDC IAM Role

The IAM role requires ECR push permissions and the GetAuthorizationToken action in order to be able to log into ECR.

Example permissions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "Statement": [
    {
      "Action": "ecr:*",
      "Effect": "Allow",
      "Resource": "arn:aws:ecr:eu-central-1:123456789012:repository/devops-terraform",
      "Sid": "AllowAllEcrActions"
    },
    {
      "Action": "ecr:GetAuthorizationToken",
      "Effect": "Allow",
      "Resource": "*",
      "Sid": "EcrGetAuthorizationToken"
    }
  ],
  "Version": "2012-10-17"
}

In the trust relationships section, we need to add the arn of the previously created Bitbucket OIDC provider and allw the AssumeRoleWithWebIdentity action for our specific Bitbucket repository. We can also add the IP addresses of the Bitbucket servers that will be using the OIDC provider in case you are using dedicated self-hosted Bitbucket runners.

Example trust relationships:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::123456789012:oidc-provider/api.bitbucket.org/2.0/workspaces/stulz_bitbucket/pipelines-config/identity/oidc"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "api.bitbucket.org/2.0/workspaces/stulz_bitbucket/pipelines-config/identity/oidc:sub": "{YOUR-BITBUCKET-REPO-ID}*"
        },
        "IpAddress": {
          "aws:SourceIp": [
            "64.x.y.z/32",
            "32.x.y.z/32"
          ]
        }
      }
    }
  ]
}

ECR Push Pipeline

After setting up the IAM role, we can use it in our pipelines as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
pipelines:
  custom:
    dockerEcrBuildPush:
      - variables:
          - name: IMAGE_NAME
            default: cicd-tf
          - name: IMAGE_TAG
            default: 1.12.0-6.5.0
          - name: AWS_DEFAULT_REGION
            default: eu-central-1
      - step:
          name: Build & Push Docker Image
          oidc: true
          runs-on:
            - 'self.hosted'
            - 'linux'
          script:
            - docker build -t $IMAGE_NAME:$IMAGE_TAG -t $IMAGE_NAME:latest .
            - pipe: atlassian/aws-ecr-push-image:2.6.0
              variables:
                AWS_DEFAULT_REGION: '$AWS_DEFAULT_REGION'
                AWS_OIDC_ROLE_ARN: 'arn:aws:iam::123456789012:role/devops-terraform-oidc'
                IMAGE_NAME: '$IMAGE_NAME'
                TAGS: '$IMAGE_TAG latest'

The above pipeline will build the docker image and push it to ECR using the IAM role we created and using the official Bitbucket Pipelines Pipe: AWS ECR push image atlassian/aws-ecr-push-image.

If we want to use this image as a base image in our future pipelines, we can reference it in the image name section and specify the OIDC IAM role that can be used to pull it from ECR.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
  steps:
    - step:
        name: TF Plan
        image:
          name: '123456789012.dkr.ecr.eu-central-1.amazonaws.com/devops-terraform:1.12.0-6.5.0'
          aws:
            oidc-role: 'arn:aws:iam::123456789012:role/devops-terraform-oidc'
        oidc: true
        script:
          - terraform init
          - terraform validate
          - terraform plan -out=plan.tfplan
        runs-on:
          - 'self.hosted'
          - 'linux'

This way, the terraform plan step will run inside the designated container image with a pre-installed terraform binary pinned to a specific version (1.12.0-6.5.0).

Conclusion

In this post, we have seen how to use Bitbucket OIDC integration with AWS ECR. We have also seen how to use the official Bitbucket Pipelines Pipe: AWS ECR push image to build and push a docker image to ECR. Hopefully, this will help you in your future projects.

References: