Repository navigation
WolfStack v23.10.2
v23.10.2: fix fleet-security propagation auth — peers with custom cluster secrets were rejecting block/unblock/policy push
Operator reported "5 unique IPs blocked across 12 nodes (2 nodes
unreachable)" with each IP only appearing on 1-2 nodes despite all
14 having v23.10.1 installed. Investigation found the bug: every
new fleet-security endpoint I added in v23.10.x was using the
hardcoded default_cluster_secret() constant for both sending AND
the receiver auth check, instead of state.cluster_secret (the
loaded per-cluster value the operator actually has configured).
Existing federation calls correctly used state.cluster_secret and
the receivers accept any of three valid values via require_auth's
triple-check. My new code's senders sent the built-in default and
my new code's receivers checked ONLY the built-in default. In a
cluster with a custom secret (the standard production setup) that
meant:
- Aggregation queries WORKED because they hit endpoints that go
through require_auth, which accepts the built-in as a fallback
on top of the custom secret. - Propagation FAILED because the new receivers rolled their own
v == default_cluster_secret()check with no fallback to the
custom secret — and the sender was using the built-in which
didn't match the loaded custom secret on the receiver's mental
model anyway. Net effect: kernel-block only ever happened on
the detecting node, never propagated.
What changed
-
main.rs: hook capture now uses
app_state.cluster_secret.clone()
instead ofdefault_cluster_secret().to_string()so block and
unblock fan-outs use the operator's configured secret. -
api/mod.rs (8 sender sites):
let secret = default_cluster_secret() .to_string();→let secret = state.cluster_secret.clone();
across security_auth_unblock, security_rotate_fleet,
fleet_fanout_get, fleet_security_push_lockout_policy,
fleet_security_force_logout_all, fleet_security_ssh_hardening,
fleet_security_push_scan_detector. -
api/mod.rs (7 receiver sites): the custom
v == default_cluster_secret()checks (and the variant using
validate_cluster_secret against the default) replaced with a
singlerequire_auth(&req, &state)call. require_auth already
does the correct triple-check (loaded / hardcoded / on-disk)
AND falls through to session-cookie auth if the operator hits
the endpoint from a browser. Less code, correct semantics. -
The cluster-secret-rotation receiver and sender (line 11333 etc)
still uses default_cluster_secret intentionally — same pattern
as the existing rotation code; rotation needs a known-fallback
secret to bootstrap from when the custom secret might be out
of sync between nodes mid-rotation.
Tests
895/895 pass — no test changes needed (the bug was in production-
auth wiring, not testable without two-node integration).
Operator impact
After upgrading to v23.10.2 on every node:
- Brute-force block on ANY node will propagate to all 14 (visible
in the Fleet Security blocked-IPs table as "Blocked on: 14/14"). - Existing local-only blocks from before v23.10.2 stay where they
are. New blocks will propagate correctly. - Fleet operations (push lockout policy, push SSH hardening,
push scan-detector config, force-logout-all) now actually reach
every peer.
Verifying this release
Each binary is signed via cosign keyless OIDC (no key distribution — signing identity is the GitHub Actions workflow itself, anchored to the Sigstore Fulcio CA and the Rekor transparency log) and ships with a SLSA build provenance attestation.
Verify the cosign signature:
cosign verify-blob \
--bundle wolfstack-x86_64.cosign.bundle \
--certificate-identity-regexp 'https://github.com/wolfsoftwaresystemsltd/WolfStack/\.github/workflows/release\.yml@.*' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
wolfstack-x86_64
Verify the build provenance:
gh attestation verify wolfstack-x86_64 --repo wolfsoftwaresystemsltd/WolfStack
Verify the SHA-256 checksum:
sha256sum -c SHA256SUMS
Artifacts
wolfstack-x86_64/wolfstack-aarch64— static musl binaries (Linux x86_64 and ARM64 / Raspberry Pi 4+).wolfstack-<arch>.cosign.bundle— cosign signature bundle (cert + signature + Rekor entry).SHA256SUMS— checksums for both binaries.
For per-version history see CHANGELOG.md.