Skip to content

Instantly share code, notes, and snippets.

@bigsnarfdude
Last active April 5, 2020 02:50
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bigsnarfdude/a833143c198982710d85 to your computer and use it in GitHub Desktop.
Save bigsnarfdude/a833143c198982710d85 to your computer and use it in GitHub Desktop.
cloudtrail console login on slack
#! /usr/local/env python
# coding: utf-8
import gzip
import json
from pprint import pprint
import pandas as pd
from pandas.io.json import json_normalize
import sys
import socket
import boto
import os
import ipaddress
import asyncio
import glob
from urllib.parse import urljoin
from urllib.parse import urlencode
import urllib.request as urlrequest
class Slack():
def __init__(self, url=""):
self.url = url
self.opener = urlrequest.build_opener(urlrequest.HTTPHandler())
def notify(self, **kwargs):
"""
Send message to slack API
"""
return self.send(kwargs)
def send(self, payload):
"""
Send payload to slack API
"""
payload_json = json.dumps(payload)
data = urlencode({"payload": payload_json})
req = urlrequest.Request(self.url)
response = self.opener.open(req, data.encode('utf-8')).read()
return response.decode('utf-8')
class CloudtrailAnalysis():
@staticmethod
def check_value(file_name, df_data, value):
if df_data[df_data['eventName'] == value].empty:
pass
else:
frame = df_data[df_data['eventName'] == value]
#print(df_data[df_data['eventName'] == value])
try:
normalized_name = frame['userIdentity.userName'].values[0]
except:
normalized_name = "noNameFound"
result = value, frame['eventTime'].values[0], frame['sourceIPAddress'].values[0], normalized_name
#print(file_name)
return result
async def get_file_analyse_local_events(zipped, event, outgoing_message):
#print("+++ Found new log: ", f)
with gzip.open(zipped, "rb") as f:
d = json.loads(f.read().decode("ascii"))
records = d["Records"]
df_data = json_normalize(records)
if CloudtrailAnalysis.check_value(zipped, df_data, event) == None:
pass
else:
outgoing_message.append(CloudtrailAnalysis.check_value(zipped, df_data, event))
return CloudtrailAnalysis.check_value(zipped, df_data, event)
async def main(unzipped, event, outgoing_message):
await get_file_analyse_local_events(unzipped, event, outgoing_message)
"""
($.eventName=CreateTrail)
($.eventName=UpdateTrail)
($.eventName=DeleteTrail)
($.eventName=DeleteGroupPolicy)
($.eventName=DeleteRolePolicy)
($.eventName=DeleteUserPolicy)
($.eventName=PutGroupPolicy)
($.eventName=PutRolePolicy)
($.eventName=PutUserPolicy)
($.eventName=CreatePolicy)
($.eventName=DeletePolicy)
($.eventName=CreatePolicyVersion)
($.eventName=DeletePolicyVersion)
($.eventName=AttachRolePolicy)
($.eventName=DetachRolePolicy)
($.eventName=AttachUserPolicy)
($.eventName=DetachUserPolicy)
($.eventName=AttachGroupPolicy)
($.eventName=DetachGroupPolicy)
"""
#security_events = ['ConsoleLogin','CreateKeyPair', 'CheckMfa','PutUserPolicy','DeleteTrail']
# list group of Cloudtrail logs you want processed
hdd_files = glob.glob("/Users/bigsnarfdude/cloudtrail_logs/*.json.gz")
security_events = ['ConsoleLogin']
outgoing_message = []
loop = asyncio.get_event_loop()
for zipped in hdd_files:
for event in security_events:
loop.run_until_complete(main(zipped, event, outgoing_message))
loop.close()
deduped = [ str(x) for x in list(set(outgoing_message))]
sort_deduped = deduped.sort()
post = "\n".join(deduped)
# put in the details of your slack webhook
slack = Slack(url="https://hooks.slack.com/services/asdfasdf/qwerqwer/asdfqwerasdfqwer")
slack.notify(text=post, channel="#testing", username="security-bot", icon_emoji=":robot_face:")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment