Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m35s
CD Pipeline / build-and-deploy (push) Failing after 7m35s
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 16s
152 lines
5.5 KiB
Python
152 lines
5.5 KiB
Python
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[3]
|
|
INSTALLER = ROOT / "scripts/reboot-recovery/install-host112-guest-recovery.sh"
|
|
|
|
|
|
def source() -> str:
|
|
return INSTALLER.read_text(encoding="utf-8")
|
|
|
|
|
|
def test_installer_shell_syntax_is_valid() -> None:
|
|
result = subprocess.run(
|
|
["bash", "-n", str(INSTALLER)],
|
|
text=True,
|
|
capture_output=True,
|
|
check=False,
|
|
timeout=10,
|
|
)
|
|
assert result.returncode == 0, result.stdout + result.stderr
|
|
|
|
|
|
def test_apply_and_rollback_require_safe_control_identity() -> None:
|
|
text = source()
|
|
|
|
assert '--trace-id ID --run-id ID --work-item-id ID' in text
|
|
assert 'BLOCKER incomplete_control_identity' in text
|
|
assert 'BLOCKER unsafe_control_identity' in text
|
|
assert 'BLOCKER installer_control_identity_required' in text
|
|
assert '^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$' in text
|
|
|
|
|
|
def test_sudo_policy_has_exact_correlated_apply_and_dry_run_only() -> None:
|
|
text = source()
|
|
|
|
assert "SUDOERS_ARGUMENT_REGEX='^--apply --trace-id " in text
|
|
assert "SUDOERS_DRY_RUN_ARGUMENT_REGEX='^--dry-run --trace-id " in text
|
|
assert '"$TARGET_USER" "$READINESS_TARGET" "$SUDOERS_ARGUMENT_REGEX"' in text
|
|
assert (
|
|
'"$TARGET_USER" "$READINESS_TARGET" '
|
|
'"$SUDOERS_DRY_RUN_ARGUMENT_REGEX"' in text
|
|
)
|
|
assert 'SUDO_CORRELATED_APPLY_NOPASSWD' in text
|
|
assert 'SUDO_CORRELATED_DRY_RUN_NOPASSWD' in text
|
|
assert 'SUDO_LEGACY_UNCORRELATED_APPLY_NOPASSWD' in text
|
|
assert 'SUDO_UNSAFE_IDENTITY_NOPASSWD' in text
|
|
assert 'SUDO_POLICY_READY' in text
|
|
|
|
|
|
def test_windows99_direct_route_is_fingerprint_bound_and_not_forced() -> None:
|
|
text = source()
|
|
route = text[
|
|
text.index("agent99_direct_authorization_ready() {") : text.index(
|
|
"readiness_check_no_write_ready() {"
|
|
)
|
|
]
|
|
|
|
assert 'HOST112_AGENT99_SOURCE_ADDRESS:-192.168.0.99' in text
|
|
assert 'HOST112_AGENT99_EXPECTED_KEY_FINGERPRINT' in text
|
|
assert 'AGENT99_99_DIRECT_ROUTE_READY' in text
|
|
assert 'index($1, "command=") == 0' in route
|
|
assert 'has_restrict($1)' in route
|
|
assert 'ssh-keygen -lf -' in route
|
|
assert 'cat "$AUTH_FILE"' not in text
|
|
assert 'from="%s",restrict,command="%s --check"' in text
|
|
assert 'CONTROL_SOURCE_ADDRESS:-192.168.0.110' in text
|
|
|
|
|
|
def test_apply_is_transactional_and_has_a_verified_rollback() -> None:
|
|
text = source()
|
|
apply_path = text[text.index("static_source_preflight\n") :]
|
|
handler = text[
|
|
text.index("handle_apply_failure() {") : text.index(
|
|
"static_source_preflight() {"
|
|
)
|
|
]
|
|
|
|
assert 'set -Eeuo pipefail' in text
|
|
assert 'TRANSACTION_ACTIVE=1' in apply_path
|
|
assert "trap 'handle_apply_failure $?' ERR" in apply_path
|
|
assert "trap 'handle_apply_failure 130' INT TERM" in apply_path
|
|
assert 'restore_from_backup "$BACKUP_DIR"' in handler
|
|
assert 'verify_rollback "$BACKUP_DIR"' in handler
|
|
assert 'ROLLBACK_VERIFIED=1' in handler
|
|
assert 'install_failed_rolled_back_verified' in handler
|
|
assert 'cmp -s "$backup_dir/rootfs/${path#/}" "$path"' in text
|
|
assert 'timer_was_enabled' in text
|
|
assert 'timer_was_active' in text
|
|
|
|
|
|
def test_static_gate_precedes_timer_activation_and_no_oneshot_is_started() -> None:
|
|
text = source()
|
|
apply_path = text[text.index("static_source_preflight\n") :]
|
|
|
|
static_gate = apply_path.index("post_install_static_gate\n")
|
|
timer_start = apply_path.index(
|
|
"systemctl start awoooi-host112-guest-recovery.timer"
|
|
)
|
|
final_gate = apply_path.index("check\n", timer_start)
|
|
receipt = apply_path.index(
|
|
'write_install_receipt "installed_timer_activated_recovery_separate"'
|
|
)
|
|
assert static_gate < timer_start < final_gate < receipt
|
|
assert 'systemctl enable awoooi-host112-guest-recovery.timer' in apply_path
|
|
assert 'systemctl enable --now awoooi-host112-guest-recovery.timer' not in text
|
|
assert 'systemctl start awoooi-host112-guest-recovery.service' not in text
|
|
assert "grep -Fq 'TimeoutStartSec=480'" in text
|
|
assert "for tool in bash cksum cmp flock" in text
|
|
assert "TimeoutStartSec=600" not in text
|
|
assert 'INSTALLER_SYNCHRONOUS_RECOVERY_START=0' in text
|
|
assert 'RECOVERY_EXECUTION_PERFORMED=0' in text
|
|
|
|
|
|
def test_install_receipt_does_not_claim_a_recovery_run() -> None:
|
|
text = source()
|
|
receipt = text[
|
|
text.index("write_install_receipt() {") : text.index(
|
|
"handle_apply_failure() {"
|
|
)
|
|
]
|
|
|
|
assert 'schema_version=host112_guest_recovery_install_receipt_v1' in receipt
|
|
assert 'install_verified=$install_verified' in receipt
|
|
assert 'manager_runtime_write_performed=0' in receipt
|
|
assert 'recovery_execution_performed=0' in receipt
|
|
assert 'recovery_run_id=none' in receipt
|
|
assert 'recovery_receipt_ref=none' in receipt
|
|
assert 'agent99_99_direct_runtime_probe=not_started' in receipt
|
|
assert 'rollback_attempted=$rollback_attempted' in receipt
|
|
assert 'rollback_verified=$rollback_verified' in receipt
|
|
|
|
|
|
def test_check_gate_requires_policy_route_timer_and_no_write_readback() -> None:
|
|
text = source()
|
|
check = text[text.index("check() {") : text.index("require_root() {")]
|
|
|
|
for required in (
|
|
'SUDO_POLICY_READY',
|
|
'AGENT99_99_DIRECT_ROUTE_READY',
|
|
'READINESS_NO_WRITE_READY',
|
|
'TIMER_ENABLED',
|
|
'TIMER_ACTIVE',
|
|
'CHECK_GATE_READY',
|
|
):
|
|
assert required in check
|
|
assert 'runtime_write_performed=0' in text
|
|
assert 'manager_runtime_write_performed=0' in text
|
|
assert 'receipt_write_performed=0' in text
|