Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3411 define events #3560

Merged
merged 3 commits into from
Aug 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- Ability to filter Agent events by tag. #3396
- Provide a server to the plugins that can be used to serve agent binaries to
the exploited machine over HTTP. #3410
- CPUConsumptionEvent. #3411
- RAMConsumptionEvent. #3411
- HTTPRequestEvent. #3411

### Changed
- Plugin source is now gzipped. #3392
Expand Down
3 changes: 3 additions & 0 deletions monkey/common/agent_events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@
from .os_discovery_event import OSDiscoveryEvent
from .hostname_discovery_event import HostnameDiscoveryEvent
from .register import register_common_agent_events
from .cpu_consumption_event import CPUConsumptionEvent
from .ram_consumption_event import RAMConsumptionEvent
from .http_request_event import HTTPRequestEvent
18 changes: 18 additions & 0 deletions monkey/common/agent_events/cpu_consumption_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pydantic import conint

from common.types import Percent

from . import AbstractAgentEvent


class CPUConsumptionEvent(AbstractAgentEvent):
"""
An event that occurs when the Agent consumes significant CPU resources for its own purposes.

Attributes:
:param utilization: The percentage of the CPU that is utilized
:param cpu_number: The number of the CPU core that is utilized
"""

utilization: Percent
cpu_number: conint(ge=0, strict=True) # type: ignore [valid-type]
18 changes: 18 additions & 0 deletions monkey/common/agent_events/http_request_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from http import HTTPMethod

from pydantic import AnyHttpUrl

from . import AbstractAgentEvent


class HTTPRequestEvent(AbstractAgentEvent):
"""
An event that occurs when the Agent sends an HTTP request to any server other than the Island.

Attributes:
:param method: The HTTP method used to make the request
:param url: The URL to which the request was sent
"""

method: HTTPMethod
url: AnyHttpUrl
18 changes: 18 additions & 0 deletions monkey/common/agent_events/ram_consumption_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from pydantic import conint

from common.types import Percent

from . import AbstractAgentEvent


class RAMConsumptionEvent(AbstractAgentEvent):
"""
An event that occurs when the Agent consumes significant RAM for its own purposes.

Attributes:
:param utilization: The percentage of the RAM is utilized
:param bytes: The number of bytes of RAM that are utilized
"""

utilization: Percent
bytes: conint(ge=0, strict=True) # type: ignore [valid-type]
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from uuid import UUID

import pytest

from common.agent_events import CPUConsumptionEvent

AGENT_ID = UUID("012e7238-7b81-4108-8c7f-0787bc3f3c10")
TIMESTAMP = 1664371327.4067292
UTILIZATION = 77
CPU_NUMBER = 3


def test_constructor():
event = CPUConsumptionEvent(
source=AGENT_ID, timestamp=TIMESTAMP, utilization=UTILIZATION, cpu_number=CPU_NUMBER
)

assert event.source == AGENT_ID
assert event.timestamp == TIMESTAMP
assert event.target is None
assert len(event.tags) == 0
assert event.utilization == UTILIZATION
assert event.cpu_number == CPU_NUMBER


@pytest.mark.parametrize("invalid_utilization", ("not-an-int", -1, -5.0, None))
def test_invalid_utilization(invalid_utilization):
with pytest.raises((ValueError, TypeError)):
CPUConsumptionEvent(
source=AGENT_ID,
timestamp=TIMESTAMP,
utilization=invalid_utilization,
cpu_number=CPU_NUMBER,
)


