A Kubernetes operator for managing dynamic RBAC through Custom Resource Definitions. Auth Operator simplifies multi-tenant authorization by providing declarative APIs for generating roles and bindings based on deny-list patterns and dynamic namespace selection.
- 🔐 Dynamic Role Generation — Create ClusterRoles/Roles using a deny-list pattern instead of explicit permissions
- 🔗 Flexible Bindings — Bind subjects to roles with dynamic namespace selection via label selectors
- 🏷️ Namespace Ownership — Admission supports
platform,tenant,thirdparty, andaddonownership; see the namespace label contract. - 🔄 Auto-Discovery — Automatically discovers new CRDs and updates roles accordingly
- 🛡️ Drift Protection — Periodically reconciles to prevent unauthorized manual changes
- 📜 Self-Signed TLS — No cert-manager required; uses cert-controller for automatic certificate rotation
- 🚫 Namespace Deletion Protection — Platform and opted-in namespaces require an explicit allow-deletion annotation before deletion; system namespaces are never deletable, with no admin bypass (ValidatingAdmissionPolicy + webhook fallback)
- 🧾 Creator Tracking — Optionally records effective creator and contributor identities
with Kubernetes MutatingAdmissionPolicy. The native path requires Kubernetes
1.34+. On 1.34/1.35, set kube-apiserver
--feature-gates=MutatingAdmissionPolicy=trueand--runtime-config=admissionregistration.k8s.io/v1beta1=true. Older clusters can use the Kyverno alternatives. See the creator tracking guide.
- Installation
- Quick Start
- Configuration
- CRD Reference
- Architecture
- Development
- Additional Documentation
- License
- Kubernetes 1.28+
- Helm 3.17+ (for Helm installation)
- kubectl configured with cluster access
Note: cert-manager is NOT required. The operator uses cert-controller for automatic TLS certificate management.
helm install auth-operator oci://ghcr.io/telekom/charts/auth-operator \
--version <chart-version> \
--namespace auth-operator-system \
--create-namespaceNote: Published charts use
image.digestfor immutable, digest-pinned images by default. If digest is empty, falls back toimage.tag, thenChart.AppVersion. See values.yaml for details.
For configuration options, see the Helm Chart README.
git clone https://github.com/telekom/auth-operator.git
cd auth-operator
make deploy OVERLAY=default
> **⚠️ WARNING:** The Kustomize `default` overlay provides a basic installation but does **not** include the production-hardening primitives (split ServiceAccounts, NetworkPolicies, PodDisruptionBudgets, secure-metrics) provided by the Helm chart. For production environments, the Helm chart is the **only** recommended and fully hardened installation path.kubectl get pods -n auth-operator-system
kubectl get crds | grep t-caas.telekom.comAuth Operator provides six CRDs for managing RBAC:
| CRD | Purpose |
|---|---|
| RoleDefinition | Generates ClusterRoles/Roles using deny-list pattern |
| BindDefinition | Creates ClusterRoleBindings/RoleBindings for subjects |
| WebhookAuthorizer | Configures webhook-based SubjectAccessReview authorization |
| RBACPolicy | Defines policy constraints for restricted CRDs |
| RestrictedRoleDefinition | Policy-governed variant of RoleDefinition |
| RestrictedBindDefinition | Policy-governed variant of BindDefinition |
Trust boundary: Plain
RoleDefinitionandBindDefinitionwrite access is for platform-admin or trusted-admin workflows. Writers can cause the operator to create or bind real Kubernetes RBAC. For delegated or self-service RBAC, useRBACPolicywithRestrictedRoleDefinitionandRestrictedBindDefinition.
Generate a ClusterRole that includes all resources except those in the deny list:
apiVersion: authorization.t-caas.telekom.com/v1alpha1
kind: RoleDefinition
metadata:
name: tenant-developer
spec:
targetRole: ClusterRole
targetName: tenant-developer
scopeNamespaced: true
# Deny list - excluded from generated role
restrictedApis:
- name: authorization.t-caas.telekom.com
- name: cert-manager.io
restrictedResources:
- name: secrets
- name: nodes
restrictedVerbs:
- deletecollectionkubectl apply -f roledefinition.yaml
kubectl get clusterrole tenant-developer -o yamlBind subjects to roles with dynamic namespace selection:
apiVersion: authorization.t-caas.telekom.com/v1alpha1
kind: BindDefinition
metadata:
name: tenant-developers
spec:
targetName: tenant
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: developers@example.com
- kind: ServiceAccount
name: ci-runner
namespace: ci-system
clusterRoleBindings:
clusterRoleRefs:
- view
- tenant-developer
roleBindings:
- clusterRoleRefs:
- edit
namespaceSelector:
- matchLabels:
team: alphakubectl apply -f binddefinition.yaml
kubectl get rolebindings -A -l app.kubernetes.io/managed-by=auth-operatorThe operator uses CLI flags (not environment variables) for most settings. See the Operator Guide for the full reference.
| Flag | Default | Description |
|---|---|---|
--namespace |
$POD_NAMESPACE |
Operator namespace (value of POD_NAMESPACE env var; empty if unset) |
--health-probe-bind-address |
:8081 |
Health probe bind address |
--metrics-bind-address |
:8080 |
Metrics bind address |
--leader-elect |
true |
Enable leader election for HA |
| Parameter | Description | Default |
|---|---|---|
controller.replicas |
Controller replica count | 1 |
webhookServer.replicas |
Webhook server replica count | 2 |
controller.podDisruptionBudget.enabled |
Enable PDB | false |
See values.yaml for all options.
RBACPolicy impersonation RBAC is not granted by default. Enable
controller.impersonation.enabled with either explicit serviceAccounts entries
or clusterWide=true only when RBACPolicy writers are platform-admin trusted.
Kustomize deployments can opt in by adding the optional
config/rbac/impersonation_clusterrole*.yaml resources.
Dynamically generates ClusterRoles or Roles by discovering all available API resources and subtracting a deny list.
How it works:
- Discovers all API groups and resources in the cluster
- Filters out resources matching
restrictedApis,restrictedResources, andrestrictedVerbs - Creates/updates the target ClusterRole or Role with the remaining permissions
Reconciliation triggers:
- Changes to RoleDefinition resources
- New CRD registrations (to include new resource types)
- Periodic sync every 60 seconds (drift protection)
Example: See config/samples/authorization_v1alpha1_roledefinition.yaml
Creates ClusterRoleBindings and RoleBindings to bind subjects (Users, Groups, ServiceAccounts) to roles.
Key capabilities:
- Dynamic namespace selection — Use label selectors to automatically bind to matching namespaces
- ServiceAccount auto-creation — Creates ServiceAccounts if they don't exist
- Mixed bindings — Combine ClusterRoleBindings and RoleBindings in one resource
Naming convention:
Bindings are named as: {targetName}-{roleName}-binding
Reconciliation triggers:
- Changes to BindDefinition resources
- New Namespace creation (to apply bindings)
- Periodic sync every 60 seconds (drift protection)
Example: See config/samples/authorization_v1alpha1_binddefinition.yaml
Configures fine-grained SubjectAccessReview decisions for the webhook server.
The Kubernetes API server must be configured with an authorization webhook that
calls the auth-operator /authorize endpoint before these resources affect live
API authorization.
Within a WebhookAuthorizer, denied principals are rejected before allow rules
are evaluated. Allowed principals must also match a resource or non-resource
rule. When multiple authorizers match, they are evaluated deterministically by
name; the first allow or deny decision is returned. A request with no matching
authorizer returns no opinion, so the API server can continue evaluating later
authorizers in its chain.
Key capabilities:
- Resource and non-resource rules - Match Kubernetes API requests or paths such as
/healthz - Allow and deny principals - Match users, groups, or ServiceAccount identities
- Namespace scoping - Use
namespaceSelectorto limit resource requests to matching namespaces - Status reporting - Sets
status.authorizerConfigured=trueandReady=Trueafter reconciliation
Example: See config/samples/authorization_v1alpha1_webhookauthorizer.yaml
flowchart LR
RD[RoleDefinition] --> RC[Role controllers]
RRD[RestrictedRoleDefinition] --> RC
BD[BindDefinition] --> BC[Binding controllers]
RBD[RestrictedBindDefinition] --> BC
P[RBACPolicy] --> RC
P --> BC
API[Kubernetes API discovery] --> RC
RC --> R[Roles and ClusterRoles]
BC --> B[RoleBindings and ClusterRoleBindings]
WA[WebhookAuthorizer] --> WC[Authorizer controller]
WC --> S[Authorizer status]
WA --> W[Webhook server]
K[Kubernetes API server] -->|Admission requests| W
K -->|SubjectAccessReview at /authorize| W
Controllers reconcile the six CRDs into RBAC resources and status. Restricted
definitions are checked against their referenced RBACPolicy. The webhook server
validates custom resources, optionally manages namespace admission, and evaluates
authorization requests against WebhookAuthorizer rules. The API server must be
configured to call /authorize for webhook authorization; identity-provider
configuration remains outside this operator.
Before adding helpers, follow the upstream-first guidance.
Auth Operator uses t-caas-go-library
packages ssa, patch, discovery/tracker, namespaceselector, ratelimit,
and certrotation; operator-specific policy stays local. See
the integration points
before replacing or extending these adapters.
- Go version specified in
go.mod - Docker
- kubectl
- kind v0.31.0+
- Helm v3.17.0+
# Build and test
make build # Build binary
make test # Run unit tests
make lint # Run linter
make manifests generate # Generate code (after editing *_types.go)
# Local development
make deploy OVERLAY=dev # Deploy to current cluster
make run-ctrl # Run controller locally
# E2E tests
make test-e2e-full # Full E2E suite
make test-e2e-helm-full # Helm E2E suite
make test-e2e-ha # HA/leader-election testsE2E tests use kind for local Kubernetes clusters:
make test-e2e-full
# Keep cluster for debugging
SKIP_E2E_CLEANUP=true make test-e2e-full
# View test artifacts
ls test/e2e/output/Troubleshooting:
# Export cluster logs
kind export logs ./kind-logs --name auth-operator-e2e
# Check operator logs
kubectl logs -n auth-operator-system -l control-plane=controller-managerFor detailed development instructions, see CONTRIBUTING.md.
- Protected Namespaces — Canonical access classification, selector contract, lifecycle, and upgrade guidance
- Operator Guide — Installation, configuration, HA, upgrades, and day-to-day operations
- Debugging Guide — Troubleshooting, diagnostics, and log analysis
- Metrics and Alerting — Prometheus metrics and recommended alert rules
- API Reference — Full CRD specification
- Constrained Impersonation — Kubernetes KEP-5284 support: typed API, modes, guardrails, and the version compatibility matrix
- Flux Impersonation and API Discovery RBAC — what Flux needs from an authorization layer, the nonResourceURLs discovery trap, and the opaque
failed to get server groupsfailure - Creator Tracking — Native creator/contributor annotations, modes, trust boundaries, API availability, and benchmark status
- SSA Architecture — Server-Side Apply patterns, field ownership, and conflict resolution
- Condition Lifecycle — Condition types, state transitions, and kstatus compliance
- Helm Chart — Helm installation and configuration
- Multi-tenant Integration — Namespace ownership and policy-backed RBAC examples
- k8s-breakglass Integration — Integration with temporary privilege escalation system
- Security Policy — Vulnerability reporting
- k8s-breakglass — Temporary privilege escalation system for Kubernetes
Apache 2.0 — See LICENSE for details.