OpenID

OpenID.

Introduction

I did an exercise in which I implemented AWS EKS using Terraform. In my previous post AWS Load Balancer Controller, I explained how I created a kubernetes ingress for the solution. In this new blog post, I describe how I used OpenID federated identity to let Githut Actions to assume temporary credentials for an AWS IAM Role.

What Is OpenID and Federated Identity?

For a CI/CD pipeline you need to give the pipeline access to your cloud resources. Often, you see a solution that a developer creates a dedicated CI/CD AWS IAM user and then configures that user’s credentials permanently to the CI/CD pipeline. Even though most CI/CD machines provide various secrets, storing credentials in a CI/CD machine is not considered as a best practice.

What if you could provide some kind of federated identity solution, in which both parties agree to trust each other? This is exactly how you can use OpenID with AWS IAM Role.

The high-level flow goes like this:

  • You create an IAM role. The IAM role comprises just those rights that your CI/CD pipeline needs (e.g. push images to ECR).
  • You configure the trust relationship between this IAM role and your CI/CD pipeline using OpenID. I.e., only your CI/CD pipeline can assume this role.
  • Your CI/CD pipeline assumes the IAM role, gets temporary AWS credentials and then uses those temporary credentials to do the needed steps in your pipeline (.e.g. push images to ECR).

Let’s see this in real life.

OpenID Federated Identity Configuration Using Terraform

There are good instructions in the web how to do this. First you need to create the OpenID connector:

resource "aws_iam_openid_connect_provider" "github_openid_connect_provider" {
  url = "https://token.actions.githubusercontent.com"
  client_id_list = ["sts.amazonaws.com"]
  thumbprint_list = [
    "6938fd4d98bab03faadb97b34396831e3780aea1"
  ]
}

The thumbprint relates to Github well-known openid-configuration.

Then provide the IAM policy document:


data "aws_iam_policy_document" "github_actions_assume_iam_role_policy_document" {
  statement {
    effect = "Allow"
    actions = ["sts:AssumeRoleWithWebIdentity"]
    principals {
      type        = "Federated"
      identifiers = [aws_iam_openid_connect_provider.github_openid_connect_provider.arn]
    }
    condition {
      test     = "StringEquals"
      variable = "token.actions.githubusercontent.com:aud"
      values   = ["sts.amazonaws.com"]
    }
    condition {
      test     = "StringLike"
      variable = "token.actions.githubusercontent.com:sub"
      values = var.github-repositories
    }
  }
}

Note this line: values = var.github-repositories. You can give the right to assume this IAM role for a specific Github repository - no other party can assume the IAM role.

Then the last step is to create the actual IAM role and give the IAM role the permissions you need (e.g. to push images to ECR), and bind above mentioned policy to the IAM role.

Using the OpenID Federated Identity in Github Actions

It is quite straightforward to use the above mentioned OpenID Federated Identity in Github Actions. You just need to store the AWS IAM role arn as a secret in your Github Actions configuration. Storing the arn itself poses not that much of a security threat, since the IAM role arn is not a credential, and you have already configured in the IAM role side that this federated identity can only be assumed by your Github repository.

In your Github Actions pipeline you can use aws-actions/configure-aws-credentials plugin to do this:


      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: ${{ secrets.AWS_GITHUB_IAM_ROLE_ARN }}
          aws-region: ${{ secrets.AWS_DEFAULT_REGION }}
          

Note this line: role-to-assume: ${{ secrets.AWS_GITHUB_IAM_ROLE_ARN }} - we tell Github Actions to assume our AWS IAM role.

So, now your CI/CD pipeline can use the AWS IAM role to do the AWS related steps in your pipeline. Example:

...
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
...
        docker push ${ECR_REGISTRY}/${ECR_REPO_NAME}:${IMAGE_TAG}
...

Conclusions

There is no reason to create a dedicated CI/CD IAM user and store the permanent AWS credentials in your CI/CD machine, since it is quite easy to provide a secure federated identity between your CI/CD pipeline and AWS.

The writer is working at a major international IT corporation building cloud infrastructures and implementing applications on top of those infrastructures.

Kari Marttila

Kari Marttila’s Home Page in LinkedIn: https://www.linkedin.com/in/karimarttila/