Skip to content

Commit 88b38f9

Browse files
committed
Merge branch '3167-run-credentials-collectors-as-plugins' into 3167-ui-credentials-collectors
Issue #3167 PR #3260
2 parents b14ef8e + a077210 commit 88b38f9

File tree

6 files changed

+15
-40
lines changed

6 files changed

+15
-40
lines changed

monkey/infection_monkey/credential_collectors/mimikatz_collector/mimikatz_credential_collector.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def __init__(self, agent_event_queue: IAgentEventQueue, agent_id: AgentID):
3131
self._agent_event_queue = agent_event_queue
3232
self._agent_id = agent_id
3333

34-
def collect_credentials(self, options=None) -> Sequence[Credentials]:
34+
def run(self, options=None, interrupt=None) -> Sequence[Credentials]:
3535
logger.info("Attempting to collect windows credentials with pypykatz.")
3636
windows_credentials = pypykatz_handler.get_windows_creds()
3737

monkey/infection_monkey/credential_collectors/ssh_collector/ssh_credential_collector.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, agent_event_queue: IAgentEventQueue, agent_id: AgentID):
1919
self._agent_event_queue = agent_event_queue
2020
self._agent_id = agent_id
2121

22-
def collect_credentials(self, _options=None) -> Sequence[Credentials]:
22+
def run(self, options=None, interrupt=None) -> Sequence[Credentials]:
2323
logger.info("Started scanning for SSH credentials")
2424
ssh_info = ssh_handler.get_ssh_info(self._agent_event_queue, self._agent_id)
2525
logger.info("Finished scanning for SSH credentials")

monkey/infection_monkey/i_puppet/i_credentials_collector.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
from typing import Mapping, Optional, Sequence
33

44
from common.credentials import Credentials
5+
from common.types import Event
56

67

78
class ICredentialsCollector(ABC):
89
@abstractmethod
9-
def collect_credentials(self, options: Optional[Mapping]) -> Sequence[Credentials]:
10+
def run(self, options: Optional[Mapping], interrupt: Event) -> Sequence[Credentials]:
1011
pass

monkey/infection_monkey/master/automated_master.py

+5-27
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22
import multiprocessing
33
import time
44
from ipaddress import IPv4Interface
5-
from typing import Any, Callable, Collection, Dict, List, Optional, Sequence
5+
from typing import Any, Callable, Dict, List, Optional, Sequence
66

77
from egg_timer import EggTimer
88

9-
from common.agent_configuration import PluginConfiguration
109
from infection_monkey.i_control_channel import IControlChannel, IslandCommunicationError
1110
from infection_monkey.i_master import IMaster
1211
from infection_monkey.i_puppet import IPuppet
@@ -127,7 +126,7 @@ def _run_simulation(self):
127126
return
128127

