You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.8 KiB
73 lines
2.8 KiB
import logging
|
|
from collections import Iterable
|
|
from apiclient import discovery
|
|
from oauth2client.service_account import ServiceAccountCredentials
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
TIMESTAMP_FIELD = "id.time"
|
|
USER_FIELD = "actor.email"
|
|
IP_FIELD = "ipAddress"
|
|
USER_AGENT_FIELD = "events.0.login_type"
|
|
FILTER_FIELD = "events.0.name"
|
|
FILTERED_EVENTS = ["login_failure"]
|
|
|
|
|
|
def poll(config):
|
|
data = []
|
|
scopes = ['https://www.googleapis.com/auth/admin.reports.audit.readonly']
|
|
credentials = ServiceAccountCredentials.from_json_keyfile_name(config["pollers"]["gsuite"]["credential_file"], scopes=scopes)
|
|
credentials = credentials.create_delegated(config["pollers"]["gsuite"]["admin_email"])
|
|
service = discovery.build('admin', 'reports_v1', credentials=credentials)
|
|
request = service.activities().list(userKey='all', applicationName='login')
|
|
for i in range(1, 101):
|
|
logger.info("Polling page %s..." % i)
|
|
results = request.execute()
|
|
activities = results.get('items', [])
|
|
for event in activities:
|
|
flattened = flatten(event)
|
|
if flattened[TIMESTAMP_FIELD] > str(config["last_polled"]["gsuite"]["last_polled_time"]):
|
|
data.append(flattened)
|
|
elif flattened[TIMESTAMP_FIELD] == str(config["last_polled"]["gsuite"]["last_polled_time"]):
|
|
if flattened["id.uniqueQualifier"] == config["last_polled"]["gsuite"]["last_polled_event"]["id.uniqueQualifier"]:
|
|
caught_up = True
|
|
break
|
|
else:
|
|
data.append(flattened)
|
|
else:
|
|
caught_up = True
|
|
break
|
|
request = service.activities().list_next(request, results)
|
|
if caught_up or request is None:
|
|
break
|
|
return data
|
|
|
|
|
|
def notify(config, alerts):
|
|
return
|
|
|
|
|
|
def flatten(event, prefix=''):
|
|
flattened = {}
|
|
for field_no, field in enumerate(event):
|
|
if 'keys' in dir(event):
|
|
# Special case "parameters" values. We should to treat those as dicts.
|
|
if field == "parameters":
|
|
for param in event[field]:
|
|
if isinstance(param["value"], Iterable) and not isinstance(param["value"], str):
|
|
flattened.update(param["value"], prefix + param["name"] + ".")
|
|
else:
|
|
flattened[prefix + param["name"]] = param["value"]
|
|
continue
|
|
else:
|
|
nextLevel = event[field]
|
|
currEntry = prefix + str(field)
|
|
else:
|
|
nextLevel = event[field_no]
|
|
currEntry = prefix + str(field_no)
|
|
if isinstance(nextLevel, Iterable) and not isinstance(nextLevel, str):
|
|
flattened.update(flatten(nextLevel, currEntry + "."))
|
|
else:
|
|
flattened[currEntry] = nextLevel
|
|
return flattened
|
|
|