Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
88 lines
5.3 KiB
Python
88 lines
5.3 KiB
Python
"""Source-only contract checks against the actual owner validator and declarations."""
|
|
import copy, importlib.util, os, sys
|
|
from pathlib import Path
|
|
import pytest, yaml
|
|
PACKAGE=Path(__file__).resolve().parents[1]
|
|
OWNER=Path(os.environ.get("NET_KINGDOM_ROOT", "/home/worsch/net-kingdom"))
|
|
VP=OWNER/"tools/security-case-types/security_case_validator.py"
|
|
sys.path.insert(0,str(VP.parent))
|
|
spec=importlib.util.spec_from_file_location("security_case_validator",VP)
|
|
v=importlib.util.module_from_spec(spec);sys.modules[spec.name]=v;spec.loader.exec_module(v)
|
|
TYPE=yaml.safe_load((PACKAGE/"type.yaml").read_text())
|
|
FORGEJO=yaml.safe_load((PACKAGE/"examples/forgejo.yaml").read_text())
|
|
paths,discovery=v.discover_declarations(TYPE,OWNER.parent)
|
|
DECLS,loading=v.composer.load_declarations(paths)
|
|
def render(case):
|
|
issues,result=v.render_case(case,TYPE,DECLS,require_implemented=False)
|
|
assert not v.has_errors(discovery+loading+issues)
|
|
return result
|
|
|
|
def test_full_package_and_proposed_boundary():
|
|
assert not v.has_errors(v.validate_type(TYPE,PACKAGE))
|
|
assert TYPE["spec"]["status"]=="proposed"
|
|
assert FORGEJO["spec"]["status"]=="proposed"
|
|
assert "acceptance" not in FORGEJO["spec"]
|
|
assert v.has_errors(v.validate_case(FORGEJO,TYPE))
|
|
|
|
def test_acknowledged_is_still_not_implemented_admission():
|
|
acknowledged=copy.deepcopy(TYPE);acknowledged["spec"]["status"]="acknowledged"
|
|
assert v.has_errors(v.validate_case(FORGEJO,acknowledged))
|
|
|
|
@pytest.mark.parametrize("example",sorted((PACKAGE/"examples").glob("*.yaml")))
|
|
def test_examples_valid_deterministic_and_nonexecuting(example):
|
|
case=yaml.safe_load(example.read_text())
|
|
assert not v.has_errors(v.validate_case(case,TYPE,require_implemented=False))
|
|
first=render(case);assert first==render(case)
|
|
assert first["execution"]["permitted"] is False
|
|
assert first["composition"]["execution"]["permitted"] is False
|
|
|
|
def test_sixth_role_is_exact_consumer_identity_and_namespace():
|
|
case=copy.deepcopy(FORGEJO);case["spec"]["parameters"]["consumer_namespace"]="forgejo-preview"
|
|
r=render(case);objects={x["id"]:x for x in r["materialization"]}
|
|
assert len(objects)==6
|
|
consumer=yaml.safe_load(objects["consumer-eso-role"]["body"])
|
|
assert consumer["bound_service_account_names"]==["forgejo-keycape-forgejo-eso"]
|
|
assert consumer["bound_service_account_namespaces"]==["forgejo-preview"]
|
|
assert consumer["audience"]=="openbao"
|
|
assert consumer["token_policies"]==["workload-kv-read-keycape-forgejo-forgejo"]
|
|
assert consumer["token_no_default_policy"] is True
|
|
provider=yaml.safe_load(objects["eso-role"]["body"])
|
|
assert provider["bound_service_account_names"]!=consumer["bound_service_account_names"]
|
|
|
|
def test_original_five_structural_bodies_unchanged():
|
|
old=yaml.safe_load((OWNER/"security-case-types/oidc-browser-relying-party/type.yaml").read_text())
|
|
case=yaml.safe_load((OWNER/"security-cases/forgejo-netkingdom-oidc.yaml").read_text())
|
|
issues,before=v.render_case(case,old,DECLS,require_implemented=False)
|
|
assert not v.has_errors(issues)
|
|
after={x["id"]:x["body"] for x in render(FORGEJO)["materialization"]}
|
|
for item in before["materialization"]:assert item["body"]==after[item["id"]]
|
|
|
|
def test_public_has_no_secret_or_delivery_hooks():
|
|
r=render(yaml.safe_load((PACKAGE/"examples/example-public-portal.yaml").read_text()))
|
|
assert [x["id"] for x in r["materialization"]]==["catalog-entry"]
|
|
assert not {"mint-secret","deliver-secret","deliver-consumer-secret","bind-env"}&{x["id"] for x in r["follow_through"]}
|
|
|
|
@pytest.mark.parametrize("key,value",[("consumer_namespace",None),("consumer_namespace","default/other"),("consumer_namespace","x"*64),("consuming_service","x"*64),("redirect_uris","http://portal.invalid/callback"),("redirect_uris","https://portal.invalid/*"),("redirect_uris","https://portal.invalid/callback?x=y"),("redirect_uris","https://portal.invalid/callback#x"),("allowed_scopes","openid,email"),("consumer_reader_service_account","default"),("secret_path","other/path")])
|
|
def test_invalid_or_unsettable_parameter_refused(key,value):
|
|
case=copy.deepcopy(FORGEJO)
|
|
if value is None:case["spec"]["parameters"].pop(key)
|
|
else:case["spec"]["parameters"][key]=value
|
|
assert v.has_errors(v.validate_case(case,TYPE,require_implemented=False))
|
|
|
|
def test_created_only_role_recovery_precedes_policy_and_needs_revocation():
|
|
rollback=render(FORGEJO)["rollback"];ids=[x["reverses"] for x in rollback]
|
|
assert ids.index("consumer-eso-role")<ids.index("consumer-reader-policy")
|
|
action=next(x["action"] for x in rollback if x["reverses"]=="consumer-eso-role")
|
|
assert "case-created" in action and "revoke" in action and "expiration" in action
|
|
delivery=next(x["action"] for x in rollback if x["reverses"]=="deliver-consumer-secret")
|
|
assert "UID" in delivery and "preexisting" in delivery and "consumer secret reference" in delivery
|
|
|
|
@pytest.mark.parametrize("omitted",["README.md","tests/test_source_contract.py","examples"])
|
|
def test_full_package_validator_rejects_incomplete_supplement(tmp_path,omitted):
|
|
import shutil
|
|
trial=tmp_path/"package";shutil.copytree(PACKAGE,trial,ignore=shutil.ignore_patterns("__pycache__",".pytest_cache"))
|
|
target=trial/omitted
|
|
if target.is_dir():
|
|
for example in target.glob("*.yaml"):example.unlink()
|
|
else:target.unlink()
|
|
assert v.has_errors(v.validate_type(TYPE,trial))
|