Workload Identity
Configure workload identity rules to let CI workloads authenticate with Develocity using short-lived OIDC tokens instead of long-lived access keys.
Overview
Workload identity federation is based on the OpenID Connect (OIDC) standard. Instead of storing a long-lived Develocity access key, you exchange a short-lived OIDC token from your CI provider for a Develocity access token.
The exchange works in these steps:
-
The CI provider issues a short-lived OIDC token at the start of the job. A GitHub Actions token lasts about five minutes.
-
The CI integration exchanges the token for a Develocity access token via a
POST /api/auth/tokenrequest. -
The build authenticates with the returned Develocity access token for the rest of the run.
Your CI job mints the OIDC token from your CI provider; no Develocity plugin mints it for you.
You supply that token in place of your access key, in host-qualified form, and the CI integration exchanges it for a Develocity access token the same way it exchanges an access key.
For how each provider mints and supplies the token, see the provider examples below and the Continuous Integration section.
Because the OIDC token is issued fresh for each job and is short-lived, there is no shared secret to store, rotate, or leak. Claim requirements let you scope a rule to a specific organization, repository, branch, or workflow, so each workload receives only the access it needs.
Use workload identity when your CI provider issues OIDC tokens and you want to remove long-lived Develocity access keys from CI configuration, or grant roles based on which repository, branch, or workflow is authenticating.
|
You can present the OIDC token directly in place of an access key, but it usually expires partway through a build, which is why the CI integration exchanges it for a longer-lived Develocity access token. On a CI system with no integration that performs the exchange, see Other CI Systems for the direct path. |
Prerequisites
-
An account with permission to configure access control in Develocity.
-
A CI provider that issues OIDC tokens (GitHub Actions, Google Cloud Workload Identity, HashiCorp Vault, and similar).
-
Network connectivity from Develocity to the issuer’s JWKS endpoint (see Issuer Key-Refresh Failures).
Configure via the User Interface
Navigate to and select Add.
|
Develocity evaluates each incoming token against every configured rule for its issuer. A rule matches when the issuer, audience, and all claim requirements match. If multiple rules match, Develocity applies all of them and grants the union of their roles and project groups. |
-
ID: Enter a unique identifier for the rule.
-
Issuer: Enter the
issclaim value from the provider’s tokens (for example,https://token.actions.githubusercontent.comfor GitHub Actions). Select Test to verify Develocity can reach the issuer’s JWKS endpoint before saving. If Develocity cannot reach the JWKS endpoint, see Issuer Key-Refresh Failures. -
Audience: Enter the
audclaim the JWT must carry. The workload requests this value from its provider at token issuance time. -
Assigned roles and Assigned project groups: Select the roles and project groups to grant to every token that matches this rule.
-
Roles claim and Project groups claim: Optionally enter a claim name for dynamic grants. At authentication time, Develocity reads that claim from the token and matches its values against the identity provider (IdP) attribute values configured on each role or project group. Both string and list claims are supported: a list-valued claim grants all roles or project groups whose IdP attribute value matches any element.
After you save the rule, Develocity opens the claim requirements screen. Add one or more claim requirements that must all match. Available match types are Equals, Starts With, Ends With, Contains, and Regular Expression.
|
A rule with no claim requirements never matches any token. At least one claim requirement must be added before the rule can authenticate a workload. If you truly need to accept tokens with no other claim criteria, you can add a requirement for the issuer or audience claim. |
Each rule also carries Read isolation level and Write isolation level under Universal Cache isolation, which appear only while trusted artifact isolation is on. See Universal Cache Isolation.
|
Save stores the rule as a draft without applying it. A banner then appears at the top of the page: There are saved configuration changes that have not been applied. Select Apply in that banner to put the rule into effect. If you leave the page or select Discard first, you lose the change. Develocity does not restart when you apply a workload identity change. |
Claim Requirement Match Types
| Match Type | Behavior |
|---|---|
Equals |
Claim value must match exactly. |
Starts With |
Claim value must begin with the specified string. |
Ends With |
Claim value must end with the specified string. |
Contains |
Claim value must include the specified string. |
Regular Expression |
Claim value must match the regular expression. |
Starts With, Ends With, and Contains compare the requirement string literally against the claim value.
The boundary character is not a special or stripped token; it is simply the character that bounds a segment in the claim’s own format, matched as part of the required string.
For example, the : in repo:acme/acme-app:, a / in a path, or an @ in a workflow ref each follow from the claim’s own format.
Any character can serve as the boundary as long as it naturally ends a segment in the real claim value.
|
Include the boundary character at the end of a Starts With string (or the start of an Ends With string), or the requirement over-matches.
A Starts With requirement of |
Provider Examples
Each provider emits its own set of claims. Configure the issuer and audience, then add claim requirements that scope the rule to an organization, a repository, or a branch. Develocity reads each required claim as a string, so scope only on string-valued claims: numeric, boolean, and array claims are treated as absent and the requirement fails.
GitHub Actions
GitHub Actions tokens use the issuer https://token.actions.githubusercontent.com.
Set the Develocity audience to the value your workflow passes to getIDToken(); it defaults to the repository owner URL, such as https://github.com/acme.
Scope on the dedicated string claims repository_owner, repository, ref, workflow_ref, and job_workflow_ref.
| Goal | Claim requirement(s) |
|---|---|
Limit to an organization |
|
Limit to a single repository |
|
Limit to a single branch |
|
Limit to a single workflow file |
|
Limit to a shared reusable workflow |
|
The workflow_ref and job_workflow_ref claims both use the format {owner}/{repo}/.github/workflows/{file}@{ref}.
workflow_ref identifies the top-level workflow that started the run, so scoping on it pins authentication to one workflow file and rejects every other workflow in the repository.
job_workflow_ref identifies the reusable workflow the job actually calls, which lets a central repository own the build logic and authorize only jobs that run it.
Include the trailing @ when scoping to a file regardless of ref, or use Equals with a full @{ref} suffix to pin a specific ref.
Do not scope on sub.
GitHub gives repositories created after 2026-07-15 an immutable sub that embeds numeric owner and repository IDs, so a sub Starts With rule written for the older format stops matching with no warning.
The claims ref_type (branch or tag) and environment are also string-valued if you need to narrow further.
For the workflow setup that mints and supplies the token, see Authenticate With Workload Identity, or the GitHub Actions OpenID Connect documentation for the underlying GitHub mechanism.
GitLab CI
GitLab CI tokens use the GitLab instance URL as the issuer, such as https://gitlab.com or https://gitlab.acme.org.
Set the Develocity audience to the value you configure under aud: in the job’s id_tokens block.
Scope on the string claims namespace_path, project_path, and ref.
| Goal | Claim requirement(s) |
|---|---|
Limit to a group or namespace |
|
Limit to a single project |
|
Limit to a single branch |
|
To also exclude tag pipelines, add ref_type Equals branch.
GitLab emits project_id and namespace_id as string values that survive renames, so use them with Equals when rename safety matters more than readable path-based rules.
For the job setup that mints and supplies the token, see Authenticate With Workload Identity, or the GitLab ID token authentication documentation for the underlying GitLab mechanism.
Jenkins
The OpenID Connect Provider plugin makes Jenkins an OIDC issuer.
Its issuer is your Jenkins URL followed by /oidc, such as https://jenkins.example.com/oidc, and you set the audience per credential on the OpenID Connect ID Token credential in Jenkins.
By default the plugin sets sub to the job URL (JOB_URL) and a numeric build_number that Develocity cannot match, and it exposes no repository or branch claims, so scope on sub.
JOB_URL always ends in a trailing slash, and for a multibranch pipeline the branch is a child job whose name is percent-encoded, such as https://jenkins.example.com/job/acme-app/job/main/.
| Goal | Claim requirement(s) |
|---|---|
Limit to all jobs in a folder |
|
Limit to a single job |
|
Limit to all branches of a multibranch pipeline |
|
Limit to a single branch |
|
Always include the trailing slash on an Equals value.
To scope on anything other than the job URL, add a custom claim template in Jenkins under that exposes a claim such as branch.
Admins who store the credential on a folder can use the folder-scoped issuer, which appends the folder path to the issuer, such as https://jenkins.example.com/oidc/job/acme-team.
For the pipeline setup that binds and supplies the token, see Authenticate With Workload Identity.
Universal Cache Isolation
The Workload identity page also carries the controls for trusted artifact isolation, which splits every Universal Cache key into a trusted entry and an untrusted one. They live here because isolation levels come from claim matching, so they can only be assigned to a workload identity rule, never to an access key.
Under Universal Cache isolation:
-
Enable Universal Cache isolation turns isolation on for the installation. It is off by default, and upgrading does not turn it on.
-
Read isolation level and Write isolation level on each rule decide which of the two entries a matching workload writes, and which it may read. Develocity hides these per-rule controls while isolation is off.
Enabling isolation changes cache behavior for every workload, and the order in which you enable it and set the levels matters. For what each level does, the one combination Develocity refuses, which levels suit each kind of workload, and the procedure for turning isolation on, see Trusted Artifact Isolation.
Troubleshooting
A problem reported against a workload identity rule is usually one of two things: Develocity cannot reach the rule’s issuer, or the rule’s isolation levels are producing cache behavior you did not expect.
Issuer Key-Refresh Failures
Develocity displays an admin notice when it cannot refresh signing keys from a configured issuer. Develocity fetches signing keys (JWKS) from each configured issuer and retries every minute if the fetch fails. The admin notice appears once an issuer has been unreachable for 15 minutes. After 24 hours without a successful refresh, Develocity drops the cached keys and token validation for that issuer fails, breaking any builds that use it.
To diagnose:
-
Navigate to . The rule list shows the JWKS status per issuer.
-
Select Test on the affected rule to attempt a live fetch and see the error.
-
Check Develocity server logs for WARN-level messages from
WorkloadIdentityRegistry.
Common causes:
-
The OIDC configuration endpoint at
{issuer}/.well-known/openid-configurationis unreachable from the Develocity host (firewall, egress proxy, or DNS). -
The JWKS endpoint (from the
jwks_urifield in the discovery document) is unreachable. -
The issuer URL is wrong: typo, trailing-slash mismatch, or HTTP instead of HTTPS.
-
A TLS trust failure: self-signed or expired certificate, or missing intermediate CA.
|
Per the OpenID Connect Discovery 1.0 spec, the issuer must be an HTTPS URL with no query string or fragment, and must match the Develocity fetches |
Fix the issuer URL or network path, or add the CA certificate to Develocity’s trusted store if TLS is the cause. Develocity retries every minute and clears the notice once a fetch succeeds.
Unexpected Cache Behavior
Trusted artifact isolation decides what a build may read and write from the levels on the rule its credentials matched, so a mistake in those levels surfaces as a cache problem rather than an authentication one.
A build that starts missing every cache key, a cache response of 409 Conflict carrying an X-Cache-Isolation-Conflict header, and a job whose Artifact Cache summary reports zero trusted entries all share that shape: the token validated and the rule matched, and only the isolation levels are wrong.
Diagnose these from Trusted Artifact Isolation, which gives the cause and the remedy for each.