Skip to content

Commit addc1f5

Browse files
committed
Island: Fix a bug and UT's for add_remediation_to_issue
1 parent 9489000 commit addc1f5

File tree

2 files changed

+119
-122
lines changed
  • monkey

2 files changed

+119
-122
lines changed

monkey/monkey_island/cc/services/reporting/report.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -552,8 +552,9 @@ def get_issues(cls):
552552

553553
@classmethod
554554
def add_remediation_to_issue(cls, issue: Dict[str, Any]) -> Dict[str, Any]:
555-
manifests = cls._get_exploiter_manifests()
556-
issue["remediation_suggestion"] = manifests.get(issue["type"], "")
555+
manifest = cls._get_exploiter_manifests().get(issue["type"])
556+
if manifest:
557+
issue["remediation_suggestion"] = manifest.remediation_suggestion
557558
return issue
558559

559560
@classmethod
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1+
from copy import deepcopy
12
from datetime import datetime
23
from ipaddress import IPv4Address, IPv4Interface
34
from unittest.mock import MagicMock
45
from uuid import UUID
56

67
import pytest
78
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
814
from tests.monkey_island import (
915
InMemoryAgentConfigurationRepository,
1016
InMemoryAgentEventRepository,
1117
InMemoryAgentRepository,
1218
)
13-
14-
from common import OperatingSystem
1519
from common.agent_events import (
1620
AgentShutdownEvent,
1721
ExploitationEvent,
1822
PasswordRestorationEvent,
1923
PropagationEvent,
2024
)
21-
from common.agent_plugins import AgentPluginManifest, AgentPluginType
2225
from common.hard_coded_exploiter_manifests import HARD_CODED_EXPLOITER_MANIFESTS
2326
from common.types import SocketAddress
2427
from monkey_island.cc.models import Agent, CommunicationType, Machine, Node
@@ -31,118 +34,117 @@
3134

3235
EVENT_1 = AgentShutdownEvent(source=UUID("2d56f972-78a8-4026-9f47-2dfd550ee207"), timestamp=10)
3336
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,
3942
)
4043
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,
4649
)
4750
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,
5356
)
5457
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,
5962
)
6063

6164
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,
6770
)
6871
EVENTS = [EVENT_2, EVENT_3, EVENT_4, EVENT_1, EVENT_5]
6972

7073
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")],
7679
)
7780

7881
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")],
8386
)
8487

8588
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")],
8992
)
9093

9194
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")],
9598
)
9699

97100
AGENTS = [
98101
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),
104107
),
105108
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),
111114
),
112115
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),
118121
),
119122
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),
125128
),
126129
]
127130

128131
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),
134137
)
135138

136-
137139
NODES = [
138140
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])},
141143
),
142144
Node(machine_id=99, connections={"1": frozenset([CommunicationType.SCANNED])}),
143145
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])},
146148
),
147149
]
148150

@@ -165,25 +167,26 @@
165167
},
166168
]
167169

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}
169180

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}
171185

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}
187190

188191

189192
def get_machine_by_id(machine_id):
@@ -215,9 +218,9 @@ def mock_agent_plugin_repository() -> IAgentPluginRepository:
215218

216219
@pytest.fixture(autouse=True)
217220
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,
221224
):
222225
ReportService._machine_repository = MagicMock()
223226
ReportService._machine_repository.get_machines.return_value = MACHINES
@@ -271,7 +274,7 @@ def test_report_service_get_latest_event_timestamp():
271274
def test_report_generation(monkeypatch, agent_event_repository):
272275
monkeypatch.setattr(ReportService, "get_issues", lambda: [])
273276
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)
275278

276279
ReportService.update_report()
277280
actual_report = ReportService.get_report()
@@ -297,32 +300,25 @@ def test_report_generation__no_agent_repository():
297300

298301

299302
@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)]
319307
)
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))
327323

328-
assert actual_remediation_suggestion == expected_remediation_suggestions
324+
assert "remediation_suggestion" not in issue

0 commit comments

Comments
 (0)