MozDef/rest/index.py

194 строки
7.2 KiB
Python
Исходник Обычный вид История

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Copyright (c) 2014 Mozilla Corporation
#
# Contributors:
# Jeff Bryner jbryner@mozilla.com
2014-02-18 11:55:10 +04:00
import sys
import bottle
from bottle import debug,route, run, template, response,request,post, default_app
from bottle import _stdout as bottlelog
import json
from configlib import getConfig,OptionParser
import pyes
from elasticutils import S
from datetime import datetime
from datetime import timedelta
from dateutil.parser import parse
import pytz
options=None
# cors decorator for rest/ajax
def enable_cors(fn):
def _enable_cors(*args, **kwargs):
# set CORS headers
response.headers['Access-Control-Allow-Origin'] = '*'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
if bottle.request.method != 'OPTIONS':
# actual request; reply with the actual response
return fn(*args, **kwargs)
return _enable_cors
@route('/test')
@route('/test/')
def index():
ip = request.environ.get('REMOTE_ADDR')
#response.headers['X-IP'] = '{0}'.format(ip)
response.status=200
@route('/status')
@route('/status/')
def index():
if request.body:
request.body.read()
request.body.close()
response.status=200
response.content_type="application/json"
return(json.dumps(dict(status='ok')))
@route('/ldapLogins')
@route('/ldapLogins/')
@enable_cors
def index():
if request.body:
request.body.read()
request.body.close()
response.content_type="application/json"
return(esLdapResults())
@route('/alerts')
@route('/alerts/')
@enable_cors
def index():
if request.body:
request.body.read()
request.body.close()
response.content_type="application/json"
return(esAlertsSummary())
#debug(True)
def toUTC(suspectedDate,localTimeZone="US/Pacific"):
'''make a UTC date out of almost anything'''
utc=pytz.UTC
objDate=None
if type(suspectedDate)==str:
objDate=parse(suspectedDate,fuzzy=True)
elif type(suspectedDate)==datetime:
objDate=suspectedDate
if objDate.tzinfo is None:
objDate=pytz.timezone(localTimeZone).localize(objDate)
objDate=utc.normalize(objDate)
else:
objDate=utc.normalize(objDate)
if objDate is not None:
objDate=utc.normalize(objDate)
return objDate
def esAlertsSummary(begindateUTC=None, enddateUTC=None):
resultsList=list()
if begindateUTC is None:
begindateUTC=datetime.now() - timedelta(hours=12)
begindateUTC=toUTC(begindateUTC)
if enddateUTC is None:
enddateUTC= datetime.now()
enddateUTC= toUTC(enddateUTC)
try:
#q=S().es(urls=['http://{0}:{1}'.format(options.esserver,options.esport)]).query(_type='alert').filter(utctimestamp__range=[begindateUTC.isoformat(),enddateUTC.isoformat()])
#f=q.facet_raw(alerttype={"terms" : {"script_field" : "_source.type","size" : 500}})
#get all alerts
2014-03-20 23:37:19 +04:00
#q= S().es(urls=['http://{0}:{1}'.format(options.esserver,options.esport)]).query(_type='alert')
q= S().es(urls=list('{0}'.format(s) for s in options.esservers)).query(_type='alert')
2014-04-14 03:17:37 +04:00
#create a facet field using the entire 'category' field (not the sub terms) and filter it by date.
2014-02-18 11:55:10 +04:00
f=q.facet_raw(\
alerttype={"terms" : {"script_field" : "_source.category"},\
"facet_filter":{'range': {'utctimestamp': \
{'gte': begindateUTC.isoformat(), 'lte': enddateUTC.isoformat()}}}\
})
return(json.dumps(f.facet_counts()['alerttype']))
except Exception as e :
sys.stderr.write('%r'%e)
def esLdapResults(begindateUTC=None, enddateUTC=None):
resultsList=list()
if begindateUTC is None:
begindateUTC=datetime.now() - timedelta(hours=12)
begindateUTC=toUTC(begindateUTC)
if enddateUTC is None:
enddateUTC= datetime.now()
enddateUTC= toUTC(enddateUTC)
try:
2014-03-20 23:37:19 +04:00
es=pyes.ES((list('{0}'.format(s) for s in options.esservers)))
2014-02-18 11:55:10 +04:00
#qDate=e=pyes.MatchQuery("message",options.datePhrase,"phrase")
qDate=pyes.RangeQuery(qrange=pyes.ESRange('utctimestamp',from_value=begindateUTC,to_value=enddateUTC))
q = pyes.MatchAllQuery()
q = pyes.FilteredQuery(q,qDate)
q = pyes.FilteredQuery(q,pyes.TermFilter('tags','ldap'))
q = pyes.FilteredQuery(q,pyes.TermFilter('details.result','ldap_invalid_credentials'))
q2=q.search()
q2.facet.add_term_facet('details.result')
q2.facet.add_term_facet('details.dn',size=20)
2014-04-14 03:17:37 +04:00
results=es.search(q2, indices='events')
2014-02-18 11:55:10 +04:00
#sys.stdout.write('{0}\n'.format(results.facets))
stoplist=('o','mozilla','dc','com','mozilla.com','mozillafoundation.org','org')
for t in results.facets['details.dn'].terms:
if t['term'] in stoplist:
continue
#print(t['term'])
failures=0
success=0
dn=t['term']
#re-query with the terms of the details.dn
qt = pyes.MatchAllQuery()
qt = pyes.FilteredQuery(qt,qDate)
qt = pyes.FilteredQuery(qt,pyes.TermFilter('tags','ldap'))
qt = pyes.FilteredQuery(qt,pyes.TermFilter('details.dn',t['term']))
qt2=qt.search()
qt2.facet.add_term_facet('details.result')
results=es.search(qt2)
#sys.stdout.write('{0}\n'.format(results.facets['details.result'].terms))
for t in results.facets['details.result'].terms:
#print(t['term'],t['count'])
if t['term']=='ldap_success':
success=t['count']
if t['term']=='ldap_invalid_credentials':
failures=t['count']
resultsList.append(dict(dn=dn,failures=failures,success=success,begin=begindateUTC.isoformat(),end=enddateUTC.isoformat()))
return(json.dumps(resultsList))
except pyes.exceptions.NoServerAvailable:
sys.stderr.write('Elastic Search server could not be reached, check network connectivity\n')
def initConfig():
#change this to your default zone for when it's not specified
options.defaultTimeZone=getConfig('defaulttimezone','US/Pacific',options.configfile)
2014-03-20 23:37:19 +04:00
options.esservers=list(getConfig('esservers','http://localhost:9200',options.configfile).split(','))
print(options)
2014-02-18 11:55:10 +04:00
if __name__ == "__main__":
parser=OptionParser()
2014-03-20 23:37:19 +04:00
parser.add_option("-c", dest='configfile' , default=sys.argv[0].replace('.py','.conf'), help="configuration file to use")
2014-02-18 11:55:10 +04:00
(options,args) = parser.parse_args()
initConfig()
run(host="localhost", port=8081)
else:
parser=OptionParser()
2014-03-20 23:37:19 +04:00
parser.add_option("-c", dest='configfile' , default=sys.argv[0].replace('.py','.conf'), help="configuration file to use")
2014-02-18 11:55:10 +04:00
(options,args) = parser.parse_args()
initConfig()
application = default_app()