diff --git a/bin/deltalogparse.py b/bin/deltalogparse.py index e46b6e868a1f2d03c0df8515891f336c429d011a..67073508c0fc4fe7258c55389e261539d0dacfbd 100755 --- a/bin/deltalogparse.py +++ b/bin/deltalogparse.py @@ -1,19 +1,123 @@ #!/usr/bin/env python3 +import sys +import time +import re +import pprint import lib_path import lib import ldap3 -s = ldap3.Server('ldapi:///var/run/slapd/ldapi', get_info=[ldap3.ALL, ldap3.OFFLINE_SLAPD_2_4]) -c = ldap3.Connection(s, authentication=ldap3.SASL, sasl_mechanism=ldap3.EXTERNAL, sasl_credentials='', auto_bind='NONE', version=3, client_strategy='SYNC') -c.bind() - +update_every = 1 search_base = 'cn=deltalog' -search_filter = '(objectClass=auditModify)' +search_filter = '(|(objectClass=auditModify)(objectClass=auditAdd)(objectClass=auditDelete))' search_scope = ldap3.SUBTREE attributes = [ldap3.ALL_ATTRIBUTES, ldap3.ALL_OPERATIONAL_ATTRIBUTES] -r = c.search(search_base=search_base, search_filter=search_filter, search_scope=search_scope, attributes=attributes) -if r == True: - for entry in c.response: - print(entry['dn'], entry['attributes']) +rgx_filter = re.compile( + r'^(' + r'heartbeatTimestamp|' + r'modifyTimestamp|' + r'lastUse.*?|' + r'(context|entry)CSN' + r'):' +) + + +def is_filtered(attributes): + for attribute in attributes: + if not rgx_filter.search(attribute): + return False + else: + print('filter match: %s' % attribute) + + return True + + +def backup(req_type, req_dn, entry=None): + if entry: + attributes = dict(entry['attributes']) + entry['attributes'] = attributes + del entry['raw_attributes'] + pprint.pprint(entry, indent=4) + + if req_type == 'skip': + print('skip: %s' % req_dn) + else: + print('backup: %s %s' % (req_type, req_dn)) + + +def main(): + """Connect to slapd socket and parse accesslog""" + server = ldap3.Server( + 'ldapi:///var/run/slapd/ldapi', + get_info=[ + ldap3.ALL, + ldap3.OFFLINE_SLAPD_2_4] + ) + + connection = ldap3.Connection( + server, + authentication=ldap3.SASL, + sasl_mechanism=ldap3.EXTERNAL, + sasl_credentials='', + auto_bind='NONE', + version=3, + client_strategy='SYNC' + ) + + connection.bind() + + response = connection.search( + search_base=search_base, + search_filter=search_filter, + search_scope=search_scope, + attributes=attributes + ) + + while True: + start_time = time.perf_counter() + req_start = None + + if response: + #for entry in connection.entries: + # print(entry.entry_dn) + # print(entry['reqStart']) + for entry in connection.response: + req_start = entry['attributes']['reqStart'][0] + req_type = entry['attributes']['reqType'][0] + req_dn = entry['attributes']['reqDN'][0] + + print(' '.join(['\nprocessing:', req_start, entry['dn']])) + + if req_type == 'modify': + req_mods = entry['attributes']['reqMod'] + if is_filtered(req_mods): + backup('skip', req_dn, entry) + continue + + #backup(req_type, req_dn, entry=entry) + backup(req_type, req_dn) + + current_time = time.perf_counter() + elapsed_time = current_time - start_time + sleep_time = update_every - elapsed_time + + print('\nruntime %0.3fs, sleeping %0.3fs' % (elapsed_time, sleep_time)) + + if sleep_time > 0: + time.sleep(sleep_time) + #else: + # time.sleep(update_every) + + response = connection.search( + search_base=search_base, + search_filter=search_filter, + search_scope=search_scope, + attributes=attributes + ) + + +if __name__ == '__main__': + main() + sys.exit(0)