129128
credentials_collector_thread = create_daemon_thread(
130-
target=self._run_plugins_legacy,
129+
target=self._run_plugins,
131130
name="CredentialsCollectorThread",
132131
args=(
133132
config.credentials_collectors,
@@ -156,13 +155,13 @@ def _run_simulation(self):
156155
payload_thread.start()
157156
payload_thread.join()
158157

159-
def _collect_credentials(self, collector: PluginConfiguration):
158+
def _collect_credentials(self, collector_name: str, collector_options: Dict[str, Any]):
160159
credentials = self._puppet.run_credentials_collector(
161-
collector.name, collector.options, self._stop
160+
collector_name, collector_options, self._stop
162161
)
163162

164163
if not credentials:
165-
logger.debug(f"No credentials were collected by {collector}")
164+
logger.debug(f"No credentials were collected by {collector_name}")
166165

167166
def _run_payload(self, name: str, options: Dict):
168167
self._puppet.run_payload(name, options, self._stop)
@@ -188,26 +187,5 @@ def _run_plugins(
188187

189188
logger.info(f"Finished running {plugin_type}s")
190189

191-
def _run_plugins_legacy(
192-
self,
193-
plugins: Collection[PluginConfiguration],
194-
plugin_type: str,
195-
callback: Callable[[Any], None],
196-
):
197-
logger.info(f"Running {plugin_type}s")
198-
logger.debug(f"Found {len(plugins)} {plugin_type}(s) to run")
199-
200-
interrupted_message = f"Received a stop signal, skipping remaining {plugin_type}s"
201-
for p in interruptible_iter(plugins, self._stop, interrupted_message):
202-
try:
203-
callback(p)
204-
except Exception:
205-
logger.exception(
206-
f"Got unhandled exception when running {plugin_type} plugin {p}. "
207-
f"Plugin was passed to {callback}"
208-
)
209-
210-
logger.info(f"Finished running {plugin_type}s")
211-
212190
def cleanup(self):
213191
pass

monkey/tests/unit_tests/infection_monkey/credential_collectors/test_mimikatz_collector.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def patch_pypykatz(win_creds: Sequence[WindowsCredentials], monkeypatch):
2828

2929
def collect_credentials() -> Sequence[Credentials]:
3030
mock_event_queue = MagicMock(spec=IAgentEventQueue)
31-
return MimikatzCredentialCollector(mock_event_queue, AGENT_ID).collect_credentials()
31+
return MimikatzCredentialCollector(mock_event_queue, AGENT_ID).run()
3232

3333

3434
@pytest.mark.parametrize(
@@ -133,7 +133,7 @@ def test_mimikatz_credentials_stolen_event_published(monkeypatch):
133133
patch_pypykatz([], monkeypatch)
134134

135135
mimikatz_credential_collector = MimikatzCredentialCollector(mock_event_queue, AGENT_ID)
136-
mimikatz_credential_collector.collect_credentials()
136+
mimikatz_credential_collector.run()
137137

138138
mock_event_queue.publish.assert_called_once()
139139

@@ -147,7 +147,7 @@ def test_mimikatz_credentials_stolen_event_tags(monkeypatch):
147147
patch_pypykatz([], monkeypatch)
148148

149149
mimikatz_credential_collector = MimikatzCredentialCollector(mock_event_queue, AGENT_ID)
150-
mimikatz_credential_collector.collect_credentials()
150+
mimikatz_credential_collector.run()
151151

152152
mock_event_queue_call_args = mock_event_queue.publish.call_args[0][0]
153153

@@ -164,7 +164,7 @@ def test_mimikatz_credentials_stolen_event_stolen_credentials(monkeypatch):
164164
patch_pypykatz(win_creds, monkeypatch)
165165

166166
mimikatz_credential_collector = MimikatzCredentialCollector(mock_event_queue, AGENT_ID)
167-
collected_credentials = mimikatz_credential_collector.collect_credentials()
167+
collected_credentials = mimikatz_credential_collector.run()
168168

169169
mock_event_queue_call_args = mock_event_queue.publish.call_args[0][0]
170170

monkey/tests/unit_tests/infection_monkey/credential_collectors/test_ssh_credentials_collector.py

+2-6
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ def patch_ssh_handler(ssh_creds, monkeypatch):
2222
)
2323
def test_ssh_credentials_empty_results(monkeypatch, ssh_creds):
2424
patch_ssh_handler(ssh_creds, monkeypatch)
25-
collected = SSHCredentialCollector(
26-
MagicMock(spec=IAgentEventQueue), AGENT_ID
27-
).collect_credentials()
25+
collected = SSHCredentialCollector(MagicMock(spec=IAgentEventQueue), AGENT_ID).run()
2826
assert not collected
2927

3028

@@ -69,7 +67,5 @@ def test_ssh_info_result_parsing(monkeypatch):
6967
Credentials(identity=username3, secret=None),
7068
Credentials(identity=None, secret=ssh_keypair3),
7169
]
72-
collected = SSHCredentialCollector(
73-
MagicMock(spec=IAgentEventQueue), AGENT_ID
74-
).collect_credentials()
70+
collected = SSHCredentialCollector(MagicMock(spec=IAgentEventQueue), AGENT_ID).run()
7571
assert expected == collected

0 commit comments

Comments
 (0)