ops(reboot): add post-reboot next gate dispatch [skip ci]
This commit is contained in:
171
scripts/reboot-recovery/post-reboot-next-gate-dispatch.sh
Executable file
171
scripts/reboot-recovery/post-reboot-next-gate-dispatch.sh
Executable file
@@ -0,0 +1,171 @@
|
||||
#!/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)"
|
||||
overall_declaration="$(value_for OVERALL_DECLARATION)"
|
||||
next_required_gates="$(value_for NEXT_REQUIRED_GATES)"
|
||||
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)"
|
||||
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 "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" ]]; then
|
||||
echo
|
||||
echo "BLOCKED_SERVICE_GREEN=0"
|
||||
echo "NEXT_STEP=restore_service_before_boundary_dispatch"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
gate_count=0
|
||||
|
||||
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}"
|
||||
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
|
||||
Reference in New Issue
Block a user