diff --git a/api.py b/api.py index 1a814fc..8a2b463 100644 --- a/api.py +++ b/api.py @@ -9,9 +9,13 @@ def __post_request(url, json_data): headers = {'X-API-Key': api_key, 'Content-type': 'application/json'} req = requests.post(api_url, headers=headers, json=json_data) - rsp = req.json() req.close() + try: + rsp = req.json() + except: + sys.exit(f"API {url}: not a valid JSON response") + if isinstance(rsp, list): rsp = rsp[0] @@ -88,9 +92,13 @@ def check_user(email): url = f"{api_host}/api/v1/get/mailbox/{email}" headers = {'X-API-Key': api_key, 'Content-type': 'application/json'} req = requests.get(url, headers=headers) - rsp = req.json() req.close() + try: + rsp = req.json() + except: + sys.exit("API get/mailbox: not a valid JSON response") + if not isinstance(rsp, dict): sys.exit("API get/mailbox: got response of a wrong type") @@ -101,3 +109,14 @@ def check_user(email): sys.exit(f"API {url}: {rsp['type']} - {rsp['msg']}") return (True, bool(rsp['active_int']), rsp['name']) + + +def check_api(): + api_url = f"{api_host}/api/v1/get/status/containers" + headers = {'X-API-Key': api_key, 'Content-type': 'application/json'} + + req = requests.get(api_url, headers=headers, verify=False) + req.close() + if req.status_code == 200: + return True + return False diff --git a/syncer.py b/syncer.py index 993a2bc..7b2b979 100644 --- a/syncer.py +++ b/syncer.py @@ -47,68 +47,80 @@ def main(): def sync(): - ldap_connector = ldap.initialize(f"{config['LDAP_URI']}") - ldap_connector.set_option(ldap.OPT_REFERRALS, 0) - ldap_connector.simple_bind_s( - config['LDAP_BIND_DN'], config['LDAP_BIND_DN_PASSWORD']) + api_status = api.check_api() + + if api_status != True: + logging.info(f"mailcow is not fully up, skipping this sync...") + return + + try: + ldap_connector = ldap.initialize(f"{config['LDAP_URI']}") + ldap_connector.set_option(ldap.OPT_REFERRALS, 0) + ldap_connector.simple_bind_s( + config['LDAP_BIND_DN'], config['LDAP_BIND_DN_PASSWORD']) + except: + logging.info( + f"Can't connect to LDAP server {config['LDAP_URI']}, skipping this sync...") + return ldap_results = ldap_connector.search_s(config['LDAP_BASE_DN'], ldap.SCOPE_SUBTREE, config['LDAP_FILTER'], - ['userPrincipalName', 'cn', 'userAccountControl']) + ['mail', 'displayName', 'userAccountControl']) + logging.info(ldap_results) filedb.session_time = datetime.datetime.now() for x in ldap_results: try: - logging.info("Working on " + x[1]['sAMAccountName']) - email = x[1]['userPrincipalName'][0].decode() - ldap_name = x[1]['displayName'][0].decode() - ldap_active = False if int( - x[1]['userAccountControl'][0].decode()) & 0b10 else True - - (db_user_exists, db_user_active) = filedb.check_user(email) - (api_user_exists, api_user_active, api_name) = api.check_user(email) - - unchanged = True - - if not db_user_exists: - filedb.add_user(email, ldap_active) - (db_user_exists, db_user_active) = (True, ldap_active) - logging.info( - f"Added filedb user: {email} (Active: {ldap_active})") - unchanged = False - - if not api_user_exists: - api.add_user(email, ldap_name, ldap_active, 5120) - (api_user_exists, api_user_active, api_name) = ( - True, ldap_active, ldap_name) - logging.info( - f"Added Mailcow user: {email} (Active: {ldap_active})") - unchanged = False - - if db_user_active != ldap_active: - filedb.user_set_active_to(email, ldap_active) - logging.info( - f"{'Activated' if ldap_active else 'Deactived'} {email} in filedb") - unchanged = False - - if api_user_active != ldap_active: - api.edit_user(email, active=ldap_active) - logging.info( - f"{'Activated' if ldap_active else 'Deactived'} {email} in Mailcow") - unchanged = False - - if api_name != ldap_name: - api.edit_user(email, name=ldap_name) - logging.info( - f"Changed name of {email} in Mailcow to {ldap_name}") - unchanged = False - - if unchanged: - logging.info(f"Checked user {email}, unchanged") - except Exception: - logging.info(f"Exception during something. See above") - pass + ldap_item = x[1] + logging.info(f"Working on {ldap_item['mail']}") + except: + logging.info( + f"An error occurred while iterating through the LDAP users, skipping this sync...") + return + + email = ldap_item['mail'][0].decode() + ldap_name = ldap_item['displayName'][0].decode() + ldap_active = True + + (db_user_exists, db_user_active) = filedb.check_user(email) + (api_user_exists, api_user_active, api_name) = api.check_user(email) + + unchanged = True + + if not db_user_exists: + filedb.add_user(email, ldap_active) + (db_user_exists, db_user_active) = (True, ldap_active) + logging.info(f"Added filedb user: {email} (Active: {ldap_active})") + unchanged = False + + if not api_user_exists: + api.add_user(email, ldap_name, ldap_active, 5120) + (api_user_exists, api_user_active, api_name) = ( + True, ldap_active, ldap_name) + logging.info( + f"Added Mailcow user: {email} (Active: {ldap_active})") + unchanged = False + + if db_user_active != ldap_active: + filedb.user_set_active_to(email, ldap_active) + logging.info( + f"{'Activated' if ldap_active else 'Deactived'} {email} in filedb") + unchanged = False + + if api_user_active != ldap_active: + api.edit_user(email, active=ldap_active) + logging.info( + f"{'Activated' if ldap_active else 'Deactived'} {email} in Mailcow") + unchanged = False + + if api_name != ldap_name: + api.edit_user(email, name=ldap_name) + logging.info(f"Changed name of {email} in Mailcow to {ldap_name}") + unchanged = False + + if unchanged: + logging.info(f"Checked user {email}, unchanged") for email in filedb.get_unchecked_active_users(): (api_user_exists, api_user_active, _) = api.check_user(email) diff --git a/templates/dovecot/ldap/passdb.conf b/templates/dovecot/ldap/passdb.conf index 48739b2..c7014d4 100644 --- a/templates/dovecot/ldap/passdb.conf +++ b/templates/dovecot/ldap/passdb.conf @@ -2,4 +2,4 @@ uris = $ldap_uri ldap_version = 3 base = $ldap_base_dn auth_bind = yes -auth_bind_userdn = %u +auth_bind_userdn = uid=%Ln,$ldap_base_dn diff --git a/templates/sogo/plist_ldap b/templates/sogo/plist_ldap index cf39ee5..b3f2423 100644 --- a/templates/sogo/plist_ldap +++ b/templates/sogo/plist_ldap @@ -8,9 +8,9 @@ CNFieldName cn IDFieldName - cn + uidNumber UIDFieldName - userPrincipalName + mail baseDN $ldap_base_dn @@ -21,7 +21,7 @@ $ldap_bind_dn_password bindFields - userPrincipalName + mail bindAsCurrentUser @@ -36,9 +36,9 @@ $sogo_ldap_filter isAddressBook - NO + YES displayName - Active Directory + Webba adresboek scope SUB