Delegate authorization by namespace
Use PlatformRoleBinding to let namespace administrators grant approved roles
on the MCP servers they manage. Cluster admins maintain the role catalog, while
namespace admins maintain bindings in their namespaces.
When to use it
Use delegated authorization when a team owns the workload and has its own IdP
group. The team can manage access in the same manifests as its MCPServer by
selecting roles from the cluster admin's ClusterPlatformRole catalog.
How the trust model works
The effective principal set on a ToolhiveAuthorizationPolicy is the union of:
- every matching
ClusterPlatformRoleBindingat the cluster scope, and - every matching
PlatformRoleBindingin the policy's own namespace.
Namespace bindings can only add principals to that union. They cannot remove a
grant that a ClusterPlatformRoleBinding made cluster-wide. To deny an access
path for a specific MCP target, use the policy's deny[] list, which compiles
to a Cedar forbid rule and overrides every grant. The escalation direction is
intentional: the cluster admin retains a clean override path through
ClusterPlatformRoleBinding, and the team gets fast iteration on additive
grants.
| Source | Scope | Who authors |
|---|---|---|
ClusterPlatformRoleBinding | Cluster-wide | Cluster admin |
PlatformRoleBinding | One namespace | Namespace owner |
ToolhiveAuthorizationPolicy | One MCP target | Namespace owner |
For full field details on each resource, see the ClusterPlatformRoleBinding, PlatformRoleBinding, and ToolhiveAuthorizationPolicy CRD references.
Walkthrough
This walkthrough builds on the
Quickstart: GitHub MCP with Entra ID. The difference
is the namespace: the team owns team-alpha and has deployed an MCPServer named
alpha-tools-mcp there. The cluster admin has previously authored a read-only
ClusterPlatformRole and granted the team's namespace RBAC to manage
platformrolebindings and toolhiveauthorizationpolicies in team-alpha.
1. Bind the IdP role to the catalog role
Create a PlatformRoleBinding in team-alpha that maps the Entra app role
mcp-team-alpha-engineers to the cluster-published read-only
ClusterPlatformRole:
apiVersion: platform.enterprise.stacklok.com/v1alpha1
kind: PlatformRoleBinding
metadata:
name: alpha-engineers-readonly
namespace: team-alpha
spec:
bindings:
- roleRef:
kind: ClusterPlatformRole
name: read-only
from:
- roles:
- mcp-team-alpha-engineers
kubectl apply -f alpha-engineers-readonly.yaml
This binding only contributes principals to authorization policies in
team-alpha. The roleRef points at a cluster-scoped role, so the team
consumes the catalog without authoring verbs.
2. Attach the role to the MCP target
Create a ToolhiveAuthorizationPolicy in team-alpha that binds the
read-only role to alpha-tools-mcp:
apiVersion: toolhive.enterprise.stacklok.com/v1alpha1
kind: ToolhiveAuthorizationPolicy
metadata:
name: alpha-tools-readonly
namespace: team-alpha
spec:
targetRef:
name: alpha-tools-mcp
bindings:
- roleRef:
kind: ClusterPlatformRole
name: read-only
kubectl apply -f alpha-tools-readonly.yaml
targetRef.kind defaults to MCPServer, so it's omitted. The policy's
namespace and the MCPServer's namespace must match.
3. Wait for the policy to compile
kubectl wait --for=condition=Compiled \
tap/alpha-tools-readonly -n team-alpha --timeout=60s
When the Compiled condition flips to True, the operator has turned the
policy plus the matching PlatformRoleBinding into the Cedar policy bundle the
proxy will enforce.
4. Verify with a token from the team's IdP group
Obtain a token for a user assigned to mcp-team-alpha-engineers and call a tool
through the proxy at alpha-tools-mcp, following the pattern in
step 6 of the Entra quickstart.
Expected outcome: tool calls that carry the readOnlyHint annotation return
200, and tool calls that don't carry it return 403. The read-only role's
principal set was contributed entirely by the team's PlatformRoleBinding; no
cluster-wide binding had to change.
Delegation boundaries
Namespace admins have these restrictions:
- Subtract a cluster-wide grant. If a
ClusterPlatformRoleBindinggrants a role to a principal that also matches aToolhiveAuthorizationPolicyin the team's namespace, the team cannot drop that principal locally. The options are adeny[]entry on the authorization policy to override grants for one specific MCP target, or a request to the cluster admin to change theClusterPlatformRoleBinding. - Author or edit a
ClusterPlatformRole. Roles live in the cluster-admin-owned catalog. The team consumes them byroleRef. - Bind across namespaces. A
PlatformRoleBindinginteam-alphaonly contributes principals to authorization policies whose namespace isteam-alpha. Cross-namespace effects require aClusterPlatformRoleBinding, which only the cluster admin can author.
Limit the available roles
The access gate on namespace self-service is namespace-level Kubernetes RBAC on
platformrolebindings and toolhiveauthorizationpolicies. A team with those
permissions can reference any ClusterPlatformRole in the cluster. Publish a
curated catalog of narrowly scoped roles that are safe for namespace admins to
assign.
Next steps
- See every field on the namespace binding in the PlatformRoleBinding CRD reference.
- See the cluster-scoped counterpart in the ClusterPlatformRoleBinding CRD reference.
- Read how identity, roles, and bindings fit together in the Authentication and authorization framework.