Give each controller or lifecycle Job only the OpenBao capabilities needed for its operation. Authentication proves the actor’s identity; these policies decide what that actor can do.
Separate the policy surfaces
| Policy | Actor | Required capabilities | Reason for separation |
|---|---|---|---|
| Controller | Controller Deployment | Health, step-down, Raft configuration, peer removal, and Autopilot | Routine reconciliation must not receive restore authority |
| Backup | Backup Job | Read sys/storage/raft/snapshot | Snapshot streaming is independent of storage credentials |
| Restore | Restore Job | Update sys/storage/raft/snapshot-force | Restore can replace the complete cluster state |
| Rolling upgrade | Upgrade Job | Health, step-down, snapshot read, and Autopilot state | Upgrade authority exists only on the executor |
| BlueGreen upgrade | Upgrade Job | Rolling capabilities plus join and peer management | Parallel cutover needs wider, temporary orchestration authority |
Define the backup and restore policies
Backup policy
path "sys/storage/raft/snapshot" {
capabilities = ["read"]
}Restore policy
path "sys/storage/raft/snapshot-force" {
capabilities = ["update"]
}Backup and restore can use explicit token Secrets as a fallback. That does not make the controller or main OpenBao ServiceAccount the correct identity for either operation.
Define the upgrade policy
Rolling upgrades require snapshot read as well as health, step-down, and Autopilot state:
RollingUpdate policy
path "sys/health" {
capabilities = ["read"]
}
path "sys/step-down" {
capabilities = ["sudo", "update"]
}
path "sys/storage/raft/snapshot" {
capabilities = ["read"]
}
path "sys/storage/raft/autopilot/state" {
capabilities = ["read"]
}BlueGreen uses the same baseline and adds these peer-management paths:
Additional BlueGreen capabilities
path "sys/storage/raft/join" {
capabilities = ["update"]
}
path "sys/storage/raft/configuration" {
capabilities = ["read", "update"]
}
path "sys/storage/raft/remove-peer" {
capabilities = ["update"]
}
path "sys/storage/raft/promote" {
capabilities = ["update"]
}
path "sys/storage/raft/demote" {
capabilities = ["update"]
}Built-in upgrade orchestration uses JWT. When an initialized cluster changes from RollingUpdate to BlueGreen,
self-init does not update the existing role. Add the peer-management capabilities before requesting the new strategy.
Maintain policies after bootstrap
Self-init creates the initial policies only during initialization. For an existing cluster:
- Review operator release notes for new OpenBao capabilities.
- Compare the implemented policy with the cluster’s current policy.
- Apply the narrow policy change through an authenticated human administration path.
- Verify the affected condition or operation before proceeding with other changes.
Missing controller capabilities can produce Unknown conditions or permission errors. The operator does not widen the
policy automatically.
Troubleshoot authorization
| Symptom | Likely boundary | Check first |
|---|---|---|
| JWT login succeeds but the request is denied | Policy lacks the required path or capability | Identify the actor and compare its exact policy |
| Backup works but restore fails | Restore role or snapshot-force policy is missing | Restore ServiceAccount, role, and policy binding |
| Rolling works but BlueGreen stalls | Peer-management paths were not added | Accepted strategy and upgrade policy |
| Controller has restore or broad upgrade powers | Job policies were merged into the controller | Remove the shortcut and restore separate roles |
| Upgrade fails before changing a Pod | Snapshot-read capability is missing | sys/storage/raft/snapshot on the upgrade policy |
Return to operator authentication when the failure occurs before a policy decision.