Service accounts¶
A service account is a non-human identity in your tenant. CI/CD pipelines, scripts and test harnesses use it to call the Helena REST API, for example to run a test and fail the build if it doesn't pass.
Manage service accounts under Configuration → Service Accounts. Any member can create and manage them. The number you can create depends on your plan.
A service account has:
- a scope, which is what it may do
- environment access, which is where it may do it
- one or more credentials, which is how it proves who it is: a client secret, or an OIDC workload identity trust with no stored secret
When it authenticates, it receives a short-lived bearer token (1 hour) that it uses for the rest of the API.
Create a service account¶
- Go to Configuration → Service Accounts → New service account.
- Fill in the details, the environment access and the Initial credential (see below).
- Select Create service account.
- If you chose a client secret, copy the Client ID and Client secret from the Save these credentials now panel. The secret is never shown again. Then select I have saved these credentials.
Account fields¶
| Field | Required | Default | Supported values / notes |
|---|---|---|---|
| Name | ✅ | — | Unique within the tenant, e.g. github-actions-ci. |
| Description | — | Free text. | |
| Scope | ✅ | Read | See Scopes. |
| Environment access | ✅ | — | All environments, including ones created later, or tick individual environments. |
| Expires | Never | A date. The account stops authenticating at the end of that day. | |
| Status | Active | On the account page. Active, or Inactive (revokes issued tokens). Deactivating immediately invalidates every token the account holds. |
Scopes¶
Each scope includes the ones below it.
| Scope | Allows |
|---|---|
Read (read) |
View environments, test configuration (without secrets) and the Test Log. |
Write (write) |
Read, plus trigger test runs. |
Admin (admin) |
Write, plus future environment- and tenant-level management endpoints. |
A request that needs a higher scope is refused with 403 INSUFFICIENT_SCOPE, and the refusal is audited.
Least privilege
A pipeline that only runs tests needs Write on the one environment it targets. Don't grant All environments to a pipeline that only uses one.
Credentials¶
A service account can hold up to 10 credentials, in any mix of the two types. Add them on the account page with Add client secret or Add OIDC trust.
Client secret¶
| Field | Required | Notes |
|---|---|---|
| Credential name | ✅ | E.g. Primary or Rotation 2026-11. |
| Credential expires | Optional date. |
Helena generates:
- a Client ID (
helena_followed by 32 characters) - a 64-character Client secret, which is shown once
Store both in your CI/CD secret store. Helena keeps only a hash of the secret, so a lost secret cannot be recovered. Add a new credential instead.
OIDC workload identity trust¶
With an OIDC trust, nothing secret is stored anywhere. Your workload presents an ID token issued by its own platform, such as GitHub Actions, GitLab CI, Kubernetes or a cloud workload identity, and Helena checks it against the trust policy you define.
| Field | Required | Notes |
|---|---|---|
| Credential name | ✅ | |
| Issuer URL | ✅ | The token issuer, exactly as it appears in the token's iss claim. GitHub Actions: https://token.actions.githubusercontent.com. GitLab.com: https://gitlab.com. |
| Subject (sub claim) | ✅ | Exact match. GitHub: repo:ORG/REPO:ref:refs/heads/BRANCH. GitLab: project_path:GROUP/PROJECT:ref_type:branch:ref:BRANCH. |
| Audience (aud claim) | ✅ | Pre-filled with https://app.helena.dev/api/v1/service-account/auth. Request your workload's ID token with this audience. |
| Additional claim conditions | Optional claim/value pairs that must match exactly, e.g. repository_owner = acme, environment = production or namespace_path = acme. A claim that is an array matches if it contains the value. |
|
| Credential expires | Optional date. |
The credential still gets a Client ID. It tells Helena which trust policy to check the token against, and is not a secret.
A presented token is accepted only if all of the following hold:
- It is signed with
RS256,RS384,RS512,ES256orES384by a key published at the issuer's JWKS (found through its/.well-known/openid-configuration). Unsigned andHS*tokens are refused. issequals the Issuer URL exactly.audcontains the Audience.subequals the Subject.- Every claim condition matches.
exp,nbfandiatare valid, allowing 60 seconds of clock skew.- The token has no more than 1 hour of remaining lifetime.
- The token hasn't been used before. Each
jtiis accepted once.
No wildcards
Subjects and claim conditions are exact matches. This is deliberate, because wildcards make it too easy to trust more than you meant. To trust another branch or repository, add another OIDC trust.
Rotating a client secret without downtime¶
- Add client secret to create a second credential.
- Update your pipeline's stored secret to the new one.
- Once the old credential's Last used time stops advancing, Revoke it.
Revoking and deleting¶
| Action | Effect |
|---|---|
| Revoke a credential | It can no longer authenticate, and tokens it issued stop working immediately. It stays listed as Revoked. |
| Delete a credential | Removes it permanently. |
| Inactive status on the account | All of the account's tokens stop working. Set it back to Active to allow authentication again. |
| Delete service account | Deletes the account, its credentials and all issued tokens. Pipelines that use it will fail. |
Usage information¶
The account page shows when the account was last used and how many requests it has made. Each credential has its own Last used time. Use these to find credentials that are no longer used and can be removed.
The Getting a token panel on the account page shows a ready-to-copy example for its credentials. See REST API and CI/CD examples.