- 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.
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.
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
412and 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.
- Kubernetes
- Google
One Kubernetes service account per workspace namespace. The same name in every namespace is enough: Or The service account needs no RBAC role: the Sidecar does not call the Kubernetes API.
hoop-sidecar in ws-acme and hoop-sidecar in ws-beta are two identities, because the namespace is part of the subject.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: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
- Helm chart
- Kubernetes manifest
- Google service account
values.yaml
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:Several clusters
Give each cluster’s entry its own prefix. Two clusters that both have aws-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_patternbeats 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
Anissuer and audience pair belongs to one organization. Another organization that writes the same pair gets 409:
https://hoop.your-company.com/org/acme:
- Kubernetes: set it on the projected token volume, or
controlPlane.identityAudiencein the Helm chart. - Google:
HOOP_SIDECAR_IDENTITY_AUDIENCE, orcontrolPlane.identityAudiencein the Helm chart.
Any valid identity
A bare* pattern admits every service account of the issuer. It needs "allow_any_subject": true, set on purpose:
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.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.
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.
Troubleshooting
The Sidecar prints the Control Plane’s reason after the subject it presented: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.