#!/usr/bin/env bash # Final lifecycle gate: offline completes locally; READY requires enrolled remote proof. set -euo pipefail LOG_FILE="${LOG_FILE:-/var/log/blueforce-install.log}"; STATE_DIR="${STATE_DIR:-/var/lib/blueforce}"; CHECK_MODE=0 [[ "${1:-}" == --check ]] && CHECK_MODE=1 OFFLINE="${BF_OFFLINE:-0}"; SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" log() { echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) [18-final-check] $1" | tee -a "$LOG_FILE"; } # Operator GUI runtime gate. The field application is the Python GUI (bfos), and # tkinter is a separate package on Ubuntu: a minimal image has python3 but no # window toolkit, so the operator would be left with no working entry point and # no network to fix it. Checked here because every install path reaches this # module, offline or not. When the GUI is unavailable the terminal console still # works, so this reports the degradation instead of aborting the install. if python3 -c 'import tkinter' >/dev/null 2>&1; then log 'OK: operatör arayüzü (tkinter) hazır' else log 'WARN: tkinter yok; operatör arayüzü açılamaz. Terminal konsolu çalışır: sudo bf --tui' log 'WARN: python3-tk paketi bu imajda eksik (offline depoda pinli: provisioning/offline-repo/manifests/base-packages.txt)' fi if [[ "$CHECK_MODE" == 1 ]]; then command -v bf >/dev/null 2>&1 || log 'WARN(check): bf komutu PATH üzerinde yok; kurulum bf simgesini oluşturur' fi if [[ "$OFFLINE" == 1 ]]; then # Only local gates are meaningful offline. No central peer, handshake, or READY claim. for g in 01-precheck 02-system 03-user 04-hostname 05-network 06-wireguard 07-ssh 08-rdp 10-docker 11-meg 12-monitoring 13-firewall 14-update-policy 15-logrotate 16-gui 17-healthcheck; do LOG_FILE=/dev/null BF_OFFLINE=1 bash "$SCRIPT_DIR/$g.sh" --check >/dev/null || { log "FAIL: offline local gate $g failed"; exit 1; } done [[ "$CHECK_MODE" == 1 ]] && { log 'OK(check): offline local gates pass'; exit 0; } log 'OK: offline local gates pass; installer records PROVISIONED_OFFLINE'; exit 0 fi [[ "$CHECK_MODE" == 1 ]] && exec /usr/local/bin/bf-check-ready /usr/local/bin/bf-check-ready python3 - "$STATE_DIR/state.json" <<'PY' import json,os,sys,tempfile p=sys.argv[1]; s=json.load(open(p)); if s.get('phase') not in ('ENROLLED','READY'): raise SystemExit('not enrolled') s.update({'phase':'READY','fleet_status':'READY'}) fd,t=tempfile.mkstemp(prefix='state.json.',dir=os.path.dirname(p)); os.fchmod(fd,0o600) with os.fdopen(fd,'w') as f: json.dump(s,f,sort_keys=True); f.write('\n') os.replace(t,p) PY log 'OK: enrolled device has current handshake and remote checks; READY recorded'