The package pool was committed but the installer still stopped at "no local package repository": it requires the compiled bundle (Packages, Packages.gz, packages.lock.tsv, SHA256SUMS), and building that had never run. The bundle - 1321 packages, 884 MiB, Ubuntu 26.04 amd64, built with apt-ftparchive on the fleet's own release so the closure matches the devices. - built/pool/ is gitignored: those .deb files are already tracked once under provisioning/offline-repo/packages/, and the same ~890 MB does not need a second path. What the installer reads from the bundle is the index. - The output directory is chmod 0755: mktemp -d created it 0700 and left it so, which made a valid bundle unreadable to the installer's probe. dpkg-deb output was parsed wrong in four places - `dpkg-deb -f <file> Package Version` prints "<Field>: <value>", and the callers kept the whole line, so the value carried its label. build-index.sh therefore accepted no package at all and reported an empty pool; add-packages.sh rejected every real .deb as an invalid name, missed version conflicts, and copied a duplicate; build-offline-repo.sh never matched a pin. - The test suite could not see any of this: its dpkg-deb stub emitted bare values. The stub now prints the labels exactly as the real tool does, which is what surfaced the remaining three sites. Tests - The secret scan covers the files we author, not apt-ftparchive's index over third-party packages: polkit's own description reads "...asked for their password:", which is prose in the packages, not a leak. Any secret reaching a manifest, README or tool is still caught. - The "test build must not touch the bundle" assertion now compares the directory before and after instead of demanding it be empty, so a maintainer's real build is not reported as test spill.
44 lines
2.6 KiB
Bash
Executable file
44 lines
2.6 KiB
Bash
Executable file
#!/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'
|