Reject unsafe intent before it becomes persisted state.
The operator uses Kubernetes ValidatingAdmissionPolicy to enforce key safety rules at the API boundary. These policies are not a replacement for reconciliation logic; they are the front line that prevents invalid, privileged, or drifted state from landing in etcd in the first place.
Diagram
Admission enforcement flow
GitOps, human operators, and controller identities all cross the same API boundary. Admission guardrails stop invalid or dangerous objects before the reconcile loop has to repair them.
Decision matrix
Policy families
| Family | What it protects | Representative policies |
|---|---|---|
| Managed-resource ownership | Prevents users, GitOps, and controllers from mutating operator-managed objects outside the allowed patterns. | openbao-lock-managed-resource-mutations, controller StatefulSet self-protection, image digest enforcement. |
| Spec validation | Rejects invalid OpenBaoCluster, OpenBaoTenant, and OpenBaoRestore objects before they persist. | openbao-validate-openbaocluster, openbao-validate-openbao-tenant, openbao-validate-openbaorestore. |
| Provisioner restrictions | Constrains tenant onboarding, namespace mutation, and day-0 governance writes. | openbao-restrict-provisioner-rbac, namespace-mutation, and tenant-governance policies. |
| Controller restrictions | Constrains controller RBAC, ServiceAccount creation, and Secret writes. | openbao-restrict-controller-rbac, ServiceAccount, and Secret-write policies. |
Fail-closed startup and runtime behavior
Reference table
Admission dependency model
| State | Operator behavior | Why |
|---|---|---|
| Required policy set present and bound | Startup and sensitive reconciliation proceed normally. | The operator can rely on the API-level guardrails it expects. |
| Required policy set missing at startup | Startup fails closed by default. | It is safer to refuse operation than to reconcile privileged workflows without guardrails. |
| Required policy disappears or becomes misbound later | Sensitive reconciliation paths pause and surface degraded status. | The admission dependency is part of the runtime safety model, not only a bootstrap check. |
| Unsafe mode explicitly enabled | The operator can start without admission dependency enforcement. | This is intended only for development or break-glass scenarios and materially weakens defense in depth. |
The required fail-closed dependency set includes:
openbao-validate-openbaoclusteropenbao-validate-openbao-tenantopenbao-validate-openbaorestoreopenbao-lock-controller-statefulset-mutationsopenbao-restrict-provisioner-rbacopenbao-restrict-provisioner-namespace-mutationsopenbao-restrict-provisioner-tenant-governanceopenbao-restrict-controller-rbacopenbao-restrict-controller-serviceaccountsopenbao-restrict-controller-secret-writesopenbao-lock-managed-resource-mutationsopenbao-enforce-managed-image-digests
Disabling admission policies is treated as unsafe mode. Even if the cluster otherwise uses Hardened settings, turning off API-level guardrails weakens the operator’s defense-in-depth model substantially.
Provisioner guardrails
Reference table
Provisioner policy goals
| Policy area | What it constrains | Why it matters |
|---|---|---|
| RBAC writes | Only fixed Role and RoleBinding names, subjects, and allowed verbs are permitted. | This prevents the provisioner from becoming a generic RBAC minting identity. |
| Namespace mutation | Provisioner namespace updates are limited to fixed Pod Security label enforcement and blocked in system namespaces. | Tenant onboarding should not become a generic namespace-mutation channel. |
| Tenant governance objects | Only operator-owned ResourceQuota and LimitRange shapes are allowed for the fixed names. | Day-0 guardrails should remain centrally shaped and not drift through arbitrary direct edits. |
Controller guardrails
Reference table
Controller policy goals
| Policy area | What it constrains | Why it matters |
|---|---|---|
| RBAC writes | Only a narrow per-cluster pod-discovery and service-registration role pattern is allowed. | This blocks RBAC self-escalation inside tenant namespaces. |
| ServiceAccount writes | Only operator-managed main, backup, restore, and upgrade ServiceAccounts are allowed. | The controller should not become a general-purpose ServiceAccount management identity. |
| Secret writes | Only fixed operator-managed Secret names can be created or mutated. | A broader RBAC grant should not silently become arbitrary tenant Secret mutation. |
| Managed-resource mutation | Drift on operator-managed StatefulSets, Services, Pods, and other objects is denied. | This protects the reconciliation contract and keeps GitOps or manual edits from undermining the lifecycle model. |
The provisioner supports an optional admission canary that submits a dry-run RBAC request which must be denied. This gives stronger assurance that policy enforcement is active, not only that the policy objects exist.
Configuration ownership
Admission policy is one of the reasons the operator can separate user intent from platform-owned configuration:
- user-owned surfaces stay in the CR where customization is supported
- operator-owned networking, seal, listener identity, and lifecycle wiring stay protected
- unsafe or drifted changes are rejected before they have to be repaired later
Continue platform controls
You are reading the unreleased main docs. Use the version menu for the newest published release, or check the release notes for what is already out.
Was this page helpful?
Use Needs work to open a structured GitHub issue for this page. The Yes button only acknowledges the signal locally.