mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-16 19:59:26 +00:00
Task 2.2. Handlers on the same resource under the same module are siblings; when at least min_siblings of them discharge an obligation and one does not, that one is the anomaly and the discharging siblings are its evidence (Req 3.2). A set with fewer members than the minimum is under-populated and never reported (Req 3.3). A public route among authenticated siblings is a missing path guard with the mapper's access classification as evidence (Req 3.4). The sibling key is the module path without its suffix, so two same-named files in different directories are never merged. Witness validity (an identity constraint counts only when it binds the authenticated context) is one helper shared by operations, siblings and the checker. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01T7XD7x5KonMdmGRkp63EQG
50 lines
2.4 KiB
Python
50 lines
2.4 KiB
Python
"""authorization-obligations task 2.3: the declared policy has a closed schema (offline)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
GOOD = (
|
|
'version = 1\nidentity_source = "request.user"\n\n'
|
|
'[[resource]]\nname = "book"\nsensitivity = "high"\nidentity_field = "user_id"\n\n'
|
|
'[[route]]\npath = "/health"\naccess = "public"\n\n[[route]]\npath = "/admin/*"\naccess = "role"\nroles = ["admin"]\n'
|
|
)
|
|
|
|
|
|
def test_valid_policy_loads_with_a_version_hash(tmp_path: Path) -> None:
|
|
from openultrasast.semantic.obligations.policy import load_declared_policy
|
|
|
|
path = tmp_path / "obligations.toml"
|
|
path.write_text(GOOD)
|
|
policy = load_declared_policy(path)
|
|
assert policy is not None and policy.version == 1 and policy.identity_source == "request.user"
|
|
assert policy.resources["book"].sensitivity == "high" and policy.resources["book"].identity_field == "user_id"
|
|
assert (
|
|
policy.route_access("/health") == "public"
|
|
and policy.route_access("/admin/users") == "role"
|
|
and policy.route_access("/books/1") is None
|
|
)
|
|
assert len(policy.version_hash) == 40 and policy.version_hash == load_declared_policy(path).version_hash # type: ignore[union-attr]
|
|
path.write_text(GOOD + "\n# comment\n")
|
|
assert load_declared_policy(path).version_hash == policy.version_hash # type: ignore[union-attr] # normalized: comments do not change the version
|
|
assert load_declared_policy(tmp_path / "missing.toml") is None
|
|
|
|
|
|
def test_unknown_fields_and_values_are_rejected_by_name(tmp_path: Path) -> None:
|
|
from openultrasast.semantic.obligations.policy import PolicyError, load_declared_policy
|
|
|
|
path = tmp_path / "obligations.toml"
|
|
for bad, needle in (
|
|
(GOOD.replace('access = "public"', 'access = "sometimes"'), "sometimes"),
|
|
(GOOD + '\n[[resource]]\nname = "x"\nsensitivity = "high"\nmood = "strict"\n', "mood"),
|
|
(GOOD.replace('sensitivity = "high"', 'sensitivity = "critical"'), "critical"),
|
|
(GOOD + "\nallow_everything = true\n", "allow_everything"),
|
|
(GOOD.replace('identity_source = "request.user"', 'identity_source = "whatever.works"'), "identity_source"),
|
|
(GOOD + '\n[[route]]\npath = "/x"\naccess = "public"\ncolor = "blue"\n', "color"),
|
|
):
|
|
path.write_text(bad)
|
|
with pytest.raises(PolicyError, match=needle):
|
|
load_declared_policy(path)
|