Files
awoooi/scripts/reboot-recovery/post-reboot-next-gate-dispatch.sh
ogt 6afa3e4f35
Some checks failed
Code Review / ai-code-review (push) Successful in 19s
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled
ops(reboot): classify stock eod freshness window
2026-06-26 18:24:42 +08:00

220 lines
11 KiB
Bash
Executable File

#!/usr/bin/env bash
# AWOOOI post-reboot next-gate dispatch checklist.
# Read-only by design. It does not send requests, restart services, modify
# hosts, query secrets, or enable runtime actions.
set -uo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SUMMARY_FILE=""
RUN_SUMMARY=1
NO_COLOR_FLAG=0
usage() {
cat <<'USAGE'
Usage: post-reboot-next-gate-dispatch.sh [options]
Turns post-reboot readiness summary blockers into a deterministic owner/action
checklist. This is a dispatch checklist only; it does not dispatch requests.
Options:
--summary-file PATH Use an existing post-reboot readiness summary file.
--no-run-summary Do not run post-reboot-readiness-summary.sh.
--no-color Disable color in delegated summary.
-h, --help Show this help.
Exit codes:
0 = checklist emitted. Runtime action remains unauthorized.
2 = summary unavailable or service blocker observed.
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--summary-file)
shift
SUMMARY_FILE="${1:-}"
;;
--no-run-summary)
RUN_SUMMARY=0
;;
--no-color)
NO_COLOR_FLAG=1
;;
-h|--help)
usage
exit 0
;;
*)
printf 'Unknown argument: %s\n' "$1" >&2
usage >&2
exit 2
;;
esac
shift
done
if [[ -z "$SUMMARY_FILE" && "$RUN_SUMMARY" -eq 1 ]]; then
SUMMARY_FILE="$(mktemp -t awoooi-post-reboot-summary.XXXXXX)"
summary_args=()
[[ "$NO_COLOR_FLAG" -eq 1 ]] && summary_args+=(--no-color)
bash "$ROOT_DIR/scripts/reboot-recovery/post-reboot-readiness-summary.sh" "${summary_args[@]}" >"$SUMMARY_FILE" 2>&1
summary_rc=$?
else
summary_rc=0
fi
if [[ -z "$SUMMARY_FILE" || ! -s "$SUMMARY_FILE" ]]; then
echo "BLOCKED_SUMMARY_UNAVAILABLE=1"
echo "RUNTIME_ACTION_AUTHORIZED=0"
exit 2
fi
value_for() {
local key="$1"
awk -F= -v key="$key" '$1 == key {value=$2; found=1} END {if (found) print value; else print ""}' "$SUMMARY_FILE"
}
service_green="$(value_for SERVICE_GREEN)"
product_data_green="$(value_for PRODUCT_DATA_GREEN)"
overall_declaration="$(value_for OVERALL_DECLARATION)"
next_required_gates="$(value_for NEXT_REQUIRED_GATES)"
stock_freshness_status="$(value_for STOCK_FRESHNESS_STATUS)"
stock_latest_trading_date="$(value_for STOCK_LATEST_TRADING_DATE)"
stock_blockers="$(value_for STOCK_BLOCKERS)"
stock_eod_window_pending="$(value_for STOCK_EOD_WINDOW_PENDING)"
stock_eod_classification="$(value_for STOCK_EOD_CLASSIFICATION)"
stock_eod_next_action="$(value_for STOCK_EOD_NEXT_ACTION)"
stock_eod_first_full_window_end="$(value_for STOCK_EOD_FIRST_FULL_WINDOW_END_LOCAL)"
stock_eod_final_retry_window_end="$(value_for STOCK_EOD_FINAL_RETRY_WINDOW_END_LOCAL)"
escrow_missing_count="$(value_for ESCROW_MISSING_COUNT)"
host_188_hygiene_blocked="$(value_for HOST_188_HYGIENE_BLOCKED)"
wazuh_registry_accepted="$(value_for WAZUH_MANAGER_REGISTRY_ACCEPTED)"
wazuh_coverage_scope="$(value_for WAZUH_COVERAGE_SCOPE)"
wazuh_direct_active="$(value_for WAZUH_DIRECT_ACTIVE)"
wazuh_no_transport="$(value_for WAZUH_NO_TRANSPORT)"
wazuh_ssh_blocked="$(value_for WAZUH_SSH_BLOCKED)"
wazuh_route_code="$(value_for WAZUH_ROUTE_CODE)"
wazuh_transport_count="$(value_for WAZUH_TRANSPORT_COUNT)"
wazuh_dashboard_api_connection="$(value_for WAZUH_DASHBOARD_API_CONNECTION)"
wazuh_dashboard_index_ok="$(value_for WAZUH_DASHBOARD_INDEX_OK)"
runtime_action_authorized="$(value_for RUNTIME_ACTION_AUTHORIZED)"
summary_artifact_dir="$(value_for ARTIFACT_DIR)"
contains_gate() {
local gate="$1"
[[ ",${next_required_gates}," == *",${gate},"* ]]
}
print_gate_header() {
local id="$1"
local title="$2"
echo
echo "GATE_ID=$id"
echo "GATE_TITLE=$title"
}
echo "AWOOOI_POST_REBOOT_NEXT_GATE_DISPATCH=1"
echo "SUMMARY_FILE=$SUMMARY_FILE"
echo "SUMMARY_ARTIFACT_DIR=${summary_artifact_dir:-unknown}"
echo "SUMMARY_RC=$summary_rc"
echo "SERVICE_GREEN=${service_green:-unknown}"
echo "PRODUCT_DATA_GREEN=${product_data_green:-unknown}"
echo "OVERALL_DECLARATION=${overall_declaration:-unknown}"
echo "NEXT_REQUIRED_GATES=${next_required_gates:-unknown}"
echo "RUNTIME_ACTION_AUTHORIZED=0"
echo "DISPATCH_AUTHORIZED=0"
echo "REQUEST_SENT_COUNT=0"
echo "HOST_WRITE_AUTHORIZED=0"
echo "SECRET_VALUE_COLLECTION_ALLOWED=0"
if [[ "$service_green" != "1" ]] \
&& ! contains_gate "product_data_freshness_recovery" \
&& ! contains_gate "stockplatform_eod_window_completion"; then
echo
echo "BLOCKED_SERVICE_GREEN=0"
echo "NEXT_STEP=restore_service_before_boundary_dispatch"
exit 2
fi
gate_count=0
if contains_gate "stockplatform_eod_window_completion"; then
gate_count=$((gate_count + 1))
print_gate_header "stockplatform_eod_window_completion" "StockPlatform scheduled EOD freshness completion"
echo "GATE_PRIORITY=P0"
echo "GATE_STATUS=scheduled_eod_window_pending"
echo "CURRENT_EVIDENCE=status:${stock_freshness_status:-unknown};latest_trading_date:${stock_latest_trading_date:-unknown};blockers:${stock_blockers:-unknown};pending:${stock_eod_window_pending:-unknown};classification:${stock_eod_classification:-unknown};next:${stock_eod_next_action:-unknown};first_full_window_end:${stock_eod_first_full_window_end:-unknown};final_retry_window_end:${stock_eod_final_retry_window_end:-unknown}"
echo "OWNER_GROUP=stockplatform_data_owner,market_data_owner,oncall_operator"
echo "REQUIRED_EVIDENCE=freshness_endpoint_after_19_15,cron_log_refs,daily_ingestion_ref,price_ref,chips_ref,margin_ref,ai_recommendation_ref"
echo "FORBIDDEN_PAYLOADS=raw_db_dump,secret_value,api_token,manual_fake_row,handwritten_freshness_override"
echo "FORBIDDEN_ACTIONS=manual_db_update,truncate_restore,fake_freshness_marker,skip_data_gate,declare_product_data_green_before_status_ok"
echo "ALLOWED_ACTION=wait_for_scheduled_cron_and_recheck_summary"
echo "DONE_CRITERIA=stock_freshness_status:ok,product_data_green:1,post_reboot_summary_recheck_after_eod_window"
fi
if contains_gate "product_data_freshness_recovery"; then
gate_count=$((gate_count + 1))
print_gate_header "product_data_freshness_recovery" "Product data freshness recovery"
echo "GATE_PRIORITY=P0"
echo "GATE_STATUS=data_freshness_recovery_required"
echo "CURRENT_EVIDENCE=status:${stock_freshness_status:-unknown};latest_trading_date:${stock_latest_trading_date:-unknown};blockers:${stock_blockers:-unknown};classification:${stock_eod_classification:-unknown};next:${stock_eod_next_action:-unknown}"
echo "OWNER_GROUP=stockplatform_data_owner,market_data_owner,rollback_owner"
echo "REQUIRED_EVIDENCE=source_of_truth_commit,cron_entrypoint_refs,cron_log_refs,official_source_status,db_count_readback,freshness_endpoint_after_recovery,rollback_plan"
echo "FORBIDDEN_PAYLOADS=raw_db_dump,secret_value,api_token,manual_fake_row,handwritten_freshness_override"
echo "FORBIDDEN_ACTIONS=manual_db_update,truncate_restore,fake_freshness_marker,skip_data_gate,declare_product_data_green_before_status_ok"
echo "ALLOWED_ACTION=diagnose_source_or_cron_failure_before_controlled_recovery"
echo "DONE_CRITERIA=stock_freshness_status:ok,product_data_green:1,post_reboot_summary_status:not_service_blocked"
fi
if contains_gate "credential_escrow_evidence"; then
gate_count=$((gate_count + 1))
print_gate_header "credential_escrow_evidence" "DR credential escrow non-secret evidence"
echo "GATE_PRIORITY=P0"
echo "GATE_STATUS=owner_evidence_required"
echo "CURRENT_EVIDENCE=escrow_missing_count:${escrow_missing_count:-unknown}"
echo "OWNER_GROUP=backup_dr_owner,security_owner,business_owner"
echo "REQUIRED_ITEMS=restic_repository_password,offsite_provider_credentials,break_glass_admin_credentials,dns_registrar_recovery,oauth_ai_provider_recovery"
echo "REQUIRED_EVIDENCE=non_secret_evidence_id,owner_role,owner_team,evidence_location,review_date,reviewer"
echo "FORBIDDEN_PAYLOADS=password,token,secret_value,hash,prefix,suffix,raw_credential,screenshot_with_secret"
echo "ALLOWED_ACTION=collect_non_secret_marker_evidence_only"
echo "FORBIDDEN_ACTION=mark_placeholder,write_fake_marker,store_secret,disable_alert"
echo "DONE_CRITERIA=escrow_missing_count:0,offsite_report_full_marker:1,backup_status_core_blockers:0"
fi
if contains_gate "host_188_hygiene_maintenance_window"; then
gate_count=$((gate_count + 1))
print_gate_header "host_188_hygiene_maintenance_window" "188 host PostgreSQL / certbot hygiene maintenance window"
echo "GATE_PRIORITY=P0"
echo "GATE_STATUS=maintenance_window_required"
echo "CURRENT_EVIDENCE=host_188_hygiene_blocked:${host_188_hygiene_blocked:-unknown}"
echo "OWNER_GROUP=188_host_owner,db_owner,dns_tls_owner,rollback_owner"
echo "REQUIRED_DECISIONS=postgresql_14_main_retire_or_restore_or_break_glass,certbot_dns_acme_owner_path,startup_unit_source_of_truth,rollback_owner,postcheck_owner"
echo "REQUIRED_EVIDENCE=maintenance_window,rollback_plan,precheck_artifact,postcheck_artifact,service_impact,stop_condition"
echo "FORBIDDEN_ACTIONS=pg_resetwal,certbot_renew,nginx_reload,systemctl_reset_failed,db_restore,docker_restart,host_file_write"
echo "ALLOWED_ACTION=prepare_maintenance_packet_and_read_only_preflight"
echo "DONE_CRITERIA=service_green:1,host_188_hygiene_blocked:0,systemd_failed_units:0,certbot_owner_evidence_accepted:1"
fi
if contains_gate "wazuh_manager_registry_export"; then
gate_count=$((gate_count + 1))
print_gate_header "wazuh_manager_registry_export" "Wazuh manager registry redacted export"
echo "GATE_PRIORITY=P0"
echo "GATE_STATUS=readonly_registry_export_required"
echo "CURRENT_EVIDENCE=wazuh_manager_registry_accepted:${wazuh_registry_accepted:-unknown};coverage_scope:${wazuh_coverage_scope:-unknown};direct_active:${wazuh_direct_active:-unknown};no_transport:${wazuh_no_transport:-unknown};ssh_blocked:${wazuh_ssh_blocked:-unknown};route:${wazuh_route_code:-unknown};transport:${wazuh_transport_count:-unknown};dashboard_api:${wazuh_dashboard_api_connection:-unknown};index_ok:${wazuh_dashboard_index_ok:-unknown}"
echo "OWNER_GROUP=iwooos_soc_owner,wazuh_owner,host_owner"
echo "REQUIRED_EXPORT=redacted_manager_registry_counts,per_host_alias_status,dashboard_api_connection_status,dashboard_api_version_status,collection_time_window,reviewer"
echo "FORBIDDEN_PAYLOADS=agent_real_name,internal_ip,client_keys,raw_wazuh_payload,token,password,authorization_header"
echo "FORBIDDEN_ACTIONS=active_response,agent_reenroll,wazuh_restart,secret_patch,host_write,kali_active_scan"
echo "ALLOWED_ACTION=collect_redacted_registry_export_or_no_data_attestation"
echo "DONE_CRITERIA=manager_registry_accepted:1,owner_evidence_accepted:1,runtime_gate:0"
fi
echo
echo "NEXT_GATE_COUNT=$gate_count"
echo "NEXT_STEP=dispatch_owner_packets_manually_after_review"
echo "POSTCHECK_COMMAND=scripts/reboot-recovery/post-reboot-readiness-summary.sh --no-color"
echo "NO_FALSE_GREEN_RULE=service_green_does_not_equal_dr_complete_or_wazuh_registry_recovered"
exit 0