release v0.12.30 (e203793533) #92

Merged
pipeline-bot merged 5 commits from _promote/v0.12.30 into main 2026-07-27 23:40:46 +00:00
Contributor
No description provided.
chore: devbump 0.12.29 -> 0.12.30-dev
All checks were successful
pipeline/ci CI green v0.12.30-dev
8c5297161e
fix(secrets): require positive ownership evidence to adopt a destination
All checks were successful
pipeline/ci CI green v300bfd723c2b
300bfd723c
destination.overwrite exists so an operator can deliberately take over a
Secret it did not create. The guard around it drifted in two ways.

First, "reclaim stale ownerless destinations" made a Secret adoptable
when it carried a COMPLETE set of operator ownership labels but a
different vso-ownerRefUID, on the theory that a missing ownerReference
means the previous resource is gone. It does not: ownerReferences are
routinely absent after a --cascade=orphan delete, an etcd restore, or a
write by a version that never set them. The operator cannot tell a
replaced resource from a live one, because it never looks the UID up. So
one OpenBaoDynamicSecret could take a live destination away from
another; the loser then fails its own ownership check, latches Degraded,
and has no path back. Any owner label that is not ours is now a refusal.

Second, adoption replaced the destination's labels and annotations
outright. Taking over a Secret's DATA is not a licence to erase the
bookkeeping other systems keep on the object — Helm release metadata,
ArgoCD tracking, kubectl's last-applied — which silently detaches it
from whatever manages it. Adoption now seeds from what is already there
and overlays the configured set. Secrets we already own keep the old
replace-from-empty behavior, because for those the configured set is
authoritative and drift correction depends on dropped labels actually
being dropped.

Adoption is also no longer silent: it logs at Info, since it ownerRef's
someone else's object to the syncable-secret and thereby enrolls it in
that resource's garbage collection.

The test that asserted the foreign-UID steal was intended behavior is
inverted, and a new test covers metadata preservation.
fix(client): pair response-text heuristics with their status codes
All checks were successful
pipeline/ci CI green v98db99e429bb
98db99e429
normalizeOpenBaoAPIError is the one place allowed to read OpenBao's
untyped response strings, and it matched "no default issuer", "is
sealed", and "standby" at ANY status code. The sentinels it produces are
load-bearing:

  - ErrNoDefaultIssuer makes GetRootCert and GetIntermediateCA report
    the certificate ABSENT rather than failing, which makes the
    controller generate a new CA and invalidate every chain issued from
    the old one. A 403 reading "permission denied: no default issuer
    currently configured" was therefore enough to regenerate a CA.
  - ErrOpenBaoSealed and ErrOpenBaoStandby feed IsOpenBaoServerNotReady,
    which classifyOpenBaoError checks ahead of the auth case, so an auth
    failure whose body happened to contain those words was retried as a
    dependency blip instead of surfacing.

Each heuristic is now paired with the status code OpenBao actually uses
for it — 400 for an unconfigured issuer, 503 for sealed, 429/473 for
standby. Anything else keeps the generic API kind and the caller sees a
plain error, which is the safe direction for all three.

Also: stop restarting workloads for a credential that did not change.
The ReReadOnRefresh horizon fed the rollout-restart decision on its own,
so an allowStaticCreds secret with an unchanged password rolled every
target on every refresh interval — and the destination Secret is not
even rewritten in that case, since the HMAC short-circuits, so the
restarted pod re-read what it already had. The decision now hinges on
the credential actually changing, or on a spec change that moves the
destination or path; where a re-mint does produce new material the sync
reports it and the restart still happens. Extracting the decision into
shouldRolloutRestart makes it testable, and left leaseReconcileDecision
with a dead ForceRollout field, which is removed.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
sean/openbao-operator!92
No description provided.