зеркало из https://github.com/mozilla/MozDef.git
131 строка
5.8 KiB
Python
Executable File
131 строка
5.8 KiB
Python
Executable File
#!/usr/bin/env 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
|
|
|
|
import os
|
|
import sys
|
|
from configlib import getConfig,OptionParser,setConfig
|
|
import logging
|
|
from logging.handlers import SysLogHandler
|
|
import boto
|
|
import gzip
|
|
from StringIO import StringIO
|
|
import json
|
|
import time
|
|
import pyes
|
|
from datetime import datetime
|
|
from datetime import timedelta
|
|
from dateutil.parser import parse
|
|
from datetime import date
|
|
import pytz
|
|
|
|
logger = logging.getLogger(sys.argv[0])
|
|
logger.level=logging.INFO
|
|
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s %(message)s')
|
|
|
|
def toUTC(suspectedDate,localTimeZone=None):
|
|
'''make a UTC date out of almost anything'''
|
|
utc=pytz.UTC
|
|
objDate=None
|
|
if localTimeZone is None:
|
|
localTimeZone=options.defaultTimeZone
|
|
if type(suspectedDate) in (str,unicode):
|
|
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 main():
|
|
if options.output=='syslog':
|
|
logger.addHandler(SysLogHandler(address=(options.sysloghostname,options.syslogport)))
|
|
else:
|
|
sh=logging.StreamHandler(sys.stderr)
|
|
sh.setFormatter(formatter)
|
|
logger.addHandler(sh)
|
|
|
|
logger.debug('started')
|
|
#logger.debug(options)
|
|
try:
|
|
es=pyes.ES((list('{0}'.format(s) for s in options.esservers)))
|
|
boto.connect_cloudtrail(aws_access_key_id=options.aws_access_key_id,aws_secret_access_key=options.aws_secret_access_key)
|
|
#capture the time we start running so next time we catch any files created while we run.
|
|
lastrun=toUTC(datetime.now()).isoformat()
|
|
#in case we don't archive files..only look at today and yesterday's files.
|
|
yesterday=date.strftime(datetime.utcnow()-timedelta(days=1),'%Y/%m/%d')
|
|
today = date.strftime(datetime.utcnow(),'%Y/%m/%d')
|
|
for region in boto.cloudtrail.regions():
|
|
logger.debug('connecting to AWS region {0}'.format(region.name))
|
|
ct=boto.cloudtrail.connect_to_region(region.name,aws_access_key_id=options.aws_access_key_id,aws_secret_access_key=options.aws_secret_access_key)
|
|
trails=ct.describe_trails()['trailList']
|
|
|
|
for trail in trails:
|
|
s3 = boto.connect_s3(aws_access_key_id=options.aws_access_key_id,aws_secret_access_key=options.aws_secret_access_key)
|
|
ctbucket=s3.get_bucket(trail['S3BucketName'])
|
|
#ctbucket.get_all_keys()
|
|
filelist=list()
|
|
for bfile in ctbucket.list():
|
|
|
|
if 'CloudTrail' in bfile.key and 'json' in bfile.key:
|
|
if today in bfile.key or yesterday in bfile.key:
|
|
filelist.append(bfile.key)
|
|
else:
|
|
if options.purge: #delete old files so we don't try to keep reading them.
|
|
s3file=ctbucket.get_key(afile)
|
|
s3file.delete()
|
|
for afile in filelist:
|
|
s3file=ctbucket.get_key(afile)
|
|
logger.debug('{0} {1}'.format(afile,s3file.last_modified))
|
|
|
|
if toUTC(s3file.last_modified)>options.lastrun:
|
|
compressedData=s3file.read()
|
|
databuf=StringIO(compressedData)
|
|
f=gzip.GzipFile(fileobj=databuf)
|
|
jlog=json.loads(f.read())
|
|
try:
|
|
for r in jlog['Records']:
|
|
r['utctimestamp']=toUTC(r['eventTime']).isoformat()
|
|
jbody=json.dumps(r)
|
|
res=es.index(index='events',doc_type='cloudtrail',doc=jbody)
|
|
#logger.debug(res)
|
|
except Exception as e:
|
|
logger.error('Error handling log record {0} {1}'.format(r, e))
|
|
continue
|
|
setConfig('lastrun',lastrun,options.configfile)
|
|
except boto.exception.NoAuthHandlerFound:
|
|
logger.error("No auth handler found, check your credentials")
|
|
except Exception as e:
|
|
logger.error("Unhandled exception, terminating: %r"%e)
|
|
|
|
|
|
def initConfig():
|
|
options.output=getConfig('output','stdout',options.configfile) #output our log to stdout or syslog
|
|
options.sysloghostname=getConfig('sysloghostname','localhost',options.configfile) #syslog hostname
|
|
options.syslogport=getConfig('syslogport',514,options.configfile) #syslog port
|
|
options.defaultTimeZone=getConfig('defaulttimezone','US/Pacific',options.configfile)
|
|
options.aws_access_key_id=getConfig('aws_access_key_id','',options.configfile) #aws credentials to use to connect to cloudtrail
|
|
options.aws_secret_access_key=getConfig('aws_secret_access_key','',options.configfile)
|
|
options.esservers=list(getConfig('esservers','http://localhost:9200',options.configfile).split(','))
|
|
options.lastrun=toUTC(getConfig('lastrun',toUTC(datetime.now()-timedelta(hours=1)),options.configfile))
|
|
options.purge=getConfig('purge',False,options.configfile)
|
|
|
|
if __name__ == '__main__':
|
|
parser=OptionParser()
|
|
parser.add_option("-c", dest='configfile' , default='{0}.conf'.format(sys.argv[0]), help="configuration file to use")
|
|
(options,args) = parser.parse_args()
|
|
initConfig()
|
|
main()
|