#!/usr/bin/env python from ldap3 import Connection, Server, ANONYMOUS, SIMPLE, SYNC, ASYNC, core from getpass import getpass import configparser import logging import argparse import os import requests import urllib3 import json def request(resource, seafileURL, seafileToken, method='GET', data=None, dataIsJson=True): if data is None: httpHeaders = {'Accept': 'application/json; charset=utf-8; indent=4', 'Authorization': 'Token {0}'.format(seafileToken)} data = '' else: if dataIsJson: data = json.dumps(data) httpHeaders = {'Content-type': 'application/json', 'Accept': 'application/json; charset=utf-8; indent=4', 'Authorization': 'Token {0}'.format(seafileToken)} else: httpHeaders = {'Content-type': 'application/x-www-form-urlencoded', 'Accept': 'application/json; charset=utf-8; indent=4', 'Authorization': 'Token {0}'.format(seafileToken)} url = '{0}/api/v2.1/{1}'.format(seafileURL, resource) logger.debug('Request URL: {0}'.format(url)) logger.debug('Request Method: {0}'.format(method)) logger.debug('Request Headers: {0}'.format(httpHeaders)) logger.debug('Request Data: {0}'.format(data)) r = requests.request( method, url, data = data, headers = httpHeaders, ) logger.debug('Response: {0}'.format(r)) logger.debug('Request Status Code: {0}'.format(r.status_code)) if r.ok: try: logger.debug('Request Returned JSON: {0}'.format(r.json())) return {'ok': r.ok, 'status_code': r.status_code, 'response': r.json()} except: logger.debug('Request Returned Text: {0}'.format(r.text)) return {'ok': r.ok, 'status_code': r.status_code, 'response': r.text} raise ValueError(r) #def parser = argparse.ArgumentParser(description='Sync LDAP with Seafile') parser.add_argument('-v', '--verbose', action='store_true', help='increase log level to debug') args = parser.parse_args() logger = logging.getLogger(__name__) logFormatter = logging.Formatter('%(asctime)s - [%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S') logger.setLevel(logging.INFO) if args.verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) #fileHandler = logging.FileHandler("/tmp/seafile-ldap.log") #fileHandler.setFormatter(logFormatter) #logger.addHandler(fileHandler) consoleHandler = logging.StreamHandler() consoleHandler.setFormatter(logFormatter) logger.addHandler(consoleHandler) # get directory of script cwd = os.path.dirname(os.path.realpath(__file__)) configPath = os.path.join(cwd, 'config.ini') # import the config file logger.debug("Starting to read the config.ini file.") logger.debug("Using file {0}.".format(configPath)) if os.path.exists(configPath): config = configparser.ConfigParser() config.read(configPath) else: logger.critical("Unable to find/read config file. Please ensure the config.ini is in the same directory as this script and readable.") exit(1) seafileToken = config['Seafile']['token'] adminEmail = config['Seafile']['adminEmail'] seafileURL = config['Seafile']['SERVICE_URL'] logger.debug("Seafile URL: {0}".format(seafileURL)) logger.debug("Seafile Token: {0}".format(seafileToken)) logger.debug("Seafile Admin Email: {0}".format(adminEmail)) ldapHost = config['LDAP']['HOST'] #ldapPort = config['LDAP SERVER'].getint('port') #ldapSSL = config['LDAP SERVER'].getboolean('ssl') ldapBase = config['LDAP']['BASE'] ldapUserDN = config['LDAP']['USER_DN'] ldapUserPassword = config['LDAP']['PASSWORD'] ldapFilter = config['LDAP']['FILTER'] logger.debug("LDAP Host: {0}, LDAP Base: {1}, LDAP User DN: {2}, LDAP Filter: {3}".format(ldapHost, ldapBase, ldapUserDN, ldapFilter)) logger.debug("Finished reading the config.ini file.") # setup the server ldapServer = Server(ldapHost) logger.debug("Setup LDAP server connection uri: {0}".format(ldapServer)) try: ldap = Connection(ldapServer, ldapUserDN, ldapUserPassword, auto_bind=True) except core.exceptions.LDAPBindError as e: logger.critical("LDAP Bind Failed. {0}".format(e)) exit() logger.debug("Bind successful.") # get seafile users and loop through and check group membership and disable or not logger.debug("Starting query for users in Seafile") seafileUsers = request('admin/users/', seafileURL, seafileToken)['response']['data'] # need to substract one from the len as the admin account is in the list logger.debug("Found {0} Seafile users excluding the admin account, {1}".format(len(seafileUsers)-1, adminEmail)) for seafileUser in seafileUsers: if seafileUser['email'] == adminEmail: continue else: logger.debug("Found user {0} with active status {1} in seafile".format(seafileUser['email'], bool(seafileUser['is_active']))) logger.debug("Checking if {0} user has extensionAttribute1 set, is active, and is in the seafile group".format(seafileUser['email'])) ldap.search(ldapBase, '(&(extensionAttribute1={0})(!(userAccountControl:1.2.840.113556.1.4.803:=2))({1}))'.format(seafileUser['email'], ldapFilter), attributes=['*']) count = len(ldap.entries) logger.debug("Found {0} LDAP user.".format(count)) if count == 0: logger.debug("User {0} doesn't have extensionAttribute1 set, isn't active, or isn't in the seafile group, disabling in seafile...".format(seafileUser['email'])) if not seafileUser['is_active']: logger.debug("User {0} is already disabled in Seafile".format(seafileUser['email'])) continue disableUserinSeafile = request('admin/users/{0}/'.format(seafileUser['email']), seafileURL, seafileToken, "PUT", {"is_active": "false"})['response'] if not disableUserinSeafile['is_active']: logger.info("User {0} was set to disabled in Seafile".format(seafileUser['email'])) else: logger.error("There was an error setting user {0} to disabled in Seafile".format(seafileUser['email'])) else: logger.debug("User {0} has extensionAttribute1 set, is active, and is in the seafile group".format(seafileUser['email'])) if seafileUser['is_active']: logger.debug("User {0} is already active in Seafile".format(seafileUser['email'])) continue ActiveUserinSeafile = request('admin/users/{0}/'.format(seafileUser['email']), seafileURL, seafileToken, "PUT", {"is_active": "true"})['response'] if ActiveUserinSeafile['is_active']: logger.info("User {0} was set to active in Seafile".format(seafileUser['email'])) else: logger.error("There was an error setting user {0} to active in Seafile".format(seafileUser['email']))