Skip to main content
Version: 0.1.0

Diagram

Split-controller RBAC model

The provisioner creates the tenant `Role` and `RoleBinding`, but the binding points at the controller ServiceAccount rather than granting those permissions back to the provisioner.

Projected Kubernetes API tokens

The operator disables default token auto-mounting and uses explicit projected ServiceAccount tokens for Kubernetes API access. Audience pinning can be configured, but the important contract here is that API identity stays explicit and short-lived rather than inherited implicitly.

Decision matrix

Identity split at a glance

Identity split at a glance.
IdentityPrimary jobWhat it must not become
ControllerReconcile OpenBaoCluster workloads and day-1/day-2 lifecycle actions inside onboarded namespaces.An identity that can discover arbitrary namespaces or rewrite the RBAC that grants its own access.

Provisioner access model

Reference table

Provisioner scope

Provisioner scope.
Resource or actionWhy it existsWhy it stays narrow
Patch Namespaces for fixed PSS labelsTenant namespaces must be hardened as part of onboarding.Namespace mutation is limited to the fixed Pod Security label set and blocked in system namespaces.
Create and patch fixed Role and RoleBinding objectsThe provisioner must bind the controller into the target namespace.Admission policy constrains names, subjects, verbs, and object shapes so this cannot expand into arbitrary RBAC minting.
Create tenant guardrails such as ResourceQuota and LimitRangeDay-0 governance belongs to provisioning, not to workload reconciliation.The provisioner manages only the operator-owned fixed objects and does not treat these resources as general namespace inventory.
Blind-write pattern

The provisioner writes the RBAC that grants the controller access, but it does not grant itself those permissions. That is the core security property of the onboarding path.

Controller access model

Reference table

Controller scope

Controller scope.
Resource or actionWhy it existsWhy it stays narrow
Manage tenant-scoped workload resourcesStatefulSets, Services, ConfigMaps, Jobs, and related resources are the normal lifecycle surface.This access only exists where the provisioner already introduced the controller via RoleBinding.
Read and write allowlisted SecretsLifecycle workflows need specific Secret names for bootstrap, TLS, and operations.Secret access is fixed-name, non-enumerating, and guarded by dedicated admission policy.
Create minimal per-cluster Role and RoleBinding objectsSome service-registration and pod-discovery flows need narrow additional RBAC.The controller policy only allows a tightly scoped pattern to prevent RBAC self-escalation.
Create operator-managed ServiceAccounts for workload and jobsBackup, restore, and upgrade paths need explicit job identities.Admission policy constrains names and shapes so the controller cannot mutate unrelated ServiceAccounts.

What the RBAC model guarantees

Decision matrix

Security properties

Security properties.
PropertyWhat it means operationallyPrimary control
No Secret enumerationOperator identities should not browse tenant Secrets as generic inventory.Name-scoped Secret roles and the controller Secret-write policy.
Privilege separationThe identity that grants access is not the identity that consumes it.Split provisioner/controller model plus admission guardrails.
Blind-create, name-scoped mutateThe operator can create the Secrets it owns without broadening into arbitrary tenant Secret mutation.Dedicated Secret roles and fixed-name admission constraints.
Unsafe mode weakens the model

Installing with admission policies disabled materially weakens the RBAC defense-in-depth story. The split-controller design still matters, but without the admission guardrails a broader or drifted RBAC grant has fewer backstops.

Continue platform controls

Published release documentation

You are reading docs for version 0.1.0. Use the version menu to switch to next or another archived release.

Was this page helpful?

Use Needs work to open a structured GitHub issue for this page. The Yes button only acknowledges the signal locally.