Skip to content

Instantly share code, notes, and snippets.

@baszoetekouw
Last active March 31, 2020 14:07
Show Gist options
  • Save baszoetekouw/0436704c28066919e88a9359c8b8e884 to your computer and use it in GitHub Desktop.
Save baszoetekouw/0436704c28066919e88a9359c8b8e884 to your computer and use it in GitHub Desktop.
script to calculate checksum of an ldif (e.g., slapcat output)
#!/usr/bin/env python3
import sys
import ldif
import hashlib
#import json
import numbers
from typing import Collection, Any
"""
# old approach; works well, but in json lists are ordered, so it is quite hard to get python to sort them aphabetically
# custom encoder
class MyEncoder(json.JSONEncoder):
def default(self, obj):
# handle byte objects
if isinstance(obj, bytes):
return obj.decode('utf8')
return obj.hex()
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
ldifparser = ldif.LDIFRecordList(sys.stdin)
ldifparser.parse()
# note: this still doesn't sort lists of attributes
#print(json.dumps(ldifparser.all_records, cls=MyEncoder, sort_keys=True, indent=2))
#sys.exit(0)
"""
# custom sorting of lists and tuples, with nonstrings at the end
def getsortkey(s: Any) -> str:
if isinstance(s, bytes):
return s.decode('utf8')
if isinstance(s, str):
return s
if isinstance(s, numbers.Number):
return str(s)
# sort other objects (dicts etc) at the end
return '\uffff'
# iterate over an LDIF structure
# LOOK MOM, IT'S RECURSION!
def iter_ldif(d: Collection[Any]) -> str:
if isinstance(d, dict):
result = "{" + ','.join([f"{iter_ldif(k)}: {iter_ldif(v)}" for k, v in sorted(d.items())]) + '}'
return result + "\n"
# be default, ldap object are returned as a (dn,{attributes}) tuple; uncomment this if you want a dict instead
#if isinstance(d, tuple) and len(d) == 2:
# return iter_ldif(dict((d,)))
if isinstance(d, list) or isinstance(d, tuple):
result = '[' + ','.join([iter_ldif(v) for v in sorted(d, key=getsortkey)]) + ']'
return result + "\n"
if isinstance(d, bytes):
return iter_ldif(d.decode('utf8'))
if isinstance(d, str):
return '"' + ''.join([c if ' ' <= c < '~' and c != '"' else f"\\u{ord(c):04x}" for c in d]) + '"'
raise Exception(f"weird object of type {type(d).__name__} found")
ldifparser = ldif.LDIFRecordList(sys.stdin)
ldifparser.parse()
json_data = iter_ldif(ldifparser.all_records)
#print(json_data)
h = hashlib.sha256(json_data.encode('ascii'))
print(h.hexdigest())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment