Skip to main content
Connect a Sidecar issues one token per Sidecar before it is deployed. That works for a few Sidecars. It does not work for a fleet that automation deploys: every workspace would need a call to the Control Plane, a secret to store and a secret to inject, before the pod even exists. A Sidecar can authenticate with the identity its platform already gives it instead:
  • A Kubernetes service account. A projected token, signed by the cluster, rotated by the kubelet. GKE, EKS, AKS and self-managed clusters.
  • A Google service account. An ID token from the metadata server, on GKE with Workload Identity, GCE or Cloud Run.
An admin adds one sidecar service account entry per cluster or project. Every workspace whose service account matches it enrolls on its first handshake. The manifest of a workspace is static: no token, no pre-step.
This page says workspace for whatever unit you already use to separate workloads: a namespace per team, application, environment or tenant on Kubernetes, or a VM or Cloud Run service on Google Cloud. Each workspace runs its own Sidecar, in front of the databases and services its workload uses, and gets its own Sidecar in the Control Plane. Identity Mapping shows the common layouts.
The token flow keeps working unchanged. A Control Plane can serve Sidecars of both kinds at the same time.

How it works

Two halves: the Sidecar gets a token from its platform, and the Control Plane checks that token against keys the issuer publishes.

1. The Sidecar gets a token

Nothing calls the Sidecar. It reads a token its platform already maintains, on every request to the Control Plane. The kubelet never talks to the Sidecar: it only keeps the file current.

2. The Control Plane checks the token

The Control Plane only fetches public keys. It never calls the Kubernetes API or a Google API with credentials, and it never connects to the Sidecar.

Connectivity the Control Plane needs

Discovery connects only to public addresses and does not go through HTTPS_PROXY. A Control Plane without direct egress to the issuer uses a static jwks too. Keys are cached per issuer for an hour, fetched again when a token names a key the cache does not hold (at most once a minute), and refused once a refresh has been failing for 24 hours. The Sidecar needs outbound HTTPS to the Control Plane only, plus the metadata server for a Google service account.

What the Control Plane decides

  • The name is the key. The entry turns the token’s subject into a Sidecar name. The Control Plane looks the Sidecar up by that name in your organization and creates it only when none exists. Restarts, new pods, rollouts and replicas all produce the same name, so they all reach the same Sidecar.
  • A Sidecar is bound to the first service account that reaches it. From then on only that service account reaches it. Another service account whose entry renders the same name is refused until an admin clears the binding, so a namespace that happens to share a name cannot take a Sidecar over.
  • The identity only authorizes. A token proves which service account is calling; the entry decides whether that service account may reach a Sidecar, and which one.
  • First boot is the normal import. A new Sidecar holds no configuration, so the handshake answers 412 and the Sidecar seeds it from its local config file, exactly as in Connect a Sidecar. From then on the Control Plane owns the configuration.
  • The token is re-read on every request. A projected token lives an hour by default and the kubelet replaces the file before it expires. A Google ID token is cached until five minutes before it expires.

Steps

1

Give each workspace its own service account

The service account is the identity the Control Plane matches. Create one per workspace, before the Sidecar is deployed.
One Kubernetes service account per workspace namespace. The same name in every namespace is enough: hoop-sidecar in ws-acme and hoop-sidecar in ws-beta are two identities, because the namespace is part of the subject.
Or kubectl -n ws-acme create serviceaccount hoop-sidecar. With the Helm chart, serviceAccount.create: true and serviceAccount.name: hoop-sidecar create it for you. Its tokens carry this subject:
The service account needs no RBAC role: the Sidecar does not call the Kubernetes API.
2

Add a sidecar service account entry

One entry per cluster (Kubernetes) or per project (Google). Entries are managed through the API by an admin; the organization needs an Enterprise license.Read the cluster’s issuer:
Create the entry:
With this entry, the service account hoop-sidecar in namespace ws-acme reaches the Sidecar gke-eu-acme. See The entry for every field.
3

Deploy the workspace

values.yaml
The chart mounts a projected token with the Control Plane URL as its audience and sets HOOP_SIDECAR_IDENTITY_TYPE=kubernetes. It refuses to render controlPlane.token and controlPlane.identity together.
4

Check it enrolled

The Sidecar log says:
GET /api/sidecars lists it under the rendered name, with the service account that reached it in identity_issuer and identity_subject, and a recent last_seen_at.

Credentials on the Sidecar

A Sidecar connected to a Control Plane uses exactly one credential: the token, or the identity type. Both set is a startup error that names both. HOOP_SIDECAR_IDENTITY_TOKEN_FILE or HOOP_SIDECAR_IDENTITY_AUDIENCE set for another type stops startup, because it would do nothing. The identity travels in the hoop-sidecar-identity request header. A credential set without HOOP_CONTROL_PLANE_URL, or a URL without a credential, stops startup with a message that names the fix.

The entry

Clusters the Control Plane cannot reach

GKE and EKS publish their issuer’s keys on the internet, so discovery needs nothing more. A self-managed cluster, or AKS without its OIDC issuer enabled, usually does not. Discovery also refuses private, loopback and link-local addresses, so an issuer on a private network needs a static key set. Paste the cluster’s key set into the entry:
A static key set does not follow a rotation of the cluster’s signing key. Update the entry when the cluster rotates it.

Several clusters

Give each cluster’s entry its own prefix. Two clusters that both have a ws-acme namespace then reach two Sidecars, not one: Without the prefix, both clusters render acme and share one Sidecar and its configuration.

Which entry wins

  • An exact subject_pattern beats a wildcard one.
  • Among wildcards, the one with the longest literal text wins.
  • A token that matches entries in more than one organization is refused.

One organization per issuer and audience

An issuer and audience pair belongs to one organization. Another organization that writes the same pair gets 409:
On a Control Plane that serves one organization, the Control Plane URL is the audience and nothing else is needed. On one shared by several organizations, each picks its own audience, any string the issuer will mint, for example https://hoop.your-company.com/org/acme:
  • Kubernetes: set it on the projected token volume, or controlPlane.identityAudience in the Helm chart.
  • Google: HOOP_SIDECAR_IDENTITY_AUDIENCE, or controlPlane.identityAudience in the Helm chart.
Several entries in the same organization may share a pair, for example one per namespace pattern in one cluster.

Any valid identity

A bare * pattern admits every service account of the issuer. It needs "allow_any_subject": true, set on purpose:
Use it only on an issuer your organization owns, such as your own cluster. It is refused for https://accounts.google.com: every Google account in the world holds a valid token from that issuer. A Google entry must use claim: email and end in a literal @<project>.iam.gserviceaccount.com:

What happens when…

Deleted names

Deleting a Sidecar that a service account reached records its name, so the next heartbeat does not bring it back. Deleting a Sidecar created with a token records nothing; its token simply stops working.
Deleting, clearing the name and restarting the pod is also how a Sidecar starts over from its local config file.

Bindings

GET /api/sidecars shows the service account a Sidecar is bound to in identity_issuer and identity_subject. Clearing it lets the next service account that reaches the Sidecar bind to it:

Moving token Sidecars to service accounts

Sidecars registered with a token keep their names and configuration when they move to service accounts. Create the entry with "adopt_existing_sidecars": true and a name_template that renders each Sidecar’s existing name, then redeploy each workspace with controlPlane.identity. Each Sidecar binds to the first service account that reaches it, and its token keeps working. Turn the flag off once the move is done.

Revoking access

  • One workspace: delete or disable its service account, or delete its Sidecar.
  • A whole cluster: narrow or delete its entry.
Revoking stops configuration updates and keeps new pods from starting. It does not stop traffic: running pods keep serving their last configuration while the Control Plane refuses them. To stop traffic now, also scale down or delete the workspace’s Sidecar pods.

Fleets

  • One entry per cluster, not per workspace. 2,000 workspaces in one cluster are one entry and 2,000 Sidecars.
  • One service account per workspace. A service account shared by several workspaces is one identity: all of them reach the same Sidecar and serve the same configuration, and any of them can read it.
  • Rules are copied per Sidecar. Each Sidecar imports the rules in its own config file as its own rule items. A rule shared by the whole fleet is changed in each copy, or in each file followed by a fresh import.
  • Rows outlive workspaces. A torn-down workspace leaves its Sidecar in the list. Delete it when the workspace goes away.
Identity Mapping shows every layout of credentials, clusters, projects and workspaces, with tokens, Kubernetes and Google service accounts side by side.

Troubleshooting

The Sidecar prints the Control Plane’s reason after the subject it presented:
Before a token is verified, the Control Plane says nothing more than the service account token failed verification, so an unauthenticated caller learns nothing about its configuration. The precise cause is in the Control Plane’s log, with the issuer. A Google service account can also fail before the Control Plane is reached. The Sidecar exits with code 1 and prints the metadata server’s answer:

Next

Connect a Sidecar

The handshake, the license and staying in sync.

Kubernetes

The Helm chart’s Control Plane attributes.

Identity Mapping

Every layout of credentials, clusters and workspaces.