Added the API /test/clear_caches

Currently clears only the reports from Mongo
This commit is contained in:
Shay Nehmad 2020-02-23 14:02:18 +02:00
parent 51099504e3
commit 4461097c60
7 changed files with 77 additions and 1 deletions

View File

@ -85,3 +85,13 @@ class MonkeyIslandClient(object):
def is_all_monkeys_dead(self): def is_all_monkeys_dead(self):
query = {'dead': False} query = {'dead': False}
return len(self.find_monkeys_in_db(query)) == 0 return len(self.find_monkeys_in_db(query)) == 0
def clear_caches(self):
"""
Tries to clear caches.
:raises: If error (by error code), raises the error
:return: The response
"""
response = self.requests.delete("api/test/clear_caches")
response.raise_for_status()
return response

View File

@ -61,6 +61,14 @@ class MonkeyIslandRequests(object):
headers=self.get_jwt_header(), headers=self.get_jwt_header(),
verify=False) verify=False)
@_Decorators.refresh_jwt_token
def delete(self, url):
return requests.delete( # noqa: DOU123
self.addr + url,
headers=self.get_jwt_header(),
verify=False
)
@_Decorators.refresh_jwt_token @_Decorators.refresh_jwt_token
def get_jwt_header(self): def get_jwt_header(self):
return {"Authorization": "JWT " + self.token} return {"Authorization": "JWT " + self.token}

View File

@ -25,6 +25,7 @@ from monkey_island.cc.resources.root import Root
from monkey_island.cc.resources.telemetry import Telemetry from monkey_island.cc.resources.telemetry import Telemetry
from monkey_island.cc.resources.telemetry_feed import TelemetryFeed from monkey_island.cc.resources.telemetry_feed import TelemetryFeed
from monkey_island.cc.resources.pba_file_download import PBAFileDownload from monkey_island.cc.resources.pba_file_download import PBAFileDownload
from monkey_island.cc.resources.test.clear_caches import ClearCaches
from monkey_island.cc.resources.version_update import VersionUpdate from monkey_island.cc.resources.version_update import VersionUpdate
from monkey_island.cc.resources.pba_file_upload import FileUpload from monkey_island.cc.resources.pba_file_upload import FileUpload
from monkey_island.cc.resources.attack.attack_config import AttackConfiguration from monkey_island.cc.resources.attack.attack_config import AttackConfiguration
@ -116,6 +117,7 @@ def init_api_resources(api):
api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/') api.add_resource(VersionUpdate, '/api/version-update', '/api/version-update/')
api.add_resource(MonkeyTest, '/api/test/monkey') api.add_resource(MonkeyTest, '/api/test/monkey')
api.add_resource(ClearCaches, '/api/test/clear_caches')
api.add_resource(LogTest, '/api/test/log') api.add_resource(LogTest, '/api/test/log')

View File

@ -1,4 +1,4 @@
""" """
This package contains resources used by blackbox tests This package contains resources used by blackbox tests
to analize test results, download logs and so on. to analyze test results, download logs and so on.
""" """

View File

@ -0,0 +1,35 @@
import logging
import flask_restful
from monkey_island.cc.auth import jwt_required
from monkey_island.cc.services.attack.attack_report import AttackReportService
from monkey_island.cc.services.reporting.report import ReportService
NOT_ALL_REPORTS_DELETED = "Not all reports have been cleared from the DB!"
logger = logging.getLogger(__name__)
class ClearCaches(flask_restful.Resource):
"""
Used for timing tests - we want to get actual execution time of functions in BlackBox without caching - so we use this
to clear the caches.
:note: DO NOT CALL THIS IN PRODUCTION CODE as this will slow down the user experience.
"""
@jwt_required()
def delete(self, **kw):
try:
logger.warning("Trying to clear caches! Make sure this is not production")
ReportService.delete_saved_report_if_exists()
AttackReportService.delete_saved_report_if_exists()
# TODO: Monkey.clear_caches(), clear LRU caches of function in the Monkey object
except RuntimeError as e:
logger.exception(e)
flask_restful.abort(500, error_info=str(e))
if ReportService.is_report_generated() or AttackReportService.is_report_generated():
logger.exception(NOT_ALL_REPORTS_DELETED)
flask_restful.abort(500, error_info=NOT_ALL_REPORTS_DELETED)
return {"success": "true"}

View File

@ -103,3 +103,11 @@ class AttackReportService:
""" """
generated_report = mongo.db.attack_report.find_one({}) generated_report = mongo.db.attack_report.find_one({})
return generated_report is not None return generated_report is not None
@staticmethod
def delete_saved_report_if_exists():
if AttackReportService.is_report_generated():
latest_report = mongo.db.attack_report.find_one({'name': REPORT_NAME})
delete_result = mongo.db.report.delete_one({"_id": latest_report['_id']})
if delete_result.deleted_count != 1:
raise RuntimeError("Error while deleting report:" + str(delete_result))

View File

@ -773,6 +773,19 @@ class ReportService:
return False return False
@staticmethod
def delete_saved_report_if_exists():
"""
This function clears the saved report from the DB.
:raises RuntimeError if deletion failed
"""
latest_report_doc = mongo.db.report.find_one({}, {'meta.latest_monkey_modifytime': 1})
if latest_report_doc:
delete_result = mongo.db.report.delete_one({"_id": latest_report_doc['_id']})
if delete_result.deleted_count != 1:
raise RuntimeError("Error while deleting report:" + str(delete_result))
@staticmethod @staticmethod
def decode_dot_char_before_mongo_insert(report_dict): def decode_dot_char_before_mongo_insert(report_dict):
""" """