From 08329e0cf4fd6b4bc2c858aba479c87d4460ae33 Mon Sep 17 00:00:00 2001 From: John Gaunt Date: Mon, 23 May 2022 19:11:20 -0400 Subject: [PATCH] removed ldap file --- seafile-ldap.py | 332 ------------------------------------------------ 1 file changed, 332 deletions(-) delete mode 100644 seafile-ldap.py diff --git a/seafile-ldap.py b/seafile-ldap.py deleted file mode 100644 index fd4d0d7..0000000 --- a/seafile-ldap.py +++ /dev/null @@ -1,332 +0,0 @@ -#!/usr/bin/env python - -from ldap import filter -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 -import mysql.connector - -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') - #group = parser.add_mutually_exclusive_group() - #group.add_argument('-e', '--encrypt', action='store_true', help='encrypt') - #group.add_argument('-d', '--decrypt', action='store_true', help='decrypt') - #parser.add_argument('-t', '--text', type=str, help='text to encrypt/decrypt') - #group2 = parser.add_mutually_exclusive_group() - #group2.add_argument('-t', '--text', type=str, help='text to encrypt/decrypt') - #group2.add_argument('-f', '--file', type=str, help='file to encrypt/decrypt, will create a .pynacl file when encrypting, and requires .pynacl file to decrypt') -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'] -ccnetPath = config['Seafile']['ccnetPath'] -adminEmail = config['Seafile']['adminEmail'] -logger.debug("Seafile Token: {0}".format(seafileToken)) -logger.debug("Seafile ccnet.conf File Path: {0}".format(ccnetPath)) -logger.debug("Seafile Admin Email: {0}".format(adminEmail)) -logger.debug("Finished reading the config.ini file.") -logger.debug("Starting to read the ccnet.conf file.") -if os.path.exists(ccnetPath): - ccnetConfig = configparser.ConfigParser() - ccnetConfig.read(ccnetPath) -else: - logger.critical("Unable to find/read ccnet.conf file. Please ensure the ccnet.conf path is correct in the config.ini.") - exit(2) - -# Seafile url -seafileURL = ccnetConfig['General']['SERVICE_URL'] - -# DB config -dbEngine = ccnetConfig['Database']['ENGINE'] -dbHost = ccnetConfig['Database']['HOST'] -dbPort = ccnetConfig['Database'].getint('PORT') -dbUser = ccnetConfig['Database']['USER'] -dbPassword = ccnetConfig['Database']['PASSWD'] -dbName = ccnetConfig['Database']['DB'] -dbCharset = ccnetConfig['Database']['CONNECTION_CHARSET'] -logger.debug("DB Engine: {0}, DB Host: {1}, DB Port: {2}, DB User: {3}, DB Name: {4}, DB Connection Charset: {5}".format(dbEngine, dbHost, dbPort, dbUser, dbName, dbCharset)) - -# ldap Config -ldapHost = ccnetConfig['LDAP']['HOST'] -#ldapPort = ccnetConfig['LDAP SERVER'].getint('port') -#ldapSSL = ccnetConfig['LDAP SERVER'].getboolean('ssl') -ldapBase = ccnetConfig['LDAP']['BASE'] -ldapUserDN = ccnetConfig['LDAP']['USER_DN'] -ldapUserPassword = ccnetConfig['LDAP']['PASSWORD'] -ldapFilter = ccnetConfig['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 ccnet.conf file.") - -# Config DB Varaibles -dbconfig = { - 'user': dbUser, - 'password': dbPassword, - 'host': dbHost, - 'port': dbPort, - 'database': dbName, - 'charset': dbCharset, - 'raise_on_warnings': True -} - -# 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 from LDAP -logger.debug("Searching for users that have a email address, are enabled, and in the {} group.".format(ldapFilter)) -ldap.search(ldapBase, '(&(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))({0}))'.format(ldapFilter), attributes=['*']) -logger.debug("Found {0} LDAP users.".format(len(ldap.entries))) -ldapUsers = ldap.entries -for user in ldapUsers: - logger.debug("User: {0} - Email: {1} - UserDN: {2}".format(user.displayName, user.mail, user.distinguishedName)) - - -# Starting query for seafile ldap users -seafileLDAPUsers = [] -logger.debug("Starting query for LDAPUsers in Seafile") -seafileUsers = request('admin/search-user/?query=@{0}'.format(adminEmail.split("@")[1]), seafileURL, seafileToken)['response']['user_list'] -# need to substract one from the len as the admin account is in the list -logger.debug("Found {0} Seafile LDAP users".format(len(seafileUsers)-1)) -for seafileUser in seafileUsers: - if seafileUser['email'] == adminEmail: - continue - else: - logger.debug("User: {0} - Active: {1}".format(seafileUser['email'], bool(seafileUser['is_active']))) - seafileLDAPUsers.append(seafileUser) - - - -# Loop through the ldap users and make sure they are in the sql ldap users table -# if they are not in the sql table, insert a new row to add them -# if they are disabled in the sql table, enable them -for ldapUser in ldapUsers: - logger.debug("Searching if LDAP user {0} is in Seafile".format(ldapUser.mail)) - checkSeafileUser = request('admin/search-user/?query={0}'.format(ldapUser.mail), seafileURL, seafileToken)['response']['user_list'] - # loop through the results and make sure we match on the email - for seafileUser in checkSeafileUser: - if seafileUser['email'] == ldapUser.mail: - # User is in the sql table - # are they active - is_active = bool(seafileUser['is_active']) - # log the results - logger.debug("LDAP User {0} is already in Seafile, Is Active: {1}".format(ldapUser.mail, is_active)) - # if user is not active, they should be - if not is_active: - logger.info("User {0} is NOT active in Seafile".format(ldapUser.mail)) - # call the api to enable the user in seafile - enableSeafileUser = request('admin/users/{0}/'.format(ldapUser.mail), seafileURL, seafileToken, "PUT", {"is_active": "true"})['response'] - if enableSeafileUser['is_active']: - logger.info("User {0} was set to active in Seafile".format(ldapUser.mail)) - else: - logger.error("There was an error setting user {0} to active in Seafile".format(ldapUser.mail)) - # user is not in the SQL table - else: - logger.info("LDAP User {0} is NOT in Seafile".format(ldapUser.mail)) - # add user to ldap table - cnx = mysql.connector.connect(**dbconfig) - cursor = cnx.cursor() - query = "INSERT INTO LDAPUsers (email, password, is_staff, is_active) VALUES ('{0}', '', {1}, {2})".format(ldapUser.mail, 0, 1) - logger.debug("Query: {0}".format(query)) - cursor.execute(query) - cnx.commit() - row_count = cursor.rowcount - if row_count == 1: - logger.info("LDAP user {0} was added to the Seafile SQL Table".format(ldapUser.mail)) - else: - logger.error("Failed to add LDAP user {0} to the Seafile SQL Table".format(ldapUser.mail)) - cnx.close() - # Update seafile user profile with new name - updateSeafileUserName = request('admin/users/{0}/'.format(ldapUser.mail), seafileURL, seafileToken, "PUT", {"name": "{0}".format(ldapUser.displayName)}) - if updateSeafileUserName['ok']: - logger.debug("User {0} name was updated to {1}".format(ldapUser.mail, ldapUser.displayName)) - else: - logger.error("There was an error setting user {0} name to {1}".format(ldapUser.mail, ldapUser.displayName)) - -# Loop through the sql ldap users and disable those not in the ldap list -for seafileLDAPUser in seafileLDAPUsers: - if not seafileLDAPUser['is_active']: - logger.debug("User {0} is already disabled in Seafile".format(seafileLDAPUser['email'])) - continue - logger.debug("Searching for user {0} that has an email address, are enabled, and in the {1} group.".format(seafileLDAPUser['email'], ldapFilter)) - ldap.search(ldapBase, '(&(mail={0})(!(userAccountControl:1.2.840.113556.1.4.803:=2))({1}))'.format(seafileLDAPUser['email'], ldapFilter), attributes=['*']) - count = len(ldap.entries) - logger.debug("Found {0} LDAP user.".format(count)) - if count == 0: - # User is not enabled, have email, or in the group, disable their account - disableUserinSeafile = request('admin/users/{0}/'.format(seafileLDAPUser['email']), seafileURL, seafileToken, "PUT", {"is_active": "false"})['response'] - if not disableUserinSeafile['is_active']: - logger.info("User {0} was set to disabled in Seafile".format(seafileLDAPUser['email'])) - else: - logger.error("There was an error setting user {0} to disabled in Seafile".format(seafileLDAPUser['email'])) - -# get ad groups and import them into seafile -# loop through each group and list members -# compare members to users in seafile group -# add users to group if missing and in the seafile group -# remove members in not in group or seafile group -# remove seafile groups if ad group is removed -ldap.search(ldapBase, '(objectClass=group)', attributes=['*']) -ldapGroups = [] -for group in ldap.entries: - try: - if group.member: - logger.debug("Group {0} has {1} members".format(group.name, len(group.member))) - ldapGroups.append(group) - finally: - continue -for ldapGroup in ldapGroups: - # loop through the results and make sure we match on the group name - searchSeafileGroup = request('admin/search-group/?query={0}'.format(ldapGroup.name), seafileURL, seafileToken)['response']['group_list'] - if len(searchSeafileGroup) == 0: - # group not in Seafile - createSeafileGroup = request('admin/groups/', seafileURL, seafileToken, "POST", {"group_name": "{0}".format(ldapGroup.name), "group_owner": "{0}".format(adminEmail)})['response'] - logger.info("Created Seafile group {0}".format(ldapGroup.name)) - searchSeafileGroup = request('admin/search-group/?query={0}'.format(ldapGroup.name), seafileURL, seafileToken)['response']['group_list'] - elif len(searchSeafileGroup) > 0 and not [item for item in searchSeafileGroup if ldapGroup.name == item['name']]: - # group not in Seafile but similar group name is - createSeafileGroup = request('admin/groups/', seafileURL, seafileToken, "POST", {"group_name": "{0}".format(ldapGroup.name), "group_owner": "{0}".format(adminEmail)})['response'] - logger.info("Created Seafile group {0}".format(ldapGroup.name)) - searchSeafileGroup = request('admin/search-group/?query={0}'.format(ldapGroup.name), seafileURL, seafileToken)['response']['group_list'] - for seafileGroup in searchSeafileGroup: - if seafileGroup['name'] == ldapGroup.name: - for ldapGroupMember in ldapGroup.member: - logger.debug("Searching for LDAP user {0}".format(ldapGroupMember)) - ldap.search(ldapBase, '(&(distinguishedName={0})(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))({1}))'.format(filter.filter_format('%s', (ldapGroupMember,)), ldapFilter), attributes=['mail']) - count = len(ldap.entries) - logger.debug("Found {0} LDAP user.".format(count)) - if count == 1: - addMembertoSeafileGroup = request('admin/groups/{0}/members/'.format(seafileGroup['id']), seafileURL, seafileToken, "POST", "email={0}".format(ldap.entries[0]['mail']), False)['response'] - if len(addMembertoSeafileGroup['failed']) == 1: - # user wasn't added to group - if addMembertoSeafileGroup['failed'][0]['error_msg'].endswith(" is already a group member."): - logger.debug("User {0} is already member of Seafile Group {1}".format(ldap.entries[0]['mail'], seafileGroup['name'])) - else: - logger.error("User {0} was NOT added to Seafile Group {1}".format(ldap.entries[0]['mail'], seafileGroup['name'])) - logger.error("{0}".format(addMembertoSeafileGroup['failed'][0]['error_msg'])) - elif len(addMembertoSeafileGroup['success']) == 1: - # user was added to group - logger.info("User {0} was added to Seafile Group {1}".format(ldap.entries[0]['mail'], seafileGroup['name'])) - -seafileGroups = request('admin/groups/', seafileURL, seafileToken)['response']['groups'] -# loop through seafile groups and remove those groups no longer in AD or empty -# also check seafile group membership against ldap group -for seafileGroup in seafileGroups: - # need to check if group exists in ad first and if not delete it - logger.debug("Searching for ldap group {0}.".format(seafileGroup)) - ldap.search(ldapBase, '(samaccountname={0})'.format(seafileGroup), attributes=['*']) - count = len(ldap.entries) - logger.debug("Found {0} LDAP group.".format(count)) - - seafileGroupMembers = request('admin/groups/{0}/members/'.format(seafileGroup['id']), seafileURL, seafileToken)['response']['members'] - #for seafileGroupMember in seafileGroupMembers: - - - - #seafileGroupMembers = request('admin/groups/{0}/members/'.format(seafileGroup['id']), seafileURL, seafileToken)['response']['members'] - #for ldapGroupMember in ldapGroup.member: - # logger.debug("Searching for LDAP user {0}".format(ldapGroupMember)) - # ldap.search(ldapBase, '(&(distinguishedName={0})(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2))({1}))'.format(ldapGroupMember, ldapFilter), attributes=['mail']) - # count = len(ldap.entries) - # logger.debug("Found {0} LDAP user.".format(count)) - # if count == 1: - # if [item for item in seafileGroupMembers if ldap.entries[0]['mail'] == item['email']]: - # logger.debug("User {0} is already member of Seafile Group {1}".format(ldap.entries[0]['mail'], seafileGroup['name'])) - # continue - # else: - # logger.info("User {0} is not a member of Seafile Group {1}".format(ldap.entries[0]['mail'], seafileGroup['name'])) - # addMembertoSeafileGroup = request('admin/groups/{0}/members/'.format(seafileGroup['id']), seafileURL, seafileToken, "POST", {"email": "{0}".format(ldap.entries[0]['mail'])})['response'] - # else: - # logger.debug("User {0} is not enabled, have no email, or not in the Seafile Group".format(ldap.entries[0]['mail'])) - - #logger.debug("Checking if LDAP group {0} is in SQL Table".format(ldapGroup.name)) - #cnx = mysql.connector.connect(**dbconfig) - #cursor = cnx.cursor() - #query = "SELECT * FROM Group WHERE group_name = '{0}'".format(ldapGroup.name) - #logger.debug("Query: {0}".format(query)) - #cursor.execute(query) - #sqlLDAPgroup = cursor.fetchall() - #row_count = cursor.rowcount - #logger.debug("Found {0} SQL LDAP Group".format(row_count)) - #cnx.close() - #if row_count == 1: - # group is in seafile - - #else: - # create the seafile group - # createSeafileGroup = request('admin/groups/', seafileURL, seafileToken, "POST", {"group_name": "{0}".format(ldapGroup.name), "group_owner": "{0}".format(adminEmail)})['response']