Add log sending logic to monkey
Add log processing logic to monkey island backend
This commit is contained in:
parent
0e9206728f
commit
dbe7a6a378
|
@ -1,3 +1,4 @@
|
|||
import base64
|
||||
import json
|
||||
import logging
|
||||
import platform
|
||||
|
@ -111,6 +112,21 @@ class ControlClient(object):
|
|||
LOG.warn("Error connecting to control server %s: %s",
|
||||
WormConfiguration.current_server, exc)
|
||||
|
||||
@staticmethod
|
||||
def send_log(log):
|
||||
if not WormConfiguration.current_server:
|
||||
return
|
||||
try:
|
||||
telemetry = {'monkey_guid': GUID, 'log': base64.b64encode(log)}
|
||||
reply = requests.post("https://%s/api/log" % (WormConfiguration.current_server,),
|
||||
data=json.dumps(telemetry),
|
||||
headers={'content-type': 'application/json'},
|
||||
verify=False,
|
||||
proxies=ControlClient.proxies)
|
||||
except Exception as exc:
|
||||
LOG.warn("Error connecting to control server %s: %s",
|
||||
WormConfiguration.current_server, exc)
|
||||
|
||||
@staticmethod
|
||||
def load_control_config():
|
||||
if not WormConfiguration.current_server:
|
||||
|
|
|
@ -12,6 +12,7 @@ from config import WormConfiguration, EXTERNAL_CONFIG_FILE
|
|||
from dropper import MonkeyDrops
|
||||
from model import MONKEY_ARG, DROPPER_ARG
|
||||
from monkey import ChaosMonkey
|
||||
import utils
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
@ -78,12 +79,10 @@ def main():
|
|||
|
||||
try:
|
||||
if MONKEY_ARG == monkey_mode:
|
||||
log_path = os.path.expandvars(
|
||||
WormConfiguration.monkey_log_path_windows) if sys.platform == "win32" else WormConfiguration.monkey_log_path_linux
|
||||
log_path = utils.get_monkey_log_path()
|
||||
monkey_cls = ChaosMonkey
|
||||
elif DROPPER_ARG == monkey_mode:
|
||||
log_path = os.path.expandvars(
|
||||
WormConfiguration.dropper_log_path_windows) if sys.platform == "win32" else WormConfiguration.dropper_log_path_linux
|
||||
log_path = utils.get_dropper_log_path()
|
||||
monkey_cls = MonkeyDrops
|
||||
else:
|
||||
return True
|
||||
|
@ -91,6 +90,8 @@ def main():
|
|||
return True
|
||||
|
||||
if WormConfiguration.use_file_logging:
|
||||
if os.path.exists(log_path):
|
||||
os.remove(log_path)
|
||||
LOG_CONFIG['handlers']['file']['filename'] = log_path
|
||||
LOG_CONFIG['root']['handlers'].append('file')
|
||||
else:
|
||||
|
|
|
@ -6,6 +6,7 @@ import sys
|
|||
import time
|
||||
|
||||
import tunnel
|
||||
import utils
|
||||
from config import WormConfiguration
|
||||
from control import ControlClient
|
||||
from model import DELAY_DELETE_CMD
|
||||
|
@ -226,6 +227,8 @@ class ChaosMonkey(object):
|
|||
|
||||
firewall.close()
|
||||
|
||||
self.send_log()
|
||||
|
||||
self._singleton.unlock()
|
||||
|
||||
if WormConfiguration.self_delete_in_cleanup and -1 == sys.executable.find('python'):
|
||||
|
@ -244,3 +247,13 @@ class ChaosMonkey(object):
|
|||
LOG.error("Exception in self delete: %s", exc)
|
||||
|
||||
LOG.info("Monkey is shutting down")
|
||||
|
||||
def send_log(self):
|
||||
monkey_log_path = utils.get_monkey_log_path()
|
||||
if os.path.exists(monkey_log_path):
|
||||
with open(monkey_log_path, 'r') as f:
|
||||
log = f.read()
|
||||
else:
|
||||
log = ''
|
||||
|
||||
ControlClient.send_log(log)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from config import WormConfiguration
|
||||
|
||||
|
||||
def get_monkey_log_path():
|
||||
return os.path.expandvars(WormConfiguration.monkey_log_path_windows) if sys.platform == "win32" \
|
||||
else WormConfiguration.monkey_log_path_linux
|
||||
|
||||
|
||||
def get_dropper_log_path():
|
||||
return os.path.expandvars(WormConfiguration.dropper_log_path_windows) if sys.platform == "win32" \
|
||||
else WormConfiguration.dropper_log_path_linux
|
|
@ -1,22 +1,24 @@
|
|||
from datetime import datetime
|
||||
|
||||
import bson
|
||||
from bson.json_util import dumps
|
||||
from flask import Flask, send_from_directory, redirect, make_response
|
||||
import flask_restful
|
||||
from bson.json_util import dumps
|
||||
from flask import Flask, send_from_directory, make_response
|
||||
from werkzeug.exceptions import NotFound
|
||||
|
||||
from cc.database import mongo
|
||||
from cc.resources.client_run import ClientRun
|
||||
from cc.resources.monkey import Monkey
|
||||
from cc.resources.edge import Edge
|
||||
from cc.resources.local_run import LocalRun
|
||||
from cc.resources.telemetry import Telemetry
|
||||
from cc.resources.log import Log
|
||||
from cc.resources.monkey import Monkey
|
||||
from cc.resources.monkey_configuration import MonkeyConfiguration
|
||||
from cc.resources.monkey_download import MonkeyDownload
|
||||
from cc.resources.netmap import NetMap
|
||||
from cc.resources.edge import Edge
|
||||
from cc.resources.node import Node
|
||||
from cc.resources.report import Report
|
||||
from cc.resources.root import Root
|
||||
from cc.resources.telemetry import Telemetry
|
||||
from cc.resources.telemetry_feed import TelemetryFeed
|
||||
from cc.services.config import ConfigService
|
||||
|
||||
|
@ -91,5 +93,6 @@ def init_app(mongo_url):
|
|||
api.add_resource(Node, '/api/netmap/node', '/api/netmap/node/')
|
||||
api.add_resource(Report, '/api/report', '/api/report/')
|
||||
api.add_resource(TelemetryFeed, '/api/telemetry-feed', '/api/telemetry-feed/')
|
||||
api.add_resource(Log, '/api/log', '/api/log/')
|
||||
|
||||
return app
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
import json
|
||||
|
||||
import flask_restful
|
||||
from bson import ObjectId
|
||||
from flask import request
|
||||
|
||||
from cc.database import mongo
|
||||
from cc.services.log import LogService
|
||||
from cc.services.node import NodeService
|
||||
|
||||
__author__ = "itay.mizeretz"
|
||||
|
||||
|
||||
class Log(flask_restful.Resource):
|
||||
def get(self):
|
||||
monkey_id = request.args.get('id')
|
||||
exists_monkey_id = request.args.get('exists')
|
||||
if monkey_id:
|
||||
return LogService.get_log_by_monkey_id(ObjectId(monkey_id))
|
||||
else:
|
||||
return LogService.log_exists(ObjectId(exists_monkey_id))
|
||||
|
||||
def post(self):
|
||||
telemetry_json = json.loads(request.data)
|
||||
|
||||
monkey_id = NodeService.get_monkey_by_guid(telemetry_json['monkey_guid'])['_id']
|
||||
log_id = LogService.add_log(monkey_id, telemetry_json['log'])
|
||||
|
||||
return mongo.db.log.find_one_or_404({"_id": log_id})
|
|
@ -33,7 +33,8 @@ class Root(flask_restful.Resource):
|
|||
|
||||
@staticmethod
|
||||
def reset_db():
|
||||
[mongo.db[x].drop() for x in ['config', 'monkey', 'telemetry', 'node', 'edge', 'report']]
|
||||
[mongo.db[x].drop() for x in
|
||||
['config', 'monkey', 'telemetry', 'node', 'edge', 'report', 'log', 'fs.chunks', 'fs.files']]
|
||||
ConfigService.init_config()
|
||||
return jsonify(status='OK')
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
from datetime import datetime
|
||||
|
||||
import gridfs
|
||||
|
||||
import cc.services.node
|
||||
from cc.database import mongo
|
||||
|
||||
__author__ = "itay.mizeretz"
|
||||
|
||||
|
||||
class LogService:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_log_by_monkey_id(monkey_id):
|
||||
log = mongo.db.log.find_one({'monkey_id': monkey_id})
|
||||
if log:
|
||||
fs = gridfs.GridFS(mongo.db)
|
||||
log_file = fs.get(log['file_id'])
|
||||
monkey_label = cc.services.node.NodeService.get_monkey_label(
|
||||
cc.services.node.NodeService.get_monkey_by_id(log['monkey_id']))
|
||||
return \
|
||||
{
|
||||
'monkey_label': monkey_label,
|
||||
'log': log_file.read(),
|
||||
'timestamp': log['timestamp']
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def remove_logs_by_monkey_id(monkey_id):
|
||||
fs = gridfs.GridFS(mongo.db)
|
||||
for log in mongo.db.log.find({'monkey_id': monkey_id}):
|
||||
fs.delete(log['file_id'])
|
||||
mongo.db.log.delete_many({'monkey_id': monkey_id})
|
||||
|
||||
@staticmethod
|
||||
def add_log(monkey_id, log_data, timestamp=datetime.now()):
|
||||
LogService.remove_logs_by_monkey_id(monkey_id)
|
||||
fs = gridfs.GridFS(mongo.db)
|
||||
file_id = fs.put(log_data)
|
||||
return mongo.db.log.insert(
|
||||
{
|
||||
'monkey_id': monkey_id,
|
||||
'file_id': file_id,
|
||||
'timestamp': timestamp
|
||||
}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def log_exists(monkey_id):
|
||||
return mongo.db.log.find_one({'monkey_id': monkey_id}) is not None
|
|
@ -1,9 +1,12 @@
|
|||
from datetime import datetime, timedelta
|
||||
|
||||
from bson import ObjectId
|
||||
|
||||
import cc.services.log
|
||||
from cc.database import mongo
|
||||
from cc.services.edge import EdgeService
|
||||
from cc.utils import local_ip_addresses
|
||||
|
||||
__author__ = "itay.mizeretz"
|
||||
|
||||
|
||||
|
@ -54,6 +57,7 @@ class NodeService:
|
|||
else:
|
||||
new_node["services"] = []
|
||||
|
||||
new_node['has_log'] = cc.services.log.LogService.log_exists(ObjectId(node_id))
|
||||
return new_node
|
||||
|
||||
@staticmethod
|
||||
|
@ -241,7 +245,7 @@ class NodeService:
|
|||
|
||||
@staticmethod
|
||||
def get_monkey_island_pseudo_net_node():
|
||||
return\
|
||||
return \
|
||||
{
|
||||
"id": NodeService.get_monkey_island_pseudo_id(),
|
||||
"label": "MonkeyIsland",
|
||||
|
|
Loading…
Reference in New Issue