deploy: hardening collector enumerates mesh peers from the -stats prefix its credential can actually list (#1176)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 file changed,
+12
−2
deploy/hardening-posture.sh+12 −2
diff --git a/deploy/hardening-posture.sh b/deploy/hardening-posture.sh| index 5cbd2c8..6be88ea 100755 |
| --- a/deploy/hardening-posture.sh |
| +++ b/deploy/hardening-posture.sh |
| @@ -279,7 +279,7 @@ enumerate_members() { |
| prefix=$(env_str "$ROUTER_ENV" LCHAT_HIBERNATE_PREFIX) |
| [ -n "$bucket" ] && [ -n "$prefix" ] || return # mesh off -> no peers, just self |
| region=$(env_str "$ROUTER_ENV" LCHAT_HIBERNATE_REGION); region=${region:-eu-west-1} |
| - # Must match hc.meshPrefix() (activator.go): membership at |
| + # Layout per hc.meshPrefix() (activator.go): membership at |
| # "<prefix>/mesh/members/<peer>", stats at "<prefix>/mesh/members-stats/<peer>". |
| mesh_prefix="${prefix}/mesh/members" |
| @@ -287,8 +287,18 @@ enumerate_members() { |
| # crashes on this fleet's aws-cli/Python combination (a botocore/argparse |
| # regression), same reason status-publish.sh gives. `s3 ls` prints |
| # "YYYY-MM-DD HH:MM:SS SIZE KEY"; the key is the b64url leaf. |
| + # |
| + # Members are enumerated from the "-stats/" SIBLING prefix, not members/ |
| + # itself: the status-publisher credential is deliberately scoped to |
| + # "*-stats/*" in the hibernation bucket (infra/prod/status.tf) so it can |
| + # never touch instance replicas, and a members/ listing comes back |
| + # AccessDenied — silently empty here, which published a peer-less page on |
| + # the collector's first real run (2026-07-19). Both prefixes carry the same |
| + # b64url(peerURL) leaf at the same heartbeat cadence, so the stats listing |
| + # is the same membership signal — read exactly as status-publish.sh's |
| + # mesh_peer_boxes reads it. |
| local listing cutoff line date_part time_part key peer statsfile label reg |
| - listing=$(aws s3 ls "s3://$bucket/${mesh_prefix}/" --region "$region" 2>/dev/null) || true |
| + listing=$(aws s3 ls "s3://$bucket/${mesh_prefix}-stats/" --region "$region" 2>/dev/null) || true |
| [ -n "$listing" ] || return |
| cutoff=$(date -u -d "-${STALE_SECONDS} seconds" '+%Y-%m-%d %H:%M:%S') |