index.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. """
  2. This is a RESTful interface implemented using Flask micro framework.
  3. The API is driven by configuration that is organized in terms of the monitoring classes
  4. The API is both restful and websocket/socketio enabled.
  5. We designed the classes to be reusable (and powered by labels):
  6. 'monitoring-type':
  7. 'class':'<class-name>'
  8. 'config':<labeled-class-specific-configuration>'
  9. """
  10. from flask import Flask, session, request, redirect, Response
  11. from flask.templating import render_template
  12. from flask_session import Session
  13. import time
  14. import sys
  15. import os
  16. import json
  17. import re
  18. import monitor
  19. import Queue
  20. from utils.transport import *
  21. from utils.workers import ThreadManager, Factory
  22. from utils.ml import ML,AnomalyDetection,AnalyzeAnomaly
  23. import utils.params as SYS_ARGS
  24. import atexit
  25. app = Flask(__name__)
  26. app.config['SECRET_KEY'] = '!h8-[0v8]247-4-360'
  27. #app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX=?RT'
  28. PARAMS = SYS_ARGS.PARAMS
  29. f = open(PARAMS['path'])
  30. CONFIG = json.loads(f.read())
  31. f.close()
  32. #
  33. #
  34. #from threading import Thread, RLock
  35. p = CONFIG['store']['args']
  36. class_read = CONFIG['store']['class']['read']
  37. class_write= CONFIG['store']['class']['write']
  38. factory = DataSourceFactory()
  39. # gReader = factory.instance(type=class_read,args=p)
  40. atexit.register(ThreadManager.stop)
  41. @app.route('/get/<id>')
  42. def procs(id):
  43. try:
  44. gReader = factory.instance(type=class_read,args=p)
  45. data = gReader.read()
  46. ahandler = AnalyzeAnomaly()
  47. learn = {}
  48. if 'learn' in data :
  49. for row in data['learn'] :
  50. label = row['label']
  51. learn[label] = row
  52. r = {}
  53. for label in data :
  54. if label not in ['learn','folders'] :
  55. index = len(data[label]) - 1
  56. row = data[label][index]
  57. r[label] = row
  58. #
  59. # Let us determine if this is a normal operation or not
  60. # We will update the status of the information ...
  61. #
  62. for row in r[label] :
  63. index = r[label].index(row)
  64. if row['label'] in learn:
  65. id = row['label']
  66. px = ahandler.predict([row],learn[id])
  67. if px :
  68. # row['anomaly'] = px[1]==1
  69. print ""
  70. print label,' *** ',index
  71. row = dict(row,**px)
  72. r[label][index] =row
  73. #
  74. # @TODO:
  75. # Compile a report here that will be sent to the mailing list
  76. #
  77. except Exception, e:
  78. print e
  79. r = []
  80. return json.dumps(r)
  81. """
  82. This function/endpoint will assess n-virtual environments and return the results
  83. @TODO: Should this be stored for future mining (I don't think so but could be wrong)
  84. """
  85. @app.route('/sandbox')
  86. def sandbox():
  87. global CONFIG
  88. if 'sandbox' in CONFIG: #CONFIG['monitor']:
  89. #handler = HANDLERS['sandbox']['class']
  90. #conf = HANDLERS['sandbox']['config']
  91. r = []
  92. # p = Factory.instance('sandbox',CONFIG)
  93. handler = monitor.Sandbox()
  94. conf = CONFIG['sandbox']
  95. for id in conf:
  96. try:
  97. handler.init(conf[id])
  98. r.append (dict(handler.composite(),**{"label":id}))
  99. except Exception,e:
  100. pass
  101. else:
  102. r = []
  103. return json.dumps(r)
  104. @app.route('/trends')
  105. def trends ():
  106. id = request.args.get('id')
  107. app = request.args.get('app').strip()
  108. p = CONFIG['store']['args']
  109. class_read = CONFIG['store']['class']['read']
  110. gReader = factory.instance(type=class_read,args=p)
  111. r = gReader.read()
  112. if id in r:
  113. r = r[id] #--matrix
  114. series = []
  115. for row in r:
  116. series += [item for item in row if str(item['label'])== app]
  117. if len(series) > 12 :
  118. beg = len(series) - 8
  119. series = series[beg:]
  120. return json.dumps(series)
  121. else:
  122. return "[]"
  123. @app.route('/download',methods=['POST'])
  124. def requirements():
  125. stream = request.form['missing']
  126. print stream
  127. stream = "\n".join(json.loads(stream))
  128. headers = {"content-disposition":"attachment; filename=requirements.txt"}
  129. return Response(stream,mimetype='text/plain',headers=headers)
  130. @app.route('/dashboard')
  131. def dashboard():
  132. context = PARAMS['context']
  133. if 'title' in PARAMS :
  134. title = PARAMS['title']
  135. else:
  136. title = 'Zulu OverWatch'
  137. return render_template('dashboard.html',context=context,title=title)
  138. """
  139. This function is designed to trigger learning for anomaly detection
  140. @TODO: forward this to a socket i.e non-blocking socket
  141. """
  142. @app.route('/anomalies/get')
  143. def learn():
  144. global CONFIG
  145. p = CONFIG['store']['args']
  146. class_read = CONFIG['store']['class']['read']
  147. gReader = factory.instance(type=class_read,args=p)
  148. d = gReader.read()
  149. if 'learn' in d :
  150. info = d['learn']
  151. del d['learn']
  152. else :
  153. info = []
  154. r = []
  155. if 'id' in request.args:
  156. id = request.args['id']
  157. d = d[id]
  158. params = {}
  159. for item in info:
  160. label = item['label']
  161. params[label] = item
  162. #apps = list(set(ML.Extract(['label'],d)))
  163. r = []
  164. if params :
  165. #
  166. # If we have parameters available
  167. p = AnomalyDetection()
  168. apps = params.keys()
  169. for name in apps :
  170. if name not in params:
  171. continue
  172. _info = params[name]
  173. try:
  174. xo = ML.Filter('label',name,d)
  175. except Exception,e:
  176. xo = []
  177. #print name,e
  178. if len(xo) == 0:
  179. continue
  180. xo = [xo[ len(xo) -1]]
  181. value = p.predict(xo,_info)[0]
  182. if len(value):
  183. report = dict(_info,**{'predicton':value})
  184. r.append(report)
  185. #print app,value
  186. #if value is not None:
  187. # r.append(value)
  188. return json.dumps(r)
  189. """
  190. This function returns anomalies for a given context or group of processes
  191. The information returned is around precision/recall and f-score and parameters
  192. """
  193. @app.route('/anomalies/status')
  194. def anomalies_status():
  195. global CONFIG
  196. p = CONFIG['store']['args']
  197. class_read = CONFIG['store']['class']['read']
  198. gReader = factory.instance(type=class_read,args=p)
  199. d = gReader.read()
  200. if 'learn' in d :
  201. info = d['learn']
  202. del d['learn']
  203. else :
  204. info = []
  205. print info
  206. r = []
  207. if 'id' in request.args:
  208. id = request.args['id']
  209. r = info
  210. return json.dumps(r)
  211. @app.route('/folders')
  212. def get_folders():
  213. global CONFIG
  214. p = CONFIG['store']['args']
  215. class_read = CONFIG['store']['class']['read']
  216. gReader = factory.instance(type=class_read,args=p)
  217. d = gReader.read()
  218. if 'folders' in d:
  219. d = d['folders']
  220. hosts = set([row[0]['id'] for row in d])
  221. m = {}
  222. for id in hosts:
  223. for row in d:
  224. if id == row[0]['id'] :
  225. m[id] = row
  226. d = m.values()
  227. for row in d:
  228. print row[0]['id']
  229. # index = len(d) - 1
  230. # d = d[index]
  231. # m = {}
  232. # for row in d :
  233. # key = row.keys()[0]
  234. # row = row[key]
  235. # if key not in m:
  236. # r.append(row)
  237. # m[key] = len(r) -1
  238. # else:
  239. # index = m[key]
  240. # r[index] = row
  241. # d = r
  242. else:
  243. d = []
  244. return json.dumps(d)
  245. if __name__== '__main__':
  246. # ThreadManager.start(CONFIG)
  247. if 'port' not in SYS_ARGS.PARAMS :
  248. SYS_ARGS.PARAMS['port'] = 5000
  249. PORT = int(SYS_ARGS.PARAMS['port'])
  250. app.run(host='0.0.0.0',port=PORT,debug=True,threaded=True)