@pytest.mark.parametrize("invalid_cpu_number", ("not-an-int", -1, 5.2, None))
def test_invalid_cpu_number(invalid_cpu_number):
with pytest.raises((ValueError, TypeError)):
CPUConsumptionEvent(
source=AGENT_ID,
timestamp=TIMESTAMP,
utilization=UTILIZATION,
cpu_number=invalid_cpu_number,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from http import HTTPMethod
from uuid import UUID

import pytest

from common.agent_events import HTTPRequestEvent

AGENT_ID = UUID("012e7238-7b81-4108-8c7f-0787bc3f3c10")
TIMESTAMP = 1664371327.4067292
HTTP_URL = "http://www.test.org/RESTFUL/test?filter=my_filter"
HTTPS_URL = "https://www.test.org/RESTFUL/test?filter=my_filter"
METHOD = HTTPMethod.GET


@pytest.mark.parametrize("url", (HTTP_URL, HTTPS_URL))
def test_constructor(url: str):
event = HTTPRequestEvent(source=AGENT_ID, timestamp=TIMESTAMP, method=METHOD, url=url)

assert event.source == AGENT_ID
assert event.timestamp == TIMESTAMP
assert event.target is None
assert len(event.tags) == 0
assert event.method == METHOD
assert event.url == url


@pytest.mark.parametrize(
"invalid_url", ("www.missing-schema.org", -1, None, "ftp://wrong.schema.org")
)
def test_invalid_url(invalid_url):
with pytest.raises((ValueError, TypeError)):
HTTPRequestEvent(
source=AGENT_ID,
timestamp=TIMESTAMP,
method=METHOD,
url=invalid_url,
)


@pytest.mark.parametrize("invalid_method", ("not-a-method", "POST/GET", None, 999))
def test_invalid_method(invalid_method):
with pytest.raises((ValueError, TypeError)):
HTTPRequestEvent(source=AGENT_ID, timestamp=TIMESTAMP, method=invalid_method, url=HTTP_URL)
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from uuid import UUID

import pytest

from common.agent_events import RAMConsumptionEvent

AGENT_ID = UUID("012e7238-7b81-4108-8c7f-0787bc3f3c10")
TIMESTAMP = 1664371327.4067292
UTILIZATION = 77
BYTES_CONSUMED = 42 * (1024**3) # 42 Gigabytes


def test_constructor():
event = RAMConsumptionEvent(
source=AGENT_ID, timestamp=TIMESTAMP, utilization=UTILIZATION, bytes=BYTES_CONSUMED
)

assert event.source == AGENT_ID
assert event.timestamp == TIMESTAMP
assert event.target is None
assert len(event.tags) == 0
assert event.utilization == UTILIZATION
assert event.bytes == BYTES_CONSUMED


@pytest.mark.parametrize("invalid_utilization", ("not-an-int", -1, -5.0, None))
def test_invalid_utilization(invalid_utilization):
with pytest.raises((ValueError, TypeError)):
RAMConsumptionEvent(
source=AGENT_ID,
timestamp=TIMESTAMP,
utilization=invalid_utilization,
bytes=BYTES_CONSUMED,
)


@pytest.mark.parametrize("invalid_bytes_consumed", ("not-an-int", -1, 5.2, None))
def test_invalid_ram_consumption(invalid_bytes_consumed):
with pytest.raises((ValueError, TypeError)):
RAMConsumptionEvent(
source=AGENT_ID,
timestamp=TIMESTAMP,
utilization=UTILIZATION,
bytes=invalid_bytes_consumed,
)
17 changes: 16 additions & 1 deletion vulture_allowlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@

from common import DIContainer
from common.agent_configuration import ScanTargetConfiguration
from common.agent_events import AbstractAgentEvent, FileEncryptionEvent
from common.agent_events import (
AbstractAgentEvent,
CPUConsumptionEvent,
FileEncryptionEvent,
HTTPRequestEvent,
RAMConsumptionEvent,
)
from common.agent_plugins import (
AgentPlugin,
AgentPluginManifest,
Expand Down Expand Up @@ -192,3 +198,12 @@

# Remove when cryptojacker is completed
Percent.as_decimal_fraction
CPUConsumptionEvent
CPUConsumptionEvent.utilization
CPUConsumptionEvent.cpu_number
RAMConsumptionEvent
RAMConsumptionEvent.utilization
RAMConsumptionEvent.bytes
HTTPRequestEvent
HTTPRequestEvent.method
HTTPRequestEvent.url