Authorization
Identity and access management (IAM) determines who can read, create, change, or operate OpenClaw Enterprise resources. Every operation is checked against its exact action, resource, and Namespace. Requests without an explicit matching grant are denied. This page defines the current authorization contract; authentication defines how API clients establish a session or verify a service key.
Principal, ServicePrincipal, or Group │ ▼AccessBinding ──► Role ──► Permission │ │ └── exact scope ──────┘ │ ▼ Matching Restriction? yes ──► deny no ──► allowAn authenticated principal is not automatically authorized. A user session or service API key establishes the caller identity; the selected IAM Driver separately checks whether that principal can perform the requested operation.
Supported policy surface
Fresh native-IAM bootstrap provisions the human administrator and one Installation-scoped, non-Agent ServicePrincipal. Each receives its own binding to the same administrator Role, with no Namespace or resource filter:
| Resource kind | Actions |
|---|---|
installation |
administer, read |
namespace |
create, read, delete |
configuration, preset, service_account |
create, read, update, delete |
secret |
create, read, update, delete, operate |
agent |
create, read, update, delete, deploy, operate, administer |
agent_revision |
read |
These grants cover existing and future Namespaces in this Installation, subject to exact authorization and matching Restrictions. They confer no Kubernetes or provider authority. Rerunning bootstrap does not rewrite stored grants. The Preset upgrade extends only the unchanged built-in administrator Role; see Preset upgrade eligibility. Removing the original human account does not remove the service identity. See bootstrap authentication for credential delivery and lifecycle.
Administrators can provision additional local authentication accounts with a binding to an existing Role, as defined in account provisioning. Public signup is disabled. Creating an account does not create a Role or implicitly grant administrator rights.
Administrators manage immutable Namespace Roles and exact-resource identity AccessBindings through the Namespace policy APIs. Group, membership, Restriction, and broad grant management remain unavailable through HTTP. The policy records below illustrate internal semantics; use the API request shapes for public mutations.
Principals
A principal names the actor requesting access. The platform has exactly two principal types:
- Principal: An explicitly provisioned human identity identified by its trusted issuer and immutable subject.
- ServicePrincipal: An automation identity scoped to the Installation or one Namespace. Each Agent owns exactly one immutable, Namespace-scoped ServicePrincipal; ordinary service principals can represent non-Agent automation.
The controller authenticates a user session for the human Principal or a
service API key for an explicitly provisioned,
non-Agent ServicePrincipal. Service-key lookup supplies the verified
servicePrincipalId and its stored Namespace to the selected IAM Driver; it does
not reinterpret a human issuer/subject as an automation identity.
An Agent created or deployed by that Principal retains its own separate service
principal. Agent-owned service principals have the same role-granted platform
capabilities as human Principals, subject to their Namespace scope, exact
resource grants, and matching Restrictions. When explicitly selected, the
Kubernetes Compute Driver provisions an Agent-specific
ServiceAccount and can project a short-lived, audience-scoped ServiceAccount
token into that Agent's revision Pods. This projected token is credential
evidence for the Agent's existing ServicePrincipal, not another platform
principal. OCC token verification, identity exchange, and ServicePrincipal
workload authentication through the controller API remain deferred. Ordinary
service keys are deliberately unavailable to Agent-owned principals.
An unknown identity is denied. Email addresses, display names, caller-supplied identity headers, or membership in another Namespace do not grant access.
Permissions and Roles
A Permission allows one action on one resource kind. Supported permission
actions are create, read, update, delete, deploy, operate, and
administer; not every action has a corresponding public endpoint yet. Any of
these actions can be granted to either a human Principal or an Agent-owned
ServicePrincipal through an appropriately scoped Role and AccessBinding.
Resource kinds currently include installation, namespace, configuration,
preset, agent, agent_revision, secret, credential_source, and
service_account. Use the
permissions cheat sheet for the resource matrix and
operations that require additional grants.
An OCC-owned service account is not an IAM principal.
Creation requires create in its exact Namespace; account operations require
their exact-account permission. Associated Agent operations require account
read; updating/detaching requires current-account read, and replacement
requires read on both old and new accounts. IAM never accesses credentials.
The generated API reference documents session and service-key authentication
and the exact permissions required by every operation. Its source is the
generated OpenAPI contract,
where each human-readable operation description is accompanied by an
x-openclaw-permissions array containing each required action, resourceKind,
and scope. Collection scopes distinguish access to the requested parent from
the separate permission checked for each returned resource.
A Role groups Permissions:
{ "id": "role-support-agents", "namespaceId": "ns_45b6dbdb-2fc2-4c2c-9cc4-a94cf26cc6c2", "permissions": [ { "action": "read", "resourceKind": "agent" }, { "action": "create", "resourceKind": "agent" } ]}This example illustrates an internal policy record. Role creation takes only
name and permissions; OCC supplies its ID and Namespace.
Access bindings and Groups
An AccessBinding attaches a Role to one principal or Group at a specific scope.
For example, this internal record grants the preceding Role to a Principal in
the support Namespace:
{ "id": "binding-support-alex", "namespaceId": "ns_45b6dbdb-2fc2-4c2c-9cc4-a94cf26cc6c2", "subjectKind": "identity", "subjectId": "principal-alex", "roleId": "role-support-agents"}Groups collect human Principals so one binding can grant the same Role to multiple members; ServicePrincipals receive direct AccessBindings rather than Group membership. Membership is direct and must remain inside the Group's scope; a Namespace-scoped Group cannot grant access in another Namespace.
Bindings can apply to the singleton Installation, one Namespace, or one exact
resource. A binding without namespaceId is Installation-wide; a
Namespace-scoped binding applies only to its exact Namespace. An exact-resource
binding additionally identifies the resource kind and ID.
Manage Namespace policy
Use /namespaces/:namespaceId/iam/roles and
/namespaces/:namespaceId/iam/access-bindings. Collection GET lists policy in
that Namespace and POST creates a server-identified resource. Item GET
reads one resource; item DELETE removes only that resource. Reads return
200, creation 201, deletion 204, and missing resources 404.
The Namespace IAM policy flow traces the
controller, Driver, persistence, and audit path.
Installation bootstrap policy is excluded from these lists. Reads include existing
broad and Group bindings in the Namespace; deletion can revoke one by its exact
ID. The narrower subject and target requirements below apply to creation.
Every operation requires Installation administer and exact Namespace read,
evaluated by the selected IAM Driver and applicable Restrictions. Creating a
binding also requires read on its exact target. Ordinary resource access
does not authorize delegation. Drivers without policy management return
503 DEPENDENCY_UNAVAILABLE; OCC never substitutes native IAM.
Create a reusable Role with a nonempty, duplicate-free permission set:
{ "name": "Use a model Secret", "permissions": [{ "action": "operate", "resourceKind": "secret" }]}Bind it to the immutable servicePrincipalId returned in the Agent response:
{ "subjectKind": "identity", "subjectId": "<agent-service-principal-id>", "roleId": "<role-id>", "resourceKind": "secret", "resourceId": "<secret-id>"}The subject must be an existing human Principal or a ServicePrincipal in the
path Namespace. A human does not need a separate Namespace ServicePrincipal.
The Role and target must exist in the path Namespace. Exact targets and Role
permission kinds are namespace, agent, agent_revision, configuration,
credential_source, preset, secret, or service_account. namespace
permissions support only read, and for a namespace target, resourceId must
equal the Namespace ID in the path. A ServiceAccount
resource is not an IAM identity. Caller IDs, scope, wildcard targets, Groups, unknown permissions,
and extra fields are rejected. Native IAM commits validated policy and its
attributable audit event together; later requests on other replicas see it
without a restart.
For human discovery, grant read on that exact Namespace and separately grant
the required actions on each exact Agent. A Namespace target grants only
Namespace actions; it does not grant access to its Agents or permission to
create child resources. Human enrollment and grant creation are separate steps.
Roles and bindings cannot be updated. Create replacements and explicitly
remove old bindings. A referenced Role cannot be deleted (409), and deleting
one binding preserves equivalent and unrelated bindings. Deleting an Agent,
Configuration, Preset, Secret, credential source, or ServiceAccount removes the
bindings that target it in the same transaction. After an unknown
creation outcome, list and inspect policy before retrying; equivalent bindings
may coexist. Names are labels: inspect permissions before reusing a Role.
Deleting a binding does not establish effective denial: other bindings and Restrictions still apply. Revocation blocks later admission but cannot retract already delivered bytes. Stop the Agent and revoke upstream credentials when immediate containment is necessary; IAM changes do neither automatically.
Restrictions
A Restriction narrows permissions that would otherwise be granted. It can deny an exact action for a resource kind, a Namespace, or an exact resource:
{ "id": "restriction-support-deploy", "namespaceId": "ns_45b6dbdb-2fc2-4c2c-9cc4-a94cf26cc6c2", "action": "deploy", "resourceKind": "agent", "effect": "deny"}A matching Restriction overrides direct identity grants and Group grants. A Restriction never grants access, expands scope, or selects a different authorization provider.
Authorization decisions
For each protected operation, the controller:
- Verifies the user session or service key and resolves its existing Principal or non-Agent ServicePrincipal through the selected IAM Driver.
- Uses the server-configured IAM Driver for the requested resource.
- Loads current policy, including principal bindings and direct Group memberships.
- Requires a Role Permission matching the exact action and resource kind.
- Verifies the exact Installation, Namespace, or resource scope.
- Rejects matching Restrictions equally for human and service principals.
- Records attributable authorization evidence without exposing credentials.
Lists are also authorized per resource. Permission to deploy an Agent does not
automatically grant permission to read it, and permission to read one Agent
does not expose every Agent in the Namespace. First deployment additionally
checks Agent read and operate if Compute must generate missing transport
credentials.
The selected IAM Driver loads current authoritative policy for each identity lookup and authorization decision. Account and permission changes become visible across controller instances without restarting or replacing the Driver.
An unavailable IAM Driver, invalid policy, missing grant, mismatched scope, or ambiguous identity fails closed.
Denials and failures
401: The session cookie or service key is missing, invalid, expired, or revoked.403: The principal lacks an exact grant, belongs to another Namespace, or matches a deny Restriction.404: The requested resource does not exist under its exact parent.503 DEPENDENCY_UNAVAILABLE: The selected IAM or audit dependency is unavailable; no fallback authorization provider is used.- A resource is absent from a list: Your identity may not have
readpermission for that specific resource. 409deleting a Role: remove its referencing bindings explicitly first.- Group or broad-grant mutation is rejected: Namespace policy APIs support identity subjects and exact resource targets only.
Evidence and related references
The current policy implementation is the IAM package.
For a working authenticated request, see the quickstart.
