# Copyright 2026 Guildhouse Dev # SPDX-License-Identifier: Apache-2.0 """Tests for the template system — manifest, policy, loader, registry.""" import os import pytest from pathlib import Path from gsap_broker.templates.manifest import TemplateManifest from gsap_broker.templates.policy import CompliancePolicy from gsap_broker.templates.loader import TemplateLoader, LoadResult from gsap_broker.templates.registry import AccordRegistry, PolicyRegistry FIXTURE_DIR = Path(__file__).parent / "fixtures" / "sample-template" # ── Manifest parsing ───────────────────────────────────────────── def test_parse_full_manifest(): """TEST 2: Full bastion.toml parsed correctly.""" m = TemplateManifest.from_toml(FIXTURE_DIR / "bastion.toml") assert m.template.name == "test-baseline" assert m.template.version == "0.1.0" assert m.template.vertical == "testing" assert "test-framework" in m.template.compliance_frameworks assert m.compatibility.bastion_min == "0.3.0" assert "intune" in m.compatibility.connectors_required assert "org_name" in m.variables assert m.variables["org_name"].required is True assert m.variables["api_key"].sensitive is True def test_parse_minimal_manifest(tmp_path): """TEST 3: Minimal bastion.toml with only required fields.""" toml = tmp_path / "bastion.toml" toml.write_text('[template]\nname = "minimal"\nversion = "0.1.0"\n') m = TemplateManifest.from_toml(toml) assert m.template.name == "minimal" assert m.compatibility.bastion_min == "0.5.0" # default assert m.contents.policies == "policies/" # default def test_validate_variables_missing_required(): """TEST 4: Missing required variable produces error.""" m = TemplateManifest.from_toml(FIXTURE_DIR / "bastion.toml") errors = m.validate_variables({}) # org_name missing assert any("org_name" in e for e in errors) def test_validate_variables_all_provided(): """TEST 5: All required variables provided — no errors.""" m = TemplateManifest.from_toml(FIXTURE_DIR / "bastion.toml") errors = m.validate_variables({"org_name": "TestCorp"}) assert errors == [] # ── Policy parsing ─────────────────────────────────────────────── def test_parse_policy(): """TEST 6: Multi-condition policy parsed correctly.""" p = CompliancePolicy.from_toml(FIXTURE_DIR / "policies" / "test-workstation.toml") assert p.name == "test-workstation-policy" assert p.framework == "test-framework" assert len(p.conditions) == 2 assert p.conditions[0].id == "disk-encryption" assert p.conditions[0].severity == "critical" assert p.breach_response.critical == "suspend_access" assert p.schedule.interval_seconds == 300 def test_policy_platform_filtering(): """TEST 7: conditions_for_platform filters correctly.""" p = CompliancePolicy.from_toml(FIXTURE_DIR / "policies" / "test-workstation.toml") linux_conds = p.conditions_for_platform("linux") windows_conds = p.conditions_for_platform("windows") # disk-encryption has linux check, antivirus doesn't assert len(linux_conds) == 1 assert linux_conds[0].id == "disk-encryption" # Both conditions have windows checks assert len(windows_conds) == 2 # ── Template loader ────────────────────────────────────────────── def test_template_loader_full(): """TEST 8: Full template load — policies and accords registered.""" policies = PolicyRegistry() accords = AccordRegistry() loader = TemplateLoader(policies, accords) result = loader.load(FIXTURE_DIR, {"org_name": "TestCorp"}) assert result.success assert "test-workstation-policy" in result.policies_loaded assert "standard-operations" in result.accords_loaded assert policies.get("test-workstation-policy") is not None assert accords.get("standard-operations") is not None def test_variable_substitution_bastion_files_only(): """TEST 9: Variable substitution applies to Bastion files, not Ansible files.""" policies = PolicyRegistry() accords = AccordRegistry() loader = TemplateLoader(policies, accords) loader.load(FIXTURE_DIR, {"org_name": "AcmeCorp"}) # Policy file should have substitution applied policy = policies.get("test-workstation-policy") assert policy is not None assert "AcmeCorp" in policy.description # Ansible playbook should be UNTOUCHED playbook_path = FIXTURE_DIR / "ansible" / "playbooks" / "test-playbook.yml" content = playbook_path.read_text() assert "${org_name}" in content # NOT substituted def test_variable_substitution_sensitive_not_logged(caplog): """TEST 10: Sensitive variable values not in log output.""" import logging policies = PolicyRegistry() accords = AccordRegistry() loader = TemplateLoader(policies, accords) with caplog.at_level(logging.DEBUG): loader.load(FIXTURE_DIR, {"org_name": "TestCorp", "api_key": "SECRET_VALUE_123"}) # The sensitive value should not appear in logs assert "SECRET_VALUE_123" not in caplog.text # Non-sensitive org_name value DOES appear (confirms substitution ran) assert "TestCorp" in caplog.text def test_missing_bastion_toml(tmp_path): """Missing bastion.toml produces error, not crash.""" policies = PolicyRegistry() accords = AccordRegistry() loader = TemplateLoader(policies, accords) result = loader.load(tmp_path, {}) assert not result.success assert any("bastion.toml" in e for e in result.errors) # ── Registries ─────────────────────────────────────────────────── def test_accord_registry_builtin_fallback(): """TEST 11: AccordRegistry falls back to builtins for known accords.""" reg = AccordRegistry() # shell-exec is a builtin assert reg.get("shell-exec") is not None assert reg.get("shell-exec")["capability_ceiling"] == "CAP_MUTATE" # unknown returns None assert reg.get("nonexistent") is None def test_accord_registry_template_overrides_builtin(): """Template-loaded accord overrides builtin with same name.""" reg = AccordRegistry() reg.register("shell-exec", {"name": "shell-exec", "custom": True}) assert reg.get("shell-exec")["custom"] is True def test_policy_registry_by_framework(): """PolicyRegistry.for_framework filters correctly.""" reg = PolicyRegistry() p1 = CompliancePolicy(name="p1", framework="hipaa") p2 = CompliancePolicy(name="p2", framework="pci") p3 = CompliancePolicy(name="p3", framework="hipaa") reg.register(p1) reg.register(p2) reg.register(p3) hipaa = reg.for_framework("hipaa") assert len(hipaa) == 2 assert all(p.framework == "hipaa" for p in hipaa)