Skip to content

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

  1. Go to Configuration → Service Accounts → New service account.
  2. Fill in the details, the environment access and the Initial credential (see below).
  3. Select Create service account.
  4. 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, ES256 or ES384 by a key published at the issuer's JWKS (found through its /.well-known/openid-configuration). Unsigned and HS* tokens are refused.
  • iss equals the Issuer URL exactly.
  • aud contains the Audience.
  • sub equals the Subject.
  • Every claim condition matches.
  • exp, nbf and iat are 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 jti is 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

  1. Add client secret to create a second credential.
  2. Update your pipeline's stored secret to the new one.
  3. 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.