Skip to content

Attestation

Attestation is the material the control-plane verifies at enrollment to decide which tenant this runner belongs to. You choose it with RUNNER_ATTESTATION_MODE.

Mode Status Where to use it
bootstrap-token default Development and proofs of concept. It’s the weakest link: a secret someone has to mint and hand over.
aws-sts implemented EC2, EKS, or a laptop authenticated with aws sso login.
gke-oidc implemented GKE with Workload Identity.
eks-oidc not implemented Nowhere. On EKS, use aws-sts.
Terminal window
RUNNER_ATTESTATION_MODE=bootstrap-token
RUNNER_BOOTSTRAP_TOKEN=<token minted per tenant>

The token is minted per tenant, and it is what pins which organization the runner joins. Without it, boot fails fast with its own message:

RUNNER_ATTESTATION_MODE=bootstrap-token requires RUNNER_BOOTSTRAP_TOKEN

That fail-fast exists because the alternative is worse: without it the runner boots, tries to enroll, takes a 401, and enters a reconnect loop, an error that looks like networking and is credentials.

Terminal window
RUNNER_ATTESTATION_MODE=aws-sts
AWS_REGION=us-east-1

This is the mode that closes the cold-start problem for a fleet: with an AWS identity there is no token to mint by hand, so bringing the fleet up stops requiring a human in a browser.

The runner pre-signs an sts:GetCallerIdentity request (Vault’s IAM-auth style) and sends the parts (signed headers, body, and region), never a URL. The control-plane executes the call against an STS endpoint from its own allowlist and reads the ARN from the response.

Two properties follow:

  • AWS validates the signature. The control-plane signs nothing and cannot be tricked into calling an arbitrary host: it’s anti-SSRF by construction.
  • Nothing secret travels. The SigV4 signature proves possession of the credential without revealing it, and the X-Amz-Security-Token accompanying temporary credentials is already public by construction.

The credential comes from the SDK’s default chain: environment variables, the SSO cache, IRSA on EKS, IMDS on EC2.

RUNNER_ATTESTATION_MODE=aws-sts requires AWS_REGION

The region is not guessed, on purpose: the control-plane only accepts regions from its own allowlist, and a wrong guess would surface as an attestation_invalid that reads like a credential problem.

Terminal window
RUNNER_ATTESTATION_MODE=gke-oidc
# RUNNER_GKE_TOKEN_PATH=/var/run/secrets/tokens/gke-oidc/token # default

The runner reads the projected OIDC token of the Kubernetes ServiceAccount and sends it as attestation. Nothing secret enters the image: the token is a short-lived, audience-bound JWT projected by the kubelet. The control-plane verifies it against Google’s JWKS and maps the KSA and project to the tenant.

The pod needs a projected volume with a serviceAccountToken mounted exactly at the configured path. If it’s missing, the error says so:

RUNNER_ATTESTATION_MODE=gke-oidc: failed to read projected KSA token at
/var/run/secrets/tokens/gke-oidc/token (is the Workload Identity token volume mounted?)

And if the file exists but is empty:

RUNNER_ATTESTATION_MODE=gke-oidc: projected token at … is empty

Certificate renewal uses its own attestation, mtls-renewal, which is not a configurable mode. See Enrollment and mTLS.