diff --git a/CHANGELOG.md b/CHANGELOG.md index a7ea1b39d0c..5a5a42959a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Added - Add an option to the Hadoop exploiter to try all discovered HTTP ports. #2136 +- `GET /api/agent-otp`. #3076 + ### Changed ### Removed ### Fixed diff --git a/monkey/monkey_island/cc/services/authentication_service/flask_resources/__init__.py b/monkey/monkey_island/cc/services/authentication_service/flask_resources/__init__.py index 61f13aa2f0f..be9980ab9e1 100644 --- a/monkey/monkey_island/cc/services/authentication_service/flask_resources/__init__.py +++ b/monkey/monkey_island/cc/services/authentication_service/flask_resources/__init__.py @@ -3,3 +3,4 @@ from .login import Login from .logout import Logout from .register_resources import register_resources +from .agent_otp import AgentOTP diff --git a/monkey/monkey_island/cc/services/authentication_service/flask_resources/agent_otp.py b/monkey/monkey_island/cc/services/authentication_service/flask_resources/agent_otp.py new file mode 100644 index 00000000000..eaf5956ecf8 --- /dev/null +++ b/monkey/monkey_island/cc/services/authentication_service/flask_resources/agent_otp.py @@ -0,0 +1,23 @@ +from flask import make_response + +from monkey_island.cc.flask_utils import AbstractResource + + +class AgentOTP(AbstractResource): + """ + A resource for requesting an Agent's one-time password + + One-time passwords may be requested by an Agent that has already authenticated, + so that Agents that it propagates can authenticate with the Island. + """ + + urls = ["/api/agent-otp"] + + def get(self): + """ + Requests an Agent's one-time password + + :return: One-time password in the response body + """ + + return make_response({"otp": "supersecretpassword"}) diff --git a/monkey/monkey_island/cc/services/authentication_service/flask_resources/register_resources.py b/monkey/monkey_island/cc/services/authentication_service/flask_resources/register_resources.py index f6dba0e3b64..1b3cdf10ef7 100644 --- a/monkey/monkey_island/cc/services/authentication_service/flask_resources/register_resources.py +++ b/monkey/monkey_island/cc/services/authentication_service/flask_resources/register_resources.py @@ -3,6 +3,7 @@ from common import DIContainer from ..authentication_facade import AuthenticationFacade +from .agent_otp import AgentOTP from .login import Login from .logout import Logout from .register import Register @@ -18,3 +19,4 @@ def register_resources(api: flask_restful.Api, container: DIContainer): ) api.add_resource(Login, *Login.urls, resource_class_args=(authentication_facade,)) api.add_resource(Logout, *Logout.urls, resource_class_args=(authentication_facade,)) + api.add_resource(AgentOTP, *AgentOTP.urls) diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/conftest.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/conftest.py index b783da74960..155d111635e 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/conftest.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/conftest.py @@ -7,6 +7,7 @@ AuthenticationFacade, ) from monkey_island.cc.services.authentication_service.flask_resources import ( + AgentOTP, Login, Logout, Register, @@ -37,6 +38,7 @@ def get_mock_auth_app(authentication_facade: AuthenticationFacade): api.add_resource( RegistrationStatus, *RegistrationStatus.urls, resource_class_args=(authentication_facade,) ) + api.add_resource(AgentOTP, *AgentOTP.urls) return app diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/flask_resources/test_agent_otp.py b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/flask_resources/test_agent_otp.py new file mode 100644 index 00000000000..0fc5dcd8260 --- /dev/null +++ b/monkey/tests/unit_tests/monkey_island/cc/services/authentication_service/flask_resources/test_agent_otp.py @@ -0,0 +1,20 @@ +import pytest + +from monkey_island.cc.services.authentication_service.flask_resources.agent_otp import AgentOTP + + +@pytest.fixture +def make_otp_request(flask_client): + url = AgentOTP.urls[0] + + def _make_otp_request(): + return flask_client.get(url) + + return _make_otp_request + + +def test_agent_otp__successful(make_otp_request): + response = make_otp_request() + + assert response.status_code == 200 + assert response.json["otp"] == "supersecretpassword"