Island: Remove agent controls

Agent controls are being replaced by agent signal events
This commit is contained in:
vakarisz 2022-09-23 12:08:24 +03:00 committed by Mike Salvatore
parent a49ddf7a4a
commit b11cd9c5f1
11 changed files with 2 additions and 196 deletions

View File

@ -88,6 +88,7 @@ class MonkeyIslandClient(object):
@avoid_race_condition @avoid_race_condition
def kill_all_monkeys(self): def kill_all_monkeys(self):
# TODO change this request, because monkey-control resource got removed
response = self.requests.post_json( response = self.requests.post_json(
"api/agent-signals/terminate-all-agents", json={"terminate_time": time.time()} "api/agent-signals/terminate-all-agents", json={"terminate_time": time.time()}
) )

View File

@ -27,7 +27,6 @@ from monkey_island.cc.resources import (
TerminateAllAgents, TerminateAllAgents,
) )
from monkey_island.cc.resources.AbstractResource import AbstractResource from monkey_island.cc.resources.AbstractResource import AbstractResource
from monkey_island.cc.resources.agent_controls import StopAgentCheck
from monkey_island.cc.resources.attack.attack_report import AttackReport from monkey_island.cc.resources.attack.attack_report import AttackReport
from monkey_island.cc.resources.auth import Authenticate, Register, RegistrationStatus, init_jwt from monkey_island.cc.resources.auth import Authenticate, Register, RegistrationStatus, init_jwt
from monkey_island.cc.resources.blackbox.log_blackbox_endpoint import LogBlackboxEndpoint from monkey_island.cc.resources.blackbox.log_blackbox_endpoint import LogBlackboxEndpoint
@ -199,7 +198,6 @@ def init_restful_endpoints(api: FlaskDIWrapper):
api.add_resource(PropagationCredentials) api.add_resource(PropagationCredentials)
api.add_resource(RemoteRun) api.add_resource(RemoteRun)
api.add_resource(Version) api.add_resource(Version)
api.add_resource(StopAgentCheck)
# Resources used by black box tests # Resources used by black box tests
# API Spec: Fix all the following endpoints, see comments in the resource classes # API Spec: Fix all the following endpoints, see comments in the resource classes

View File

@ -1 +0,0 @@
from .agent_controls import AgentControls

View File

@ -1,8 +0,0 @@
from mongoengine import Document, FloatField
# TODO rename to Simulation, add other metadata
class AgentControls(Document):
# Timestamp of the last "kill all agents" command
last_stop_all = FloatField(default=None)

View File

@ -22,10 +22,6 @@ from monkey_island.cc.models.monkey_ttl import MonkeyTtl, create_monkey_ttl_docu
from monkey_island.cc.server_utils.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS from monkey_island.cc.server_utils.consts import DEFAULT_MONKEY_TTL_EXPIRY_DURATION_IN_SECONDS
class ParentNotFoundError(Exception):
"""Raise when trying to get a parent of monkey that doesn't have one"""
class Monkey(Document): class Monkey(Document):
""" """
This class has 2 main section: This class has 2 main section:
@ -98,18 +94,6 @@ class Monkey(Document):
monkey_is_dead = True monkey_is_dead = True
return monkey_is_dead return monkey_is_dead
def has_parent(self):
for p in self.parent:
if p[0] != self.guid:
return True
return False
def get_parent(self):
if self.has_parent():
return Monkey.objects(guid=self.parent[0][0]).first()
else:
raise ParentNotFoundError(f"No parent was found for agent with GUID {self.guid}")
def get_os(self): def get_os(self):
os = "unknown" os = "unknown"
if self.description.lower().find("linux") != -1: if self.description.lower().find("linux") != -1:

View File

@ -1 +0,0 @@
from .stop_agent_check import StopAgentCheck

View File

@ -1,11 +0,0 @@
from monkey_island.cc.resources.AbstractResource import AbstractResource
from monkey_island.cc.services.infection_lifecycle import should_agent_die
class StopAgentCheck(AbstractResource):
# API Spec: Rename to AgentStopStatus or something, endpoint for this could be
# "/api/agents/<GUID>/stop-status"
urls = ["/api/monkey-control/needs-to-stop/<int:monkey_guid>"]
def get(self, monkey_guid: int):
return {"stop_agent": should_agent_die(monkey_guid)}

