Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Have the ldap_group alert aggregate on details.email (#1642)
Browse files Browse the repository at this point in the history
* Have the ldap_fixup mq plugin parse the email and username out of an actor string and add them to ldap events

* Set email and username to none when not parsed out of details.actor

* Have the ldapGroupModify alert aggregate on the new details.email field

* Wildcards around member

* Shorten line > 80 characters

* Import syntax fix
  • Loading branch information
arcrose committed Jun 24, 2020
1 parent bfea37d commit da5546f
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 10 deletions.
26 changes: 18 additions & 8 deletions alerts/ldap_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
# Copyright (c) 2014 Mozilla Corporation

from lib.alerttask import AlertTask
from mozdef_util.query_models import SearchQuery, TermMatch, PhraseMatch, WildcardMatch
from mozdef_util.query_models import\
PhraseMatch,\
SearchQuery,\
TermMatch,\
WildcardMatch


class ldapGroupModify(AlertTask):
Expand All @@ -22,20 +26,26 @@ def main(self):
# ignore test accounts and attempts to create accounts that already exist.
search_query.add_must_not([
WildcardMatch('details.actor', '*bind*'),
WildcardMatch('details.changepairs', '*delete:member*')
WildcardMatch('details.changepairs', 'delete:*member*')
])

self.filtersManual(search_query)
# Search events
self.searchEventsSimple()
self.walkEvents()
self.searchEventsAggregated('details.email', samplesLimit=50)
self.walkAggregations(threshold=1, config={})

# Set alert properties
def onEvent(self, event):
def onAggregation(self, agg):
email = agg['value']
events = agg['events']

category = 'ldap'
tags = ['ldap']
severity = 'INFO'
summary = '{0}'.format(event['_source']['summary'])

if email is None:
summary = 'LDAP group change detected'
else:
summary = 'LDAP group change initiated by {0}'.format(email)

# Create the alert object based on these properties
return self.createAlertDict(summary, category, tags, [event], severity)
return self.createAlertDict(summary, category, tags, events, severity)
35 changes: 35 additions & 0 deletions mq/plugins/ldap_fixup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2014 Mozilla Corporation

import typing as types

from mozdef_util.utilities.key_exists import key_exists


Expand All @@ -28,4 +30,37 @@ def onMessage(self, message, metadata):
if 'source' not in message:
message['source'] = 'ldap'

details = message.get('details', {})
actor_str = details.get('actor', '')
actor_email = _parse_email_from_actor(actor_str)

if actor_email is None:
details['email'] = None
details['username'] = None

message['details'] = details

return (message, metadata)

username = actor_email.split('@')[0]

details['email'] = actor_email
details['username'] = username

message['details'] = details

return (message, metadata)


def _parse_email_from_actor(actor_str: str) -> types.Optional[str]:
'''Parse the email from a string like
`"mail=username@mozilla.com,o=com,dc=mozilla"`
'''

mapping = dict([
pair.split('=')
for pair in actor_str.split(',')
if '=' in pair
])

return mapping.get('mail')
6 changes: 4 additions & 2 deletions tests/alerts/test_ldap_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class TestldapGroupModify(AlertTestSuite):
"details": {
"dn": "cn=example_cn,ou=groups,dc=example",
"changetype": "modify",
"actor": "mail=user_la@example.com,o=com,dc=example"
"actor": "mail=user_la@example.com,o=com,dc=example",
"email": "user_la@example.com",
"username": "user_la"
},
"category": "ldapChange",
"processid": "1697",
Expand All @@ -30,7 +32,7 @@ class TestldapGroupModify(AlertTestSuite):
"category": "ldap",
"tags": ["ldap"],
"severity": "INFO",
"summary": "mail=user_la@example.com,o=com,dc=example modify cn=example_cn,ou=groups,dc=example add:memberUid: anotheruser@example.com",
"summary": "LDAP group change initiated by user_la@example.com",
}

test_cases = []
Expand Down
20 changes: 20 additions & 0 deletions tests/mq/plugins/test_ldap_fixup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def test_ldap_fixup_plugin(self):
'details': {
'tls': 'true',
'authenticated': 'true',
'actor': 'o=com,mail=tester@mozilla.com,dc=mozilla'
}
}
(retmessage, retmeta) = self.plugin.onMessage(msg, {})
Expand All @@ -30,7 +31,26 @@ def test_ldap_fixup_plugin(self):
'details': {
'tls_encrypted': 'true',
'authenticated': 'true',
'email': 'tester@mozilla.com',
'username': 'tester',
'actor': 'o=com,mail=tester@mozilla.com,dc=mozilla'
}
}
assert retmessage == expected_message
assert retmeta == {}

def test_ldap_fixup_missing_actor(self):
msg = {
'summary': 'LDAP-Humanizer:45582:1.1.1.1',
'hostname': 'random.host.com',
'category': 'ldap',
'details': {
'tls': 'true',
'authenticated': 'true',
}
}

(retmessage, retmeta) = self.plugin.onMessage(msg, {})

assert retmessage['details'].get('email') is None
assert retmessage['details'].get('username') is None

0 comments on commit da5546f

Please sign in to comment.