1
+ from copy import deepcopy
1
2
from datetime import datetime
2
3
from ipaddress import IPv4Address , IPv4Interface
3
4
from unittest .mock import MagicMock
4
5
from uuid import UUID
5
6
6
7
import pytest
7
8
import pytz
9
+
10
+ from common .agent_plugins import AgentPluginType
11
+ from tests .data_for_tests .agent_plugin .manifests import EXPLOITER_NAME_1 , EXPLOITER_NAME_2 ,\
12
+ REMEDIATION_SUGGESTION_1 , REMEDIATION_SUGGESTION_2 , EXPLOITER_INCOMPLETE_MANIFEST ,\
13
+ PLUGIN_MANIFESTS
8
14
from tests .monkey_island import (
9
15
InMemoryAgentConfigurationRepository ,
10
16
InMemoryAgentEventRepository ,
11
17
InMemoryAgentRepository ,
12
18
)
13
-
14
- from common import OperatingSystem
15
19
from common .agent_events import (
16
20
AgentShutdownEvent ,
17
21
ExploitationEvent ,
18
22
PasswordRestorationEvent ,
19
23
PropagationEvent ,
20
24
)
21
- from common .agent_plugins import AgentPluginManifest , AgentPluginType
22
25
from common .hard_coded_exploiter_manifests import HARD_CODED_EXPLOITER_MANIFESTS
23
26
from common .types import SocketAddress
24
27
from monkey_island .cc .models import Agent , CommunicationType , Machine , Node
31
34
32
35
EVENT_1 = AgentShutdownEvent (source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ), timestamp = 10 )
33
36
EVENT_2 = ExploitationEvent (
34
- source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
35
- target = IPv4Address ("1.1.1.1" ),
36
- success = False ,
37
- exploiter_name = "ssh" ,
38
- timestamp = 1 ,
37
+ source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
38
+ target = IPv4Address ("1.1.1.1" ),
39
+ success = False ,
40
+ exploiter_name = "ssh" ,
41
+ timestamp = 1 ,
39
42
)
40
43
EVENT_3 = ExploitationEvent (
41
- source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
42
- target = IPv4Address ("1.1.1.1" ),
43
- success = True ,
44
- exploiter_name = "ssh" ,
45
- timestamp = 2 ,
44
+ source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
45
+ target = IPv4Address ("1.1.1.1" ),
46
+ success = True ,
47
+ exploiter_name = "ssh" ,
48
+ timestamp = 2 ,
46
49
)
47
50
EVENT_4 = PropagationEvent (
48
- source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
49
- target = IPv4Address ("1.1.1.1" ),
50
- success = True ,
51
- exploiter_name = "ssh" ,
52
- timestamp = 3 ,
51
+ source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
52
+ target = IPv4Address ("1.1.1.1" ),
53
+ success = True ,
54
+ exploiter_name = "ssh" ,
55
+ timestamp = 3 ,
53
56
)
54
57
EVENT_5 = PasswordRestorationEvent (
55
- source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
56
- target = IPv4Address ("1.1.1.1" ),
57
- success = True ,
58
- timestamp = 4 ,
58
+ source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
59
+ target = IPv4Address ("1.1.1.1" ),
60
+ success = True ,
61
+ timestamp = 4 ,
59
62
)
60
63
61
64
EVENT_6 = ExploitationEvent (
62
- source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
63
- target = IPv4Address ("2.2.2.2" ),
64
- success = False ,
65
- exploiter_name = "wmi" ,
66
- timestamp = 11 ,
65
+ source = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
66
+ target = IPv4Address ("2.2.2.2" ),
67
+ success = False ,
68
+ exploiter_name = "wmi" ,
69
+ timestamp = 11 ,
67
70
)
68
71
EVENTS = [EVENT_2 , EVENT_3 , EVENT_4 , EVENT_1 , EVENT_5 ]
69
72
70
73
ISLAND_MACHINE = Machine (
71
- id = 99 ,
72
- island = True ,
73
- hostname = "Island" ,
74
- hardware_id = 5 ,
75
- network_interfaces = [IPv4Interface ("10.10.10.99/24" )],
74
+ id = 99 ,
75
+ island = True ,
76
+ hostname = "Island" ,
77
+ hardware_id = 5 ,
78
+ network_interfaces = [IPv4Interface ("10.10.10.99/24" )],
76
79
)
77
80
78
81
MACHINE_1 = Machine (
79
- id = 1 ,
80
- hardware_id = 9 ,
81
- hostname = "machine_1" ,
82
- network_interfaces = [IPv4Interface ("10.10.10.1/24" )],
82
+ id = 1 ,
83
+ hardware_id = 9 ,
84
+ hostname = "machine_1" ,
85
+ network_interfaces = [IPv4Interface ("10.10.10.1/24" )],
83
86
)
84
87
85
88
MACHINE_2 = Machine (
86
- id = 2 ,
87
- hardware_id = 9 ,
88
- network_interfaces = [IPv4Interface ("10.10.10.2/24" )],
89
+ id = 2 ,
90
+ hardware_id = 9 ,
91
+ network_interfaces = [IPv4Interface ("10.10.10.2/24" )],
89
92
)
90
93
91
94
MACHINE_3 = Machine (
92
- id = 3 ,
93
- hardware_id = 9 ,
94
- network_interfaces = [IPv4Interface ("10.10.10.3/24" )],
95
+ id = 3 ,
96
+ hardware_id = 9 ,
97
+ network_interfaces = [IPv4Interface ("10.10.10.3/24" )],
95
98
)
96
99
97
100
AGENTS = [
98
101
Agent (
99
- id = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
100
- machine_id = 1 ,
101
- start_time = 100 ,
102
- stop_time = 500 ,
103
- cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
102
+ id = UUID ("2d56f972-78a8-4026-9f47-2dfd550ee207" ),
103
+ machine_id = 1 ,
104
+ start_time = 100 ,
105
+ stop_time = 500 ,
106
+ cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
104
107
),
105
108
Agent (
106
- id = UUID ("65c641f2-af47-4a42-929b-109b30f0d8d6" ),
107
- machine_id = 2 ,
108
- start_time = 200 ,
109
- stop_time = 600 ,
110
- cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
109
+ id = UUID ("65c641f2-af47-4a42-929b-109b30f0d8d6" ),
110
+ machine_id = 2 ,
111
+ start_time = 200 ,
112
+ stop_time = 600 ,
113
+ cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
111
114
),
112
115
Agent (
113
- id = UUID ("290da3c3-f410-4f5e-a472-b04416860a2c" ),
114
- machine_id = 3 ,
115
- start_time = 300 ,
116
- stop_time = 700 ,
117
- cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
116
+ id = UUID ("290da3c3-f410-4f5e-a472-b04416860a2c" ),
117
+ machine_id = 3 ,
118
+ start_time = 300 ,
119
+ stop_time = 700 ,
120
+ cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
118
121
),
119
122
Agent (
120
- id = UUID ("e5cd334a-5ca5-4f19-a2ab-a68d515fea46" ),
121
- machine_id = 1 ,
122
- start_time = 600 ,
123
- stop_time = 40309 ,
124
- cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
123
+ id = UUID ("e5cd334a-5ca5-4f19-a2ab-a68d515fea46" ),
124
+ machine_id = 1 ,
125
+ start_time = 600 ,
126
+ stop_time = 40309 ,
127
+ cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
125
128
),
126
129
]
127
130
128
131
AGENT_NOT_DEAD = Agent (
129
- id = UUID ("10e603df-609f-42c6-af08-59c63e82b873" ),
130
- machine_id = 2 ,
131
- start_time = 601 ,
132
- stop_time = None ,
133
- cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
132
+ id = UUID ("10e603df-609f-42c6-af08-59c63e82b873" ),
133
+ machine_id = 2 ,
134
+ start_time = 601 ,
135
+ stop_time = None ,
136
+ cc_server = SocketAddress (ip = "127.0.0.1" , port = 5000 ),
134
137
)
135
138
136
-
137
139
NODES = [
138
140
Node (
139
- machine_id = 1 ,
140
- connections = {"2" : frozenset ([CommunicationType .EXPLOITED , CommunicationType .SCANNED ])},
141
+ machine_id = 1 ,
142
+ connections = {"2" : frozenset ([CommunicationType .EXPLOITED , CommunicationType .SCANNED ])},
141
143
),
142
144
Node (machine_id = 99 , connections = {"1" : frozenset ([CommunicationType .SCANNED ])}),
143
145
Node (
144
- machine_id = 3 ,
145
- connections = {"99" : frozenset ([CommunicationType .CC , CommunicationType .EXPLOITED ])},
146
+ machine_id = 3 ,
147
+ connections = {"99" : frozenset ([CommunicationType .CC , CommunicationType .EXPLOITED ])},
146
148
),
147
149
]
148
150
165
167
},
166
168
]
167
169
168
- REMEDIATION_SUGGESTION = "Fix it like this!"
170
+ ISSUE_1 = {'machine_id' : 8 ,
171
+ 'machine' : 'hadoop-2' ,
172
+ 'ip_address' : '10.2.2.2' ,
173
+ 'type' : EXPLOITER_NAME_1 ,
174
+ 'password_restored' : None }
175
+
176
+ ISSUE_2 = {'machine_id' : 9 , 'machine' : 'hadoop-3' ,
177
+ 'ip_address' : '10.2.2.3' ,
178
+ 'type' : EXPLOITER_NAME_2 ,
179
+ 'password_restored' : True }
169
180
170
- MOCK_EXPLOITER_NAME = "MockExploiter"
181
+ ISSUE_3 = {'machine_id' : 10 , 'machine' : 'hadoop-4' ,
182
+ 'ip_address' : '10.2.2.4' ,
183
+ 'type' : EXPLOITER_INCOMPLETE_MANIFEST ,
184
+ 'password_restored' : True }
171
185
172
- PLUGIN_MANIFESTS = {
173
- AgentPluginType .EXPLOITER : {
174
- MOCK_EXPLOITER_NAME : AgentPluginManifest (
175
- name = MOCK_EXPLOITER_NAME ,
176
- plugin_type = AgentPluginType .EXPLOITER ,
177
- supported_operating_systems = (OperatingSystem .WINDOWS ,),
178
- target_operating_systems = (OperatingSystem .WINDOWS ,),
179
- title = "Mock Exploiter" ,
180
- description = "Description for mock exploiter" ,
181
- remediation_suggestion = REMEDIATION_SUGGESTION ,
182
- link_to_documentation = "htp:/no_link" ,
183
- safe = True ,
184
- )
185
- }
186
- }
186
+ ISSUE_4 = {'machine_id' : 10 , 'machine' : 'hadoop-4' ,
187
+ 'ip_address' : '10.2.2.4' ,
188
+ 'type' : 'non existent' ,
189
+ 'password_restored' : True }
187
190
188
191
189
192
def get_machine_by_id (machine_id ):
@@ -215,9 +218,9 @@ def mock_agent_plugin_repository() -> IAgentPluginRepository:
215
218
216
219
@pytest .fixture (autouse = True )
217
220
def report_service (
218
- agent_repository : IAgentRepository ,
219
- agent_event_repository : IAgentEventRepository ,
220
- mock_agent_plugin_repository : IAgentPluginRepository ,
221
+ agent_repository : IAgentRepository ,
222
+ agent_event_repository : IAgentEventRepository ,
223
+ mock_agent_plugin_repository : IAgentPluginRepository ,
221
224
):
222
225
ReportService ._machine_repository = MagicMock ()
223
226
ReportService ._machine_repository .get_machines .return_value = MACHINES
@@ -271,7 +274,7 @@ def test_report_service_get_latest_event_timestamp():
271
274
def test_report_generation (monkeypatch , agent_event_repository ):
272
275
monkeypatch .setattr (ReportService , "get_issues" , lambda : [])
273
276
monkeypatch .setattr (ReportService , "get_cross_segment_issues" , lambda : [])
274
- monkeypatch .setattr (ReportService , "get_remediation_suggestions " , lambda _ : {} )
277
+ monkeypatch .setattr (ReportService , "add_remediation_to_issue " , lambda issue : issue )
275
278
276
279
ReportService .update_report ()
277
280
actual_report = ReportService .get_report ()
@@ -297,32 +300,25 @@ def test_report_generation__no_agent_repository():
297
300
298
301
299
302
@pytest .mark .parametrize (
300
- "issues_set, expected_remediation_suggestions" ,
301
- [
302
- ({MOCK_EXPLOITER_NAME }, {MOCK_EXPLOITER_NAME : REMEDIATION_SUGGESTION }),
303
- ({"NonExistingExploiter" }, {}),
304
- ({}, {}),
305
- (
306
- {"SSHExploiter" },
307
- {"SSHExploiter" : HARD_CODED_EXPLOITER_MANIFESTS ["SSHExploiter" ].remediation_suggestion },
308
- ),
309
- (
310
- {MOCK_EXPLOITER_NAME , "SSHExploiter" },
311
- {
312
- "SSHExploiter" : HARD_CODED_EXPLOITER_MANIFESTS [
313
- "SSHExploiter"
314
- ].remediation_suggestion ,
315
- MOCK_EXPLOITER_NAME : REMEDIATION_SUGGESTION ,
316
- },
317
- ),
318
- ],
303
+ "issue, expected_remediation" ,
304
+ [(ISSUE_1 , REMEDIATION_SUGGESTION_1 ),
305
+ (ISSUE_2 , REMEDIATION_SUGGESTION_2 ),
306
+ (ISSUE_3 , None )]
319
307
)
320
- def test_report__get_remediation_suggestions (
321
- issues_set ,
322
- expected_remediation_suggestions ,
323
- mock_agent_plugin_repository ,
324
- ):
325
- mock_agent_plugin_repository .get_all_plugin_manifests .return_value = PLUGIN_MANIFESTS
326
- actual_remediation_suggestion = ReportService .get_remediation_suggestions (issues_set )
308
+ def test_report__add_remediation_to_issue (issue , expected_remediation , monkeypatch ):
309
+ monkeypatch .setattr (ReportService , "_get_exploiter_manifests" ,
310
+ MagicMock (return_value = PLUGIN_MANIFESTS [AgentPluginType .EXPLOITER ]))
311
+
312
+ issue = deepcopy (issue )
313
+ issue_with_remediation = ReportService .add_remediation_to_issue (issue )
314
+
315
+ assert issue_with_remediation ["remediation_suggestion" ] == expected_remediation
316
+
317
+
318
+ def test_report__add_remediation_to_issue_missing_manifest (monkeypatch ):
319
+ monkeypatch .setattr (ReportService , "_get_exploiter_manifests" ,
320
+ MagicMock (return_value = {}))
321
+
322
+ issue = ReportService .add_remediation_to_issue (deepcopy (ISSUE_1 ))
327
323
328
- assert actual_remediation_suggestion == expected_remediation_suggestions
324
+ assert "remediation_suggestion" not in issue
0 commit comments