OIDC setup and usage

5 minute read

OpenID Connect (OIDC) offers a secure and standardized way to authenticate users, allowing CloudBees workflows to interact with external resources efficiently.

To set up OIDC for use in the CloudBees platform, first establish an identity trust relationship between AWS and CloudBees platform using OIDC, and then create an AWS IAM role with assigned permissions. Then you can configure CloudBees platform workflows to use OIDC tokens.

Add CloudBees as a trusted IdP in AWS

Use OIDC to establish CloudBees as a trusted identity provider (IdP) in AWS.

To add the CloudBees platform as a trusted IdP in AWS:

  1. Sign in to your AWS account and go to Identity and Access Management (IAM)  Identity providers  Add provider.

  2. Select the OIDC option.

  3. Set Provider URL to https://api.cloudbees.io.

  4. Set Audience to sts.amazonaws.com.

  5. Select Get Thumbprint to validate the provider URL and certificate.

  6. Select Add provider to complete the setup.

Your AWS account is configured to accept the CloudBees platform as a trusted IdP.

Trust policy considerations

AWS limits the set of claims you can match in your trust policy. Of the keys provided in the Amazon AWS STS condition keys documentation, the following can be used:

  • aud matches the azp claim.

  • oaud matches the aud claim.

  • sub.

CloudBees suggests that the use of the aud condition is redundant as long as you have a StringEquals condition on the oaud key. Depending on your use case and the granted role permissions, you may not require a sub condition.

CloudBees strongly recommends:

  • Use the oaud key with a StringEquals condition to ensure that only tokens issued for components in your CloudBees org are trusted.

  • For roles that can effect changes, use a sub key with a StringEquals condition that limits the role to the absolute minimum set of repositories that require use of the role.

Table 1. How standard OIDC claims map in AWS and CloudBees.
AWS STS condition key IdP JWT claim Set by CloudBees Required in trust policy?

aud

azp. If no value is set for azp, the aud condition key maps to the aud claim.

azp is set to sts.amazonaws.com.

Use this check to verify that the token issued by CloudBees was issued for use against AWS [1]

oaud

aud

aud is set to your platform root organization (org) ID, in the format <your_organization_id>@sts.amazonaws.com.[2]

Only required if you want the claim to originate from your platform org. CloudBees strongly recommends this check.

sub

sub

Set by CloudBees to refer to the source code repository that the component is pointing to.

Not required, as you can use oaud to restrict access to just your organization. Restricts role assumption to workflows from a specific set of repositories by matching the token subject (sub).[3]

[1] This is a redundant check, as CloudBees already appends the azp value to the CloudBees aud value (so checking oaud is sufficient).

[2] The organization ID is listed in the Organization profile. Refer to Organizations and sub-organizations for more information.

[3] CloudBees strongly recommends that policies that have mutation permissions are ideally tightly limited to a single repository.

Trust policy examples

Below are examples of appropriate trust policies for use with the platform. The Condition block specifies those conditions that are valid for the trust policy. For exact matches, use the StringEquals specifier; for partial matches, use the StringLike specifier.

  • Because AWS sets a 2048-byte size restriction on trust policies, you are limited in the number of repositories you may include in your trust policy.

  • Because repository names cannot include a colon (:), the wild card (*) match is limited by the colon that follows it.

  • CloudBees recommends that you limit use of the wild card, as environment names do not include character restrictions. For example, if the environment is named gotcha:ref:/refs/main or gotcha:environment:production, provider:github:repo:cloudbees/:ref:/refs/main and provider:github:repo:cloudbees/:environment:production will match, thus bypassing branch and environment protections.

  • If you have multiple StringEquals conditions, CloudBees recommends including multiple key-value pairs within a single StringEquals block to improve readability and performance.

  • Your GitHub org ID is located after the last / in the GitHub org URL. For example:

    • In https://github.com/my-org, the org ID is my-org.

    • In https://github.com/enterprise/my-enterprise-org, the org ID is enterprise.

The trust policy example below only allows access if the following criteria are met:

  • Only allow AWS account ID 012345678901.

  • Only allow CloudBees platform root organization ID 1234abcd-56ef78gh-90ij-klmn1234opqr.

  • Only allow the main and qc branches of the my-repo repository in the my-org GitHub organization.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::012345678901:oidc-provider/api.cloudbees.io" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "api.cloudbees.io:oaud": "cbp://1234abcd-56ef78gh-90ij-klmn1234opqr@sts.amazonaws.com" }, "StringEquals": { "api.cloudbees.io:sub": ["provider:github:repo:my-org/my-repo:ref:/refs/head/main", "provider:github:repo:my-org/my-repo:ref:/refs/head/qc"] } } } ] }

In the following condition block example, any branch with a v1. tag in the my-org GitHub organization is acceptable:

