Skip to main content

Service accounts

A service account is a directory identity for a workload instead of a person. An agent, job, or service running in Kubernetes calls the AI Gateway and the Connector Gateway as its service account by presenting the projected ServiceAccount token Kubernetes gives its pod. There's no key to issue, store, or rotate. The account has its own groups, model set grants, and budget, and its spend is attributed to it.

Use a service account when a Kubernetes workload should act independently of any user. Use a virtual API key when a script or CI job should act as a person: the key carries its owner's access and budget, and the client stores it.

How a workload is recognized​

A workload's token signs it in when three conditions hold:

  • A trusted issuer tells Stacklok Enterprise which cluster's tokens to accept: the cluster's issuer URL, where its public signing keys are, and the audience workloads request their token for.
  • A binding maps the workload's Kubernetes ServiceAccount, by namespace and name and optionally its UID, to one service account.
  • The service account is Active.

After sign-in, the account's model access and budgets decide which models it can call, and its groups decide which connectors it reaches, as they do for a user. See What an account can reach.

Prerequisites​

  • An AI Gateway connected to the directory. A cluster administrator completes Accept service account workloads once per installation.
  • The platform admin grant, which covers directory administration.
  • The Kubernetes ServiceAccount the workload runs as. Stacklok Enterprise doesn't create it. Note its namespace and name.

In the console, select Administration under Experience in the account menu, then open Service Accounts.

Trust the cluster's issuer​

Each cluster whose workloads call the gateways needs one trusted issuer. You can also add an issuer from the Bindings step when you create an account.

  1. Open the Trusted issuers tab and select Add issuer.

  2. Choose where the issuer is:

    • This cluster trusts the cluster that runs Stacklok Enterprise. Gateways read its keys from the Kubernetes API, so choose it only when every gateway runs in this cluster. Check that Issuer URL matches the issuer this command prints, which on managed clusters such as Amazon EKS is a public URL:

      kubectl get --raw /.well-known/openid-configuration | jq -r .issuer
    • Another issuer trusts any other cluster. Enter its public Issuer URL, then give its public keys as a JWKS URL or with Upload JWKS.

  3. Keep the default Audience, stacklok-enterprise-platform, or enter another value that only Stacklok Enterprise accepts. Workloads request their token for this audience, so share it with the teams that deploy them.

  4. Select Add issuer.

The AI Gateway picks up a new or changed issuer on its next poll of the directory, every 30 seconds by default.

The default Signing algorithms, under Advanced, accept RS256. Change them only when the cluster signs its tokens with another type of key.

Disabling an issuer stops its workloads from signing in and keeps their bindings, so enabling it again lets them back in. You can delete an issuer only when no binding uses it.

Create a service account​

On the Accounts tab, select New service account. The wizard walks through five steps, and every step after Details can be skipped and completed later from the account's tabs.

  1. Details: enter a Name and a description that says which workload uses the account.

  2. Connectors: add the account to groups, or create one, and choose each group's connectors. The account gets everything a group confers: its connectors, budget pool, and model set grants. A change to a group's connectors applies to every member of the group. The list leaves out groups managed through SCIM and connectors that can't serve a service account.

  3. Model Sets: grant model sets directly, and optionally set a Budget amount and period. The All Users model set and the organization default budget never apply to a service account, so the account needs model access and a budget from this step or from its groups.

  4. Bindings: choose the Issuer URL, then enter the Namespace and ServiceAccount name of the workload's ServiceAccount. To pin the binding to that exact ServiceAccount, also enter its UID:

    kubectl get serviceaccount <SERVICE_ACCOUNT_NAME> -n <NAMESPACE> \
    -o jsonpath='{.metadata.uid}'
  5. Review: check the summary and select Create and activate service account.

Without a binding, the button reads Create service account and the account is created Suspended. A service account authenticates only while it's Active, and activating it requires at least one binding to an enabled issuer. Add a binding on the account's Bindings tab, then select Activate in the alert on its page.

Once the account is active, the team that deploys the workload configures it as described in Call the AI Gateway from Kubernetes workloads.

Choose between a pinned and a name-only binding​

A name-only binding matches any ServiceAccount with its namespace and name. That includes a ServiceAccount deleted and created again under the same name, and one created by anyone who can create ServiceAccounts in that namespace, which the built-in Kubernetes edit role allows. Pin the UID when the account's grants and budget are worth more than what the cluster already grants that ServiceAccount name.

A pinned binding takes precedence over a name-only binding for its UID. When another account already reaches the same ServiceAccount by name, the console asks you to confirm with Reassign. The new account takes over the ServiceAccount with that UID, and the other account keeps its name-only binding for any other ServiceAccount with that name, such as one created again later.

To change a binding, remove it from the account's Bindings tab and add a new one. Each change applies on the workload's next request.

Revoke a workload's access​

To stop a workload at once, suspend its account from the account's actions menu or remove its binding. The gateways refuse the workload's next request, and requests already admitted finish.

A token already issued keeps working until it expires, up to 60 minutes, even after you delete the Kubernetes ServiceAccount, because the gateways verify tokens by their signature. With a name-only binding, a ServiceAccount created again under the same name is the account again.

An account that loses its last binding, or whose issuers are all disabled, stays Active but its workloads are refused. Its page shows Active, but its workloads can't authenticate with a link to fix it.

Deleting a service account is permanent. It removes the account's bindings, group memberships, and grants. The account stays listed as Deleted, so its past spend remains attributed to it.

What an account can reach​

A trusted issuer accepts tokens from every namespace in its cluster, and the gateways refuse any workload without an active, bound account.

An account reaches a connector only through a group the connector is granted to, and only when the connector uses None, Bearer token, or Header injection authentication. The other authentication types act as the calling person, and a service account has no person behind it. The account's Connectors tab lists the connectors it reaches and the group each one comes through, and lets you change its groups and their connectors.

The AI Gateway's model access and budget settings decide which models the account can call:

Model accessBudgetsAn active, bound account can call
OnOnThe models its grants cover, within budget
OnOff (budgets.acknowledgeUnmetered)The models its grants cover, unmetered
OffOnAny model, within budget
OffOff (budgets.acknowledgeUnmetered)Any model, unmetered

Users get the same treatment, so a gateway with neither model access nor budgets admits every bound workload as freely as every signed-in user. See Control model access and Budgets and pricing.

Next steps​

Troubleshooting​

Activate is unavailable

The account has no binding, or every issuer its bindings use is disabled. Add a binding on the account's Bindings tab, or enable an issuer on the Trusted issuers tab.

A workload is refused with 401 or 403

See Handle errors for what each response means and where to find the reason.