Bind a workload identity
An identity binding names the ServiceAccount that a registered workload's calls use. AIControls authorizes that ServiceAccount, in that cluster, and never the workload's name or labels. You bind the identity when you register the workload, or afterward with the API on this page.
Workload Trust is available only in private, self-managed AIControls installations, on premises or in a cloud cluster that you run. It needs a dedicated cluster that you run, with Kyverno, Kyverno Runtime, and cluster OIDC and RBAC access in place. Nirmata-hosted (SaaS) workspaces don't include it. See Feature availability.
Before you begin
-
You need an administrator session. Every request on this page requires the
clusterquery parameter: the UID of the cluster'skube-systemnamespace, which this command prints:kubectl get namespace kube-system -o jsonpath='{.metadata.uid}'Until the controller can read the
kube-systemnamespace, it keys the cluster by its display name instead. AIControls refuses identity binding writes (create, update, and retire), access writes, mode changes, contains, and recommendation promotions and dismissals that name that display name ascluster, with409 cluster_identity_unavailable, because configuration written under the display name wouldn't carry over once the UID resolves. Wait for the UID, then retry with it ascluster. Release stays allowed under the display name, because containment moves to the UID when it resolves. If it has already moved, a release that names the display name returns409 cluster_identity_changedand releases nothing; retry with the UID ascluster. -
Register the workload first. See Register a workload.
-
Give the workload its own ServiceAccount. All Pods that run as one ServiceAccount are one principal and share the same access. See Workload Blueprints and Workload Registrations.
After you bind a pod_uid identity, AIControls denies the workload's calls until its registration names a Blueprint. A registration made in the wizard always does, so bind a workload you registered by another route to a Blueprint at once. A virtual_key binding stays on the legacy path: it never produces workload access and doesn't cause this denial.
Bind the identity
Send the binding. Use
expectedRevision0to create it:curl -X PUT "https://YOUR_WORKSPACE_URL/api/v1/workloads/prod/Deployment/checkout/identity-binding?cluster=$CLUSTER_UID" \-H "Authorization: Bearer $AICONTROLS_TOKEN" \-H "Content-Type: application/json" \-d '{"identityKey": "k8s://prod/checkout-sa", "rung": "pod_uid", "expectedRevision": 0}'Field Meaning identityKeyFor pod_uid,k8s://<namespace>/<serviceaccount>, and the namespace must match the workload's namespace. Forvirtual_key, any non-empty key.rungpod_uidfor a verified Pod-bound ServiceAccount. Thevirtual_keyrung records a binding, but a workload bound that way doesn't get workload access.expectedRevision0to create. For an update, the current revision.The response returns the binding
id, theidentityKey, therung, and the newrevision.Read the workload's access state to confirm the binding:
curl "https://YOUR_WORKSPACE_URL/api/v1/workloads/prod/Deployment/checkout/access?cluster=$CLUSTER_UID" \-H "Authorization: Bearer $AICONTROLS_TOKEN"identityBindingshows the active binding.registrationshows therowVersionandrowTokenthat you need to change the workload's override.Set the workload's override if it differs from its Blueprint, and switch it to Enforce when it's ready. See Register a workload and Switch a workload to Enforce.
The web UI has no identity binding screen yet. After you bind the identity, the AI access tab on the workload detail page shows the workload's Blueprint, its two bindings, and its effective access.
Change the binding
To update a binding, send the PUT request again with the current revision as expectedRevision. To bind a different ServiceAccount, retire the current binding, and then create a new one.
Retire a binding:
curl -X DELETE "https://YOUR_WORKSPACE_URL/api/v1/workloads/prod/Deployment/checkout/identity-binding?cluster=$CLUSTER_UID&expectedRevision=1" \
-H "Authorization: Bearer $AICONTROLS_TOKEN"
AIControls refuses to retire a binding that a registration still uses, with 409 identity_binding_pinned. Deleting the registration releases it. A PUT that changes the identityKey of an existing binding returns 409 identity_key_change; retire the binding, and then create a new one with expectedRevision 0.
Troubleshooting
| Response | Cause | Fix |
|---|---|---|
400 | For pod_uid, the identityKey isn't k8s://<namespace>/<serviceaccount> in the workload's namespace; for virtual_key, it is empty; or the rung isn't pod_uid or virtual_key. | Correct the request. |
409 identity_conflict | Another workload in this cluster already has a configured binding for the ServiceAccount. A discovered shared ServiceAccount alone doesn't cause this. | Give each workload its own ServiceAccount, or retire the other binding. |
409 conflict | The expectedRevision is stale, or you sent 0 for a workload that already has a binding. | Read the current revision and retry. |
409 identity_binding_pinned | You tried to retire a binding that a registration still uses. | Delete the registration, and then retire the binding. |
409 identity_key_change | You sent a different identityKey with a nonzero expectedRevision. A binding's key never changes. | Retire the binding, and then create a new one with expectedRevision 0. |
Calls denied by workload-registration-binding-incoherent | The registration doesn't name a Blueprint, the Blueprint's bindings are missing, or the identity binding moved to a new revision. | Check the registration on the workload's AI access tab, and select a Blueprint. See Fail-closed rules. |