diff --git a/bin/deltalogcat.py b/bin/deltalogcat.py index 2bbc3b8cfb9b4dc7aa38f2d2fef723fcc5b625af..fe076d27c7728c010386e855abc7f3b53cb35ab4 100755 --- a/bin/deltalogcat.py +++ b/bin/deltalogcat.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +#import os import sys import time import subprocess @@ -7,12 +8,12 @@ import select import pprint import json import argparse -#import base64 import lib_path import lib import dphysldap import tabulate +#SLEEP_INTERVAL = 1.0 update_every = 0.001 log_path = '/var/log/ldap/' log_file_deltalog = log_path + 'delta.log' @@ -40,8 +41,6 @@ def sleep(start_time): elapsed_time = current_time - start_time sleep_time = update_every - elapsed_time - #print('runtime {0:.3f}s, sleeping {1:.3f}s'.format(elapsed_time, sleep_time)) - if sleep_time > 0: time.sleep(sleep_time) @@ -123,6 +122,21 @@ def tail_file(log_file): pass +#def tail_file2(log_file): +# """Open the file in tail mode""" +# with open(log_file, 'r') as fin: +# fin.seek(0, os.SEEK_END) +# +# while True: +# where = fin.tell() +# line = fin.readline() +# +# if not line: +# time.sleep(SLEEP_INTERVAL) +# fin.seek(where) +# else: +# parse(line) + def read_file(log_file): """Read the whole file""" diff --git a/bin/deltalogparse.py b/bin/deltalogparse.py index e2a306e99a934238bef9d71c397c86aef843b5e5..35a776b5e99914a116b9a23bac889d61bca0cc05 100755 --- a/bin/deltalogparse.py +++ b/bin/deltalogparse.py @@ -117,7 +117,7 @@ def is_skipped(entry): log.debug('interesting attribute: {}'.format(attribute)) return False except: - log.exception('caught exception: while checking skipped on attribute: {}'.format(attribute)) + log.exception('error: while checking if skipped: {}'.format(attribute)) return False return True @@ -154,7 +154,7 @@ def filtered_req_mod(req_mods): if value: value = b'[REDACTED]' attribute = delim.join([key, value]) - log.info('redact: {}'.format(attribute)) + log.debug('redact: {}'.format(attribute)) elif rgx_byte and rgx_byte.search(attribute): key, delim, value = split_attribute(attribute) @@ -166,7 +166,7 @@ def filtered_req_mod(req_mods): filtered_req_mods.append(attribute.decode('utf-8')) except: - log.exception('error: while filtering attribute: {}'.format(attribute)) + log.exception('error: while filtering: {}'.format(attribute)) return filtered_req_mods @@ -231,7 +231,7 @@ def get_byte_attributes(): """Get all byte type attributes""" global rgx_byte - log.info('connecting to slapd to retrieve schema...') + log.debug('connecting to slapd to retrieve schema...') slapd = dphysldap.Slapd(get_info='SCHEMA') connect(slapd) @@ -248,14 +248,14 @@ def get_byte_attributes(): re_byte = ''.join([r'^(', '|'.join(byte_attrs), r'):']) rgx_byte = re.compile(re_byte.encode('utf-8')) - log.info('disconnecting...') + log.debug('disconnecting...') slapd.connection.unbind() def get_req_start(): """Get the timestamp of the last logged entry or now""" try: - log.info('trying to read last req from {}'.format(log_file_deltalog)) + log.debug('trying to read last req from {}'.format(log_file_deltalog)) last_line = get_last_line(log_file_deltalog).decode('utf-8') req_json = last_line.split(' >>> ', maxsplit=1)[1] req = json.loads(req_json) @@ -278,7 +278,7 @@ def main(): get_byte_attributes() req_start = get_req_start() - log.info('connecting to slapd...') + log.debug('connecting to slapd...') slapd = dphysldap.Slapd(get_info='NONE') connect(slapd) diff --git a/lib/isg/dphysldap.py b/lib/isg/dphysldap.py index 713f327bd8735478e003aae16de39aa7f8ace058..55eb0e52569881b456d4df89162362713eff3254 100644 --- a/lib/isg/dphysldap.py +++ b/lib/isg/dphysldap.py @@ -13,11 +13,6 @@ SERVERS = ['phd-aa1.ethz.ch', 'phd-aa2.ethz.ch', 'phd-aa3.ethz.ch'] BASE = 'dc=phys,dc=ethz,dc=ch' CA_CERTS = '/etc/ssl/certs/ca-certificates.crt' SLAPD_SOCKET = 'ldapi:///var/run/slapd/ldapi' -SLAPD_INFO = ldap3.ALL -#SLAPD_INFO = ldap3.OFFLINE_SLAPD_2_4 -#SLAPD_INFO = ldap3.NONE -SLAPD_SEARCH_SCOPE = ldap3.SUBTREE -SLAPD_SEARCH_ATTRS = [ldap3.ALL_ATTRIBUTES, ldap3.ALL_OPERATIONAL_ATTRIBUTES] class AttributeValue(list): @@ -94,13 +89,16 @@ class User(Entry): class Slapd(object): """ - SLAPD connection to socket + SLAPD connection via socket SASL EXTERNAL authenticated """ - def __init__(self, socket=SLAPD_SOCKET, get_info=SLAPD_INFO): + def __init__(self, socket=SLAPD_SOCKET, get_info=ldap3.ALL): self.socket = socket self.get_info = get_info def connect(self): + """ + Connect to slapd and bind as current user + """ self.server = ldap3.Server(self.socket, get_info=self.get_info) self.connection = ldap3.Connection( self.server, @@ -109,20 +107,13 @@ class Slapd(object): sasl_credentials='', auto_bind='NONE', version=3, - client_strategy='SYNC') + client_strategy=ldap3.SYNC) self.connection.bind() - def search(self, search_base, search_filter, search_scope=SLAPD_SEARCH_SCOPE, - attributes=SLAPD_SEARCH_ATTRS): - response = self.connection.search(search_base, search_filter, - search_scope=search_scope, - attributes=attributes) - return response - - def response(self): - return self.connection.response - - def reconnect(self, interval=1, retries=0): + def connect_retry(self, interval=1, retries=0): + """ + Retry connection every interval until no retries left or forever + """ forever = True if not retries else False while forever or retries > 0: @@ -135,6 +126,54 @@ class Slapd(object): return False + def search(self, search_base, search_filter, search_scope=ldap3.SUBTREE, + attributes=[ldap3.ALL_ATTRIBUTES, ldap3.ALL_OPERATIONAL_ATTRIBUTES]): + """ + LDAP search operation + """ + response = self.connection.search(search_base, search_filter, + search_scope=search_scope, + attributes=attributes) + return response + + def response(self): + """ + Get search operation response + """ + return self.connection.response + + def get_byte_syntaxes(self): + """ + Read the schema and extract byte syntaxes + """ + byte_syntaxes = set() + byte_syntaxes.add('1.3.6.1.4.1.1466.115.121.1.40') + + if self.server.schema: + for key, value in self.server.schema.ldap_syntaxes.items(): + if value.extensions: + for ext in value.extensions: + if ext[0] == 'X-NOT-HUMAN-READABLE' and ext[1][0] == 'TRUE': + byte_syntaxes.add(key) + + return byte_syntaxes + + def get_byte_attributes(self, byte_syntaxes=None): + """ + Read the schema and extract byte attributes + """ + byte_attrs = list() + + if not byte_syntaxes: + byte_syntaxes = self.get_byte_syntaxes() + + if self.server.schema: + for key, value in self.server.schema.attribute_types.items(): + if value.syntax in byte_syntaxes: + byte_attrs.append(key) + + return byte_attrs + class Ldap(object): """ LDAP connection to random server in pool @@ -213,17 +252,6 @@ class Entries(list): def sort(self, attr): super().sort(key=lambda k: str(k[attr])) - # def l(k): - # return str(k[attr]) - - # l = [] - # for i in self: - # criteria = l(i) - # l.append(criteria) - - # return sorted(l, ) - - def remove_attr(self, attr): if attr in self.attrs: self.attrs.remove(attr)