Publish curated Unraid-AppOps-Gateway source from 6d175c3333218e2b580a310496fed6c407f28114

This commit is contained in:
Public Source Publisher committed 2026-10-09 12:15:31 +00:00
1 parent 58f5e3c8c2
commit 41fd48f0bc
7 files changed
+339 -16

No files matched your search

@@ -556,3 +556,166 @@ def test_original_failed_delivery_rejects_modified_legacy_record(controller, mon
assert controller._self_upgrade_original_failed_delivery(
semantic, revision, policy,
) is None
@pytest.mark.parametrize(("status", "extra", "valid"), [
("deploying", {}, True),
("failed", {"reason": "deployment_failed"}, True),
("deployed", {"receipt_sha256": "f" * 64}, True),
("deployed", {"receipt_sha256": "invalid"}, False),
("deploying", {"reason": "deployment_failed"}, False),
("failed", {"reason": "private-secret-value"}, False),
("failed", {"receipt_sha256": "f" * 64}, False),
("failed", {"unknown": "value"}, False),
("failed", {"reason": ["deployment_failed"]}, False),
("awaiting_validation", {"reason": "gitea_validation_unavailable"}, True),
("failed", {"reason": "recovery_preimage_changed"}, True),
])
def test_signed_recovery_reader_accepts_only_typed_worker_outcome_fields(
controller, monkeypatch, tmp_path, status, extra, valid,
):
record = _recovery_delivery(controller, secret="sentinel")
record.pop("runtimeEnvironment")
record.pop("privateCredential")
record.update(status=status, **extra)
secret = b"fixture-recovery-signing-key"
journal = {
"recoveryId": record["recovery_id"], "revision": record["revision"],
"idempotencyKeySha256": record["idempotency_key_sha256"],
"preflightSha256": record["preflight_sha256"],
"semanticSha256": record["semantic_sha256"],
"originalRawSha256": record["recovery_of_sha256"],
}
payload = {
"operationId": record["semantic_sha256"], "revision": record["revision"],
"preflightSha256": record["preflight_sha256"],
"idempotencyKeySha256": record["idempotency_key_sha256"],
"recoveryId": record["recovery_id"],
"recoveryOfSha256": record["recovery_of_sha256"],
}
record["body_sha256"] = controller.hashlib.sha256(controller._self_upgrade_canonical_json({
"semanticSha256": record["semantic_sha256"], "recoveryId": record["recovery_id"],
"idempotencyKeySha256": record["idempotency_key_sha256"],
})).hexdigest()
record["recovery_hmac"] = controller._self_upgrade_public_recovery_signature(record, secret)
monkeypatch.setattr(controller, "_self_upgrade_secret", lambda: secret)
monkeypatch.setattr(controller, "_self_upgrade_recovery_journal", lambda _id: journal)
monkeypatch.setattr(controller, "_load_projects", lambda: {controller.SELF_UPGRADE_REPOSITORY: {}})
monkeypatch.setattr(controller, "_validation_policy", lambda *_a: {})
monkeypatch.setattr(controller, "_validation_snapshot_matches", lambda *_a: True)
monkeypatch.setattr(controller, "_self_upgrade_request_root", lambda **_k: tmp_path)
monkeypatch.setattr(controller, "_self_upgrade_read_private_json", lambda _path: (b"", {}))
monkeypatch.setattr(controller, "_self_upgrade_recovery_request_payload", lambda _record: payload)
def verify():
return controller._self_upgrade_recovery_record_valid(
record, semantic_digest=record["semantic_sha256"],
original_raw_sha256=record["recovery_of_sha256"],
)
assert verify() is valid
record["updated_at"] += 1
assert verify() is False # Even permitted outcome fields require the original complete HMAC.
@pytest.mark.parametrize(("uid", "gid", "mode"), [(99, 100, 0o777), (0, 0, 0o755)])
@pytest.mark.parametrize("drift", ["none", "owner", "mode", "symlink", "foreign_cache", "inode"])
def test_legacy_cache_reader_and_state_cas_bind_both_exact_appdata_profiles(
controller, monkeypatch, tmp_path, uid, gid, mode, drift,
):
if os.name == "nt" or os.geteuid() != 0:
pytest.skip("Pinned dirfd ownership contract requires root POSIX")
root = tmp_path / "virtual-host"
root.mkdir(mode=0o755)
dirs = [
("mnt", 0, 0, 0o755), ("mnt/cache", 99, 100, 0o777),
("mnt/cache/appdata", uid, gid, mode),
("mnt/cache/appdata/gitea-deploy-runners", 0, 0, 0o755),
("mnt/cache/appdata/gitea-deploy-runners/state", 0, 0, 0o755),
]
for name, owner, group, permissions in dirs:
path = root / name
path.mkdir()
os.chown(path, owner, group)
path.chmod(permissions)
appdata = root / "mnt/cache/appdata"
state_root = appdata / "gitea-deploy-runners/state"
state_path = state_root / "unraid-appops-gateway.json"
before = controller._self_upgrade_canonical_json({
"schema_version": 3, "repository": controller.SELF_UPGRADE_REPOSITORY, "marker": "old",
}) + b"\n"
state_path.write_bytes(before)
state_path.chmod(0o600)
after = before.replace(b'"old"', b'"new"')
if drift == "owner":
os.chown(appdata, 1000, 1000)
elif drift == "mode":
appdata.chmod(0o775)
elif drift == "foreign_cache":
os.chown(root / "mnt/cache", 0, 0)
(root / "mnt/cache").chmod(0o755)
elif drift == "inode":
replacement = appdata.with_name("different-inode")
replacement.mkdir()
os.chown(replacement, uid, gid)
replacement.chmod(mode)
elif drift == "symlink":
renamed = appdata.with_name("appdata-elsewhere")
appdata.rename(renamed)
appdata.symlink_to(renamed, target_is_directory=True)
monkeypatch.setattr(controller, "STATE_ROOT", Path("/mnt/cache/appdata/gitea-deploy-runners/state"))
real_open = os.open
def virtual_root_open(path, flags, *args, **kwargs):
if drift == "inode" and str(path) == "appdata":
return real_open(replacement, flags)
return real_open(root if str(path) == "/" else path, flags, *args, **kwargs)
monkeypatch.setattr(controller.os, "open", virtual_root_open)
requested = controller.STATE_ROOT / state_path.name
if drift == "none":
assert controller._self_upgrade_read_legacy_cache_file(
requested, maximum_bytes=65536, allowed_modes=frozenset({0o600}),
) == before
assert not controller._self_upgrade_write_legacy_state_cas("0" * 64, after)
assert state_path.read_bytes() == before
assert controller._self_upgrade_write_legacy_state_cas(
controller.hashlib.sha256(before).hexdigest(), after,
)
assert state_path.read_bytes() == after
else:
with pytest.raises(OSError):
controller._self_upgrade_read_legacy_cache_file(
requested, maximum_bytes=65536, allowed_modes=frozenset({0o600}),
)
assert not controller._self_upgrade_write_legacy_state_cas(
controller.hashlib.sha256(before).hexdigest(), after,
)
@pytest.mark.parametrize(("profile", "valid"), [
((99, 100, 0o777), True), ((0, 0, 0o755), True),
((0, 0, 0o775), False), ((99, 100, 0o755), False),
])
def test_source_root_allows_only_legacy_or_root_owned_appdata_anchor(
controller, monkeypatch, profile, valid,
):
from types import SimpleNamespace
root = Path("/srv/example/appdata/unraid-appops-gateway/source")
profiles = {
Path("/mnt"): (0, 0, 0o755), Path("/mnt/user"): (99, 100, 0o777),
Path("/srv/example/appdata"): profile,
root.parent: (0, 0, 0o755), root: (100, 101, 0o755),
}
def lstat(path):
uid, gid, mode = profiles[path]
return SimpleNamespace(st_uid=uid, st_gid=gid, st_mode=stat.S_IFDIR | mode)
monkeypatch.setattr(Path, "lstat", lstat)
monkeypatch.setattr(Path, "is_symlink", lambda _path: False)
assert controller._self_upgrade_source_root_safe(root) is valid
monkeypatch.setattr(Path, "is_symlink", lambda path: path == root.parent)
assert controller._self_upgrade_source_root_safe(root) is False