"Condition": { "StringEquals": { "api.cloudbees.io:oaud": "cbp://1234abcd-56ef78gh-90ij-klmn1234opqr@sts.amazonaws.com" } "StringLike": { "api.cloudbees.io:sub": "provider:github:repo:my-org/*:ref:/refs/tag/v1.*" } }

In the following condition block example, any branch in the my-repo repository in the my-org GitHub organization is acceptable:

"Condition": { "StringEquals": { "api.cloudbees.io:oaud": "cbp://1234abcd-56ef78gh-90ij-klmn1234opqr@sts.amazonaws.com" } "StringLike": { "api.cloudbees.io:sub": "provider:github:repo:my-org/my-repo:ref:*" } }

Create an AWS IAM role for CloudBees platform workflows

An appropriate trust policy must be in place to create an AWS IAM role.

To create AWS roles that can be assumed by CloudBees platform workflows using trusted CloudBees platform identity tokens:

  1. Sign in to your AWS account and go to Identity and Access Management (IAM)  Roles  Create role.

  2. Select Custom trust policy as the trusted entity type.

  3. Enter an appropriate trust policy.

  4. Select Next and assign the necessary permissions to the role. The permissions can vary depending on the required AWS operations.

Assign permissions to the role

Add additional permissions to the role to allow specific AWS operations. These permissions should be based on your workflow requirements, for example, if you need to access Amazon Elastic Container Registry (ECR) or Simple Storage Service (S3).

CloudBees strongly recommends that you avoid granting broad or unnecessary permissions, particularly administrative access, to your environments. In the event of a security breach, having limited permissions can help mitigate potential damage and demonstrate that appropriate security measures were advised.

Example workflow using an OIDC token

The following example uses an OIDC token to securely deploy an EC2 binary.

Learn more about modifying the default permissions at jobs.<job_id>.permissions. You require scm-token-own:read if the job is checking out code. CloudBees recommends that jobs should have the narrowest permission necessary.

When permissions are specified at the job level, they override any defaults set at the workflow level. In order to add id-token: write to get an OIDC token at the job level, you must also add any additional permissions even if those were already specified at the workflow level.

apiVersion: automation.cloudbees.io/v1alpha1 kind: workflow name: workflow on: push: branches: - "*" permissions: scm-token-own: read scm-token-org: read id-token: read jobs: build: steps: - name: Check out uses: https://github.com/cloudbees-io/checkout@v1 with: repository: my-name/my-repo-name - name: Run Jenkins job uses: https://github.com/cloudbees-io/jenkins-run-job@v2 with: username: ${{ secrets.JENKINS_USERNAME }} token: ${{ secrets.JENKINS_TOKEN }} url: ${{ vars.JENKINS_URL }} job-name: jenkins_job_name - name: Build container image uses: cloudbees-io/kaniko@v1 kind: build with: destination: ${{ secrets.DOCKERHUB_USER }}/test:${{ cloudbees.scm.sha }},${{ secrets.DOCKERHUB_USER }}/test:latest tar-path: container-image.tar deploy: permissions: scm-token-own: read scm-token-org: read id-token: write needs: - build steps: - name: Deploy EC2 binary uses: https://github.com/cloudbees-io/ec2-deploy-binary@v1 with: source-location: workspace/test/* destination-ec2-location: /home/ubuntu/mydeploys/helloworld/ aws-ssh-key-data: ${{ secrets.AWS-DEPLOY-KEY }} aws-user: ubuntu aws-host: ${{ secrets.AWS-HOST }} deploy-script: script1.sh

JSON Web Token claims

Use JSON Web Token (JWT) claims in your OIDC token for fine-grained access control. CloudBees OIDC tokens include JWT claims that can be used to filter trust policies. Example token claims include repository, branch, and workflow context information.

An example of OIDC JWT token claims accepted by CloudBees follows:

{ "iss": "https://api.cloudbees.io", "sub": "provider:github:repo:acme/quickstart-app-deploy", "azp": ["sts.amazonaws.com"], "aud": ["my-platform-root-org-id@sts.amazonaws.com"], "exp": 1234567890, "iat": 1234567890, "environment": "prod", "event_source": "github", "ref": "refs/heads/main", "ref_type": "branch", "repository": "quickstart-app-deploy", "repository_owner": "acme", "repository_provider": "github", "run_attempt": "1", "run_id": "1234abcd-56ef-78gh-90ij-klmn1234opqrs", "run_number": "10", "workflow": "Workflow", "workflow_ref": "acme/quickstart-app-deploy/.cloudbees/workflows/Workflow@refs/heads/main", "workflow_sha": "123abc456def789ghi012jkl345mno678pqr901st" }

AWS references

The following AWS documentation links provide guidance for setting up and managing OIDC identity providers and IAM roles in AWS.