fix: harden journal scanner startup
This commit is contained in:
@@ -279,6 +279,8 @@ import pathlib, subprocess, sys
|
|||||||
max_journal_bytes = 1_048_576
|
max_journal_bytes = 1_048_576
|
||||||
max_journal_lines = 10_000
|
max_journal_lines = 10_000
|
||||||
max_chunk_bytes = 65_536
|
max_chunk_bytes = 65_536
|
||||||
|
process = None
|
||||||
|
try:
|
||||||
actual_keys = {pathlib.Path(path).read_bytes() for path in sys.argv[2:]}
|
actual_keys = {pathlib.Path(path).read_bytes() for path in sys.argv[2:]}
|
||||||
needles = (b"thtdwh_v1", b"secret_sha256", *actual_keys)
|
needles = (b"thtdwh_v1", b"secret_sha256", *actual_keys)
|
||||||
max_needle_length = max(map(len, needles))
|
max_needle_length = max(map(len, needles))
|
||||||
@@ -287,7 +289,10 @@ process = subprocess.Popen(
|
|||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
|
except OSError:
|
||||||
|
raise SystemExit(2)
|
||||||
def stop_child():
|
def stop_child():
|
||||||
|
if process is not None:
|
||||||
if process.poll() is None:
|
if process.poll() is None:
|
||||||
process.kill()
|
process.kill()
|
||||||
process.wait()
|
process.wait()
|
||||||
|
|||||||
@@ -224,11 +224,51 @@ PY2
|
|||||||
report_pass "journal_${name}"
|
report_pass "journal_${name}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local python_bin
|
||||||
|
python_bin=$(command -v python3) || report_fail python_missing
|
||||||
|
|
||||||
run_journal_case clean 0 $'INFO clean\n' 0 0
|
run_journal_case clean 0 $'INFO clean\n' 0 0
|
||||||
run_journal_case oversized_line 2 "$(printf 'A%.0s' {1..1048577})" 0 0
|
run_journal_case oversized_line 2 "$(printf 'A%.0s' {1..1048577})" 0 0
|
||||||
run_journal_case too_many_lines 2 "$(printf 'x\n%.0s' {1..10001})" 0 0
|
run_journal_case too_many_lines 2 "$(printf 'x\n%.0s' {1..10001})" 0 0
|
||||||
run_journal_case child_failure 2 $'INFO child failure\n' 7 0
|
run_journal_case child_failure 2 $'INFO child failure\n' 7 0
|
||||||
run_journal_case actual_key_across_chunk 1 "$(printf 'A%.0s' {1..65530})REAL_SECRET_SYNTHETIC" 0 1
|
run_journal_case actual_key_across_chunk 1 "$(printf 'A%.0s' {1..65530})REAL_SECRET_SYNTHETIC" 0 1
|
||||||
|
|
||||||
|
local empty_path="$temp_root/empty-path"
|
||||||
|
mkdir -p "$empty_path"
|
||||||
|
printf '%s' 'INFO spawn failure\n' >"$data_file"
|
||||||
|
: >"$pid_file" "$stdout_file" "$stderr_file"
|
||||||
|
if PATH="$empty_path" JOURNAL_DATA_FILE="$data_file" JOURNAL_PID_FILE="$pid_file" JOURNAL_EXIT=0 JOURNAL_HOLD=0 \
|
||||||
|
"$python_bin" -c "$journal_code" synthetic-since "$key_file" "$legacy_file" >"$stdout_file" 2>"$stderr_file"; then
|
||||||
|
actual=0
|
||||||
|
else
|
||||||
|
actual=$?
|
||||||
|
fi
|
||||||
|
[[ "$actual" -eq 2 ]] || report_fail journal_spawn_failure_status
|
||||||
|
[[ ! -s "$stdout_file" && ! -s "$stderr_file" ]] || report_fail journal_spawn_failure_output
|
||||||
|
[[ ! -s "$pid_file" ]] || report_fail journal_spawn_failure_child
|
||||||
|
report_pass journal_spawn_failure
|
||||||
|
|
||||||
|
chmod 000 "$key_file"
|
||||||
|
: >"$pid_file" "$stdout_file" "$stderr_file"
|
||||||
|
if PATH="$fake_bin:$PATH" JOURNAL_DATA_FILE="$data_file" JOURNAL_PID_FILE="$pid_file" JOURNAL_EXIT=0 JOURNAL_HOLD=0 \
|
||||||
|
"$python_bin" -c "$journal_code" synthetic-since "$key_file" "$legacy_file" >"$stdout_file" 2>"$stderr_file"; then
|
||||||
|
actual=0
|
||||||
|
else
|
||||||
|
actual=$?
|
||||||
|
fi
|
||||||
|
chmod 0600 "$key_file"
|
||||||
|
[[ "$actual" -eq 2 ]] || report_fail journal_key_unreadable_status
|
||||||
|
[[ ! -s "$stdout_file" && ! -s "$stderr_file" ]] || report_fail journal_key_unreadable_output
|
||||||
|
[[ ! -s "$pid_file" ]] || report_fail journal_key_unreadable_child
|
||||||
|
report_pass journal_key_unreadable
|
||||||
|
|
||||||
|
python3 - "$key_file" <<'PY2'
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
pathlib.Path(sys.argv[1]).write_bytes(b"K" * 65_537)
|
||||||
|
PY2
|
||||||
|
run_journal_case long_key_across_chunks 1 "$(printf 'A%.0s' {1..65535})$(printf 'K%.0s' {1..65537})" 0 1
|
||||||
}
|
}
|
||||||
|
|
||||||
exercise_journal_scanner
|
exercise_journal_scanner
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ for label, relative in docs.items():
|
|||||||
text[label] = path.read_text(encoding="utf-8")
|
text[label] = path.read_text(encoding="utf-8")
|
||||||
|
|
||||||
requirements = {
|
requirements = {
|
||||||
"server": ["key_output=/root/dwh-auth-provision/psd-mac-primary.key", "legacy_key_id=legacy-shared", "v1_header_file", "legacy_header_file", "random_header_file", "--header \"@", "registry_staging", "registry_previous", "registry_restore_rollback", "journal_actual_key_scan=PASS", "sys.argv[2:]", "read_bytes()", "subprocess.Popen", "stderr=subprocess.DEVNULL", "returncode != 0", "max_journal_bytes = 1_048_576", "max_journal_lines = 10_000", "stdout=subprocess.PIPE", "max_chunk_bytes = 65_536", "process.stdout.read1(", "remaining = max_journal_bytes - bytes_seen", "searchable = carry + chunk", "max_needle_length", "process.kill()", "process.wait()", "socket_v1=PASS", "socket_legacy=PASS", "https_v1_post_revoke=PASS", "https_legacy_post_revoke=PASS", "key_file_bytes=PASS", "dd if=\"$1\" bs=65536 status=none", "manifest", "journalctl", "systemctl disable --now", "trap", "/var/lib/dwh-auth", "root:dwh-auth", "2750", ".writer.lock", "0640", "/run/dwh-auth/verify.sock", "0660", "systemd", "key create", "key list", "key status", "key revoke", "check", "backup", "rollback", "disinstallazione", "rest_api", "postgres_direct", "ssh_tunnel"],
|
"server": ["key_output=/root/dwh-auth-provision/psd-mac-primary.key", "legacy_key_id=legacy-shared", "v1_header_file", "legacy_header_file", "random_header_file", "--header \"@", "registry_staging", "registry_previous", "registry_restore_rollback", "journal_actual_key_scan=PASS", "sys.argv[2:]", "read_bytes()", "subprocess.Popen", "stderr=subprocess.DEVNULL", "returncode != 0", "max_journal_bytes = 1_048_576", "max_journal_lines = 10_000", "process = None", "except OSError:", "stdout=subprocess.PIPE", "max_chunk_bytes = 65_536", "process.stdout.read1(", "remaining = max_journal_bytes - bytes_seen", "searchable = carry + chunk", "max_needle_length", "process.kill()", "process.wait()", "socket_v1=PASS", "socket_legacy=PASS", "https_v1_post_revoke=PASS", "https_legacy_post_revoke=PASS", "key_file_bytes=PASS", "dd if=\"$1\" bs=65536 status=none", "manifest", "journalctl", "systemctl disable --now", "trap", "/var/lib/dwh-auth", "root:dwh-auth", "2750", ".writer.lock", "0640", "/run/dwh-auth/verify.sock", "0660", "systemd", "key create", "key list", "key status", "key revoke", "check", "backup", "rollback", "disinstallazione", "rest_api", "postgres_direct", "ssh_tunnel"],
|
||||||
"client": ["Workspace management", "Validate workspace source", "Test workspace connections", "Save entered secrets", "Forget stored value", "API_KEY_FILE", "THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE", "TLS_CA_FILE", "/rpc/ping", "rest_api", "postgres_direct", "ssh_tunnel", "401", "503", "rotazione", "revoca"],
|
"client": ["Workspace management", "Validate workspace source", "Test workspace connections", "Save entered secrets", "Forget stored value", "API_KEY_FILE", "THT_WS_PSD_CLINICAL_DWH_API_KEY_FILE", "TLS_CA_FILE", "/rpc/ping", "rest_api", "postgres_direct", "ssh_tunnel", "401", "503", "rotazione", "revoca"],
|
||||||
"tls": ["self-issued", ".it", ".com", "SAN", "TLS_CA_FILE", "openssl x509 -noout -fingerprint -sha256", "fuori banda", "rinnovo", "curl -k"],
|
"tls": ["self-issued", ".it", ".com", "SAN", "TLS_CA_FILE", "openssl x509 -noout -fingerprint -sha256", "fuori banda", "rinnovo", "curl -k"],
|
||||||
"rollout": ["v1=2xx", "legacy=2xx", "v1=2xx post-revoca", "legacy=401 post-revoca", "file header curl protetti 0600", "PASS/FAIL", "no raw diff", "Task 9", "Task 10", "IN_DISCUSSION", "postgres_direct", "rest_api", "legacy-shared", "nginx -t", "204", "401", "503", "Qdrant", "Ollama", "rollback"],
|
"rollout": ["v1=2xx", "legacy=2xx", "v1=2xx post-revoca", "legacy=401 post-revoca", "file header curl protetti 0600", "PASS/FAIL", "no raw diff", "Task 9", "Task 10", "IN_DISCUSSION", "postgres_direct", "rest_api", "legacy-shared", "nginx -t", "204", "401", "503", "Qdrant", "Ollama", "rollback"],
|
||||||
@@ -115,12 +115,15 @@ journal_steps = (
|
|||||||
"stdout=subprocess.PIPE",
|
"stdout=subprocess.PIPE",
|
||||||
"max_journal_bytes = 1_048_576",
|
"max_journal_bytes = 1_048_576",
|
||||||
"max_journal_lines = 10_000",
|
"max_journal_lines = 10_000",
|
||||||
|
"process = None",
|
||||||
|
"except OSError:",
|
||||||
"max_chunk_bytes = 65_536",
|
"max_chunk_bytes = 65_536",
|
||||||
"process.stdout.read1(",
|
"process.stdout.read1(",
|
||||||
"remaining = max_journal_bytes - bytes_seen",
|
"remaining = max_journal_bytes - bytes_seen",
|
||||||
"searchable = carry + chunk",
|
"searchable = carry + chunk",
|
||||||
"max_needle_length",
|
"max_needle_length",
|
||||||
"process.kill()",
|
"process.kill()",
|
||||||
|
"if process is not None:",
|
||||||
"process.wait()",
|
"process.wait()",
|
||||||
"if process.returncode != 0:",
|
"if process.returncode != 0:",
|
||||||
"any(needle in searchable for needle in needles)",
|
"any(needle in searchable for needle in needles)",
|
||||||
|
|||||||
Reference in New Issue
Block a user