Merge branch '2293-rename-event-serializers' into develop

PR #2300
This commit is contained in:
Mike Salvatore 2022-09-16 09:41:37 -04:00
commit 4e1ca659a9
47 changed files with 276 additions and 263 deletions

View File

@ -20,7 +20,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- `/api/clear-simulation-data` endpoint. #2036
- `/api/registration-status` endpoint. #2149
- authentication to `/api/island/version`. #2109
- `/api/events` endpoint. #2155
- `/api/agent-events` endpoint. #2155, #2300
- The ability to customize the file extension used by ransomware when
encrypting files. #1242
- `/api/agents` endpoint.

View File

@ -0,0 +1,5 @@
from .consts import EVENT_TYPE_FIELD
from .i_agent_event_serializer import IAgentEventSerializer, JSONSerializable
from .agent_event_serializer_registry import AgentEventSerializerRegistry
from .pydantic_agent_event_serializer import PydanticAgentEventSerializer
from .register import register_common_agent_event_serializers

View File

@ -1,15 +1,15 @@
from typing import Type, Union
from common.event_serializers import IEventSerializer
from common.events import AbstractAgentEvent
from common.agent_event_serializers import IAgentEventSerializer
from common.agent_events import AbstractAgentEvent
class EventSerializerRegistry:
class AgentEventSerializerRegistry:
"""
Registry for event serializers using event class.
Example:
event_serializer_registry = EventSerializerRegistry()
event_serializer_registry = AgentEventSerializerRegistry()
event_serializer_registry[MyEvent] = MyEventSerializer()
my_event_dict = {"type": "MyEvent", "data": "123"}
@ -22,18 +22,20 @@ class EventSerializerRegistry:
self._registry = {}
def __setitem__(
self, event_class: Type[AbstractAgentEvent], event_serializer: IEventSerializer
self, event_class: Type[AbstractAgentEvent], event_serializer: IAgentEventSerializer
):
if not issubclass(event_class, AbstractAgentEvent):
raise TypeError(f"Event class must be of type: {AbstractAgentEvent.__name__}")
if not isinstance(event_serializer, IEventSerializer):
raise TypeError(f"Event serializer must be of type: {IEventSerializer.__name__}")
if not isinstance(event_serializer, IAgentEventSerializer):
raise TypeError(f"Event serializer must be of type: {IAgentEventSerializer.__name__}")
self._registry[event_class] = event_serializer
self._registry[event_class.__name__] = event_serializer
def __getitem__(self, event_class: Union[str, Type[AbstractAgentEvent]]) -> IEventSerializer:
def __getitem__(
self, event_class: Union[str, Type[AbstractAgentEvent]]
) -> IAgentEventSerializer:
if not (isinstance(event_class, str) or issubclass(event_class, AbstractAgentEvent)):
raise TypeError(
f"Registry get key {event_class} must be of type: {AbstractAgentEvent.__name__} or "

View File

@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import Dict, List, Union
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
JSONSerializable = Union[ # type: ignore[misc]
Dict[str, "JSONSerializable"], # type: ignore[misc]
@ -14,7 +14,7 @@ JSONSerializable = Union[ # type: ignore[misc]
]
class IEventSerializer(ABC):
class IAgentEventSerializer(ABC):
"""
Manages serialization and deserialization of events
"""

View File

@ -1,17 +1,17 @@
import logging
from typing import Generic, Type, TypeVar
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
from common.utils.code_utils import del_key
from . import EVENT_TYPE_FIELD, IEventSerializer, JSONSerializable
from . import EVENT_TYPE_FIELD, IAgentEventSerializer, JSONSerializable
logger = logging.getLogger(__name__)
T = TypeVar("T", bound=AbstractAgentEvent)
class PydanticEventSerializer(IEventSerializer, Generic[T]):
class PydanticAgentEventSerializer(IAgentEventSerializer, Generic[T]):
def __init__(self, event_class: Type[T]):
self._event_class = event_class

View File

@ -0,0 +1,11 @@
from common.agent_events import CredentialsStolenEvent
from . import AgentEventSerializerRegistry, PydanticAgentEventSerializer
def register_common_agent_event_serializers(
event_serializer_registry: AgentEventSerializerRegistry,
):
event_serializer_registry[CredentialsStolenEvent] = PydanticAgentEventSerializer(
CredentialsStolenEvent
)

View File

@ -1,7 +1,7 @@
from abc import ABC, abstractmethod
from typing import Type
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
from . import AgentEventSubscriber

View File

@ -3,8 +3,8 @@ from typing import Type
from pubsub.core import Publisher
from common.agent_events import AbstractAgentEvent
from common.event_queue import PyPubSubPublisherWrapper
from common.events import AbstractAgentEvent
from . import AgentEventSubscriber, IAgentEventQueue

View File

@ -1,5 +1,5 @@
from typing import Callable
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
AgentEventSubscriber = Callable[[AbstractAgentEvent], None]

View File

@ -1,5 +0,0 @@
from .consts import EVENT_TYPE_FIELD
from .i_event_serializer import IEventSerializer, JSONSerializable
from .event_serializer_registry import EventSerializerRegistry
from .pydantic_event_serializer import PydanticEventSerializer
from .register import register_common_agent_event_serializers

View File

@ -1,9 +0,0 @@
from common.events import CredentialsStolenEvent
from . import EventSerializerRegistry, PydanticEventSerializer
def register_common_agent_event_serializers(event_serializer_registry: EventSerializerRegistry):
event_serializer_registry[CredentialsStolenEvent] = PydanticEventSerializer(
CredentialsStolenEvent
)

View File

@ -5,17 +5,16 @@ 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 common.event_serializers import EventSerializerRegistry
from common.event_serializers.i_event_serializer import JSONSerializable
from common.events import AbstractAgentEvent
from infection_monkey.utils.threading import create_daemon_thread
logger = logging.getLogger(__name__)
DEFAULT_TIME_PERIOD_SECONDS = 5
EVENTS_API_URL = "https://%s/api/events"
AGENT_EVENTS_API_URL = "https://%s/api/agent-events"
class AgentEventForwarder:
@ -24,7 +23,7 @@ class AgentEventForwarder:
"""
def __init__(
self, server_address: str, agent_event_serializer_registry: EventSerializerRegistry
self, server_address: str, agent_event_serializer_registry: AgentEventSerializerRegistry
):
self._server_address = server_address
self._agent_event_serializer_registry = agent_event_serializer_registry
@ -85,9 +84,9 @@ class BatchingAgentEventForwarder:
events.append(self._queue.get(block=False))
try:
logger.debug(f"Sending events to Island at {self._server_address}: {events}")
logger.debug(f"Sending Agent events to Island at {self._server_address}: {events}")
requests.post( # noqa: DUO123
EVENTS_API_URL % (self._server_address,),
AGENT_EVENTS_API_URL % (self._server_address,),
json=events,
verify=False,
timeout=MEDIUM_REQUEST_TIMEOUT,

View File

@ -1,9 +1,9 @@
import logging
from typing import Sequence
from common.agent_events import CredentialsStolenEvent
from common.credentials import Credentials, LMHash, NTHash, Password, Username
from common.event_queue import IAgentEventQueue
from common.events import CredentialsStolenEvent
from infection_monkey.i_puppet import ICredentialCollector
from infection_monkey.model import USERNAME_PREFIX
from infection_monkey.utils.ids import get_agent_id

View File

@ -3,9 +3,9 @@ import logging
import os
from typing import Dict, Iterable, Sequence
from common.agent_events import CredentialsStolenEvent
from common.credentials import Credentials, SSHKeypair, Username
from common.event_queue import IAgentEventQueue
from common.events import CredentialsStolenEvent
from common.utils.attack_utils import ScanStatus
from infection_monkey.telemetry.attack.t1005_telem import T1005Telem
from infection_monkey.telemetry.attack.t1145_telem import T1145Telem

View File

@ -1,6 +1,6 @@
import logging
from common.events import CredentialsStolenEvent
from common.agent_events import CredentialsStolenEvent
from . import IPropagationCredentialsRepository

View File

@ -15,9 +15,9 @@ import impacket
from impacket.dcerpc.v5 import epm, nrpc, rpcrt, transport
from impacket.dcerpc.v5.dtypes import NULL
from common.agent_events import CredentialsStolenEvent
from common.common_consts.timeouts import LONG_REQUEST_TIMEOUT
from common.credentials import Credentials, LMHash, NTHash, Username
from common.events import CredentialsStolenEvent
from infection_monkey.exploit.HostExploiter import HostExploiter
from infection_monkey.exploit.tools.wmi_tools import WmiTools
from infection_monkey.exploit.zerologon_utils.dump_secrets import DumpSecrets

View File

@ -9,12 +9,12 @@ from typing import List
from pubsub.core import Publisher
from common.event_queue import IAgentEventQueue, PyPubSubAgentEventQueue
from common.event_serializers import (
EventSerializerRegistry,
from common.agent_event_serializers import (
AgentEventSerializerRegistry,
register_common_agent_event_serializers,
)
from common.events import CredentialsStolenEvent
from common.agent_events import CredentialsStolenEvent
from common.event_queue import IAgentEventQueue, PyPubSubAgentEventQueue
from common.network.network_utils import (
address_to_ip_port,
get_my_ip_addresses,
@ -217,8 +217,8 @@ class InfectionMonkey:
register_signal_handlers(self._master)
# TODO: This is just a placeholder for now. We will modify/integrate it with PR #2279.
def _setup_agent_event_serializers(self) -> EventSerializerRegistry:
agent_event_serializer_registry = EventSerializerRegistry()
def _setup_agent_event_serializers(self) -> AgentEventSerializerRegistry:
agent_event_serializer_registry = AgentEventSerializerRegistry()
register_common_agent_event_serializers(agent_event_serializer_registry)
return agent_event_serializer_registry
@ -263,7 +263,7 @@ class InfectionMonkey:
event_queue: IAgentEventQueue,
propagation_credentials_repository: IPropagationCredentialsRepository,
server_address: str,
agent_event_serializer_registry: EventSerializerRegistry,
agent_event_serializer_registry: AgentEventSerializerRegistry,
):
event_queue.subscribe_type(
CredentialsStolenEvent,

View File

@ -1,13 +1,13 @@
import logging
from common.events import AbstractAgentEvent
from monkey_island.cc.repository import IEventRepository, StorageError
from common.agent_events import AbstractAgentEvent
from monkey_island.cc.repository import IAgentEventRepository, StorageError
logger = logging.getLogger(__name__)
class save_event_to_event_repository:
def __init__(self, event_repository: IEventRepository):
def __init__(self, event_repository: IAgentEventRepository):
self._event_repository = event_repository
def __call__(self, event: AbstractAgentEvent):

View File

@ -1,6 +1,6 @@
import logging
from common.events import CredentialsStolenEvent
from common.agent_events import CredentialsStolenEvent
from monkey_island.cc.repository import ICredentialsRepository, StorageError
logger = logging.getLogger(__name__)

View File

@ -13,9 +13,9 @@ from monkey_island.cc.database import database, mongo
from monkey_island.cc.resources import (
AgentBinaries,
AgentConfiguration,
AgentEvents,
Agents,
ClearSimulationData,
Events,
IPAddresses,
IslandLog,
PBAFileDownload,
@ -187,7 +187,7 @@ def init_restful_endpoints(api: FlaskDIWrapper):
api.add_resource(IslandLog)
api.add_resource(IPAddresses)
api.add_resource(Events)
api.add_resource(AgentEvents)
# API Spec: These two should be the same resource, GET for download and POST for upload
api.add_resource(PBAFileDownload)

View File

@ -10,7 +10,7 @@ from .i_user_repository import IUserRepository
from .i_machine_repository import IMachineRepository
from .i_agent_repository import IAgentRepository
from .i_node_repository import INodeRepository
from .i_event_repository import IEventRepository
from .i_agent_event_repository import IAgentEventRepository
from .local_storage_file_repository import LocalStorageFileRepository

View File

@ -1,13 +1,13 @@
from abc import ABC, abstractmethod
from typing import Sequence, Type, TypeVar
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
from common.types import AgentID
T = TypeVar("T", bound=AbstractAgentEvent)
class IEventRepository(ABC):
class IAgentEventRepository(ABC):
"""A repository used to store and retrieve event objects"""
@abstractmethod

View File

@ -2,19 +2,21 @@ from typing import Any, Dict, MutableMapping, Sequence, Type
from pymongo import MongoClient
from common.event_serializers import EVENT_TYPE_FIELD, EventSerializerRegistry
from common.events import AbstractAgentEvent
from common.agent_event_serializers import EVENT_TYPE_FIELD, AgentEventSerializerRegistry
from common.agent_events import AbstractAgentEvent
from common.types import AgentID
from monkey_island.cc.repository import IEventRepository
from monkey_island.cc.repository import IAgentEventRepository
from . import RemovalError, RetrievalError, StorageError
from .consts import MONGO_OBJECT_ID_KEY
class MongoEventRepository(IEventRepository):
class MongoEventRepository(IAgentEventRepository):
"""A repository for storing and retrieving events in MongoDB"""
def __init__(self, mongo_client: MongoClient, serializer_registry: EventSerializerRegistry):
def __init__(
self, mongo_client: MongoClient, serializer_registry: AgentEventSerializerRegistry
):
self._events_collection = mongo_client.monkey_island.events
self._serializers = serializer_registry

View File

@ -1,15 +1,15 @@
from typing import Sequence, Type, TypeVar
from common.events import AbstractAgentEvent
from common.agent_events import AbstractAgentEvent
from common.types import AgentID
from . import IEventRepository
from . import IAgentEventRepository
T = TypeVar("T", bound=AbstractAgentEvent)
# TODO: Remove this class after #2180 is complete
class StubbedEventRepository(IEventRepository):
class StubbedEventRepository(IAgentEventRepository):
def save_event(self, event: AbstractAgentEvent):
return

View File

@ -4,7 +4,7 @@ from typing import Optional, Sequence
from monkey_island.cc.models.zero_trust.event import Event
class IEventRepository(ABC):
class IAgentEventRepository(ABC):
def get_events(self, finding_id: Optional[str] = None) -> Sequence[Event]:
pass

View File

@ -8,5 +8,5 @@ from .ip_addresses import IPAddresses
from .agent_configuration import AgentConfiguration
from .pba_file_upload import PBAFileUpload, LINUX_PBA_TYPE, WINDOWS_PBA_TYPE
from .pba_file_download import PBAFileDownload
from .events import Events
from .agent_events import AgentEvents
from .agents import Agents

View File

@ -3,20 +3,20 @@ from http import HTTPStatus
from flask import request
from common.agent_event_serializers import EVENT_TYPE_FIELD, AgentEventSerializerRegistry
from common.event_queue import IAgentEventQueue
from common.event_serializers import EVENT_TYPE_FIELD, EventSerializerRegistry
from monkey_island.cc.resources.AbstractResource import AbstractResource
logger = logging.getLogger(__name__)
class Events(AbstractResource):
urls = ["/api/events"]
class AgentEvents(AbstractResource):
urls = ["/api/agent-events"]
def __init__(
self,
agent_event_queue: IAgentEventQueue,
event_serializer_registry: EventSerializerRegistry,
event_serializer_registry: AgentEventSerializerRegistry,
):
self._agent_event_queue = agent_event_queue
self._event_serializer_registry = event_serializer_registry

View File

@ -23,8 +23,8 @@ if str(MONKEY_ISLAND_DIR_BASE_PATH) not in sys.path:
sys.path.insert(0, MONKEY_ISLAND_DIR_BASE_PATH)
from common import DIContainer # noqa: E402
from common.event_serializers import ( # noqa: E402
EventSerializerRegistry,
from common.agent_event_serializers import ( # noqa: E402
AgentEventSerializerRegistry,
register_common_agent_event_serializers,
)
from common.network.network_utils import get_my_ip_addresses # noqa: E402
@ -140,10 +140,10 @@ def _initialize_di_container(
def _setup_agent_event_serializers(container: DIContainer):
agent_event_serializer_registry = EventSerializerRegistry()
agent_event_serializer_registry = AgentEventSerializerRegistry()
register_common_agent_event_serializers(agent_event_serializer_registry)
container.register_instance(EventSerializerRegistry, agent_event_serializer_registry)
container.register_instance(AgentEventSerializerRegistry, agent_event_serializer_registry)
def _initialize_mongodb_connection(start_mongodb: bool, data_dir: Path):

View File

@ -23,8 +23,8 @@ from monkey_island.cc.repository import (
FileSimulationRepository,
IAgentBinaryRepository,
IAgentConfigurationRepository,
IAgentEventRepository,
ICredentialsRepository,
IEventRepository,
IFileRepository,
ISimulationRepository,
IUserRepository,
@ -102,7 +102,7 @@ def _register_repositories(container: DIContainer, data_dir: Path):
container.register_instance(IUserRepository, container.resolve(JSONFileUserRepository))
# TODO: Replace with MongoEventRepository
container.register_instance(IEventRepository, StubbedEventRepository())
container.register_instance(IAgentEventRepository, StubbedEventRepository())
def _decorate_file_repository(file_repository: IFileRepository) -> IFileRepository:

View File

@ -1,11 +1,11 @@
from common import DIContainer
from common.agent_events import CredentialsStolenEvent
from common.event_queue import IAgentEventQueue
from common.events import CredentialsStolenEvent
from monkey_island.cc.agent_event_handlers import (
save_event_to_event_repository,
save_stolen_credentials_to_repository,
)
from monkey_island.cc.repository import ICredentialsRepository, IEventRepository
from monkey_island.cc.repository import IAgentEventRepository, ICredentialsRepository
def setup_agent_event_handlers(container: DIContainer):
@ -15,7 +15,7 @@ def setup_agent_event_handlers(container: DIContainer):
def _subscribe_and_store_to_event_repository(container: DIContainer):
agent_event_queue = container.resolve(IAgentEventQueue)
save_event_subscriber = save_event_to_event_repository(container.resolve(IEventRepository))
save_event_subscriber = save_event_to_event_repository(container.resolve(IAgentEventRepository))
agent_event_queue.subscribe_all_events(save_event_subscriber)
save_stolen_credentials_subscriber = save_stolen_credentials_to_repository(

View File

@ -0,0 +1,68 @@
from unittest.mock import MagicMock
import pytest
from pydantic import Field
from common.agent_event_serializers import AgentEventSerializerRegistry, IAgentEventSerializer
from common.agent_events import AbstractAgentEvent
class SomeEvent(AbstractAgentEvent):
some_param: int = Field(default=435)
class OtherEvent(AbstractAgentEvent):
other_param: float = Field(default=123.456)
class NoneEvent(AbstractAgentEvent):
none_param: float = Field(default=1.0)
SOME_SERIALIZER = MagicMock(spec=IAgentEventSerializer)
OTHER_SERIALIZER = MagicMock(spec=IAgentEventSerializer)
@pytest.fixture
def agent_event_serializer_registry():
agent_event_serializer_registry = AgentEventSerializerRegistry()
agent_event_serializer_registry[SomeEvent] = SOME_SERIALIZER
agent_event_serializer_registry[OtherEvent] = OTHER_SERIALIZER
return agent_event_serializer_registry
def test_agent_event_serializer_registry_event(agent_event_serializer_registry):
assert agent_event_serializer_registry[SomeEvent] == SOME_SERIALIZER
assert agent_event_serializer_registry[OtherEvent] == OTHER_SERIALIZER
def test_agent_event_serializer_registry_string(agent_event_serializer_registry):
assert agent_event_serializer_registry[SomeEvent.__name__] == SOME_SERIALIZER
assert agent_event_serializer_registry[OtherEvent.__name__] == OTHER_SERIALIZER
def test_agent_event_serializer_registry_set_unsupported_type(agent_event_serializer_registry):
with pytest.raises(TypeError):
agent_event_serializer_registry[SomeEvent] = "SomethingBogusVogus"
def test_agent_event_serializer_registry_set_unsupported_type_key(agent_event_serializer_registry):
with pytest.raises(TypeError):
agent_event_serializer_registry["BogusKey"] = MagicMock(spec=IAgentEventSerializer)
def test_agent_event_serializer_registry_get_unsuported_type(agent_event_serializer_registry):
with pytest.raises(TypeError):
agent_event_serializer_registry[1]
def test_agent_event_serializer_registry_get_unexisting_type(agent_event_serializer_registry):
with pytest.raises(KeyError):
agent_event_serializer_registry[NoneEvent]
def test_agent_event_serializer_registry_get_unexisting_string(agent_event_serializer_registry):
with pytest.raises(KeyError):
agent_event_serializer_registry[NoneEvent.__name__]

View File

@ -0,0 +1,67 @@
from abc import ABC
from dataclasses import dataclass
from uuid import UUID
import pytest
from pydantic import Field
from common.agent_event_serializers import (
EVENT_TYPE_FIELD,
IAgentEventSerializer,
PydanticAgentEventSerializer,
)
from common.agent_events import AbstractAgentEvent
AGENT_ID = UUID("f811ad00-5a68-4437-bd51-7b5cc1768ad5")
@dataclass(frozen=True)
class NotAgentEvent(ABC):
some_field: int
other_field: float
class SomeAgentEvent(AbstractAgentEvent):
bogus: int = Field(default_factory=int)
class PydanticEvent(AbstractAgentEvent):
some_field: str
@pytest.fixture
def pydantic_agent_event_serializer() -> IAgentEventSerializer:
return PydanticAgentEventSerializer(PydanticEvent)
@pytest.mark.parametrize(
"event",
[NotAgentEvent(some_field=1, other_field=2.0), SomeAgentEvent(source=AGENT_ID, bogus=2)],
)
def test_pydantic_agent_event_serializer__serialize_wrong_type(
pydantic_agent_event_serializer, event
):
with pytest.raises(TypeError):
pydantic_agent_event_serializer.serialize(event)
def test_pydantic_agent_event_serializer__deserialize_wrong_type(pydantic_agent_event_serializer):
with pytest.raises(TypeError):
pydantic_agent_event_serializer.deserialize("bla")
def test_pydantic_agent_event_serializer__de_serialize(pydantic_agent_event_serializer):
pydantic_event = PydanticEvent(source=AGENT_ID, some_field="some_field")
serialized_event = pydantic_agent_event_serializer.serialize(pydantic_event)
deserialized_object = pydantic_agent_event_serializer.deserialize(serialized_event)
assert type(serialized_event) != type(deserialized_object)
assert deserialized_object == pydantic_event
def test_pydantic_event_serializer__serialize_inclued_type(pydantic_agent_event_serializer):
pydantic_event = PydanticEvent(source=AGENT_ID, some_field="some_field")
serialized_event = pydantic_agent_event_serializer.serialize(pydantic_event)
assert serialized_event[EVENT_TYPE_FIELD] == PydanticEvent.__name__

View File

@ -7,7 +7,7 @@ from tests.data_for_tests.propagation_credentials import (
)
from tests.unit_tests.monkey_island.cc.models.test_agent import AGENT_ID
from common.events import CredentialsStolenEvent
from common.agent_events import CredentialsStolenEvent
TEST_EVENT = CredentialsStolenEvent(stolen_credentials=CREDENTIALS, source=AGENT_ID)

View File

@ -5,8 +5,8 @@ from uuid import UUID
import pytest
from pubsub.core import Publisher
from common.agent_events import AbstractAgentEvent
from common.event_queue import AgentEventSubscriber, IAgentEventQueue, PyPubSubAgentEventQueue
from common.events import AbstractAgentEvent
EVENT_TAG_1 = "event tag 1"
EVENT_TAG_2 = "event tag 2"

View File

@ -1,68 +0,0 @@
from unittest.mock import MagicMock
import pytest
from pydantic import Field
from common.event_serializers import EventSerializerRegistry, IEventSerializer
from common.events import AbstractAgentEvent
class SomeEvent(AbstractAgentEvent):
some_param: int = Field(default=435)
class OtherEvent(AbstractAgentEvent):
other_param: float = Field(default=123.456)
class NoneEvent(AbstractAgentEvent):
none_param: float = Field(default=1.0)
SOME_SERIALIZER = MagicMock(spec=IEventSerializer)
OTHER_SERIALIZER = MagicMock(spec=IEventSerializer)
@pytest.fixture
def event_serializer_registry():
event_serializer_registry = EventSerializerRegistry()
event_serializer_registry[SomeEvent] = SOME_SERIALIZER
event_serializer_registry[OtherEvent] = OTHER_SERIALIZER
return event_serializer_registry
def test_event_serializer_registry_event(event_serializer_registry):
assert event_serializer_registry[SomeEvent] == SOME_SERIALIZER
assert event_serializer_registry[OtherEvent] == OTHER_SERIALIZER
def test_event_serializer_registry_string(event_serializer_registry):
assert event_serializer_registry[SomeEvent.__name__] == SOME_SERIALIZER
assert event_serializer_registry[OtherEvent.__name__] == OTHER_SERIALIZER
def test_event_serializer_registry_set_unsupported_type(event_serializer_registry):
with pytest.raises(TypeError):
event_serializer_registry[SomeEvent] = "SomethingBogusVogus"
def test_event_serializer_registry_set_unsupported_type_key(event_serializer_registry):
with pytest.raises(TypeError):
event_serializer_registry["BogusKey"] = MagicMock(spec=IEventSerializer)
def test_event_serializer_registry_get_unsuported_type(event_serializer_registry):
with pytest.raises(TypeError):
event_serializer_registry[1]
def test_event_serializer_registry_get_unexisting_type(event_serializer_registry):
with pytest.raises(KeyError):
event_serializer_registry[NoneEvent]
def test_event_serializer_registry_get_unexisting_string(event_serializer_registry):
with pytest.raises(KeyError):
event_serializer_registry[NoneEvent.__name__]

View File

@ -1,61 +0,0 @@
from abc import ABC
from dataclasses import dataclass
from uuid import UUID
import pytest
from pydantic import Field
from common.event_serializers import EVENT_TYPE_FIELD, IEventSerializer, PydanticEventSerializer
from common.events import AbstractAgentEvent
AGENT_ID = UUID("f811ad00-5a68-4437-bd51-7b5cc1768ad5")
@dataclass(frozen=True)
class NotAgentEvent(ABC):
some_field: int
other_field: float
class SomeAgentEvent(AbstractAgentEvent):
bogus: int = Field(default_factory=int)
class PydanticEvent(AbstractAgentEvent):
some_field: str
@pytest.fixture
def pydantic_event_serializer() -> IEventSerializer:
return PydanticEventSerializer(PydanticEvent)
@pytest.mark.parametrize(
"event",
[NotAgentEvent(some_field=1, other_field=2.0), SomeAgentEvent(source=AGENT_ID, bogus=2)],
)
def test_pydantic_event_serializer__serialize_wrong_type(pydantic_event_serializer, event):
with pytest.raises(TypeError):
pydantic_event_serializer.serialize(event)
def test_pydantic_event_serializer__deserialize_wrong_type(pydantic_event_serializer):
with pytest.raises(TypeError):
pydantic_event_serializer.deserialize("bla")
def test_pydanitc_event_serializer__de_serialize(pydantic_event_serializer):
pydantic_event = PydanticEvent(source=AGENT_ID, some_field="some_field")
serialized_event = pydantic_event_serializer.serialize(pydantic_event)
deserialized_object = pydantic_event_serializer.deserialize(serialized_event)
assert type(serialized_event) != type(deserialized_object)
assert deserialized_object == pydantic_event
def test_pydanitc_event_serializer__serialize_inclued_type(pydantic_event_serializer):
pydantic_event = PydanticEvent(source=AGENT_ID, some_field="some_field")
serialized_event = pydantic_event_serializer.serialize(pydantic_event)
assert serialized_event[EVENT_TYPE_FIELD] == PydanticEvent.__name__

View File

@ -3,9 +3,9 @@ from unittest.mock import MagicMock
import pytest
from common.agent_events import CredentialsStolenEvent
from common.credentials import Credentials, LMHash, NTHash, Password, Username
from common.event_queue import IAgentEventQueue
from common.events import CredentialsStolenEvent
from infection_monkey.credential_collectors import MimikatzCredentialCollector
from infection_monkey.credential_collectors.mimikatz_collector.mimikatz_credential_collector import ( # noqa: E501
MIMIKATZ_EVENT_TAGS,

View File

@ -1,8 +1,8 @@
from unittest.mock import MagicMock
from uuid import UUID
from common.agent_events import CredentialsStolenEvent
from common.credentials import Credentials, Password, Username
from common.events import CredentialsStolenEvent
from infection_monkey.credential_repository import (
IPropagationCredentialsRepository,
add_credentials_from_event_to_propagation_credentials_repository,

View File

@ -3,7 +3,7 @@ import time
import pytest
import requests_mock
from infection_monkey.agent_event_forwarder import EVENTS_API_URL, BatchingAgentEventForwarder
from infection_monkey.agent_event_forwarder import AGENT_EVENTS_API_URL, BatchingAgentEventForwarder
SERVER = "1.1.1.1:9999"
@ -20,7 +20,7 @@ def event_sender():
def test_send_events(event_sender):
with requests_mock.Mocker() as mock:
mock.post(EVENTS_API_URL % SERVER)
mock.post(AGENT_EVENTS_API_URL % SERVER)
event_sender.start()
@ -38,7 +38,7 @@ def test_send_events(event_sender):
def test_send_remaining_events(event_sender):
with requests_mock.Mocker() as mock:
mock.post(EVENTS_API_URL % SERVER)
mock.post(AGENT_EVENTS_API_URL % SERVER)
event_sender.start()

View File

@ -6,10 +6,13 @@ import mongomock
import pytest
from pydantic import Field
from common.event_serializers import EventSerializerRegistry, PydanticEventSerializer
from common.events import AbstractAgentEvent
from common.agent_event_serializers import (
AgentEventSerializerRegistry,
PydanticAgentEventSerializer,
)
from common.agent_events import AbstractAgentEvent
from monkey_island.cc.repository import (
IEventRepository,
IAgentEventRepository,
MongoEventRepository,
RemovalError,
RetrievalError,
@ -34,10 +37,10 @@ EVENTS: List[AbstractAgentEvent] = [
@pytest.fixture
def event_serializer_registry() -> EventSerializerRegistry:
registry = EventSerializerRegistry()
registry[FakeAgentEvent] = PydanticEventSerializer(FakeAgentEvent)
registry[FakeAgentItemEvent] = PydanticEventSerializer(FakeAgentItemEvent)
def event_serializer_registry() -> AgentEventSerializerRegistry:
registry = AgentEventSerializerRegistry()
registry[FakeAgentEvent] = PydanticAgentEventSerializer(FakeAgentEvent)
registry[FakeAgentItemEvent] = PydanticAgentEventSerializer(FakeAgentItemEvent)
return registry
@ -51,7 +54,7 @@ def mongo_client(event_serializer_registry):
@pytest.fixture
def mongo_repository(mongo_client, event_serializer_registry) -> IEventRepository:
def mongo_repository(mongo_client, event_serializer_registry) -> IAgentEventRepository:
return MongoEventRepository(mongo_client, event_serializer_registry)
@ -73,7 +76,7 @@ def error_raising_mongo_client(mongo_client) -> mongomock.MongoClient:
@pytest.fixture
def error_raising_mongo_repository(
error_raising_mongo_client, event_serializer_registry
) -> IEventRepository:
) -> IAgentEventRepository:
return MongoEventRepository(error_raising_mongo_client, event_serializer_registry)
@ -83,7 +86,7 @@ def assert_same_contents(a, b):
assert item in b
def test_mongo_event_repository__save_event(mongo_repository: IEventRepository):
def test_mongo_event_repository__save_event(mongo_repository: IAgentEventRepository):
event = FakeAgentEvent(source=uuid.uuid4())
mongo_repository.save_event(event)
events = mongo_repository.get_events()
@ -92,7 +95,7 @@ def test_mongo_event_repository__save_event(mongo_repository: IEventRepository):
def test_mongo_event_repository__save_event_raises(
error_raising_mongo_repository: IEventRepository,
error_raising_mongo_repository: IAgentEventRepository,
):
event = FakeAgentEvent(source=uuid.uuid4())
@ -100,20 +103,20 @@ def test_mongo_event_repository__save_event_raises(
error_raising_mongo_repository.save_event(event)
def test_mongo_event_repository__get_events(mongo_repository: IEventRepository):
def test_mongo_event_repository__get_events(mongo_repository: IAgentEventRepository):
events = mongo_repository.get_events()
assert_same_contents(events, EVENTS)
def test_mongo_event_repository__get_events_raises(
error_raising_mongo_repository: IEventRepository,
error_raising_mongo_repository: IAgentEventRepository,
):
with pytest.raises(RetrievalError):
error_raising_mongo_repository.get_events()
def test_mongo_event_repository__get_events_by_type(mongo_repository: IEventRepository):
def test_mongo_event_repository__get_events_by_type(mongo_repository: IAgentEventRepository):
events = mongo_repository.get_events_by_type(FakeAgentItemEvent)
expected_events = [EVENTS[3]]
@ -121,13 +124,13 @@ def test_mongo_event_repository__get_events_by_type(mongo_repository: IEventRepo
def test_mongo_event_repository__get_events_by_type_raises(
error_raising_mongo_repository: IEventRepository,
error_raising_mongo_repository: IAgentEventRepository,
):
with pytest.raises(RetrievalError):
error_raising_mongo_repository.get_events_by_type(FakeAgentItemEvent)
def test_mongo_event_repository__get_events_by_tag(mongo_repository: IEventRepository):
def test_mongo_event_repository__get_events_by_tag(mongo_repository: IAgentEventRepository):
events = mongo_repository.get_events_by_tag("bar")
expected_events = [EVENTS[1], EVENTS[2]]
@ -135,13 +138,13 @@ def test_mongo_event_repository__get_events_by_tag(mongo_repository: IEventRepos
def test_mongo_event_repository__get_events_by_tag_raises(
error_raising_mongo_repository: IEventRepository,
error_raising_mongo_repository: IAgentEventRepository,
):
with pytest.raises(RetrievalError):
error_raising_mongo_repository.get_events_by_tag("bar")
def test_mongo_event_repository__get_events_by_source(mongo_repository: IEventRepository):
def test_mongo_event_repository__get_events_by_source(mongo_repository: IAgentEventRepository):
source_event = EVENTS[2]
events = mongo_repository.get_events_by_source(source_event.source)
@ -150,14 +153,14 @@ def test_mongo_event_repository__get_events_by_source(mongo_repository: IEventRe
def test_mongo_event_repository__get_events_by_source_raises(
error_raising_mongo_repository: IEventRepository,
error_raising_mongo_repository: IAgentEventRepository,
):
with pytest.raises(RetrievalError):
source_event = EVENTS[2]
error_raising_mongo_repository.get_events_by_source(source_event.source)
def test_mongo_event_repository__reset(mongo_repository: IEventRepository):
def test_mongo_event_repository__reset(mongo_repository: IAgentEventRepository):
initial_events = mongo_repository.get_events()
assert initial_events
@ -167,6 +170,8 @@ def test_mongo_event_repository__reset(mongo_repository: IEventRepository):
assert not events
def test_mongo_event_repository__reset_raises(error_raising_mongo_repository: IEventRepository):
def test_mongo_event_repository__reset_raises(
error_raising_mongo_repository: IAgentEventRepository,
):
with pytest.raises(RemovalError):
error_raising_mongo_repository.reset()

View File

@ -5,12 +5,15 @@ from uuid import UUID
import pytest
from tests.common import StubDIContainer
from common.agent_event_serializers import (
AgentEventSerializerRegistry,
PydanticAgentEventSerializer,
)
from common.agent_events import AbstractAgentEvent
from common.event_queue import IAgentEventQueue
from common.event_serializers import EventSerializerRegistry, PydanticEventSerializer
from common.events import AbstractAgentEvent
from monkey_island.cc.resources import Events
from monkey_island.cc.resources import AgentEvents
EVENTS_URL = Events.urls[0]
EVENTS_URL = AgentEvents.urls[0]
class SomeAgentEvent(AbstractAgentEvent):
@ -88,11 +91,13 @@ def mock_agent_event_queue():
@pytest.fixture
def event_serializer_registry() -> EventSerializerRegistry:
event_serializer_registry = EventSerializerRegistry()
event_serializer_registry[SomeAgentEvent] = PydanticEventSerializer(SomeAgentEvent)
event_serializer_registry[OtherAgentEvent] = PydanticEventSerializer(OtherAgentEvent)
event_serializer_registry[DifferentAgentEvent] = PydanticEventSerializer(DifferentAgentEvent)
def event_serializer_registry() -> AgentEventSerializerRegistry:
event_serializer_registry = AgentEventSerializerRegistry()
event_serializer_registry[SomeAgentEvent] = PydanticAgentEventSerializer(SomeAgentEvent)
event_serializer_registry[OtherAgentEvent] = PydanticAgentEventSerializer(OtherAgentEvent)
event_serializer_registry[DifferentAgentEvent] = PydanticAgentEventSerializer(
DifferentAgentEvent
)
return event_serializer_registry
@ -102,7 +107,7 @@ def flask_client(build_flask_client, mock_agent_event_queue, event_serializer_re
container = StubDIContainer()
container.register_instance(IAgentEventQueue, mock_agent_event_queue)
container.register_instance(EventSerializerRegistry, event_serializer_registry)
container.register_instance(AgentEventSerializerRegistry, event_serializer_registry)
with build_flask_client(container) as flask_client:
yield flask_client

View File

@ -18,16 +18,16 @@ from monkey_island.cc.repository import (
StubbedEventRepository,
)
from monkey_island.cc.repository.attack.IMitigationsRepository import IMitigationsRepository
from monkey_island.cc.repository.i_agent_event_repository import IAgentEventRepository
from monkey_island.cc.repository.i_agent_repository import IAgentRepository
from monkey_island.cc.repository.i_attack_repository import IAttackRepository
from monkey_island.cc.repository.i_config_repository import IConfigRepository
from monkey_island.cc.repository.i_event_repository import IEventRepository
from monkey_island.cc.repository.i_log_repository import ILogRepository
from monkey_island.cc.repository.i_machine_repository import IMachineRepository
from monkey_island.cc.repository.i_report_repository import IReportRepository
from monkey_island.cc.repository.i_simulation_repository import ISimulationRepository
from monkey_island.cc.repository.ICredentials import ICredentialsRepository
from monkey_island.cc.repository.zero_trust.IEventRepository import IEventRepository
from monkey_island.cc.repository.zero_trust.IAgentEventRepository import IAgentEventRepository
from monkey_island.cc.repository.zero_trust.IFindingRepository import IFindingRepository
fake_monkey_dir_path # unused variable (monkey/tests/infection_monkey/post_breach/actions/test_users_custom_pba.py:37)
@ -279,7 +279,7 @@ ICredentialsRepository.remove_configured_credentials
ICredentialsRepository.remove_all_credentials
ICredentialsRepository.save_stolen_credentials
ICredentialsRepository.save_configured_credentials
IEventRepository.get_events
IAgentEventRepository.get_events
IFindingRepository.get_findings
MongoAgentRepository
MongoMachineRepository
@ -299,19 +299,11 @@ publish # common\event_queue\pypubsub_agent_event_queue.py
subscribe_all_events # common\event_queue\pypubsub_agent_event_queue.py
# TODO: Remove once #2179 is closed
EventSerializerRegistry
serialize
event
deserialize
serialized_event
PydanticEventSerializer
# TODO: Remove once #2180 is closed
IEventRepository.save_event
IEventRepository.get_events_by_type
IEventRepository.get_events_by_tag
IEventRepository.get_events_by_source
IAgentEventRepository.save_event
IAgentEventRepository.get_events_by_type
IAgentEventRepository.get_events_by_tag
IAgentEventRepository.get_events_by_source
MongoEventRepository