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:
- Request token: Github Actions Worker initiates the workflow by requesting a token from the GitHub OIDC service to authenticate with Cloudsmith.
- 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.
- Present token: GitHub Actions Worker presents a JWT token to Cloudsmith for access to resources.
- Verify token: Cloudsmith verifies the JWT token with the GithHub OIDC service to ensure its authenticity and validity. This step includes verifying claims.
- 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:
-
Create a Service Account in Cloudsmith:
- Service accounts are a specific type of account that allows you to create a Cloudsmith API Key not tied to a specific user.
- Navigate to the Services section on your Cloudsmith organization's accounts page and click "Create Service."
- 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.
-
Set Access Controls
- Configure the repository access controls to allow the Service Account to push packages to Cloudsmith.
-
Configure GitHub OIDC in Cloudsmith
- 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. - Click "Create" to open the Edit Provider Settings form:
- Fill in the OIDC form:
- The Provider Name is a Unique name for the provider
- The Provider URL is unique to each provider, for Github Actions it is https://token.actions.githubusercontent.com
- 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.
- The service accounts that the user wants to be able to authenticate as with the configured provider & claims combination.
- Navigate to the OIDC Provider Settings at: https://cloudsmith.io/orgs/{ACCOUNT}/settings/openid-connect/
-
Update your GitHub Actions for OIDC:
-
Open your Github Actions YAML file which sets up your Github Actions workflow.
-
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
-
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"
-
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:- A body of
oidc_token
, with the OpenID Token as its value. - A
service_slug
as the slug of the service account the request wants to attempt to authenticate as. - The OIDC Endpoint for your Cloudsmith organization will be: https://api.cloudsmith.io/openid/{ACCOUNT}/
- A body of
-
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 asCLOUDSMITH_API_KEY
. -
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"
-
-
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
Updated 6 months ago