Split-controller RBAC model
Provisioner and controller identities stay separate. The provisioner introduces tenant access and namespace guardrails, and the controller uses tenant-scoped permissions to manage workloads.
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.
The operator disables default token auto-mounting and uses explicit projected ServiceAccount tokens for Kubernetes API access. Audience pinning can be configured. API identity remains explicit and short-lived through projected tokens.
Decision matrix
Identity split at a glance
| Identity | Primary job | What it must not become |
|---|---|---|
| Provisioner | Introduce tenant namespaces, bind tenant-scoped RBAC, and apply day-0 guardrails. | A long-running identity that can read tenant Secrets or manage tenant workloads. |
| Controller | Reconcile 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
| Resource or action | Why it exists | Why it stays narrow |
|---|---|---|
Watch OpenBaoTenant | Tenant onboarding is the trigger for introducing namespace access. | It is the only cluster-wide watch the provisioner needs for tenant onboarding. |
| Patch Namespaces for fixed PSS labels in default enforce mode | Tenant namespaces need a Pod Security baseline unless a platform policy layer already owns it. | Namespace mutation is limited to the fixed Pod Security label set and blocked in system namespaces. In external mode, Helm removes namespace update/patch RBAC from the provisioner. |
Create and patch fixed Role and RoleBinding objects | The 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 LimitRange | Day-0 governance belongs to provisioning, not to workload reconciliation. | The provisioner manages only the operator-owned fixed objects; it does not manage general namespace inventory. |
The provisioner writes the RBAC that grants the controller access, but it does not receive those tenant permissions itself. That separation is the core security property of the onboarding path.
Controller access model
Reference table
Controller scope
| Resource or action | Why it exists | Why it stays narrow |
|---|---|---|
Watch OpenBaoCluster | The controller needs the global CRD event stream to reconcile clusters. | This does not imply namespace discovery or broad tenant access by itself. |
| Manage tenant-scoped workload resources | StatefulSets, Services, ConfigMaps, Jobs, ServiceMonitors, 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 Secrets | Lifecycle workflows need specific Secret names for bootstrap, TLS, operations, and private-registry image verification. | Secret access is fixed-name, non-enumerating, and guarded by dedicated admission policy. |
Create minimal per-cluster Role and RoleBinding objects | Some 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 jobs | Backup, restore, and upgrade paths need explicit job identities. | Admission policy constrains names and shapes so the controller cannot mutate unrelated ServiceAccounts. |
The controller does not treat missing tenant RBAC as a normal write failure anymore. In multi-tenant mode it first checks for the tenant RoleBinding, then requeues cleanly until onboarding is complete. That keeps simultaneous OpenBaoTenant and OpenBaoCluster submissions safe without weakening the split-identity model.
Kubernetes RBAC controls who can read or mutate the PVC object; it does not protect files after another workload can mount the volume. Treat audit file storage as sensitive data. Restrict Pod creation, ephemeral containers, exec, collector configuration, and node or storage-admin access around any PVC used by spec.auditFileStorage.
CR author delegation
Editing an OpenBaoCluster or OpenBaoRestore grants control over operator intent. It does not
automatically grant control over every Kubernetes object, cloud identity, image trust root, or restore
target that the manifest references.
That makes tenant onboarding stricter than a plain CRD editor role. A user or GitOps identity can create ordinary cluster intent with the editor role, but feature-specific references need matching RBAC before admission accepts the manifest. This is deliberate: the API boundary should distinguish "may edit this OpenBao resource" from "may cause another identity or controller to consume that external authority."
The verbs follow common Kubernetes RBAC patterns:
getmeans the requester may read object payload, especially Secret data.usemeans the requester may cause another workload or controller to consume the object. OpenBao Operator checks this verb in admission; Kubernetes does not enforce it for these references by itself.usecloudidentitiesmeans the requester may attach cloud identity metadata to OpenBao-managed workloads.usecustomexecutablesmeans the requester may choose helper, hook, plugin, backup, upgrade, or restore executables that run with operator-managed identities or mounted data.useimagetrustrootsmeans the requester may choose custom image-verification trust roots in theHardenedprofile.publishnetworkingmeans the requester may publish OpenBao through non-ClusterIP Services, managed Ingress or Gateway routes, or Service/Ingress/Gateway annotations.restoremeans the requester may run a destructive restore against the targetOpenBaoCluster.
Reference table
Common onboarding paths
| Identity | Starting grant | Add when the manifest uses |
|---|---|---|
| Single-tenant platform operator | Single-tenant role or admin-style binding for the managed namespace. | No extra onboarding step for normal single-tenant administration, because this path intentionally grants broad cluster-management authority. |
| Namespace-scoped tenant editor | openbaocluster-editor-role bound into the tenant namespace. | Per-feature use, get, publishnetworking, usecloudidentities, usecustomexecutables, useimagetrustroots, or restore grants for the exact referenced objects and cluster names. |
| GitOps reconciler | The same editor and feature grants that a human author would need. | All references present in the rendered manifest, because admission checks the field while it exists, including unrelated future updates. |
| Restore operator | Write access to OpenBaoRestore plus restore on the target OpenBaoCluster. | get for restore credential or token Secrets, usecloudidentities for restore workload identity metadata, and usecustomexecutables for a custom restore image. |
The validation messages name the missing authority. For example, an error mentioning
spec.gateway.gatewayRef points to use on the referenced Gateway, and an error mentioning
cloud identities points to usecloudidentities on the target OpenBaoCluster. An error mentioning
network publication points to publishnetworking on the target OpenBaoCluster.
Reference table
Feature-to-grant recipes
| If the manifest configures | Grant this to the applying identity |
|---|---|
| Credential or token Secret refs | get on the named Secret. |
| Image pull, ingress TLS, or ServiceMonitor TLS references | use on the named Secret or ConfigMap; some Secret paths also accept get. |
| Custom ServiceAccount, existing PVC, Gateway, IngressClass, or StorageClass | use on the referenced object. |
| Non-ClusterIP Service exposure, managed Ingress/Gateway exposure, or Service/Ingress/Gateway annotations | publishnetworking on the target OpenBaoCluster. |
| ServiceAccount annotations or known workload identity pod metadata | usecloudidentities on the target OpenBaoCluster. |
| Custom helper, hook, plugin, backup, upgrade, or restore executable | usecustomexecutables on the target OpenBaoCluster. |
| Custom Hardened image-verification trust roots | useimagetrustroots on the target OpenBaoCluster. |
An OpenBaoRestore target cluster | restore on the target OpenBaoCluster. |
Reference table
Full CR reference authorization matrix
| CR field | Referenced object or authority | Required authorization |
|---|---|---|
spec.unseal.credentialsSecretRef | Same-namespace Secret payload | get on secrets/<name> |
spec.backup.target.credentialsSecretRef, spec.backup.tokenSecretRef | Same-namespace Secret payload | get on secrets/<name> |
OpenBaoRestore.spec.source.target.credentialsSecretRef, spec.tokenSecretRef | Same-namespace Secret payload | get on secrets/<name> |
spec.observability.metrics.serviceMonitor.authorization.credentialsSecret | Same-namespace Secret payload | get on secrets/<name> |
spec.imagePullSecrets[] | Same-namespace image pull Secret consumed by kubelet | use on secrets/<name>; get is also accepted |
spec.imageVerification.imagePullSecrets[], spec.operatorImageVerification.imagePullSecrets[] | Registry Secret payload read by image verification | get on secrets/<name> when verification is enabled |
spec.ingress.tlsSecretName | Same-namespace TLS Secret consumed by the ingress controller | use on secrets/<name>; get is also accepted |
spec.observability.metrics.serviceMonitor.tlsConfig.caSecret | Same-namespace Secret consumed by Prometheus | use on secrets/<name>; get is also accepted |
spec.observability.metrics.serviceMonitor.tlsConfig.caConfigMap | Same-namespace ConfigMap consumed by Prometheus | use on configmaps/<name>; get is also accepted |
spec.serviceAccount.name | Same-namespace ServiceAccount selected for OpenBao pods | use on serviceaccounts/<name> |
spec.tls.acme.sharedCache.existingClaimName, spec.auditFileStorage.existingClaimName | Same-namespace PersistentVolumeClaim mounted into OpenBao pods | use on persistentvolumeclaims/<name> |
spec.storage.storageClassName, read-replica storage, ACME cache storage, and audit-file storage class fields | Cluster-scoped StorageClass | use on storageclasses/<name> |
spec.ingress.className | Cluster-scoped IngressClass | use on ingressclasses/<name> |
spec.gateway.gatewayRef | Referenced Gateway in gatewayRef.namespace or the cluster namespace | use on gateways/<name> in the Gateway namespace |
spec.service.type values other than ClusterIP, spec.readReplicas.service.type values other than ClusterIP when the read Service is enabled | Kubernetes Service publication through LoadBalancer, NodePort, or another non-ClusterIP Service type | publishnetworking on openbaoclusters/<cluster> |
spec.service.annotations, enabled read-replica Service annotations, spec.ingress.annotations, spec.gateway.annotations | Controller-specific networking behavior selected through annotations | publishnetworking on openbaoclusters/<cluster> |
spec.ingress.enabled, spec.gateway.enabled | Operator-managed Ingress or Gateway route publication | publishnetworking on openbaoclusters/<cluster> |
Any spec.serviceAccount.annotations, plus identity-selector keys in spec.podMetadata.annotations or spec.podMetadata.labels | Main workload cloud identity metadata | usecloudidentities on openbaoclusters/<cluster> |
spec.backup.target.roleArn, spec.backup.target.workloadIdentity.* | Backup Job cloud identity metadata | usecloudidentities on openbaoclusters/<cluster> |
OpenBaoRestore.spec.source.target.roleArn, spec.source.target.workloadIdentity.* | Restore Job cloud identity metadata | usecloudidentities on openbaoclusters/<spec.cluster> |
OpenBaoRestore.spec.cluster | Destructive restore target OpenBaoCluster | restore on openbaoclusters/<spec.cluster> |
| Custom executables | spec.initContainer.image, backup, upgrade, restore, blue-green hook, or plugin executable fields | usecustomexecutables; usehelperimages remains a compatibility alias |
| Custom Hardened image-verification trust roots | spec.imageVerification or spec.operatorImageVerification trust-root fields | useimagetrustroots on openbaoclusters/<cluster> |
Admission checks these permissions on create and update whenever the field is present, not only when
that field changes. A Flux or Argo ServiceAccount that manages an OpenBaoCluster with a Gateway,
Ingress, LoadBalancer Service, custom StorageClass, image pull Secret, cloud identity annotation, or restore request needs the
matching use, get, publishnetworking, usecloudidentities, or restore grants before unrelated GitOps updates will
continue to apply.
What the RBAC model guarantees
Decision matrix
Security properties
| Property | What it means operationally | Primary control |
|---|---|---|
| No topology discovery | The controller is not supposed to list namespaces and infer who else exists in the cluster. | Provisioner-led namespace introduction and narrow cluster-scope reads. |
| No Secret enumeration | Operator identities should not browse tenant Secrets as generic inventory. | Name-scoped Secret roles and the controller Secret-write policy. |
| Privilege separation | The identity that grants access is not the identity that consumes it. | Split provisioner/controller model plus admission guardrails. |
| Blind-create, name-scoped mutate | The operator can create the Secrets it owns without broadening into arbitrary tenant Secret mutation. | Dedicated Secret roles and fixed-name admission constraints. |
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
You are reading docs for version 0.4.x. 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.