mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 11:49:28 +00:00
engine: stage presigned objects as .dat; task entry reports the failing step and HTTP status
Through Cloudflare, signed requests for keys ending .tar/.gz/.zip/.bin reached RustFS altered and failed with 403 (cf-cache-status BYPASS); the same signed request straight to RustFS on the LAN returned 200. A Cloudflare cache-bypass rule on files.because-security.com fixes it (all extensions 200, DYNAMIC); the engine executors keep .dat as a safeguard, the plane keeps output.tar. Implemented with Codex. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
035710493c
commit
b715ff7d0e
@@ -113,6 +113,10 @@ def test_ax_executor_success_while_running_and_cleanup(setup):
|
||||
assert set(env) == {"SOURCE_URL", "QUESTIONS_URL", "RESULT_URL", "DEADLINE", "QUESTION_DEADLINE"}
|
||||
assert len(json.dumps(manifest["spec"]["env"]).encode()) < 32768
|
||||
assert "AWS" not in calls[0]["input"]
|
||||
assert env["SOURCE_URL"].split("?")[0].endswith("/source.dat")
|
||||
assert env["RESULT_URL"].split("?")[0].endswith("/result.dat")
|
||||
assert env["QUESTIONS_URL"].split("?")[0].endswith("/questions.json")
|
||||
assert {key.rsplit("/", 1)[-1] for key in store.deleted} == {"source.dat", "questions.json", "result.dat"}
|
||||
assert store.expiries == [604] * 3
|
||||
assert len(store.deleted) == 3 and not store.objects
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ def task():
|
||||
run="run",
|
||||
id="pin",
|
||||
task_id="run-pin",
|
||||
input="engine-queue/inputs/run/pin/source.tar",
|
||||
input="engine-queue/inputs/run/pin/source.dat",
|
||||
deadline=10,
|
||||
question_deadline=2,
|
||||
pin={"repo": "owner/repo", "pin": "commit", "units": []},
|
||||
@@ -120,6 +120,7 @@ def test_engine_queue_dispatch_roundtrip_and_timeout(tmp_path):
|
||||
pin = {"repo": "owner/repo", "pin": "sha", "units": [unit], "questions": []}
|
||||
|
||||
def execute(client, item):
|
||||
assert item["input"].endswith("/source.dat")
|
||||
unpacked = tmp_path / "unpacked"
|
||||
unpacked.mkdir()
|
||||
service.unpack(client.get(item["input"])[0], unpacked)
|
||||
|
||||
@@ -37,7 +37,7 @@ def test_engine_cluster_heap_flags(monkeypatch):
|
||||
assert worker.MeasuredBackend(30, 10, lambda: None)._heap_flag() == "-J-Xmx2560m"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("readiness", ["ready", "delayed", "closed"])
|
||||
@pytest.mark.parametrize("readiness", ["ready", "delayed", "closed", "source_denied"])
|
||||
@pytest.mark.parametrize("failure", [False, True])
|
||||
@pytest.mark.parametrize("transport", ["memory", "loopback"])
|
||||
def test_task_entry_http_roundtrip(tmp_path, monkeypatch, failure, transport, readiness):
|
||||
@@ -57,6 +57,10 @@ def test_task_entry_http_roundtrip(tmp_path, monkeypatch, failure, transport, re
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
gets.append((self.path, time.monotonic() - started))
|
||||
if readiness == "source_denied" and self.path == "/source":
|
||||
self.send_response(403)
|
||||
self.end_headers()
|
||||
return
|
||||
if readiness == "closed" or (readiness == "delayed" and gets[-1][1] < 3):
|
||||
self.send_response(403 if len(gets) % 2 else 503)
|
||||
self.end_headers()
|
||||
@@ -148,7 +152,13 @@ def test_task_entry_http_roundtrip(tmp_path, monkeypatch, failure, transport, re
|
||||
assert result["done"]
|
||||
if readiness == "closed":
|
||||
assert result["status"] == "failed"
|
||||
assert result["reason"] == "egress not open after 60 s"
|
||||
assert result["reason"] == "GET questions: egress not open after 60 s"
|
||||
assert json.loads((tmp_path / "work/out/result.json").read_text()) == result
|
||||
elif readiness == "source_denied":
|
||||
assert result["status"] == "failed"
|
||||
assert result["reason"] == "GET source: HTTP 403"
|
||||
assert result["units"][0]["reason"] == "GET source: HTTP 403"
|
||||
assert base not in json.dumps(result)
|
||||
assert json.loads((tmp_path / "work/out/result.json").read_text()) == result
|
||||
elif failure:
|
||||
assert result["units"][0]["status"] == "failed"
|
||||
|
||||
@@ -1265,6 +1265,8 @@ def test_kubernetes_host_pin_success_failure_and_cleanup(tmp_path, monkeypatch,
|
||||
manifest = json.loads(kwargs["input"])
|
||||
if manifest["kind"] == "Secret":
|
||||
assert manifest["metadata"]["ownerReferences"][0]["uid"] == "job-uid"
|
||||
for variable, filename in [("SOURCE_URL", "source.dat"), ("ANALYZER_URL", "analyzer.dat"), ("RESULT_URL", "result.dat")]:
|
||||
assert manifest["stringData"][variable].split("?")[0].endswith("/" + filename)
|
||||
if manifest["kind"] == "Job":
|
||||
stdout = json.dumps({"metadata": {"uid": "job-uid"}})
|
||||
env = manifest["spec"]["template"]["spec"]["containers"][0]["env"]
|
||||
@@ -1276,10 +1278,10 @@ def test_kubernetes_host_pin_success_failure_and_cleanup(tmp_path, monkeypatch,
|
||||
entry = tarfile.TarInfo("result.json")
|
||||
entry.size = len(result_bytes)
|
||||
archive.addfile(entry, io.BytesIO(result_bytes))
|
||||
source_key = next(key for key in objects if key.endswith("source.tar"))
|
||||
source_key = next(key for key in objects if key.endswith("source.dat"))
|
||||
with tarfile.open(fileobj=io.BytesIO(objects[source_key])) as archive:
|
||||
assert archive.extractfile("app.py").read() == b"def run(): pass"
|
||||
objects[source_key.replace("source.tar", "result.tar")] = stream.getvalue()
|
||||
objects[source_key.replace("source.dat", "result.dat")] = stream.getvalue()
|
||||
if action[:2] == ["get", "job"]:
|
||||
stdout = json.dumps(
|
||||
{"status": {"conditions": [{"type": "Failed", "status": "True", "reason": "DeadlineExceeded"}]}}
|
||||
|
||||
Reference in New Issue
Block a user