View File

@ -4,7 +4,6 @@ from flask import jsonify
from monkey_island.cc.database import mongo from monkey_island.cc.database import mongo
from monkey_island.cc.models import Config from monkey_island.cc.models import Config
from monkey_island.cc.models.agent_controls import AgentControls
from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -24,7 +23,6 @@ class Database(object):
for x in mongo.db.collection_names() for x in mongo.db.collection_names()
if Database._should_drop(x, reset_config) if Database._should_drop(x, reset_config)
] ]
Database.init_agent_controls()
logger.info("DB was reset") logger.info("DB was reset")
return jsonify(status="OK") return jsonify(status="OK")
@ -44,10 +42,6 @@ class Database(object):
mongo.db[collection_name].drop() mongo.db[collection_name].drop()
logger.info("Dropped collection {}".format(collection_name)) logger.info("Dropped collection {}".format(collection_name))
@staticmethod
def init_agent_controls():
AgentControls().save()
@staticmethod @staticmethod
def is_mitigations_missing() -> bool: def is_mitigations_missing() -> bool:
return bool(AttackMitigations.COLLECTION_NAME not in mongo.db.list_collection_names()) return bool(AttackMitigations.COLLECTION_NAME not in mongo.db.list_collection_names())

View File

@ -1,7 +1,5 @@
import logging import logging
from monkey_island.cc.models import Monkey
from monkey_island.cc.models.agent_controls import AgentControls
from monkey_island.cc.services.node import NodeService from monkey_island.cc.services.node import NodeService
from monkey_island.cc.services.reporting.report import ReportService from monkey_island.cc.services.reporting.report import ReportService
from monkey_island.cc.services.reporting.report_generation_synchronisation import ( from monkey_island.cc.services.reporting.report_generation_synchronisation import (
@ -12,31 +10,6 @@ from monkey_island.cc.services.reporting.report_generation_synchronisation impor
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def should_agent_die(guid: int) -> bool:
monkey = Monkey.objects(guid=str(guid)).first()
return _should_agent_stop(monkey) or _is_monkey_killed_manually(monkey)
def _should_agent_stop(monkey: Monkey) -> bool:
if monkey.should_stop:
# Only stop the agent once, to allow further runs on that machine
monkey.should_stop = False
monkey.save()
return True
return False
def _is_monkey_killed_manually(monkey: Monkey) -> bool:
terminate_timestamp = AgentControls.objects.first().last_stop_all
if terminate_timestamp is None:
return False
if monkey.has_parent():
launch_timestamp = monkey.get_parent().launch_time
else:
launch_timestamp = monkey.launch_time
return int(terminate_timestamp) >= int(launch_timestamp)
def get_completed_steps(): def get_completed_steps():
is_any_exists = NodeService.is_any_monkey_exists() is_any_exists = NodeService.is_any_monkey_exists()
infection_done = NodeService.is_monkey_finished_running() infection_done = NodeService.is_monkey_finished_running()

View File

@ -3,7 +3,7 @@ import uuid
import pytest import pytest
from monkey_island.cc.models.monkey import Monkey, MonkeyNotFoundError, ParentNotFoundError from monkey_island.cc.models.monkey import Monkey, MonkeyNotFoundError
from monkey_island.cc.models.monkey_ttl import MonkeyTtl from monkey_island.cc.models.monkey_ttl import MonkeyTtl
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -162,35 +162,3 @@ class TestMonkey:
cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info() cache_info_after_query = Monkey.is_monkey.storage.backend.cache_info()
assert cache_info_after_query.hits == 2 assert cache_info_after_query.hits == 2
@pytest.mark.usefixtures("uses_database")
def test_has_parent(self):
monkey_1 = Monkey(guid=str(uuid.uuid4()))
monkey_2 = Monkey(guid=str(uuid.uuid4()))
monkey_1.parent = [[monkey_2.guid]]
monkey_1.save()
assert monkey_1.has_parent()
@pytest.mark.usefixtures("uses_database")
def test_has_no_parent(self):
monkey_1 = Monkey(guid=str(uuid.uuid4()))
monkey_1.parent = [[monkey_1.guid]]
monkey_1.save()
assert not monkey_1.has_parent()
@pytest.mark.usefixtures("uses_database")
def test_get_parent(self):
monkey_1 = Monkey(guid=str(uuid.uuid4()))
monkey_2 = Monkey(guid=str(uuid.uuid4()))
monkey_1.parent = [[monkey_2.guid]]
monkey_1.save()
monkey_2.save()
assert monkey_1.get_parent().guid == monkey_2.guid
@pytest.mark.usefixtures("uses_database")
def test_get_parent_no_parent(self):
monkey_1 = Monkey(guid=str(uuid.uuid4()))
monkey_1.parent = [[monkey_1.guid]]
monkey_1.save()
with pytest.raises(ParentNotFoundError):
monkey_1.get_parent()

View File

@ -1,26 +1,6 @@
import uuid import uuid
import pytest
from monkey_island.cc.models import Config, Monkey from monkey_island.cc.models import Config, Monkey
from monkey_island.cc.models.agent_controls import AgentControls
from monkey_island.cc.services.infection_lifecycle import should_agent_die
@pytest.mark.usefixtures("uses_database")
def test_should_agent_die_by_config(monkeypatch):
monkey = Monkey(guid=str(uuid.uuid4()))
monkey.config = Config()
monkey.should_stop = True
monkey.save()
assert should_agent_die(monkey.guid)
monkeypatch.setattr(
"monkey_island.cc.services.infection_lifecycle._is_monkey_killed_manually", lambda _: False
)
monkey.should_stop = True
monkey.save()
assert not should_agent_die(monkey.guid)
def create_monkey(launch_time): def create_monkey(launch_time):
@ -32,80 +12,9 @@ def create_monkey(launch_time):
return monkey return monkey
@pytest.mark.usefixtures("uses_database")
def test_should_agent_die_no_kill_event():
monkey = create_monkey(launch_time=3)
kill_event = AgentControls()
kill_event.save()
assert not should_agent_die(monkey.guid)
def create_kill_event(event_time):
kill_event = AgentControls(last_stop_all=event_time)
kill_event.save()
return kill_event
def create_parent(child_monkey, launch_time): def create_parent(child_monkey, launch_time):
monkey_parent = Monkey(guid=str(uuid.uuid4())) monkey_parent = Monkey(guid=str(uuid.uuid4()))
child_monkey.parent = [[monkey_parent.guid]] child_monkey.parent = [[monkey_parent.guid]]
monkey_parent.launch_time = launch_time monkey_parent.launch_time = launch_time
monkey_parent.save() monkey_parent.save()
child_monkey.save() child_monkey.save()
@pytest.mark.usefixtures("uses_database")
def test_was_agent_killed_manually(monkeypatch):
monkey = create_monkey(launch_time=2)
create_kill_event(event_time=3)
assert should_agent_die(monkey.guid)
@pytest.mark.usefixtures("uses_database")
def test_agent_killed_on_wakeup(monkeypatch):
monkey = create_monkey(launch_time=2)
create_kill_event(event_time=2)
assert should_agent_die(monkey.guid)
@pytest.mark.usefixtures("uses_database")
def test_manual_kill_dont_affect_new_monkeys(monkeypatch):
monkey = create_monkey(launch_time=3)
create_kill_event(event_time=2)
assert not should_agent_die(monkey.guid)
@pytest.mark.usefixtures("uses_database")
def test_parent_manually_killed(monkeypatch):
monkey = create_monkey(launch_time=3)
create_parent(child_monkey=monkey, launch_time=1)
create_kill_event(event_time=2)
assert should_agent_die(monkey.guid)
@pytest.mark.usefixtures("uses_database")
def test_parent_manually_killed_on_wakeup(monkeypatch):
monkey = create_monkey(launch_time=3)
create_parent(child_monkey=monkey, launch_time=2)
create_kill_event(event_time=2)
assert should_agent_die(monkey.guid)
@pytest.mark.usefixtures("uses_database")
def test_manual_kill_dont_affect_new_monkeys_with_parent(monkeypatch):
monkey = create_monkey(launch_time=3)
create_parent(child_monkey=monkey, launch_time=2)
create_kill_event(event_time=1)
assert not should_agent_die(monkey.guid)