This runbook covers day-2 operational workflows for the OpenBao Secret Sync
plugin: blocked sync, restore guard, queue recovery, reconcile, drift, and
incident evidence. It assumes the plugin is mounted at secret-sync/; adjust
paths if the mount name differs.
Use the user guide for the normal first-sync workflow. Use the sync model for the shared model behind source paths, associations, and provider objects. Use Convergence for queue, status, manual sync, retry, cancel, and drain behavior. Use Reconcile and drift for provider read-state and background drift behavior. Use Ownership and safety before repairing stale, drifted, missing, or ownership-lost remote objects.
Confirm the mount responds:
bao read secret-sync/configIf restore_guard=true, remote mutation is blocked until restore or clone
review is complete and the guard is acknowledged:
bao write -force secret-sync/config/restore-guard/acknowledgeCheck mount-wide pause and queue capacity:
bao read secret-sync/configPause or resume remote mutation:
bao write secret-sync/config disabled=true
bao write secret-sync/config disabled=falseBlocked or terminal responses can include a human-readable hint and structured
next_actions. Treat next_actions as the first recovery path. They name the
operation, plugin-relative path, parameters, whether the action can mutate
remote state, and an example bao command.
On successful responses, hint and next_actions are top-level response data
fields. On OpenBao error responses, the structured copy is nested under the
error data field so clients still recognize the response as an error. The
human-readable error text also includes a compact Hint: line and the first
Next action: command so bao CLI users see the recovery path without parsing
JSON.
Examples:
manual_sync: run after resolvingREMOTE_MISSING,DRIFTED, orREMOTE_OWNERSHIP_LOSTremote state.enable_source: run when hardened posture blocks association activation or dispatch because source sync is not enabled for the source path.acknowledge_restore_guard: run only after restore or clone review is complete.read_queue,drain_queue, orretry_operation: use when queue or provider capacity blocks sync.
Read destination config. Sensitive fields must be redacted:
bao read secret-sync/destinations/<type>/<name>Check destination readiness:
bao read secret-sync/destinations/<type>/<name>/checkValidate static destination configuration:
bao read secret-sync/destinations/<type>/<name>/validateCheck destination reachability and authorization:
bao read secret-sync/destinations/<type>/<name>/healthUse validation for configuration mistakes and health for runtime dependency state. A destination can validate correctly but still be unhealthy because of network, IAM, token, RBAC, or provider availability issues.
In hardened posture, confirm source sync is explicitly enabled for the path:
bao write -force secret-sync/sources/app/db/enableThis is required only when security_posture=hardened. Mounts default to
security_posture=standard.
In hardened posture, destination checks also report
destination_unconstrained until the destination has both source-path and
resolved-name prefix constraints.
To inspect the underlying metadata:
bao read secret-sync/metadata/app/dbRead the current source version:
bao read secret-sync/data/app/dbCheck source readiness:
bao read secret-sync/sources/app/db/checkPlan the association before creating or changing it:
bao write secret-sync/associations/app/db/plan \
destination=<type>/<name> \
resolved_name=<remote-name>secret-path, json, retain, and enabled=true are the defaults. Read
secret-sync/info to inspect static association defaults and registered
provider capability flags.
When updating an existing association, omitted optional fields keep the stored association values when the source path and destination identify a single existing association. This prevents partial updates from changing granularity, name template, delete mode, or enabled state by accident. Use the read output above when you need to make the update shape explicit.
Use destination=<type>/<name> for normal association disable, enable, and
manual sync operations. Association IDs remain available for exact reads,
deletes, and ambiguity escape hatches, but they are not the default lifecycle
selector.
Current-version source lifecycle endpoints participate in sync. DELETE data/<path>, delete/<path>, and destroy/<path> cancel stale queued upserts
and enqueue remote deletes for associations with delete_mode=delete.
undelete/<path> on the current version queues replacement upserts for enabled
associations.
Read existing associations:
bao read secret-sync/associations/app/dbDisable, enable, or manually sync one association:
bao write secret-sync/associations/app/db/disable destination=<type>/<name>
bao write secret-sync/associations/app/db/enable destination=<type>/<name>
bao write secret-sync/associations/app/db/sync destination=<type>/<name>Read the queue summary:
bao read secret-sync/queueQueue summaries include capacity and utilization. Treat sustained high
utilization as backpressure: increase drain frequency, reduce producer rate, or
raise queue_capacity after checking storage and provider limits.
Set queue_capacity=0 only for a deliberate enqueue freeze; existing queued
work can still drain.
Successful operations are removed from the queue after object status is
persisted; use status/<path> rather than queue/<operation-id> to confirm
completed sync.
Event-triggered dispatch is enabled by default and wakes a bounded drain after
enqueue-producing requests. Use queue/drain when you need deterministic local
testing, a controlled catch-up batch, or an explicit operator action after
temporarily disabling event dispatch. When the request reaches a read-enabled
HA standby, OpenBao forwards it to the active node before the plugin inspects or
claims queue work.
For deterministic local testing or controlled catch-up, drain due operations:
bao write secret-sync/queue/drain max_operations=10Read one operation:
bao read secret-sync/queue/<operation-id>Retry or cancel one operation:
bao write -force secret-sync/queue/<operation-id>/retry
bao write -force secret-sync/queue/<operation-id>/cancelCancel discards pending, retry-wait, or terminal failed work; it is not retained in the queue summary. Terminal failures are otherwise retained for at most seven days, with the newest 1,000 records taking precedence when the limit is reached.
queue/drain can execute remote mutations. Keep it operator-scoped. Forwarding
is limited to an HA standby within the active cluster; Secret Sync does not
forward drains from performance secondaries or enable cross-cluster forwarded
storage.
The plugin emits OpenTelemetry metric API calls only. Exporter setup remains an OpenBao deployment concern.
Useful alert inputs:
openbao.secret_sync.restore_guard.activestays1after an expected restore or deployment review window;openbao.secret_sync.queue.utilizationremains high or increases whileopenbao.secret_sync.queue.depth{state="pending"}is not draining;openbao.secret_sync.remote_mutation.blockedincreases with reasondisabled,restore_guard, orreplication_state;openbao.secret_sync.provider.requestsfailures increase by provider, operation, or error class;openbao.secret_sync.drift.repairsfailures or retries increase by destination type or granularity;openbao.secret_sync.readiness.checksfailures identify onboarding blockers without exposing source paths or destination names.
Read per-source status:
bao read secret-sync/status/app/dbUse JSON output when copying identifiers into commands:
bao read -format=json secret-sync/status/app/db | jq .dataPlan reconcile without changing local status or remote state:
bao read secret-sync/reconcile/app/db/planApply reconcile to refresh local status from provider read-state:
bao write -force secret-sync/reconcile/app/dbReconcile reads remote state. It does not write destination secrets and is safe to use while the restore guard is active.
DESTINATION_AUTH_ERROR or provider error class authn:
- check destination credential material or workload identity;
- rerun destination readiness, validation, and health;
- rotate the destination credential if compromise is suspected.
DESTINATION_POLICY_ERROR or provider error class authz:
- check IAM, RBAC, token scopes, project permissions, or namespace access;
- verify the destination can perform the requested create, update, read-state, and delete operations.
DESTINATION_RATE_LIMITED or provider error class rate_limit:
- inspect queue retry state;
- allow automatic retry to progress if attempts remain;
- reduce drain batch size during manual catch-up.
DESTINATION_UNAVAILABLE or provider error class unavailable:
- verify provider endpoint reachability;
- check proxy, DNS, private endpoint, or local test stack health;
- retry after the destination recovers.
REMOTE_OWNERSHIP_LOST or provider error class ownership:
- inspect the remote object metadata before retrying;
- decide whether the remote object was intentionally taken over;
- create a new association or remote name instead of forcing overwrite unless an operator explicitly accepts that risk.
- if the remote object was deleted or ownership was otherwise resolved, run the
manual_syncaction returned bystatus/<path>orreconcile/<path>.
VALIDATION_ERROR:
- check destination config fields;
- check provider name rules for the rendered remote object name;
- check payload size and granularity support.
- use the returned
hintandnext_actions; source sync failures point tosources/<path>/enable, while generic validation failures point to the association plan.
QUEUE_BLOCKED:
- read
secret-sync/configfor mount-wide pause or restore guard; - check queue capacity;
- verify the association and destination are enabled.
- use the returned
next_actionsto inspectqueue, drain due work where safe, or retry the failed queue operation.
Use Restore and clone review for the full review workflow.
After restore or clone, keep mutation blocked until remote ownership has been reviewed:
bao read secret-sync/config
bao read secret-sync/reconcile/app/db/planFor each important source path:
- Review local source version and association state.
- Run reconcile plan.
- Inspect remote ownership and payload hash status.
- Cancel, retry, or re-plan queued operations as needed.
- Acknowledge restore guard only after the destination state is understood.
Resume remote mutation:
bao write -force secret-sync/config/restore-guard/acknowledgeFor troubleshooting or issue reports, capture:
- mount path and plugin version;
- destination type and redacted destination config;
- association ID and source path;
- source version, not secret value;
- operation ID and queue state;
- status output with payload values removed if present in source reads;
- provider-side object metadata, not secret value;
- exact error class and message.
Do not paste secret payloads, provider tokens, static credentials, GitLab tokens, AWS external IDs, kubeconfigs, or raw audit records containing secrets.