Agent: Modify AgentEventForwarder to use IIslandAPIClient

This commit is contained in:
Ilija Lazoroski 2022-09-20 12:32:00 +02:00
parent f39007b0ce
commit b320fba2c8
2 changed files with 44 additions and 54 deletions

View File

@ -3,18 +3,15 @@ import queue
import threading
from time import sleep
import requests
from common.agent_event_serializers import AgentEventSerializerRegistry, JSONSerializable
from common.agent_events import AbstractAgentEvent
from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT
from infection_monkey.island_api_client import IIslandAPIClient
from infection_monkey.utils.threading import create_daemon_thread
logger = logging.getLogger(__name__)
DEFAULT_TIME_PERIOD_SECONDS = 5
AGENT_EVENTS_API_URL = "https://%s/api/agent-events"
class AgentEventForwarder:
@ -23,12 +20,13 @@ class AgentEventForwarder:
"""
def __init__(
self, server_address: str, agent_event_serializer_registry: AgentEventSerializerRegistry
self,
island_api_client: IIslandAPIClient,
agent_event_serializer_registry: AgentEventSerializerRegistry,
):
self._server_address = server_address
self._agent_event_serializer_registry = agent_event_serializer_registry
self._batching_agent_event_forwarder = BatchingAgentEventForwarder(self._server_address)
self._batching_agent_event_forwarder = BatchingAgentEventForwarder(island_api_client)
self._batching_agent_event_forwarder.start()
def __del__(self):
@ -37,11 +35,9 @@ class AgentEventForwarder:
def send_event(self, event: AbstractAgentEvent):
serialized_event = self._serialize_event(event)
self._batching_agent_event_forwarder.add_event_to_queue(serialized_event)
logger.debug(
f"Sending event of type {type(event).__name__} to the Island at {self._server_address}"
)
logger.debug(f"Sending event of type {type(event).__name__} to the Island")
def _serialize_event(self, event: AbstractAgentEvent):
def _serialize_event(self, event: AbstractAgentEvent) -> JSONSerializable:
serializer = self._agent_event_serializer_registry[event.__class__]
return serializer.serialize(event)
@ -51,8 +47,10 @@ class BatchingAgentEventForwarder:
Handles the batching and sending of the Agent's events to the Island
"""
def __init__(self, server_address: str, time_period: int = DEFAULT_TIME_PERIOD_SECONDS):
self._server_address = server_address
def __init__(
self, island_api_client: IIslandAPIClient, time_period: int = DEFAULT_TIME_PERIOD_SECONDS
):
self._island_api_client = island_api_client
self._time_period = time_period
self._queue: queue.Queue[AbstractAgentEvent] = queue.Queue()
@ -84,18 +82,10 @@ class BatchingAgentEventForwarder:
events.append(self._queue.get(block=False))
try:
logger.debug(f"Sending Agent events to Island at {self._server_address}: {events}")
requests.post( # noqa: DUO123
AGENT_EVENTS_API_URL % (self._server_address,),
json=events,
verify=False,
timeout=MEDIUM_REQUEST_TIMEOUT,
)
except Exception as exc:
logger.warning(
f"Exception caught when connecting to the Island at {self._server_address}"
f": {exc}"
)
logger.debug(f"Sending Agent events to Island: {events}")
self._island_api_client.send_events(events)
except Exception as err:
logger.warning(f"Exception caught when connecting to the Island: {err}")
def _send_remaining_events(self):
self._send_events_to_island()

View File

@ -1,16 +1,22 @@
import time
from unittest.mock import MagicMock
import pytest
import requests_mock
from infection_monkey.agent_event_forwarder import AGENT_EVENTS_API_URL, BatchingAgentEventForwarder
from infection_monkey.agent_event_forwarder import BatchingAgentEventForwarder
from infection_monkey.island_api_client import IIslandAPIClient
SERVER = "1.1.1.1:9999"
@pytest.fixture
def event_sender():
return BatchingAgentEventForwarder(SERVER, time_period=0.001)
def mock_island_api_client():
return MagicMock(spec=IIslandAPIClient)
@pytest.fixture
def event_sender(mock_island_api_client):
return BatchingAgentEventForwarder(mock_island_api_client, time_period=0.001)
# NOTE: If these tests are too slow or end up being racey, we can redesign AgentEventForwarder to
@ -18,35 +24,29 @@ def event_sender():
# BatchingAgentEventForwarder would have unit tests, but AgentEventForwarder would not.
def test_send_events(event_sender):
with requests_mock.Mocker() as mock:
mock.post(AGENT_EVENTS_API_URL % SERVER)
event_sender.start()
for _ in range(5):
event_sender.add_event_to_queue({})
time.sleep(0.02)
assert mock.call_count == 1
def test_send_events(event_sender, mock_island_api_client):
event_sender.start()
for _ in range(5):
event_sender.add_event_to_queue({})
time.sleep(0.02)
assert mock.call_count == 2
time.sleep(0.05)
assert mock_island_api_client.send_events.call_count == 1
event_sender.stop()
event_sender.add_event_to_queue({})
time.sleep(0.05)
assert mock_island_api_client.send_events.call_count == 2
event_sender.stop()
def test_send_remaining_events(event_sender):
with requests_mock.Mocker() as mock:
mock.post(AGENT_EVENTS_API_URL % SERVER)
event_sender.start()
for _ in range(5):
event_sender.add_event_to_queue({})
time.sleep(0.02)
assert mock.call_count == 1
def test_send_remaining_events(event_sender, mock_island_api_client):
event_sender.start()
for _ in range(5):
event_sender.add_event_to_queue({})
event_sender.stop()
assert mock.call_count == 2
time.sleep(0.05)
assert mock_island_api_client.send_events.call_count == 1
event_sender.add_event_to_queue({})
event_sender.stop()
assert mock_island_api_client.send_events.call_count == 2