perf(release): bound proxy startup to protected live configuration
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
"""Pure delivery-contract tests; these do not claim installation or VM safety."""
|
"""Pure delivery-contract tests; these do not claim installation or VM safety."""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
import importlib
|
import importlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -39,6 +40,7 @@ journal = importlib.import_module("scripts.release.journal")
|
|||||||
proxy_runtime = importlib.import_module("scripts.release.proxy_runtime")
|
proxy_runtime = importlib.import_module("scripts.release.proxy_runtime")
|
||||||
proxy_service = importlib.import_module("scripts.release.proxy_service")
|
proxy_service = importlib.import_module("scripts.release.proxy_service")
|
||||||
proxy_guard = importlib.import_module("scripts.release.proxy_guard")
|
proxy_guard = importlib.import_module("scripts.release.proxy_guard")
|
||||||
|
proxy_install = importlib.import_module("scripts.release.proxy_install")
|
||||||
backup = importlib.import_module("scripts.release.backup")
|
backup = importlib.import_module("scripts.release.backup")
|
||||||
restore = importlib.import_module("scripts.release.restore")
|
restore = importlib.import_module("scripts.release.restore")
|
||||||
restore_policy = importlib.import_module("scripts.release.restore_policy")
|
restore_policy = importlib.import_module("scripts.release.restore_policy")
|
||||||
@@ -1256,6 +1258,79 @@ def credential_acl(uid=1203, *, owner=4, user=4, group=0, mask=4, other=0):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_proxy_startup_refuses_another_protected_selected_binding(monkeypatch):
|
||||||
|
monkeypatch.setattr(proxy_install.os, "geteuid", lambda: 0)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
node_health,
|
||||||
|
"binding",
|
||||||
|
lambda: (
|
||||||
|
{"release_id": "sd-123456789abc", "configuration_id": "cfg-" + "e" * 24},
|
||||||
|
{},
|
||||||
|
ROOT,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(installer, "selection", lambda **kwargs: pytest.fail("full image scan"))
|
||||||
|
with pytest.raises(policy.DeliveryError, match="another selected configuration"):
|
||||||
|
proxy_install.check_binding("sd-123456789abc", "cfg-" + "f" * 24)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("changed", ["nginx.conf", "fullchain.pem", "key.pem", "selection"])
|
||||||
|
def test_proxy_startup_still_refuses_own_bytes_or_selection_drift(monkeypatch, changed):
|
||||||
|
selected = {"release_id": "sd-123456789abc", "configuration_id": "cfg-" + "e" * 24}
|
||||||
|
fingerprints = {
|
||||||
|
name: hashlib.sha256(("synthetic protected " + name).encode()).hexdigest()
|
||||||
|
for name in ("nginx.conf", "fullchain.pem", "key.pem")
|
||||||
|
}
|
||||||
|
changed_fingerprint = hashlib.sha256(b"changed protected proxy bytes").hexdigest()
|
||||||
|
spec = {
|
||||||
|
"schema_version": 1,
|
||||||
|
**selected,
|
||||||
|
"origin": "https://oj.test",
|
||||||
|
"configuration_sha256": fingerprints["nginx.conf"],
|
||||||
|
"certificate_sha256": fingerprints["fullchain.pem"],
|
||||||
|
"key_sha256": fingerprints["key.pem"],
|
||||||
|
}
|
||||||
|
monkeypatch.setattr(proxy_install.os, "geteuid", lambda: 0)
|
||||||
|
monkeypatch.setattr(node_health, "binding", lambda: (selected, {}, ROOT))
|
||||||
|
monkeypatch.setattr(proxy_service, "batch", lambda _: Path("/protected/proxy"))
|
||||||
|
monkeypatch.setattr(proxy_install, "read_json", lambda *args: spec)
|
||||||
|
monkeypatch.setattr(proxy_install.preflight, "protected", lambda *args, **kwargs: None)
|
||||||
|
real_stat = Path.stat
|
||||||
|
observed = {
|
||||||
|
Path("/protected/proxy/launch.json"),
|
||||||
|
Path("/protected/proxy/nginx.conf"),
|
||||||
|
proxy_service.ROOT / "tls/fullchain.pem",
|
||||||
|
proxy_service.ROOT / "tls/key.pem",
|
||||||
|
}
|
||||||
|
|
||||||
|
def file_info(path, *args, **kwargs):
|
||||||
|
if path not in observed:
|
||||||
|
return real_stat(path, *args, **kwargs)
|
||||||
|
return SimpleNamespace(
|
||||||
|
st_gid=1205 if path.name == "key.pem" else 0,
|
||||||
|
st_mode=stat.S_IFREG | (0o640 if path.name == "key.pem" else 0o644),
|
||||||
|
st_size=128,
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(Path, "stat", file_info)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
proxy_install,
|
||||||
|
"digest",
|
||||||
|
lambda p: changed_fingerprint if p.name == changed else fingerprints[p.name],
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(proxy_install.journal, "check_profile", lambda **kwargs: None)
|
||||||
|
monkeypatch.setattr(proxy_install, "storage", lambda **kwargs: None)
|
||||||
|
monkeypatch.setattr(proxy_install, "account", lambda **kwargs: None)
|
||||||
|
|
||||||
|
def selection(**kwargs):
|
||||||
|
assert kwargs == {"check_configuration": False}
|
||||||
|
return {**selected, "configuration_id": "cfg-" + "f" * 24}
|
||||||
|
|
||||||
|
monkeypatch.setattr(installer, "selection", selection)
|
||||||
|
with pytest.raises(policy.DeliveryError, match="proxy.*changed"):
|
||||||
|
proxy_install.check_binding(selected["release_id"], selected["configuration_id"])
|
||||||
|
|
||||||
|
|
||||||
def test_external_postgres_configuration_binds_ident_file_to_initialized_data():
|
def test_external_postgres_configuration_binds_ident_file_to_initialized_data():
|
||||||
files = dependencies.render("sd-123456789abc", "cfg-" + "e" * 24)
|
files = dependencies.render("sd-123456789abc", "cfg-" + "e" * 24)
|
||||||
text = files["postgresql.conf"].decode()
|
text = files["postgresql.conf"].decode()
|
||||||
|
|||||||
@@ -157,7 +157,11 @@ def known_link(path: Path) -> Path | None:
|
|||||||
def check_binding(release: str, batch: str) -> dict:
|
def check_binding(release: str, batch: str) -> dict:
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
raise DeliveryError("protected proxy operator required")
|
raise DeliveryError("protected proxy operator required")
|
||||||
selected = install.selection()
|
from .node_health import binding
|
||||||
|
|
||||||
|
# Reuse the protected live configuration and source binding. Proxy startup
|
||||||
|
# does not recertify unrelated judge images; Sandbox checks each execution.
|
||||||
|
selected, _, _ = binding()
|
||||||
if (release, batch) != (selected["release_id"], selected["configuration_id"]):
|
if (release, batch) != (selected["release_id"], selected["configuration_id"]):
|
||||||
raise DeliveryError("proxy unit belongs to another selected configuration")
|
raise DeliveryError("proxy unit belongs to another selected configuration")
|
||||||
directory = proxy_service.batch(selected)
|
directory = proxy_service.batch(selected)
|
||||||
@@ -213,6 +217,8 @@ def check_binding(release: str, batch: str) -> dict:
|
|||||||
journal.check_profile(allow_read_only=True)
|
journal.check_profile(allow_read_only=True)
|
||||||
storage(allow_read_only=True)
|
storage(allow_read_only=True)
|
||||||
account(check_lock=True)
|
account(check_lock=True)
|
||||||
|
if install.selection(check_configuration=False) != selected:
|
||||||
|
raise DeliveryError("selected proxy binding changed during startup check")
|
||||||
return {"binding_valid": True, "tls_verified": False, "execution_verified": False}
|
return {"binding_valid": True, "tls_verified": False, "execution_verified": False}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user