-
Notifications
You must be signed in to change notification settings - Fork 792
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '3424-installed-plugins-endpoint' into develop
- Loading branch information
Showing
5 changed files
with
154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
monkey/monkey_island/cc/services/agent_plugin_service/flask_resources/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
from .agent_plugins import AgentPlugins | ||
from .agent_plugins_manifest import AgentPluginsManifest | ||
from .installed_agent_plugins_manifests import InstalledAgentPluginsManifests | ||
from .register import register_resources |
48 changes: 48 additions & 0 deletions
48
...and/cc/services/agent_plugin_service/flask_resources/installed_agent_plugins_manifests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import logging | ||
from http import HTTPStatus | ||
from typing import Any, Dict | ||
|
||
from flask import make_response | ||
from flask_security import auth_token_required, roles_accepted | ||
|
||
from common.agent_plugins import AgentPluginManifest, AgentPluginType | ||
from monkey_island.cc.flask_utils import AbstractResource | ||
from monkey_island.cc.services.authentication_service import AccountRole | ||
|
||
from .. import IAgentPluginService | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class InstalledAgentPluginsManifests(AbstractResource): | ||
urls = ["/api/agent-plugins/installed/manifests"] | ||
|
||
def __init__(self, agent_plugin_service: IAgentPluginService): | ||
self._agent_plugin_service = agent_plugin_service | ||
|
||
@auth_token_required | ||
@roles_accepted(AccountRole.ISLAND_INTERFACE.name) | ||
def get(self): | ||
""" | ||
Get manifests of all installed plugins | ||
""" | ||
|
||
installed_agent_plugins_manifests = self._agent_plugin_service.get_all_plugin_manifests() | ||
installed_agent_plugins_manifests_simplified = ( | ||
self._simplify_installed_agent_plugins_manifests(installed_agent_plugins_manifests) | ||
) | ||
|
||
return make_response(installed_agent_plugins_manifests_simplified, HTTPStatus.OK) | ||
|
||
def _simplify_installed_agent_plugins_manifests( | ||
self, manifests: Dict[AgentPluginType, Dict[str, AgentPluginManifest]] | ||
) -> Dict[str, Dict[str, Dict[str, Any]]]: | ||
simplified: Dict[str, Dict[str, Dict[str, Any]]] = {} | ||
for plugin_type in manifests: | ||
simplified[plugin_type.value] = {} | ||
for plugin_name in manifests[plugin_type]: | ||
simplified[plugin_type.value][plugin_name] = manifests[plugin_type][ | ||
plugin_name | ||
].dict(simplify=True) | ||
|
||
return simplified |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
...c/services/agent_plugin_service/flask_resources/test_installed_agent_plugins_manifests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from http import HTTPStatus | ||
|
||
import pytest | ||
from tests.common import StubDIContainer | ||
from tests.monkey_island import InMemoryAgentPluginRepository | ||
from tests.unit_tests.common.agent_plugins.test_agent_plugin_manifest import ( | ||
FAKE_NAME, | ||
FAKE_NAME2, | ||
FAKE_TYPE, | ||
) | ||
from tests.unit_tests.monkey_island.cc.fake_agent_plugin_data import ( | ||
FAKE_AGENT_PLUGIN_1, | ||
FAKE_AGENT_PLUGIN_2, | ||
) | ||
from tests.unit_tests.monkey_island.conftest import get_url_for_resource | ||
|
||
from common import OperatingSystem | ||
from monkey_island.cc.repositories import RetrievalError | ||
from monkey_island.cc.services.agent_plugin_service import IAgentPluginService | ||
from monkey_island.cc.services.agent_plugin_service.agent_plugin_service import AgentPluginService | ||
from monkey_island.cc.services.agent_plugin_service.flask_resources import ( | ||
InstalledAgentPluginsManifests, | ||
) | ||
|
||
FAKE_PLUGIN_NAME = "plugin_abc" | ||
|
||
|
||
@pytest.fixture | ||
def agent_plugin_repository(): | ||
return InMemoryAgentPluginRepository() | ||
|
||
|
||
@pytest.fixture | ||
def agent_plugin_service(agent_plugin_repository): | ||
return AgentPluginService(agent_plugin_repository) | ||
|
||
|
||
@pytest.fixture | ||
def flask_client(build_flask_client, agent_plugin_service): | ||
container = StubDIContainer() | ||
container.register_instance(IAgentPluginService, agent_plugin_service) | ||
|
||
with build_flask_client(container) as flask_client: | ||
yield flask_client | ||
|
||
|
||
def test_get_installed_plugins_manifests(flask_client, agent_plugin_repository): | ||
agent_plugin_repository.store_agent_plugin(OperatingSystem.LINUX, FAKE_AGENT_PLUGIN_1) | ||
agent_plugin_repository.store_agent_plugin(OperatingSystem.WINDOWS, FAKE_AGENT_PLUGIN_2) | ||
|
||
expected_response = { | ||
"Exploiter": { | ||
FAKE_NAME: { | ||
"description": None, | ||
"link_to_documentation": "http://www.beefface.com", | ||
"name": FAKE_NAME, | ||
"plugin_type": FAKE_TYPE, | ||
"version": "1.0.0", | ||
"safe": False, | ||
"remediation_suggestion": None, | ||
"supported_operating_systems": ["linux", "windows"], | ||
"target_operating_systems": ["linux"], | ||
"title": "Remote Desktop Protocol exploiter", | ||
}, | ||
FAKE_NAME2: { | ||
"description": None, | ||
"link_to_documentation": "http://www.beefface.com", | ||
"name": FAKE_NAME2, | ||
"plugin_type": FAKE_TYPE, | ||
"version": "1.0.0", | ||
"safe": False, | ||
"remediation_suggestion": None, | ||
"supported_operating_systems": ["linux", "windows"], | ||
"target_operating_systems": ["linux"], | ||
"title": "Remote Desktop Protocol exploiter", | ||
}, | ||
} | ||
} | ||
|
||
resp = flask_client.get(get_url_for_resource(InstalledAgentPluginsManifests)) | ||
|
||
assert resp.status_code == HTTPStatus.OK | ||
assert resp.json == expected_response | ||
|
||
|
||
def test_get_installed_plugins_manifests__empty(flask_client): | ||
resp = flask_client.get(get_url_for_resource(InstalledAgentPluginsManifests)) | ||
|
||
assert resp.status_code == HTTPStatus.OK | ||
assert resp.json == {} | ||
|
||
|
||
def test_get_installed_plugins_manifests__server_error(flask_client, agent_plugin_repository): | ||
def raise_retrieval_error(): | ||
raise RetrievalError | ||
|
||
agent_plugin_repository.get_all_plugin_manifests = raise_retrieval_error | ||
|
||
resp = flask_client.get(get_url_for_resource(InstalledAgentPluginsManifests)) | ||
|
||
assert resp.status_code == HTTPStatus.INTERNAL_SERVER_ERROR |