forked from p15670423/monkey
Agent: Publish PingScanEvent from ping_scanner
This commit is contained in:
parent
0357d43d33
commit
228ce9bae1
|
@ -4,10 +4,14 @@ import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from ipaddress import IPv4Address
|
||||||
|
|
||||||
from common import OperatingSystem
|
from common import OperatingSystem
|
||||||
|
from common.agent_events import PingScanEvent
|
||||||
|
from common.event_queue import IAgentEventQueue
|
||||||
from common.types import PingScanData
|
from common.types import PingScanData
|
||||||
from infection_monkey.utils.environment import is_windows_os
|
from infection_monkey.utils.environment import is_windows_os
|
||||||
|
from infection_monkey.utils.ids import get_agent_id
|
||||||
|
|
||||||
TTL_REGEX = re.compile(r"TTL=([0-9]+)\b", re.IGNORECASE)
|
TTL_REGEX = re.compile(r"TTL=([0-9]+)\b", re.IGNORECASE)
|
||||||
LINUX_TTL = 64 # Windows TTL is 128
|
LINUX_TTL = 64 # Windows TTL is 128
|
||||||
|
@ -17,15 +21,15 @@ EMPTY_PING_SCAN = PingScanData(False, None)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def ping(host: str, timeout: float) -> PingScanData:
|
def ping(host: str, timeout: float, agent_event_queue: IAgentEventQueue) -> PingScanData:
|
||||||
try:
|
try:
|
||||||
return _ping(host, timeout)
|
return _ping(host, timeout, agent_event_queue)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("Unhandled exception occurred while running ping")
|
logger.exception("Unhandled exception occurred while running ping")
|
||||||
return EMPTY_PING_SCAN
|
return EMPTY_PING_SCAN
|
||||||
|
|
||||||
|
|
||||||
def _ping(host: str, timeout: float) -> PingScanData:
|
def _ping(host: str, timeout: float, agent_event_queue: IAgentEventQueue) -> PingScanData:
|
||||||
if is_windows_os():
|
if is_windows_os():
|
||||||
timeout = math.floor(timeout * 1000)
|
timeout = math.floor(timeout * 1000)
|
||||||
|
|
||||||
|
@ -34,6 +38,10 @@ def _ping(host: str, timeout: float) -> PingScanData:
|
||||||
ping_scan_data = _process_ping_command_output(ping_command_output)
|
ping_scan_data = _process_ping_command_output(ping_command_output)
|
||||||
logger.debug(f"{host} - {ping_scan_data}")
|
logger.debug(f"{host} - {ping_scan_data}")
|
||||||
|
|
||||||
|
agent_event_queue.publish(
|
||||||
|
PingScanEvent(source=get_agent_id(), target=IPv4Address(host), scan_data=ping_scan_data)
|
||||||
|
)
|
||||||
|
|
||||||
return ping_scan_data
|
return ping_scan_data
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ from unittest.mock import MagicMock
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from common import OperatingSystem
|
from common import OperatingSystem
|
||||||
|
from common.event_queue import IAgentEventQueue
|
||||||
from infection_monkey.network_scanning import ping
|
from infection_monkey.network_scanning import ping
|
||||||
from infection_monkey.network_scanning.ping_scanner import EMPTY_PING_SCAN
|
from infection_monkey.network_scanning.ping_scanner import EMPTY_PING_SCAN
|
||||||
|
|
||||||
|
@ -86,56 +87,75 @@ def set_os_windows(monkeypatch):
|
||||||
monkeypatch.setattr("sys.platform", "win32")
|
monkeypatch.setattr("sys.platform", "win32")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def mock_agent_event_queue():
|
||||||
|
return MagicMock(spec=IAgentEventQueue)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("set_os_linux")
|
@pytest.mark.usefixtures("set_os_linux")
|
||||||
def test_linux_ping_success(patch_subprocess_running_ping_with_ping_output):
|
def test_linux_ping_success(patch_subprocess_running_ping_with_ping_output, mock_agent_event_queue):
|
||||||
patch_subprocess_running_ping_with_ping_output(LINUX_SUCCESS_OUTPUT)
|
patch_subprocess_running_ping_with_ping_output(LINUX_SUCCESS_OUTPUT)
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert result.response_received
|
assert result.response_received
|
||||||
assert result.os == OperatingSystem.LINUX
|
assert result.os == OperatingSystem.LINUX
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("set_os_linux")
|
@pytest.mark.usefixtures("set_os_linux")
|
||||||
def test_linux_ping_no_response(patch_subprocess_running_ping_with_ping_output):
|
def test_linux_ping_no_response(
|
||||||
|
patch_subprocess_running_ping_with_ping_output, mock_agent_event_queue
|
||||||
|
):
|
||||||
patch_subprocess_running_ping_with_ping_output(LINUX_NO_RESPONSE_OUTPUT)
|
patch_subprocess_running_ping_with_ping_output(LINUX_NO_RESPONSE_OUTPUT)
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert not result.response_received
|
assert not result.response_received
|
||||||
assert result.os is None
|
assert result.os is None
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("set_os_windows")
|
@pytest.mark.usefixtures("set_os_windows")
|
||||||
def test_windows_ping_success(patch_subprocess_running_ping_with_ping_output):
|
def test_windows_ping_success(
|
||||||
|
patch_subprocess_running_ping_with_ping_output, mock_agent_event_queue
|
||||||
|
):
|
||||||
patch_subprocess_running_ping_with_ping_output(WINDOWS_SUCCESS_OUTPUT)
|
patch_subprocess_running_ping_with_ping_output(WINDOWS_SUCCESS_OUTPUT)
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert result.response_received
|
assert result.response_received
|
||||||
assert result.os == OperatingSystem.WINDOWS
|
assert result.os == OperatingSystem.WINDOWS
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("set_os_windows")
|
@pytest.mark.usefixtures("set_os_windows")
|
||||||
def test_windows_ping_no_response(patch_subprocess_running_ping_with_ping_output):
|
def test_windows_ping_no_response(
|
||||||
|
patch_subprocess_running_ping_with_ping_output, mock_agent_event_queue
|
||||||
|
):
|
||||||
patch_subprocess_running_ping_with_ping_output(WINDOWS_NO_RESPONSE_OUTPUT)
|
patch_subprocess_running_ping_with_ping_output(WINDOWS_NO_RESPONSE_OUTPUT)
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert not result.response_received
|
assert not result.response_received
|
||||||
assert result.os is None
|
assert result.os is None
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
def test_malformed_ping_command_response(patch_subprocess_running_ping_with_ping_output):
|
def test_malformed_ping_command_response(
|
||||||
|
patch_subprocess_running_ping_with_ping_output, mock_agent_event_queue
|
||||||
|
):
|
||||||
patch_subprocess_running_ping_with_ping_output(MALFORMED_OUTPUT)
|
patch_subprocess_running_ping_with_ping_output(MALFORMED_OUTPUT)
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert not result.response_received
|
assert not result.response_received
|
||||||
assert result.os is None
|
assert result.os is None
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("patch_subprocess_running_ping_to_raise_timeout_expired")
|
@pytest.mark.usefixtures("patch_subprocess_running_ping_to_raise_timeout_expired")
|
||||||
def test_timeout_expired():
|
def test_timeout_expired(mock_agent_event_queue):
|
||||||
result = ping("192.168.1.1", 1.0)
|
result = ping("192.168.1.1", 1.0, mock_agent_event_queue)
|
||||||
|
|
||||||
assert not result.response_received
|
assert not result.response_received
|
||||||
assert result.os is None
|
assert result.os is None
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -147,9 +167,9 @@ def ping_command_spy(monkeypatch):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def assert_expected_timeout(ping_command_spy):
|
def assert_expected_timeout(ping_command_spy, mock_agent_event_queue):
|
||||||
def inner(timeout_flag, timeout_input, expected_timeout):
|
def inner(timeout_flag, timeout_input, expected_timeout):
|
||||||
ping("192.168.1.1", timeout_input)
|
ping("192.168.1.1", timeout_input, mock_agent_event_queue)
|
||||||
|
|
||||||
assert ping_command_spy.call_args is not None
|
assert ping_command_spy.call_args is not None
|
||||||
|
|
||||||
|
@ -159,6 +179,8 @@ def assert_expected_timeout(ping_command_spy):
|
||||||
timeout_flag_index = ping_command.index(timeout_flag)
|
timeout_flag_index = ping_command.index(timeout_flag)
|
||||||
assert ping_command[timeout_flag_index + 1] == expected_timeout
|
assert ping_command[timeout_flag_index + 1] == expected_timeout
|
||||||
|
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 1
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,8 +200,9 @@ def test_linux_timeout(assert_expected_timeout):
|
||||||
assert_expected_timeout(timeout_flag, timeout, str(math.ceil(timeout)))
|
assert_expected_timeout(timeout_flag, timeout, str(math.ceil(timeout)))
|
||||||
|
|
||||||
|
|
||||||
def test_exception_handling(monkeypatch):
|
def test_exception_handling(monkeypatch, mock_agent_event_queue):
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"infection_monkey.network_scanning.ping_scanner._ping", MagicMock(side_effect=Exception)
|
"infection_monkey.network_scanning.ping_scanner._ping", MagicMock(side_effect=Exception)
|
||||||
)
|
)
|
||||||
assert ping("abc", 10) == EMPTY_PING_SCAN
|
assert ping("abc", 10, mock_agent_event_queue) == EMPTY_PING_SCAN
|
||||||
|
assert mock_agent_event_queue.publish.call_count == 0
|
||||||
|
|
Loading…
Reference in New Issue