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.
Status of each mode
Section titled “Status of each 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. |
bootstrap-token
Section titled “bootstrap-token”RUNNER_ATTESTATION_MODE=bootstrap-tokenRUNNER_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_TOKENThat 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.
aws-sts
Section titled “aws-sts”RUNNER_ATTESTATION_MODE=aws-stsAWS_REGION=us-east-1This 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.
How it works
Section titled “How it works”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-Tokenaccompanying 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.
AWS_REGION is required
Section titled “AWS_REGION is required”RUNNER_ATTESTATION_MODE=aws-sts requires AWS_REGIONThe 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. The
default allowlist covers us-east-1, us-west-2 and sa-east-1; if your cluster runs outside
them, talk to us before the first boot. As long as it’s the commercial partition, it’s configuration
on our side. The refusal names the accepted regions, so you can confirm from the error.
GovCloud and China are not supported: they’re different AWS partitions, with their own endpoint and ARN formats.
gke-oidc
Section titled “gke-oidc”RUNNER_ATTESTATION_MODE=gke-oidc# RUNNER_GKE_TOKEN_PATH=/var/run/secrets/tokens/gke-oidc/token # defaultThe 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, projected for the audience the control-plane requires:
volumes: - name: whystack-token projected: sources: - serviceAccountToken: path: token audience: rootpilot-enroll expirationSeconds: 3600The audience is the replay defense: without it, a KSA token projected for any other service would be
good enough to enroll. That’s why verification is fail-closed: a missing or different audience
is refused, and the refusal arrives as attestation_invalid, indistinguishable from a bad
credential. It’s the first field to check when an enroll fails with an apparently correct KSA.
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 emptyWhat about renewal?
Section titled “What about renewal?”Certificate renewal uses its own attestation, mtls-renewal, which is not a configurable mode.
See Enrollment and mTLS.