Merge pull request #2313 from guardicore/2292-island-api-client
2292 island api client
This commit is contained in:
commit
310b58392f
|
@ -0,0 +1,9 @@
|
||||||
|
from .island_api_client_errors import (
|
||||||
|
IslandAPIConnectionError,
|
||||||
|
IslandAPIError,
|
||||||
|
IslandAPIRequestError,
|
||||||
|
IslandAPIRequestFailedError,
|
||||||
|
IslandAPITimeoutError,
|
||||||
|
)
|
||||||
|
from .i_island_api_client import IIslandAPIClient
|
||||||
|
from .http_island_api_client import HTTPIslandAPIClient
|
|
@ -0,0 +1,29 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from common.common_consts.timeouts import MEDIUM_REQUEST_TIMEOUT
|
||||||
|
|
||||||
|
from . import IIslandAPIClient, IslandAPIConnectionError, IslandAPIError, IslandAPITimeoutError
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class HTTPIslandAPIClient(IIslandAPIClient):
|
||||||
|
"""
|
||||||
|
A client for the Island's HTTP API
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, island_server: str):
|
||||||
|
try:
|
||||||
|
requests.get( # noqa: DUO123
|
||||||
|
f"https://{island_server}/api?action=is-up",
|
||||||
|
verify=False,
|
||||||
|
timeout=MEDIUM_REQUEST_TIMEOUT,
|
||||||
|
)
|
||||||
|
except requests.exceptions.ConnectionError as err:
|
||||||
|
raise IslandAPIConnectionError(err)
|
||||||
|
except TimeoutError as err:
|
||||||
|
raise IslandAPITimeoutError(err)
|
||||||
|
except Exception as err:
|
||||||
|
raise IslandAPIError(err)
|
|
@ -0,0 +1,19 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
|
class IIslandAPIClient(ABC):
|
||||||
|
"""
|
||||||
|
A client for the Island's API
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self, island_server: str):
|
||||||
|
"""
|
||||||
|
Construct and island API client and connect it to the island
|
||||||
|
|
||||||
|
:param island_server: The socket address of the API
|
||||||
|
:raises IslandAPIConnectionError: If the client cannot successfully connect to the island
|
||||||
|
:raises IslandAPITimeoutError: If a timeout occurs while attempting to connect to the island
|
||||||
|
:raises IslandAPIError: If an unexpected error occurs while attempting to connect to the
|
||||||
|
island
|
||||||
|
"""
|
|
@ -0,0 +1,38 @@
|
||||||
|
class IslandAPIError(Exception):
|
||||||
|
"""
|
||||||
|
Raised when something goes wrong when calling the Island API
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IslandAPITimeoutError(IslandAPIError):
|
||||||
|
"""
|
||||||
|
Raised when the API request hits a timeout
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IslandAPIConnectionError(IslandAPIError):
|
||||||
|
"""
|
||||||
|
Raised when the API request can't find/connect to the Island
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IslandAPIRequestError(IslandAPIError):
|
||||||
|
"""
|
||||||
|
Raised when the API request fails due to an error in the request sent from the client
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IslandAPIRequestFailedError(IslandAPIError):
|
||||||
|
"""
|
||||||
|
Raised when the API request fails due to an error on the server
|
||||||
|
"""
|
||||||
|
|
||||||
|
pass
|
|
@ -0,0 +1,30 @@
|
||||||
|
import pytest
|
||||||
|
import requests
|
||||||
|
import requests_mock
|
||||||
|
|
||||||
|
from infection_monkey.island_api_client import (
|
||||||
|
HTTPIslandAPIClient,
|
||||||
|
IslandAPIConnectionError,
|
||||||
|
IslandAPIError,
|
||||||
|
IslandAPITimeoutError,
|
||||||
|
)
|
||||||
|
|
||||||
|
SERVER = "1.1.1.1:9999"
|
||||||
|
|
||||||
|
ISLAND_URI = f"https://{SERVER}/api?action=is-up"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"actual_error, expected_error",
|
||||||
|
[
|
||||||
|
(requests.exceptions.ConnectionError, IslandAPIConnectionError),
|
||||||
|
(TimeoutError, IslandAPITimeoutError),
|
||||||
|
(Exception, IslandAPIError),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_island_api_client(actual_error, expected_error):
|
||||||
|
with requests_mock.Mocker() as m:
|
||||||
|
m.get(ISLAND_URI, exc=actual_error)
|
||||||
|
|
||||||
|
with pytest.raises(expected_error):
|
||||||
|
HTTPIslandAPIClient(SERVER)
|
|
@ -9,6 +9,12 @@ from common.agent_configuration.agent_sub_configurations import (
|
||||||
)
|
)
|
||||||
from common.credentials import Credentials, LMHash, NTHash
|
from common.credentials import Credentials, LMHash, NTHash
|
||||||
from infection_monkey.exploit.log4shell_utils.ldap_server import LDAPServerFactory
|
from infection_monkey.exploit.log4shell_utils.ldap_server import LDAPServerFactory
|
||||||
|
from infection_monkey.island_api_client import (
|
||||||
|
HTTPIslandAPIClient,
|
||||||
|
IIslandAPIClient,
|
||||||
|
IslandAPIRequestError,
|
||||||
|
IslandAPIRequestFailedError,
|
||||||
|
)
|
||||||
from monkey_island.cc.event_queue import IslandEventTopic, PyPubSubIslandEventQueue
|
from monkey_island.cc.event_queue import IslandEventTopic, PyPubSubIslandEventQueue
|
||||||
from monkey_island.cc.models import Report
|
from monkey_island.cc.models import Report
|
||||||
from monkey_island.cc.models.networkmap import Arc, NetworkMap
|
from monkey_island.cc.models.networkmap import Arc, NetworkMap
|
||||||
|
@ -328,3 +334,9 @@ CC_TUNNEL
|
||||||
IslandEventTopic.AGENT_CONNECTED
|
IslandEventTopic.AGENT_CONNECTED
|
||||||
IslandEventTopic.CLEAR_SIMULATION_DATA
|
IslandEventTopic.CLEAR_SIMULATION_DATA
|
||||||
IslandEventTopic.RESET_AGENT_CONFIGURATION
|
IslandEventTopic.RESET_AGENT_CONFIGURATION
|
||||||
|
|
||||||
|
# TODO: Remove after #2292 is closed
|
||||||
|
IIslandAPIClient
|
||||||
|
HTTPIslandAPIClient
|
||||||
|
IslandAPIRequestFailedError
|
||||||
|
IslandAPIRequestError
|
||||||
|
|
Loading…
Reference in New Issue