RBAC
Role-Based Access Control (RBAC) in the MATIH platform restricts Kubernetes API access based on the principle of least privilege. Each service runs with a dedicated ServiceAccount that has only the permissions required for its operation, and administrative access is controlled through namespaced Roles and ClusterRoles.
RBAC Architecture
User/ServiceAccount --> RoleBinding/ClusterRoleBinding --> Role/ClusterRole --> API ResourcesServiceAccount Strategy
Each service deployment uses a dedicated ServiceAccount:
| Service | ServiceAccount | Namespace | Purpose |
|---|---|---|---|
| AI Service | ai-service | matih-data-plane | Access ConfigMaps, Secrets |
| Query Engine | query-engine | matih-data-plane | Access ConfigMaps |
| API Gateway | api-gateway | matih-system | Access Endpoints, Services |
| Tenant Service | tenant-service | matih-system | Create Namespaces, Secrets, Deployments |
| cert-manager | cert-manager | cert-manager | Manage Certificates, DNS |
| Prometheus | prometheus | matih-monitoring | Read all namespace metrics |
Role Types
| Type | Scope | Use Case |
|---|---|---|
| Role | Namespace | Service-specific permissions within its namespace |
| ClusterRole | Cluster-wide | Cross-namespace or cluster-level permissions |
| RoleBinding | Namespace | Binds a Role/ClusterRole to a subject in a namespace |
| ClusterRoleBinding | Cluster-wide | Binds a ClusterRole to a subject globally |
Standard Service Role
Most data plane services need minimal permissions:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ai-service
namespace: matih-data-plane
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["ai-service-secrets"]
verbs: ["get"]Tenant Service Role (Elevated)
The Tenant Service requires elevated permissions for tenant provisioning:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: tenant-provisioner
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["create", "get", "list", "delete"]
- apiGroups: [""]
resources: ["secrets", "configmaps", "services"]
verbs: ["create", "get", "list", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["create", "get", "list", "update", "delete"]
- apiGroups: ["networking.k8s.io"]
resources: ["networkpolicies", "ingresses"]
verbs: ["create", "get", "list", "update", "delete"]Monitoring ServiceAccount
Prometheus requires read access across all namespaces for metric scraping:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-reader
rules:
- apiGroups: [""]
resources: ["pods", "endpoints", "services"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["nodes/metrics"]
verbs: ["get"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]Human Access Roles
| Role | Scope | Permissions |
|---|---|---|
| Platform Admin | Cluster | Full cluster access (limited to break-glass) |
| Operator | Cluster | Read all, write to specific namespaces |
| Developer | Namespace | Read pods, logs, exec into dev pods |
| Viewer | Namespace | Read-only access to resources |
Developer Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: developer
namespace: matih-data-plane
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]RBAC Best Practices
| Practice | Implementation |
|---|---|
| Least privilege | Each service only gets permissions it needs |
| Namespace scoping | Prefer Roles over ClusterRoles |
| Named resources | Use resourceNames to restrict to specific secrets |
| No wildcards | Avoid * in resources or verbs |
| Audit logging | Enable Kubernetes audit logging for RBAC decisions |
| Regular review | Quarterly review of all ClusterRoleBindings |
Helm Integration
ServiceAccounts and RBAC resources are created by Helm charts:
# values.yaml
serviceAccount:
create: true
name: ai-service
annotations:
azure.workload.identity/client-id: "CLIENT_ID"
rbac:
create: true
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]Troubleshooting
| Issue | Symptom | Resolution |
|---|---|---|
| Forbidden error | User cannot get resource | Add missing RBAC rule |
| Secret access denied | Pod cannot read secret | Verify Role includes secret access |
| Cross-namespace denied | Cannot access resource in other namespace | Use ClusterRole + RoleBinding |
| ServiceAccount missing | Pod uses default SA | Verify serviceAccountName in deployment |