Skip to content

Commit 4dccfba

Browse files
committed
Created initial tests
1 parent eae9e51 commit 4dccfba

12 files changed

Lines changed: 658 additions & 0 deletions

tests/conftest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
Provide pytest fixtures for testing the ATTACK Python Client.
3+
4+
Include a fixture for creating a MitreAttackClient instance backed by a
5+
local STIX bundle for deterministic testing.
6+
"""
7+
8+
from pathlib import Path
9+
10+
import pytest
11+
12+
from attackcti import MitreAttackClient
13+
14+
FIXTURE_PATH = Path(__file__).resolve().parent / "fixtures" / "simple_attack_bundle.json"
15+
16+
17+
@pytest.fixture(scope="module")
18+
def attack_client():
19+
"""Return a client backed by a small STIX bundle for deterministic tests."""
20+
return MitreAttackClient.from_local(enterprise=str(FIXTURE_PATH))
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
{
2+
"type": "bundle",
3+
"id": "bundle--b8b9b0a2-6a5b-41ee-9ed3-6612b45cf66a",
4+
"spec_version": "2.1",
5+
"objects": [
6+
{
7+
"type": "attack-pattern",
8+
"spec_version": "2.1",
9+
"id": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f",
10+
"created": "2024-01-01T00:00:00.000Z",
11+
"modified": "2024-01-01T01:00:00.000Z",
12+
"name": "Sample Technique",
13+
"description": "A synthetic technique for tests.",
14+
"x_mitre_domains": ["enterprise-attack"],
15+
"x_mitre_platforms": ["Windows"],
16+
"external_references": [
17+
{
18+
"source_name": "mitre-attack",
19+
"external_id": "T0001"
20+
}
21+
],
22+
"kill_chain_phases": [
23+
{
24+
"kill_chain_name": "mitre-attack",
25+
"phase_name": "execution"
26+
}
27+
]
28+
},
29+
{
30+
"type": "intrusion-set",
31+
"spec_version": "2.1",
32+
"id": "intrusion-set--d63f0054-df6c-47d9-8a83-d8c8a2ea3c57",
33+
"created": "2024-01-01T00:00:00.000Z",
34+
"modified": "2024-01-01T01:00:00.000Z",
35+
"name": "Sample Group",
36+
"description": "A synthetic group for tests.",
37+
"aliases": [
38+
"Sample Group Alias"
39+
],
40+
"external_references": [
41+
{
42+
"source_name": "mitre-attack",
43+
"external_id": "G0001"
44+
}
45+
]
46+
},
47+
{
48+
"type": "relationship",
49+
"spec_version": "2.1",
50+
"id": "relationship--4d7bc865-2e89-4f71-9f82-40c65dd36a2d",
51+
"created": "2024-01-01T00:10:00.000Z",
52+
"modified": "2024-01-01T01:10:00.000Z",
53+
"relationship_type": "uses",
54+
"source_ref": "intrusion-set--d63f0054-df6c-47d9-8a83-d8c8a2ea3c57",
55+
"target_ref": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f",
56+
"description": "Sample Group uses Sample Technique."
57+
},
58+
{
59+
"type": "x-mitre-detection-strategy",
60+
"spec_version": "2.1",
61+
"id": "x-mitre-detection-strategy--a4a22b0c-19c8-4f60-8d08-ecf2f3d9a1a5",
62+
"created": "2024-01-01T00:00:00.000Z",
63+
"modified": "2024-01-01T01:00:00.000Z",
64+
"name": "Sample Detection Strategy",
65+
"x_mitre_analytic_refs": [
66+
"x-mitre-analytic--0d5f91d8-8c35-4dab-8dd7-1f7c7efe3b77"
67+
],
68+
"x_mitre_domains": ["enterprise-attack"]
69+
},
70+
{
71+
"type": "x-mitre-analytic",
72+
"spec_version": "2.1",
73+
"id": "x-mitre-analytic--0d5f91d8-8c35-4dab-8dd7-1f7c7efe3b77",
74+
"created": "2024-01-01T00:05:00.000Z",
75+
"modified": "2024-01-01T01:05:00.000Z",
76+
"name": "Sample Analytic",
77+
"description": "Synthetic analytic for tests.",
78+
"x_mitre_log_source_references": [
79+
{
80+
"x_mitre_data_component_ref": "x-mitre-data-component--ce5f38c9-dafe-4c1b-8ab4-8504e9e4d4ea",
81+
"name": "WinEventLog:Security",
82+
"channel": "EventCode=4688"
83+
}
84+
],
85+
"x_mitre_domains": ["enterprise-attack"]
86+
},
87+
{
88+
"type": "x-mitre-data-component",
89+
"spec_version": "2.1",
90+
"id": "x-mitre-data-component--ce5f38c9-dafe-4c1b-8ab4-8504e9e4d4ea",
91+
"created": "2024-01-01T00:00:00.000Z",
92+
"modified": "2024-01-01T01:00:00.000Z",
93+
"name": "Process Creation",
94+
"description": "Synthetic data component for tests.",
95+
"x_mitre_log_sources": [
96+
{
97+
"name": "WinEventLog:Security",
98+
"channel": "EventCode=4688"
99+
}
100+
],
101+
"external_references": [
102+
{
103+
"source_name": "mitre-attack",
104+
"external_id": "DC0001"
105+
}
106+
]
107+
},
108+
{
109+
"type": "relationship",
110+
"spec_version": "2.1",
111+
"id": "relationship--1c99a1ef-3f60-4c28-bb8b-1430de7b5bd7",
112+
"created": "2024-01-01T00:20:00.000Z",
113+
"modified": "2024-01-01T01:20:00.000Z",
114+
"relationship_type": "detects",
115+
"source_ref": "x-mitre-detection-strategy--a4a22b0c-19c8-4f60-8d08-ecf2f3d9a1a5",
116+
"target_ref": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f"
117+
},
118+
{
119+
"type": "x-mitre-data-source",
120+
"spec_version": "2.1",
121+
"id": "x-mitre-data-source--3f8c362f-890a-4b60-9b9c-2b2a5822a444",
122+
"created": "2024-01-01T00:00:00.000Z",
123+
"modified": "2024-01-01T01:00:00.000Z",
124+
"name": "Windows Event Logs",
125+
"description": "Event logs produced by Microsoft Windows operating systems.",
126+
"x_mitre_domains": [
127+
"enterprise-attack"
128+
],
129+
"x_mitre_data_components": [
130+
"x-mitre-data-component--ce5f38c9-dafe-4c1b-8ab4-8504e9e4d4ea"
131+
]
132+
},
133+
{
134+
"type": "x-mitre-tactic",
135+
"spec_version": "2.1",
136+
"id": "x-mitre-tactic--3a1a2a7a-1a56-4ca4-9e12-4e7d213f1b51",
137+
"created": "2024-01-01T00:05:00.000Z",
138+
"modified": "2024-01-01T01:05:00.000Z",
139+
"name": "Execution",
140+
"x_mitre_shortname": "execution",
141+
"x_mitre_domains": [
142+
"enterprise-attack"
143+
]
144+
},
145+
{
146+
"type": "x-mitre-matrix",
147+
"spec_version": "2.1",
148+
"id": "x-mitre-matrix--5c1d9b1e-9f9b-4e68-8d78-1e5fbf5a87e2",
149+
"created": "2024-01-01T00:00:00.000Z",
150+
"modified": "2024-01-01T01:00:00.000Z",
151+
"name": "Enterprise ATT&CK Matrix",
152+
"description": "A synthetic subset of the Enterprise ATT&CK matrix for tests.",
153+
"x_mitre_domain": "enterprise-attack",
154+
"x_mitre_version": "12"
155+
},
156+
{
157+
"type": "campaign",
158+
"spec_version": "2.1",
159+
"id": "campaign--0f00b751-6ad3-4d0d-8d3e-b637d5587ee5",
160+
"created": "2024-01-01T00:10:00.000Z",
161+
"modified": "2024-01-01T01:10:00.000Z",
162+
"name": "Sample Campaign",
163+
"description": "A synthetic campaign linking back to Sample Group.",
164+
"aliases": [
165+
"Sample Campaign Alias"
166+
],
167+
"object_marking_refs": [
168+
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
169+
]
170+
},
171+
{
172+
"type": "malware",
173+
"spec_version": "2.1",
174+
"id": "malware--22ad4d95-0d6a-4f6a-9e8b-780daef3b842",
175+
"created": "2024-01-01T00:12:00.000Z",
176+
"modified": "2024-01-01T01:12:00.000Z",
177+
"name": "Sample Malware",
178+
"description": "Provides synthetic context for tests.",
179+
"x_mitre_platforms": [
180+
"Windows"
181+
],
182+
"object_marking_refs": [
183+
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
184+
],
185+
"is_family": false
186+
},
187+
{
188+
"type": "software",
189+
"spec_version": "2.1",
190+
"id": "software--7c7f8c0a-907a-4d75-868c-41f16b8dcf6e",
191+
"created": "2024-01-01T00:15:00.000Z",
192+
"modified": "2024-01-01T01:15:00.000Z",
193+
"name": "Sample Software",
194+
"description": "Used by the sample campaign.",
195+
"x_mitre_platforms": [
196+
"Windows"
197+
],
198+
"object_marking_refs": [
199+
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
200+
],
201+
"is_family": false
202+
},
203+
{
204+
"type": "tool",
205+
"spec_version": "2.1",
206+
"id": "tool--2f9f0cb5-61cb-4e5f-95d5-f243d0c0d5a5",
207+
"created": "2024-01-01T00:17:00.000Z",
208+
"modified": "2024-01-01T01:17:00.000Z",
209+
"name": "Sample Tool",
210+
"description": "Supplementary tool entry for tests.",
211+
"object_marking_refs": [
212+
"marking-definition--fa42a846-8d90-4e51-bc29-71d5b4802168"
213+
],
214+
"is_family": false
215+
},
216+
{
217+
"type": "course-of-action",
218+
"spec_version": "2.1",
219+
"id": "course-of-action--526c95c3-3ea6-4da4-88f2-9cde76e5e7f7",
220+
"created": "2024-01-01T00:18:00.000Z",
221+
"modified": "2024-01-01T01:18:00.000Z",
222+
"name": "Sample Mitigation",
223+
"description": "Mitigates the Sample Technique."
224+
},
225+
{
226+
"type": "asset",
227+
"spec_version": "2.1",
228+
"id": "asset--e1cc8f7d-26df-44d3-9db5-1aed6c047fdc",
229+
"created": "2024-01-01T00:19:00.000Z",
230+
"modified": "2024-01-01T01:19:00.000Z",
231+
"name": "Sample Asset",
232+
"description": "Infrastructure asset for testing.",
233+
"asset_type": "workstation"
234+
},
235+
{
236+
"type": "collection",
237+
"spec_version": "2.1",
238+
"id": "collection--d2e94c7b-d61b-4cac-a61d-2f1f0b3ab5c8",
239+
"created": "2024-01-01T00:20:00.000Z",
240+
"modified": "2024-01-01T01:20:00.000Z",
241+
"name": "Sample Collection",
242+
"description": "A placeholder collection entry."
243+
},
244+
{
245+
"type": "relationship",
246+
"spec_version": "2.1",
247+
"id": "relationship--8fca4d55-3f4f-4b1c-896a-79e18aa8db4a",
248+
"created": "2024-01-01T00:25:00.000Z",
249+
"modified": "2024-01-01T01:25:00.000Z",
250+
"relationship_type": "uses",
251+
"source_ref": "campaign--0f00b751-6ad3-4d0d-8d3e-b637d5587ee5",
252+
"target_ref": "malware--22ad4d95-0d6a-4f6a-9e8b-780daef3b842"
253+
},
254+
{
255+
"type": "relationship",
256+
"spec_version": "2.1",
257+
"id": "relationship--4b3d3f1e-6f12-4dd5-9300-54f0a0e4d6df",
258+
"created": "2024-01-01T00:26:00.000Z",
259+
"modified": "2024-01-01T01:26:00.000Z",
260+
"relationship_type": "uses",
261+
"source_ref": "malware--22ad4d95-0d6a-4f6a-9e8b-780daef3b842",
262+
"target_ref": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f"
263+
},
264+
{
265+
"type": "relationship",
266+
"spec_version": "2.1",
267+
"id": "relationship--6c6fa7c8-4b3a-46ae-9a67-9557c1fc7c0c",
268+
"created": "2024-01-01T00:27:00.000Z",
269+
"modified": "2024-01-01T01:27:00.000Z",
270+
"relationship_type": "uses",
271+
"source_ref": "software--7c7f8c0a-907a-4d75-868c-41f16b8dcf6e",
272+
"target_ref": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f"
273+
},
274+
{
275+
"type": "relationship",
276+
"spec_version": "2.1",
277+
"id": "relationship--c5748b1b-a4e7-4a3d-8f8b-37101bac73fc",
278+
"created": "2024-01-01T00:28:00.000Z",
279+
"modified": "2024-01-01T01:28:00.000Z",
280+
"relationship_type": "uses",
281+
"source_ref": "intrusion-set--d63f0054-df6c-47d9-8a83-d8c8a2ea3c57",
282+
"target_ref": "tool--2f9f0cb5-61cb-4e5f-95d5-f243d0c0d5a5"
283+
},
284+
{
285+
"type": "relationship",
286+
"spec_version": "2.1",
287+
"id": "relationship--09c3d60f-7603-4be4-92b9-7bcf8817849c",
288+
"created": "2024-01-01T00:29:00.000Z",
289+
"modified": "2024-01-01T01:29:00.000Z",
290+
"relationship_type": "mitigates",
291+
"source_ref": "course-of-action--526c95c3-3ea6-4da4-88f2-9cde76e5e7f7",
292+
"target_ref": "attack-pattern--f6d79fc5-6e2a-4c1b-9d22-3be5da1be56f"
293+
}
294+
]
295+
}

tests/integration/conftest.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
Integration test configuration for the ATT&CK Python Client.
3+
4+
This module provides pytest fixtures for integration tests, including:
5+
- real_client: A MitreAttackClient instance backed by real ATT&CK STIX bundles.
6+
"""
7+
8+
import os
9+
10+
import pytest
11+
12+
from attackcti import MitreAttackClient
13+
14+
15+
@pytest.fixture(scope="session")
16+
def real_client():
17+
"""Provide a MitreAttackClient backed by the real ATT&CK STIX bundles."""
18+
if os.getenv("RUN_INTEGRATION") not in {"1", "true", "True"}:
19+
pytest.skip("integration tests require RUN_INTEGRATION=1")
20+
return MitreAttackClient.from_attack_stix_data()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Integration checks for Detections helpers using live ATT&CK data."""
2+
3+
import pytest
4+
5+
6+
@pytest.mark.integration
7+
def test_real_data_components(real_client):
8+
"""Verify detections return data components for a live technique."""
9+
techniques = real_client.query.techniques.get_techniques()
10+
assert techniques, "Expected live techniques to exist"
11+
components = real_client.query.detections.get_data_components_by_technique_via_analytics(
12+
techniques[0].id,
13+
stix_format=True,
14+
)
15+
assert isinstance(components, list)
16+
assert components, "Real ATT&CK data should expose components via analytics"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"""Integration checks for GroupsClient using real ATT&CK data."""
2+
3+
import pytest
4+
5+
6+
@pytest.mark.integration
7+
def test_real_group_alias_lookup(real_client):
8+
"""Verify alias-based lookups return a real intrusion set."""
9+
groups = real_client.query.groups.get_groups()
10+
assert groups, "Live ATT&CK data should expose intrusion-set entries"
11+
first_group = groups[0]
12+
alias = first_group.aliases[0] if getattr(first_group, "aliases", None) else first_group.name
13+
14+
matches = real_client.query.groups.get_group_by_alias(alias, case=True)
15+
assert matches, "Alias lookup should find the group"
16+
assert matches[0].name == first_group.name
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""Integration checks for Relationships helpers against live ATT&CK data."""
2+
3+
import pytest
4+
5+
6+
@pytest.mark.integration
7+
def test_export_real_layers(real_client, tmp_path):
8+
"""Ensure navigator layers can be generated from real data."""
9+
real_client.query.relationships.export_groups_navigator_layers(output_dir=str(tmp_path))
10+
generated = list(tmp_path.glob("*.json"))
11+
assert generated, "Should export at least one navigator layer from real data"
12+
13+
14+
@pytest.mark.integration
15+
def test_real_uses_relationships(real_client):
16+
"""Verify real group → technique uses relationships exist."""
17+
groups = real_client.query.groups.get_groups()
18+
assert groups, "Live feed should expose intrusion-set groups"
19+
techniques = real_client.query.relationships.get_techniques_used_by_group(groups[0])
20+
assert techniques, "Group should map to techniques"

0 commit comments

Comments
 (0)