#!/usr/bin/python3 import urllib import syslog import hashlib import ldap3 import requests def ldap_connect(): server = ldap3.Server("ldapi:///var/run/ldapi") conn = ldap3.Connection( server, authentication=ldap3.SASL, sasl_mechanism=ldap3.EXTERNAL, sasl_credentials="", client_strategy=ldap3.SYNC, ) conn.bind() conn.search( search_base="", search_filter="(objectClass=*)", search_scope=ldap3.BASE, attributes=["namingContexts"], ) basedn = conn.response[0]["attributes"]["namingContexts"][0] return (conn, basedn) def get_users(conn, basedn): conn.search( search_base=basedn, search_filter="(&(mail=*)(objectClass=inetOrgPerson))", attributes=["mail", "jpegPhoto"], ) for result in conn.response: yield (result["dn"], result["attributes"]) def get_avatar(emails): for email in emails: mailhash = hashlib.md5(email.encode("utf-8").lower()).hexdigest() url = f"https://gravatar.com/avatar/{mailhash}.jpg?d=404&size=80" req = requests.get(url) if req.status_code == 200: return req.content elif req.status_code == 404: continue raise ValueError(f"Invalid response from gravatar {req.status_code}") return None def update_avatar(conn, dn, image): if image is None: syslog.syslog(syslog.LOG_INFO, f"Removing jpegPhoto from user '{dn}'") data = (ldap3.MODIFY_REPLACE, []) else: syslog.syslog(syslog.LOG_INFO, f"Updating jpegPhoto for user '{dn}'") data = (ldap3.MODIFY_REPLACE, [image]) conn.modify(dn, {"jpegPhoto": [data]}) if __name__ == "__main__": syslog.openlog() (conn, basedn) = ldap_connect() for (dn, user) in get_users(conn, basedn): image = get_avatar(user["mail"]) if len(user["jpegPhoto"]) == 1 and user["jpegPhoto"][0] == image: continue update_avatar(conn, dn, image) syslog.closelog()