Tenant RBAC
Cosmonic Control is a Kubernetes-native platform, so multi-tenant access control uses standard Kubernetes Role and RoleBinding objects. This page covers how to set up namespace-scoped RBAC for tenant teams, what the Cosmonic Control operator requires cluster-wide, and how to restrict team access to their own namespaces.
How it works
Cosmonic Control installs one ClusterRole that the operator service account uses to manage CRDs and read core resources across all namespaces. Tenant teams are separate from the operator — they are given narrower, namespace-scoped Role objects that only permit them to manage their own workloads.
Cluster level:
operator ServiceAccount → ClusterRole (cosmonic-control)
manages all CRDs, reads ConfigMaps/Secrets/Namespaces
Namespace level (per team):
team-a ServiceAccount/User → Role (in namespace team-a)
manage HTTPTrigger, Artifact
Operator ClusterRole
The operator's ClusterRole is installed by the Helm chart and grants the following permissions:
| API Group | Resources | Verbs |
|---|---|---|
control.cosmonic.io | httptriggers, projectenvironments | full CRUD |
control.cosmonic.io | httptriggers/status, projectenvironments/status | get, update, patch |
runtime.wasmcloud.dev | artifacts, hosts, workloads, workloadreplicasets, workloaddeployments | full CRUD |
runtime.wasmcloud.dev | */status | get, update, patch |
"" (core) | configmaps, secrets, namespaces | get, list, watch |
"" (core) | events | get, list, watch, create, update, patch |
coordination.k8s.io | leases | full CRUD (leader election) |
The operator reads configmaps and secrets cluster-wide to deliver configuration to components (see Component Configuration). This means Secrets in any namespace are readable by the operator service account. Use namespace-level RBAC to control which humans and CI systems can create or read Secrets in each namespace.
Setting up a tenant namespace
The typical pattern for onboarding a team:
- Create a namespace for the team
- Create a
Rolegranting them access to Cosmonic Control resources in that namespace - Create a
RoleBindinglinking the role to the team's user, group, or service account
1. Create the namespace
kubectl create namespace team-a2. Create a Role
A standard developer role grants full access to HTTPTrigger and Artifact resources — the two resources developers interact with directly. Read access to the managed resources (WorkloadDeployment, Workload, etc.) is useful for debugging.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cosmonic-developer
namespace: team-a
rules:
# Create and manage workload entrypoints
- apiGroups: ["control.cosmonic.io"]
resources: ["httptriggers"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: ["control.cosmonic.io"]
resources: ["httptriggers/status"]
verbs: ["get", "list", "watch"]
# Manage artifact pre-fetch (enterprise)
- apiGroups: ["runtime.wasmcloud.dev"]
resources: ["artifacts"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Read-only access to managed resources for debugging
- apiGroups: ["runtime.wasmcloud.dev"]
resources:
- workloaddeployments
- workloadreplicasets
- workloads
- hosts
verbs: ["get", "list", "watch"]
# Manage own ConfigMaps and Secrets for component config
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]kubectl apply -f cosmonic-developer-role.yaml3. Create a RoleBinding
Bind the role to a user, group, or service account:
# Bind to a specific user
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-developers
namespace: team-a
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: cosmonic-developer
subjects:
- kind: User
name: alice@corp.com
apiGroup: rbac.authorization.k8s.io
- kind: User
name: bob@corp.com
apiGroup: rbac.authorization.k8s.ioFor CI/CD pipelines, bind to a service account instead:
subjects:
- kind: ServiceAccount
name: team-a-ci
namespace: team-akubectl apply -f team-a-rolebinding.yamlRead-only role
For users who need visibility without write access (e.g., on-call engineers, security auditors):
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cosmonic-viewer
namespace: team-a
rules:
- apiGroups:
- control.cosmonic.io
- runtime.wasmcloud.dev
resources: ["*"]
verbs: ["get", "list", "watch"]Verifying access
Test that a user or service account has the expected permissions with kubectl auth can-i:
# Can alice create HTTPTriggers in team-a?
kubectl auth can-i create httptriggers.control.cosmonic.io -n team-a --as alice@corp.com
# Can alice read Secrets in team-b? (should be no)
kubectl auth can-i get secrets -n team-b --as alice@corp.com
# List all permissions a user has in a namespace
kubectl auth can-i --list -n team-a --as alice@corp.comIsolation guarantees
Namespace-scoped RBAC controls who can manage Cosmonic Control resources. The isolation between running workloads is enforced by the WebAssembly sandbox — components running in different namespaces cannot communicate unless explicitly linked, and a component cannot access host resources (filesystem, network, environment) outside of what is declared in its localResources and allowedHosts manifest fields.
This means a compromised component cannot escalate to read another namespace's Secrets or ConfigMaps through the Wasm interface — the component model itself enforces the boundary. The RBAC layer ensures that the teams managing the manifests are also properly separated.