Skip to content

Commit

Permalink
Merge branch '3424-installed-plugins-endpoint' into develop
Browse files Browse the repository at this point in the history
Issue #3424
PR #3596
  • Loading branch information
mssalvatore committed Aug 21, 2023
2 parents e353033 + ff4a972 commit 9607780
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Changelog](https://keepachangelog.com/en/1.0.0/).
- HTTPRequestEvent. #3411
- RDP exploiter plugin. #3425
- A cryptojacker payload to simulate cryptojacker attacks. #3411
- `PUT /api/install-agent-plugin`. #3417
- `GET /api/agent-plugins/installed/manifests`. #3424

### Changed
- Plugin source is now gzipped. #3392
Expand Down
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
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
from .agent_plugins import AgentPlugins
from .agent_plugins_manifest import AgentPluginsManifest
from .install_agent_plugin import InstallAgentPlugin
from .installed_agent_plugins_manifests import InstalledAgentPluginsManifests


def register_resources(api: FlaskDIWrapper):
api.add_resource(AgentPlugins)
api.add_resource(AgentPluginsManifest)
api.add_resource(InstallAgentPlugin)
api.add_resource(InstalledAgentPluginsManifests)
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

0 comments on commit 9607780

Please sign in to comment.