Configure operator authentication

Align Kubernetes identities, projected JWTs, OpenBao roles, and human access during bootstrap.

Updated 9 August 2026 · 4 min read

On this page

The controller, OpenBao Pods, and lifecycle Jobs use different identities. Keep each Kubernetes ServiceAccount aligned with its projected token, OpenBao JWT role, and policy.

Map the identities

ActorKubernetes identityOpenBao authenticationBoundary
ProvisionerProvisioner ServiceAccount in the operator namespaceNoneKubernetes RBAC only
ControllerController ServiceAccount in the operator namespaceProjected JWT bound to openbao-operatorRoutine lifecycle and maintenance
OpenBao PodsPer-cluster ServiceAccountRuntime and unseal integrationsServer workload identity
Backup JobGenerated backup ServiceAccountProjected JWT or backup token SecretSnapshot read and object storage
Restore JobGenerated restore ServiceAccountProjected JWT or restore token SecretDestructive snapshot restore
Upgrade JobGenerated upgrade ServiceAccountProjected JWTRolling or BlueGreen orchestration

Changing JWT transport does not merge these identities. Each actor retains its own ServiceAccount, role, audience, and policy.

Understand the default JWT path

The controller Deployment mounts a projected one-hour ServiceAccount token. Its audience and OPENBAO_JWT_AUDIENCE both default to openbao-internal. OpenBao validates the JWT against the bound audience and the controller ServiceAccount subject.

The default inline strategy sends the JWT in the request-specific OpenBao inline-auth headers. Use standard only when a proxy or intermediary cannot carry those headers; it performs a JWT login and sends the resulting OpenBao token as X-Vault-Token.

configure

Use the standard JWT transport

kubectl -n openbao-operator-system set env \
  deployment/openbao-operator-controller \
  OPENBAO_JWT_AUTH_STRATEGY=standard
kubectl -n openbao-operator-system rollout status \
  deployment/openbao-operator-controller

Leave the variable unset, or set it to inline, for the default path. The controller propagates the selected strategy to JWT-backed backup, restore, and upgrade Jobs.

Bootstrap operator and human access

spec.selfInit.enabled: true makes OpenBao execute the initialization requests and revoke the root token. spec.selfInit.oidc.enabled: true adds the operator JWT auth method, role, and policies to that bootstrap. It does not create human access.

Self-init is one-shot. The operator uses the generated auth surface after initialization but does not continuously reconcile OpenBao policies. A human administrator must apply later policy changes required by an operator upgrade.

Configure a manual controller role

Use manual JWT configuration only for a controlled bootstrap or a custom install that cannot use self-init OIDC. Render the operator installation first, then substitute the actual namespace, ServiceAccount, and audience.

configure

Bind a custom controller identity

bao write auth/jwt-operator/role/openbao-operator \
  role_type=jwt \
  bound_audiences=openbao-internal \
  user_claim=sub \
  bound_subject=system:serviceaccount:platform-security:demo-openbao-operator-controller \
  token_policies=openbao-operator \
  token_ttl=1h \
  token_max_ttl=1h \
  token_no_default_policy=true

The controller policy needs the steady-state maintenance paths:

configure

Define the controller policy

path "sys/health" {
  capabilities = ["read"]
}

path "sys/step-down" {
  capabilities = ["sudo", "update"]
}

path "sys/storage/raft/configuration" {
  capabilities = ["read"]
}

path "sys/storage/raft/remove-peer" {
  capabilities = ["update"]
}

path "sys/storage/raft/autopilot/configuration" {
  capabilities = ["read", "update"]
}

path "sys/storage/raft/autopilot/state" {
  capabilities = ["read"]
}

Do not add backup, restore, or upgrade permissions to this policy. Those belong to job-specific roles.

Verify a custom installation

Check these values together:

  1. The rendered controller ServiceAccount name and operator namespace.
  2. The Deployment’s projected openbao-token volume and one-hour expiration.
  3. The projected audience and OPENBAO_JWT_AUDIENCE.
  4. The JWT role’s bound_audiences and bound_subject.
  5. The controller’s reachability to the configured OIDC discovery or JWKS endpoint.
  6. The separate ServiceAccounts and JWT roles generated for lifecycle Jobs.

Troubleshoot authentication

SymptomLikely causeCheck first
Controller receives permission denied immediatelyAudience or bound-subject mismatchRendered controller identity and JWT role
Self-init finishes but operator auth does not settleDiscovery or JWKS cannot be reached or validatedIssuer, discovery URL, CA, and network path
Backup or restore auth fails while the controller worksJob-specific identity or role is missingThe Job’s ServiceAccount and JWT role
A custom namespace or prefix breaks authOpenBao still trusts the default subjectAll rendered identity references and bound_subject

If JWT login succeeds but a specific request is denied, continue with operator authorization.

Search the handbook

Try “install”, “threat model”, or “compatibility”.