S-Dreamer commited on
Commit
36a2dfc
·
verified ·
1 Parent(s): 1e4e9aa

Create tests/test_policy.py

Browse files
Files changed (1) hide show
  1. tests/test_policy.py +170 -0
tests/test_policy.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from osint_core.policy import (
4
+ ALLOWED_CORRECTION_VERBS,
5
+ PolicyDecision,
6
+ PolicyErrorCode,
7
+ PolicyViolationException,
8
+ allowed_ui_modules,
9
+ canonicalize_module_name,
10
+ enforce_audit_payload,
11
+ enforce_correction_verb,
12
+ enforce_policy_mutation_gate,
13
+ evaluate_modules,
14
+ get_module_policy,
15
+ may_mutate_policy,
16
+ module_catalog,
17
+ )
18
+
19
+
20
+ def test_canonicalize_module_aliases():
21
+ assert canonicalize_module_name("Resource Links") == "resource_links"
22
+ assert canonicalize_module_name("robots.txt") == "robots_txt"
23
+ assert canonicalize_module_name("nmap") == "port_scan"
24
+
25
+
26
+ def test_low_risk_modules_allowed_in_passive_mode():
27
+ result = evaluate_modules(
28
+ ["Resource Links", "DNS Records", "Local URL Parse"],
29
+ authorized_target=False,
30
+ passive_only=True,
31
+ )
32
+
33
+ assert result.decision == PolicyDecision.ALLOW
34
+ assert result.allowed_modules == [
35
+ "resource_links",
36
+ "dns_records",
37
+ "local_url_parse",
38
+ ]
39
+ assert result.blocked_modules == []
40
+ assert result.violations == []
41
+
42
+
43
+ def test_conditional_module_blocked_without_authorization():
44
+ result = evaluate_modules(
45
+ ["HTTP Headers"],
46
+ authorized_target=False,
47
+ passive_only=False,
48
+ )
49
+
50
+ assert result.decision == PolicyDecision.CONSTRAIN
51
+ assert result.allowed_modules == []
52
+ assert result.blocked_modules == ["http_headers"]
53
+ assert result.violations[0].code == PolicyErrorCode.AUTHORIZATION_REQUIRED
54
+
55
+
56
+ def test_conditional_module_blocked_in_passive_only_even_with_authorization():
57
+ result = evaluate_modules(
58
+ ["HTTP Headers"],
59
+ authorized_target=True,
60
+ passive_only=True,
61
+ )
62
+
63
+ assert result.decision == PolicyDecision.CONSTRAIN
64
+ assert result.allowed_modules == []
65
+ assert result.blocked_modules == ["http_headers"]
66
+ assert result.violations[0].code == PolicyErrorCode.AUTHORIZATION_REQUIRED
67
+
68
+
69
+ def test_conditional_module_allowed_when_authorized_and_not_passive_only():
70
+ result = evaluate_modules(
71
+ ["HTTP Headers", "Robots.txt"],
72
+ authorized_target=True,
73
+ passive_only=False,
74
+ )
75
+
76
+ assert result.decision == PolicyDecision.ALLOW
77
+ assert result.allowed_modules == ["http_headers", "robots_txt"]
78
+ assert result.blocked_modules == []
79
+
80
+
81
+ def test_forbidden_module_is_always_blocked():
82
+ result = evaluate_modules(
83
+ ["Resource Links", "nmap", "Credential Testing"],
84
+ authorized_target=True,
85
+ passive_only=False,
86
+ )
87
+
88
+ assert result.decision == PolicyDecision.CONSTRAIN
89
+ assert "resource_links" in result.allowed_modules
90
+ assert "port_scan" in result.blocked_modules
91
+ assert "credential_testing" in result.blocked_modules
92
+ assert {v.code for v in result.violations} == {PolicyErrorCode.FORBIDDEN_MODULE}
93
+
94
+
95
+ def test_unknown_module_blocked_by_default():
96
+ result = evaluate_modules(["Unknown Thing"])
97
+
98
+ assert result.decision == PolicyDecision.CONSTRAIN
99
+ assert result.allowed_modules == []
100
+ assert result.blocked_modules == ["unknown_thing"]
101
+ assert result.violations[0].code == PolicyErrorCode.UNKNOWN_MODULE
102
+
103
+
104
+ def test_unknown_module_can_be_allowed_only_when_explicitly_enabled():
105
+ result = evaluate_modules(["Experimental"], allow_unknown_modules=True)
106
+
107
+ assert result.decision == PolicyDecision.ALLOW
108
+ assert result.allowed_modules == ["experimental"]
109
+ assert result.blocked_modules == []
110
+
111
+
112
+ def test_correction_verbs_are_closed():
113
+ assert set(ALLOWED_CORRECTION_VERBS) == {"ADAPT", "CONSTRAIN", "REVERT", "OBSERVE"}
114
+ assert enforce_correction_verb("adapt") == "ADAPT"
115
+ assert enforce_correction_verb(" OBSERVE ") == "OBSERVE"
116
+
117
+ with pytest.raises(PolicyViolationException) as exc:
118
+ enforce_correction_verb("EXPAND")
119
+
120
+ assert exc.value.violation.code == PolicyErrorCode.INVALID_CORRECTION_VERB
121
+
122
+
123
+ def test_policy_cannot_mutate_without_out_of_band_approval():
124
+ assert may_mutate_policy(out_of_band_approval=False) is False
125
+ assert may_mutate_policy(out_of_band_approval=True) is True
126
+
127
+ with pytest.raises(PolicyViolationException) as exc:
128
+ enforce_policy_mutation_gate(out_of_band_approval=False)
129
+
130
+ assert exc.value.violation.code == PolicyErrorCode.POLICY_MUTATION_BLOCKED
131
+
132
+ enforce_policy_mutation_gate(out_of_band_approval=True)
133
+
134
+
135
+ def test_audit_payload_blocks_raw_indicator_fields():
136
+ safe_payload = {
137
+ "run_id": "run_123",
138
+ "indicator_hash": "abc123",
139
+ "modules": ["resource_links"],
140
+ }
141
+ enforce_audit_payload(safe_payload)
142
+
143
+ with pytest.raises(PolicyViolationException) as exc:
144
+ enforce_audit_payload({"raw_indicator": "example.com", "indicator_hash": "abc"})
145
+
146
+ assert exc.value.violation.code == PolicyErrorCode.RAW_LOGGING_BLOCKED
147
+
148
+
149
+ def test_catalog_and_ui_modules_exclude_forbidden_by_default():
150
+ catalog = module_catalog()
151
+ names = {item["canonical_name"] for item in catalog}
152
+ assert "resource_links" in names
153
+ assert "port_scan" in names
154
+
155
+ ui_modules = allowed_ui_modules()
156
+ assert "Resource Links" in ui_modules
157
+ assert "HTTP Headers" in ui_modules
158
+ assert "Port Scan" not in ui_modules
159
+ assert "Credential Testing" not in ui_modules
160
+
161
+ passive_ui_modules = allowed_ui_modules(include_conditional=False)
162
+ assert "Resource Links" in passive_ui_modules
163
+ assert "HTTP Headers" not in passive_ui_modules
164
+
165
+
166
+ def test_get_module_policy_returns_registered_policy():
167
+ policy = get_module_policy("Resource Links")
168
+ assert policy is not None
169
+ assert policy.canonical_name == "resource_links"
170
+ assert policy.risk == "low"