Setup GitHub Actions to authenticate to Cloudsmith using OIDC

Our workflow using GitHub Actions and Cloudsmith with OIDC will push a package to Cloudsmith from Github Actions using OIDC to authenticate.

How does OIDC work with Github Actions and Cloudsmith?

The following diagram gives an overview of how GitHub's OIDC provider integrates with your workflows and Cloudsmith:

Prerequisite: Cloudsmith creates an OIDC trust relationship between your service account and your GitHub workflows that need access to Cloudsmith.

OIDC flow:

  1. Request token: Github Actions Worker initiates the workflow by requesting a token from the GitHub OIDC service to authenticate with Cloudsmith.
  2. Return token: GitHub OIDC service receives the token request. After verification and validation, it generates a JWT token. The GitHub OIDC service and the GitHub Actions Worker have implicit trust, allowing for this token exchange.
  3. Present token: GitHub Actions Worker presents a JWT token to Cloudsmith for access to resources.
  4. Verify token: Cloudsmith verifies the JWT token with the GithHub OIDC service to ensure its authenticity and validity. This step includes verifying claims.
  5. Return new token: Upon successful validation, Cloudsmith issues a short-lived access token to the GitHub Actions Worker, granting access to Cloudsmith's resources for around 90 mins to cover the duration of the job.

Workflow Enhancement with OIDC, Cloudsmith, and GitHub Actions

Our workflow using GitHub Actions and Cloudsmith with OIDC will push a package to Cloudsmith from Github Actions using OIDC to authenticate.

Step-by-Step Guide

Follow the steps below for the Cloudsmith and Github Actions OIDC Setup:

  1. Create a Service Account in Cloudsmith:

    1. Service accounts are a specific type of account that allows you to create a Cloudsmith API Key not tied to a specific user.
    2. Navigate to the Services section on your Cloudsmith organization's accounts page and click "Create Service."
    3. You are then presented with the Service creation form. Give your Service a name and optionally add a description and choose any teams in your organization that you wish to add the service to.
  2. Set Access Controls

    1. Configure the repository access controls to allow the Service Account to push packages to Cloudsmith.
  3. Configure GitHub OIDC in Cloudsmith

    1. Navigate to the OIDC Provider Settings at: https://cloudsmith.io/orgs/{ACCOUNT}/settings/openid-connect/
      NOTE: You must have the Manager or Owner role in your Cloudsmith organization to configure OIDC Provider Settings.
    2. Click "Create" to open the Edit Provider Settings form:
    3. Fill in the OIDC form:
      1. The Provider Name is a Unique name for the provider
      2. The Provider URL is unique to each provider, for Github Actions it is https://token.actions.githubusercontent.com
      3. The Required OpenID Token Claims field is very important. We strongly encourage people to set at least one claim. If you don't add claims any Github Action Worker will have permissions if they knew the service account(s) to target. In the image example above, we have set repository_owner as the claim, other supported claims can be found here.
      4. The service accounts that the user wants to be able to authenticate as with the configured provider & claims combination.
  4. Update your GitHub Actions for OIDC:

    1. Open your Github Actions YAML file which sets up your Github Actions workflow.

    2. Add the permissions setting to request the JWT:

      Permissions:  
                id-token: write # This is required for requesting the JWT  
                contents: read  # This is required for actions/checkout
      
    3. Generate the OIDC Token in GitHub Actions:
      To generate a token in Github Actions you can use getIDToken() or you can use the curl command below to request the JWT.

      curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange"
      
      
      
    4. Make a POST request to the Cloudsmith OpenID endpoint to receive the JWT token.
      If successful, this will give a JWT token that can be used as an API key. This token is active for 2 hours from the time of creation.
      This POST request must have:

      1. A body of oidc_token, with the OpenID Token as its value.
      2. A service_slug as the slug of the service account the request wants to attempt to authenticate as.
      3. The OIDC Endpoint for your Cloudsmith organization will be: https://api.cloudsmith.io/openid/{ACCOUNT}/
    5. This token works with all Cloudsmith API endpoints to manage resources, as well as format-specific endpoints, e.g. The Ruby endpoint to get all available packages
      This token will also, work with the Command-Line Interface when specified as CLOUDSMITH_API_KEY.

    6. The JWT token generated by the OIDC endpoint can be used like an API key:
      X-Api-Key header: "X-Api-Key:Bearer OIDC_TOKEN"

  5. Trigger a build in GitHub Actions, and OIDC will authenticate into Cloudsmith.

Example GitHub Actions Workflow

Below is a full example of pushing a package to Cloudsmith in GitHub Actions using OIDC to authenticate:

name: Push a debian package to Cloudsmith with OIDC
on:
  push:
    branches: [ main ]
permissions:
  id-token: write      # Necessary to GH Identity Provider to write the JWT token which Cloudsmith needs to read
  contents: read

jobs:
  push:
    runs-on: ubuntu-latest
    name: Push a Debian package to Cloudsmith using OIDC to authenticate
    steps:
      - name: Check out code
        uses: actions/checkout@v2

      - name: Get OIDC token
        run: |
          value=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange" | jq '.value')
          token=$(curl -X POST -H "Content-Type: application/json" -d "{\"oidc_token\":$value, \"service_slug\":\"SERVICE_ACCOUNT_SLUG\"}" https://api.cloudsmith.io/openid/ORGANIZATION/ | jq -r '.token')
          curl --request GET --url https://api.cloudsmith.io/v1/user/self/ --header "X-Api-Key:Bearer $token" --header 'accept: application/json'
                    
          echo "CLOUDSMITH_API_KEY=$token" >> $GITHUB_ENV
          
      - name: Cloudsmith Push Debian Package
        uses: cloudsmith-io/[email protected]
        with:
          command: 'push'
          format: 'deb'
          owner: 'DEMO_ORG'             # Your Cloudsmith account name or org name (namespace)
          repo: 'DEMO_REPOSITORY'         # Your Cloudsmith Repository name (slug)
          distro: 'debian'     # Your Distribution  (i.e Debian, Ubuntu)
          release: 'buster'         # Your Distribution Release (i.e xenial, buster)
          republish: 'true'          # needed if version is not changing
          file: 'test/cloudsmith-debian-example-1.0.0-amd64.deb'  # debian package filename


Cloudsmith is the new standard in Package / Artifact Management and Software Distribution

With support for all major package formats, you can trust us to manage your software supply chain.


Start My Free Trial Now
Cookie Declaration (Manage Cookies)