feat(orchestration): compose security scenarios
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a02929-244b-7391-b933-c04010e8eedb
This commit is contained in:
tegwick 2026-08-23 12:40:52 +02:00
parent ad46cc89fc
commit d96aab2321
20 changed files with 1464 additions and 30 deletions

View file

@ -142,6 +142,81 @@ def test_tenant_tunable_secret_reference_fails(tmp_path):
assert any("security-sensitive parameters cannot be tenant_tunable" in msg for msg in error_messages(issues))
def test_plaintext_secret_reference_default_fails(tmp_path):
data = valid_declaration()
data["spec"]["parameters"][2].update(
{
"type": "string",
"default": "plaintext-looking-value",
"sensitivity": "secret_reference",
"tuning_authority": "platform_only",
}
)
declaration = declaration_from(data, tmp_path)
issues = validator.validate_declaration(declaration)
assert any("secret_reference default must be" in msg for msg in error_messages(issues))
def test_secret_reference_uri_override_passes(tmp_path):
data = valid_declaration()
data["spec"]["parameters"][2].update(
{
"name": "credential_ref",
"type": "string",
"default": "openbao://kv/platform/reference",
"sensitivity": "secret_reference",
"tuning_authority": "platform_only",
}
)
declaration = declaration_from(data, tmp_path)
scenario = {
"id": "scenario:secret-reference",
"authority": "platform",
"requires": {"capabilities": ["s1.os-baseline"]},
"parameter_overrides": {
"railiance-infra.bootstrap-host": {
"target_hosts": ["railiance01"],
"credential_ref": "kubernetes://platform/reference#token",
}
},
}
issues, _ = validator.compose_scenario([declaration], scenario)
assert error_messages(issues) == []
def test_plaintext_secret_reference_override_fails(tmp_path):
data = valid_declaration()
data["spec"]["parameters"][2].update(
{
"name": "credential_ref",
"type": "string",
"default": "openbao://kv/platform/reference",
"sensitivity": "secret_reference",
"tuning_authority": "platform_only",
}
)
declaration = declaration_from(data, tmp_path)
scenario = {
"id": "scenario:bad-secret-reference",
"authority": "platform",
"requires": {"capabilities": ["s1.os-baseline"]},
"parameter_overrides": {
"railiance-infra.bootstrap-host": {
"target_hosts": ["railiance01"],
"credential_ref": "plaintext-looking-value",
}
},
}
issues, _ = validator.compose_scenario([declaration], scenario)
assert any("must be a secret-reference URI" in msg for msg in error_messages(issues))
def test_scenario_composition_selects_and_overrides(tmp_path):
declaration = declaration_from(valid_declaration(), tmp_path)
scenario = {
@ -196,3 +271,36 @@ def test_required_parameter_without_override_fails(tmp_path):
issues, _ = validator.compose_scenario([declaration], scenario)
assert any("required parameter has no default or override" in msg for msg in error_messages(issues))
def test_demo_composition_refuses_ambiguous_provider(tmp_path):
first = declaration_from(valid_declaration(), tmp_path)
second_data = valid_declaration()
second_data["metadata"]["id"] = "railiance-infra.bootstrap-host-alternative"
second_path = tmp_path / "alternative.yaml"
second_path.write_text(yaml.safe_dump(second_data, sort_keys=False), encoding="utf-8")
second = validator.Declaration(path=second_path, data=second_data)
scenario = {
"id": "scenario:ambiguous-provider",
"authority": "platform",
"requires": {"capabilities": ["s1.os-baseline"]},
"parameter_overrides": {},
}
issues, _ = validator.compose_scenario([second, first], scenario)
assert any("ambiguous providers" in msg for msg in error_messages(issues))
def test_demo_composition_refuses_unselected_override(tmp_path):
declaration = declaration_from(valid_declaration(), tmp_path)
scenario = {
"id": "scenario:unselected-override",
"authority": "platform",
"requires": {"capabilities": ["s1.os-baseline"]},
"parameter_overrides": {"owner.unselected": {"target_hosts": ["railiance01"]}},
}
issues, _ = validator.compose_scenario([declaration], scenario)
assert any("override targets an unselected declaration" in msg for msg in error_messages(issues))