A Kubernetes controller that manages RoleBindings through hierarchical folder structures with permission inheritance.
Kubernetes has no built-in concept of permission inheritance across namespaces. If you want the same RoleBinding in 20 namespaces, you create 20 RoleBindings. If a parent team should have access to all child team namespaces, you manage that manually.
Folder Controller introduces a Folder custom resource that lets you define a tree of folders, assign namespaces to them, and attach RoleBinding templates that optionally propagate down the tree. The controller reconciles the desired RoleBindings automatically.
Without Folder Controller, granting access across related namespaces requires individual RoleBindings:
# You'd need separate RoleBindings for platform-admin in prod-web,
# platform-admin in prod-api, prod-ops in prod-web, prod-ops in prod-api,
# web-developers in prod-web, api-developers in prod-api, etc.With a Folder resource:
apiVersion: rbac.kubevirt.io/v1alpha1
kind: Folder
metadata:
name: my-organization
spec:
folders:
- name: platform
roleBindingTemplates:
- name: platform-admin
propagate: true # Applies to all descendant folders
subjects:
- kind: Group
name: platform-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.io
- name: production
parent: platform
roleBindingTemplates:
- name: prod-ops
propagate: true
subjects:
- kind: Group
name: production-operators
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: admin
apiGroup: rbac.authorization.k8s.io
- name: web-app
parent: production
roleBindingTemplates:
- name: web-developers
subjects:
- kind: Group
name: web-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
namespaces: ["prod-web"]
- name: api-service
parent: production
roleBindingTemplates:
- name: api-developers
subjects:
- kind: Group
name: api-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
namespaces: ["prod-api"]This creates the following RoleBindings:
prod-web:platform-admin+prod-ops+web-developersprod-api:platform-admin+prod-ops+api-developers
- Hierarchical folders: Organize namespaces into trees using parent references. Folders without a
parentare roots. - Selective inheritance:
propagate: trueon a template passes it to all descendant folders. Default isfalse(local only). - Privilege escalation prevention: An admission webhook validates that users can only grant permissions they already hold, using impersonation + dry-run.
- Event-driven reconciliation: Watches Folder, RoleBinding, and Namespace resources. Only updates what changed via diff analysis.
- Namespace lifecycle handling: Existing namespaces can be deleted without breaking Folders. New namespace additions require the namespace to exist.
The controller uses an admission webhook with TLS certificates managed by cert-manager. Install it before deploying:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.16.3/cert-manager.yaml
kubectl wait deployment.apps/cert-manager-webhook --for=condition=Available -n cert-manager --timeout=5mThis is not required for local development with webhooks disabled.
kubectl apply -f https://github.com/mhenriks/kubernetes-folder-controller/releases/latest/download/install.yamlOr a specific version:
kubectl apply -f https://github.com/mhenriks/kubernetes-folder-controller/releases/download/v0.1.0/install.yamlgit clone https://github.com/mhenriks/kubernetes-folder-controller
cd kubernetes-folder-controller
make install && ENABLE_WEBHOOKS=false make runmake deploy # Deploys CRDs, controller, webhooks, and RBACSee the Quick Start Guide for a walkthrough, or the Release Guide for creating releases.
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Folder │───>│ Controller │───>│ RoleBindings │
│ Resource │ │ │ │ (Auto-managed) │
└─────────────────┘ └──────────────────┘ └─────────────────┘
^ │
│ v
┌─────────────────┐ ┌──────────────────┐
│ Admission │ │ Event Watchers │
│ Webhook │ │ (Drift Detection)│
│ (Validation) │ └──────────────────┘
└─────────────────┘
The Folder spec contains a flat list of folder definitions with optional parent references. The controller computes the resolved tree, calculates the effective RoleBinding templates for each namespace (direct + inherited propagating), and reconciles the cluster state. The resolved tree is written to status.resolvedTree.
The admission webhook validates structural integrity (no cycles, no orphans, unique names), business logic (namespace existence, template conflicts), and security (privilege escalation checks via impersonation).
The webhook prevents privilege escalation by impersonating the requesting user and performing dry-run operations for every RoleBinding that would be created, updated, or deleted. Users can only create Folder configurations that grant permissions they already hold.
The controller itself needs permissions for every ClusterRole it references. Three permission profiles are available:
- Broad (default): Covers admin/edit/view ClusterRoles
- Minimal: Common permissions only
- Custom: Define your own
See Security Model for details.
| Document | Description |
|---|---|
| Quick Start | Installation walkthrough with a working example |
| User Guide | Full documentation: usage, security, deployment, troubleshooting |
| Architecture | Technical design and component overview |
| Release Guide | How to build and publish releases |
- GitHub Issues — Bug reports and feature requests
- Discussions — Questions and ideas
- See the Development section for build/test instructions
- API Version: v1alpha1
- License: Apache 2.0
- Maintainer: @mhenriks