ServicesWorkloads

Sign in with a platform identity

Let a workload sign in with the identity token of the platform that runs it, such as GitHub Actions, GCP, Kubernetes, AWS, or Modal.

Available

Let a workload sign in with a token from the platform that runs it. There is no secret to store, copy, or rotate, because the platform issues a new token for each run. Spiral checks each token against a trust policy you attach to the workload, such as "GitHub Actions runs from my-org/pipelines on main".

Prerequisites

  • You created a workload and granted it a Project role.
  • You have the Project admin role to manage the trust policies of the workload. A trust policy lets the matching job act as the workload, with all of the workload's grants.
  • The workload runs on a platform that issues OpenID Connect tokens.

Add a trust policy

Add a trust policy for the platform. This policy admits the nightly-curation workload's GitHub Actions runs from one repository, on the main branch only:

spiral workloads trust add work_01GHI --github my-org/pipelines \
  --condition ref=refs/heads/main

Then set SPIRAL_WORKLOAD_ID where the job runs. The CLI and the SDKs find the platform token and exchange it for you:

export SPIRAL_WORKLOAD_ID=work_01GHI

The platform token's audience must match the workload's trust policy. When a policy omits an audience, Spiral expects https://auth.spiraldb.com/oauth/token; automatic token acquisition in the CLI and SDKs requests that value on platforms that allow it.

Studio's Add trust policy form prefills a workload-specific audience, such as https://auth.spiraldb.com/workloads/work_01GHI. Copy the value shown in Audience into your provider's token request. GitHub Actions jobs need id-token: write to request a token. The form's optional named fields let you constrain a Git ref, environment, repository ID, workflow, reusable workflow, actor, or other GitHub OIDC claims.

When you choose an explicit audience, obtain the platform token with that audience and provide it as SPIRAL_OIDC_PROVIDER_TOKEN alongside SPIRAL_WORKLOAD_ID. This uses your token directly instead of automatic platform-token acquisition. A provider with a fixed audience, such as Modal, keeps that value on the policy.

PlatformTrust policy optionsToken source
GitHub Actions--github OWNER/REPODetected automatically. The job needs the id-token: write permission.
GCP--gcp-service-account UNIQUE_ID, with the numeric uniqueId of the service accountThe metadata server, detected automatically.
Kubernetes--kubernetes-service-account NAMESPACE/NAME --issuer URL, with the issuer of the cluster's service-account tokensA projected service-account token with the audience above. Set SPIRAL_K8S_SA_TOKEN_PATH to the token file.
AWS--aws-role ROLE_ARN --issuer URL. See AWS roles.STS GetWebIdentityToken, detected automatically.
Modal--modal-workspace WORKSPACE_ID. Modal tokens cannot name the audience above, so the policy accepts the audience oidc.modal.com.MODAL_IDENTITY_TOKEN, detected automatically.
Any OIDC issuer--issuer URL --condition CLAIM=VALUESet SPIRAL_OIDC_PROVIDER_TOKEN to the token.

Add --condition CLAIM=VALUE to require more claims, as the example does with ref. Every trust policy names at least one claim, because an issuer alone would admit every token it signs, including tokens for other people's jobs. The issuer must publish OpenID Connect discovery at a public HTTPS URL. Its jwks_uri must also use HTTPS and resolve only to public addresses. Spiral checks DNS answers when connecting, refuses redirects and private or special-use addresses, and limits each fetched document to 64 KiB and five seconds. A private Kubernetes issuer needs publicly reachable discovery and signing-key documents before hosted sign-in can verify its tokens.

If SPIRAL_WORKLOAD_ID is set and the client finds no platform token, sign-in fails with a diagnostic instead of prompting. See How your code finds credentials.

Verify the trust policy

List the workload's trust policies:

spiral workloads trust ls work_01GHI

Run the workload, then check the principal that it signs in as:

spiral whoami

The command shows the workload ID. Remove a trust policy with spiral workloads trust rm.

Exchange a platform token over HTTP

A client without the SDK sends the platform token to the token endpoint itself, as a JWT bearer grant (RFC 7523). assertion is the platform token, and client_id is the workload ID, which is also the workload's OAuth client ID:

curl -X POST https://auth.spiraldb.com/oauth/token \
  -d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
  -d client_id=work_01GHI \
  -d assertion="$PLATFORM_TOKEN"

The response contains an access_token for the Spiral API.

AWS roles

An AWS role proves its identity with a token from STS GetWebIdentityToken. AWS issues these tokens only after you enable outbound identity federation for the account. The role also needs permission to request the token.

  1. Enable outbound identity federation for the AWS account:

    aws iam enable-outbound-web-identity-federation

    The response contains the issuer URL of the account. To show it again, run aws iam get-outbound-web-identity-federation-info.

  2. Add this statement to a policy of the role. It lets the role request tokens only for the Spiral authorization server:

    {
      "Effect": "Allow",
      "Action": "sts:GetWebIdentityToken",
      "Resource": "*",
      "Condition": {
        "ForAllValues:StringEquals": {
          "sts:IdentityTokenAudience": "https://auth.spiraldb.com/oauth/token"
        }
      }
    }
  3. Add a trust policy to the workload. Use the issuer URL from step 1 and the ARN of the role:

    spiral workloads trust add work_01GHI \
      --aws-role arn:aws:iam::123456789012:role/MyDeployRole \
      --issuer https://4f9c2a7e-1b3d-4e5f-8a6b-7c8d9e0f1a2b.tokens.sts.global.api.aws

The policy matches the sub claim, which is the role ARN, not the ARN of the role session, so it accepts every session of the role.

To see the token that the role presents, run this command where the workload runs. Then decode the token in the response:

aws sts get-web-identity-token \
  --audience https://auth.spiraldb.com/oauth/token \
  --signing-algorithm RS256

If the command fails with AccessDenied, the role does not have the permission from step 2.

Troubleshooting

ProblemCauseFix
SPIRAL_WORKLOAD_ID is set but no workload identity provider detected a valid tokenThe platform did not supply a token.Check the token source in the platform table. For GitHub Actions, add the id-token: write permission.
SPIRAL_OIDC_PROVIDER_TOKEN is set but SPIRAL_WORKLOAD_ID is not.A custom OIDC token needs the workload ID.Set SPIRAL_WORKLOAD_ID.
The token is rejectedNo trust policy matches the issuer and claims.Compare the decoded platform token with spiral workloads trust ls.

Where next: the Workloads API lists the trust policy operations.

Found a problem? Edit this page or report an issue.

On this page