def process_msg(mozmsg, msg): """Normalization function for auth0 msg. @mozmsg: MozDefEvent (mozdef message as DotDict) @msg: DotDict (json with auth0 raw message data). All the try-except loops handle cases where the auth0 msg may or may not contain expected fields. The msg structure is not garanteed. See also https://auth0.com/docs/api/management/v2#!/Logs/get_logs """ details = DotDict({}) # key words used to set category and success/failure markers authentication_words = ["Login", "Logout", "Silent", "Enrollment", "OTP", "Recovery", "Authentication", "Code", "Signup", "Push"] authorization_words = ["Authorization", "Access", "Delegation"] administration_words = ["API", "Operation", "Change", "Update", "Deleted", "unenrolled", "updated", "CORS", "Connector", "Blocked", "Breached", "Deletion", "block", "User", "released"] success_words = ["Success"] failed_words = ["Failed"] # fields that should always exist mozmsg.timestamp = msg.date details["messageid"] = msg._id details["sourceipaddress"] = msg.ip try: details["userid"] = msg.user_id except KeyError: pass try: if msg.user_name: details["username"] = msg.user_name except KeyError: pass try: # the details.request/response exist for api calls # but not for logins and other events # check and prefer them if present. if type(msg.details.response.body) is not list: details["action"] = msg.details.response.body.name except KeyError: pass try: if "email" in msg.details.response.body and msg.details.response.body.email is not None: details["email"] = msg.details.response.body.email except KeyError: pass try: details["useragent"] = msg.user_agent except KeyError: pass try: if msg.client_name: details["clientname"] = msg.client_name except KeyError: pass try: if msg.connection: details["connection"] = msg.connection except KeyError: pass try: if msg.client_id: details["clientid"] = msg.client_id except KeyError: pass try: # auth0 calls these events with an acronym and name details["eventname"] = log_types[msg.type].event # determine the event category if any(authword in details["eventname"] for authword in authentication_words): mozmsg.set_category("authentication") if any(authword in details["eventname"] for authword in authorization_words): mozmsg.set_category("authorization") if any(adminword in details["eventname"] for adminword in administration_words): mozmsg.set_category("administration") # determine success/failure if any(failword in details["eventname"] for failword in failed_words): details.success = False if any(successword in details["eventname"] for successword in success_words): details.success = True except KeyError: # New message type, check https://manage-dev.mozilla.auth0.com/docs/api/management/v2#!/Logs/get_logs for ex. logger.error("New auth0 message type, please add support: {}".format(msg.type)) details["eventname"] = msg.type # determine severity level if log_types[msg.type].level == 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_ERROR) elif log_types[msg.type].level > 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_CRITICAL) # default description details["description"] = "" try: if "description" in msg and msg.description is not None: # use the detailed description of the operation sent from auth0 # Update a rule, add a site, update a site, etc details["description"] = msg.description except KeyError: pass # set the summary # make summary be action/username (success login [email protected]) # if no details.username field exists we don't add it. # Build summary if neither email, description, nor username exists if 'eventname' in details: mozmsg.summary = "{event}".format(event=details.eventname) if 'description' in details and details['description'] != "None": mozmsg.summary += " {description}".format(event=details.eventname, description=details.description) if 'username' in details and details['username'] != "None": mozmsg.summary += " by {username}".format(username=details.username) if 'email' in details and details['email'] != "None": mozmsg.summary += " account: {email}".format(email=details.email) if 'clientname' in details and details['clientname'] != "None": mozmsg.summary += " to: {clientname}".format(clientname=details.clientname) # Get user data if present in response body try: if "multifactor" in msg.details.response.body and type(msg.details.response.body.multifactor) is list: details.mfa_provider = msg.details.response.body.multifactor except KeyError: pass try: if "ldap_groups" in msg.details.response.body and type(msg.details.response.body.ldap_groups) is list: details.ldap_groups = msg.details.response.body.ldap_groups except KeyError: pass try: if "last_ip" in msg.details.response.body and msg.details.response.body.last_ip is not None: details.user_last_known_ip = msg.details.response.body.last_ip except KeyError: pass try: if "last_login" in msg.details.response.body and msg.details.response.body.last_login is not None: details.user_last_login = msg.details.response.body.last_login except KeyError: pass # Differentiate auto login (session cookie check validated) from logged in and had password verified try: for i in msg.details.prompt: # Session cookie check if i.get("name") == "authenticate": details["authtype"] = "Login succeeded due to a valid session cookie being supplied" elif i.get("name") == "lock-password-authenticate": details["authtype"] = "Login succeeded due to a valid plaintext password being supplied" except KeyError: pass mozmsg.details = details return mozmsg
def process_msg(mozmsg, msg): """Normalization function for auth0 msg. @mozmsg: MozDefEvent (mozdef message as DotDict) @msg: DotDict (json with auth0 raw message data). All the try-except loops handle cases where the auth0 msg may or may not contain expected fields. The msg structure is not garanteed. See also https://auth0.com/docs/api/management/v2#!/Logs/get_logs """ details = DotDict({}) # defaults details.username = "******" details.userid = "UNKNOWN" # key words used to set category and success/failure markers authentication_words = ['Login', 'Logout', 'Auth'] authorization_words = ['Authorization', 'Access', 'Delegation'] success_words = ['Success'] failed_words = ['Failed'] # default category (might be modified below to be more specific) mozmsg.set_category('iam') mozmsg.source = 'auth0' # fields that should always exist mozmsg.timestamp = msg.date details['messageid'] = msg._id details['sourceipaddress'] = msg.ip try: details['userid'] = msg.user_id except KeyError: pass try: details['username'] = msg.user_name except KeyError: pass try: # the details.request/response exist for api calls # but not for logins and other events # check and prefer them if present. details['username'] = msg.details.request.auth.user.name details['action'] = msg.details.response.body.name except KeyError: pass try: details['useragent'] = msg.user_agent except KeyError: pass try: # auth0 calls these events with an acronym and name details['eventname'] = log_types[msg.type].event # determine the event category if any(authword in details['eventname'] for authword in authentication_words): mozmsg.set_category("authentication") if any(authword in details['eventname'] for authword in authorization_words): mozmsg.set_category("authorization") # determine success/failure if any(failword in details['eventname'] for failword in failed_words): details.success = False if any(successword in details['eventname'] for successword in success_words): details.success = True except KeyError: # New message type, check https://manage-dev.mozilla.auth0.com/docs/api/management/v2#!/Logs/get_logs for ex. debug('New auth0 message type, please add support: {}'.format( msg.type)) details['eventname'] = msg.type # determine severity level if log_types[msg.type].level == 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_ERROR) elif log_types[msg.type].level > 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_CRITICAL) # default description details['description'] = "" try: if 'description' in msg and msg.description is not None: # use the detailed description of the operation sent from auth0 # Update a rule, add a site, update a site, etc details['description'] = msg.description except KeyError: details['description'] = "" # set the summary if 'auth' in mozmsg._category: # make summary be action/username (success login [email protected]) mozmsg.summary = "{event} {desc}".format(event=details.eventname, desc=details.username) else: # default summary as action and description (if it exists) mozmsg.summary = "{event} {desc}".format(event=details.eventname, desc=details.description) try: details['clientname'] = msg.client_name except KeyError: pass try: details['connection'] = msg.connection except KeyError: pass try: details['clientid'] = msg.client_id except KeyError: pass # Differenciate auto login (session cookie check validated) from logged in and had password verified try: for i in msg.details.prompt: # Session cookie check if i.get('name') == 'authenticate': details[ 'authtype'] = 'Login succeeded due to a valid session cookie being supplied' elif i.get('name') == 'lock-password-authenticate': details[ 'authtype'] = 'Login succeeded due to a valid plaintext password being supplied' except KeyError: pass mozmsg.details = details mozmsg.details['raw'] = str(msg) return mozmsg
def process_msg(mozmsg, msg): """Normalization function for auth0 msg. @mozmsg: MozDefEvent (mozdef message as DotDict) @msg: DotDict (json with auth0 raw message data). All the try-except loops handle cases where the auth0 msg may or may not contain expected fields. The msg structure is not garanteed. See also https://auth0.com/docs/api/management/v2#!/Logs/get_logs """ details = DotDict({}) # defaults details.username = "******" details.userid = "UNKNOWN" # key words used to set category and success/failure markers authentication_words = ["Login", "Logout", "Auth"] authorization_words = ["Authorization", "Access", "Delegation"] success_words = ["Success"] failed_words = ["Failed"] # default category (might be modified below to be more specific) mozmsg.set_category("iam") mozmsg.source = "auth0" # fields that should always exist mozmsg.timestamp = msg.date details["messageid"] = msg._id details["sourceipaddress"] = msg.ip try: details["userid"] = msg.user_id except KeyError: pass try: details["username"] = msg.user_name except KeyError: pass try: # the details.request/response exist for api calls # but not for logins and other events # check and prefer them if present. details["username"] = msg.details.request.auth.user.name details["action"] = msg.details.response.body.name except KeyError: pass try: details["useragent"] = msg.user_agent except KeyError: pass try: # auth0 calls these events with an acronym and name details["eventname"] = log_types[msg.type].event # determine the event category if any(authword in details["eventname"] for authword in authentication_words): mozmsg.set_category("authentication") if any(authword in details["eventname"] for authword in authorization_words): mozmsg.set_category("authorization") # determine success/failure if any(failword in details["eventname"] for failword in failed_words): details.success = False if any(successword in details["eventname"] for successword in success_words): details.success = True except KeyError: # New message type, check https://manage-dev.mozilla.auth0.com/docs/api/management/v2#!/Logs/get_logs for ex. debug("New auth0 message type, please add support: {}".format(msg.type)) details["eventname"] = msg.type # determine severity level if log_types[msg.type].level == 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_ERROR) elif log_types[msg.type].level > 3: mozmsg.set_severity(mozdef.MozDefEvent.SEVERITY_CRITICAL) # default description details["description"] = "" try: if "description" in msg and msg.description is not None: # use the detailed description of the operation sent from auth0 # Update a rule, add a site, update a site, etc details["description"] = msg.description except KeyError: details["description"] = "" # set the summary if "auth" in mozmsg._category: # make summary be action/username (success login [email protected]) mozmsg.summary = "{event} {desc}".format(event=details.eventname, desc=details.username) else: # default summary as action and description (if it exists) mozmsg.summary = "{event} {desc}".format(event=details.eventname, desc=details.description) try: details["clientname"] = msg.client_name except KeyError: pass try: details["connection"] = msg.connection except KeyError: pass try: details["clientid"] = msg.client_id except KeyError: pass # Differenciate auto login (session cookie check validated) from logged in and had password verified try: for i in msg.details.prompt: # Session cookie check if i.get("name") == "authenticate": details["authtype"] = "Login succeeded due to a valid session cookie being supplied" elif i.get("name") == "lock-password-authenticate": details["authtype"] = "Login succeeded due to a valid plaintext password being supplied" except KeyError: pass mozmsg.details = details mozmsg.details["raw"] = str(msg) return mozmsg