diff --git a/1time_scripts/add_resource_group_ldap.py b/1time_scripts/add_resource_group_ldap.py deleted file mode 100644 index 308b88cd0430212d7f2ada35d3f6e8c37e510247..0000000000000000000000000000000000000000 --- a/1time_scripts/add_resource_group_ldap.py +++ /dev/null @@ -1,43 +0,0 @@ -import ldap -import ldap.modlist as modlist -import settings - -l = None -# Connect to LDAP using python-LDAP -try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) - - l = ldap.initialize(settings.LDAP_HOST) - l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) -except ldap.LDAPError as le: - print ("LDAP Connection Error - %s", le) - if l: - l.unbind() - -try: - resourceID = ['31', '32'] - #cn = 'cms-swestore' - #groupDN2 = "gidNumber=18239" + "," + settings.groupsDN - - groupDN = "gidNumber=20049" + "," + settings.groupsDN - addresource = [(ldap.MOD_REPLACE, 'resourceID', resourceID)] - - #l.modify_s(groupDN,addresource) - - - filter = "(!(resourceID=*))" - retrievedAttrs = ['gidNumber', 'resourceID', 'cn'] - - ldap_result_id = l.search(settings.groupsDN, ldap.SCOPE_SUBTREE, filter, retrievedAttrs) - #print str(ldap_result_id) - print "\n" - result_type, result_data = l.result(ldap_result_id) - - for res1 in result_data: - print str(res1) + "\n" - - -except ldap.LDAPError as le: - print ("LDAP Error -- %s",le) - diff --git a/1time_scripts/example-kerberos-useradmin.py b/1time_scripts/example-kerberos-useradmin.py deleted file mode 100755 index 87fef5317e850ac37502c6aba89bcee94d8e64c5..0000000000000000000000000000000000000000 --- a/1time_scripts/example-kerberos-useradmin.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/python3 - -# dCache Kerberos principal management -# Arguments: -# add/delete -# username - -# System definitions. -import os -import sys -import re - -# Extra installed module -import kadmin - -keytab = "/home/dcache/private/dcache-usermgmt.keytab" -adminprincipal = "dcache/usermgmt" - -# Get arguments and check. Need to have two arguments. -if len(sys.argv) != 3: - print("Add or remove user principals in kerberos.") - print("Arguments: <action> <username>") - print("") - print("Action is either add or delete.") - print("Username should match s_AAABBB usernames.") - sys.exit(1) - -action=sys.argv[1] -user = sys.argv[2] - -# Check for the user. Should look like a Swestore user. -if not (re.match("^s_", user)): - print("Not a Swestore user name.") - sys.exit(1) - -# Kadmin init or "login" -try: - kadm = kadmin.init_with_keytab(adminprincipal, keytab) - #kadm = kadmin.init_with_ccache(adminprincipal, "/tmp/krb5cc_0") - #kadm = kadmin.init_with_password(adminprincipal, "Foobar") -except Exception as e: - print("Init failed:", e) - sys.exit(1) - -# Get the user principal. -# Will be None if no-such-user and this would not be an error. -try: - princ = kadm.getprinc(user) -except Exception as e: - print("Getprinc failed:", e) - sys.exit(1) - -# Run the actions -if (action == "add"): - if (princ is None): - # User does not exist, add it. - try: - kadm.addprinc(user, None) - print("User " + user + " added.") - except Exception as e: - print("Addprinc failed:", e) - sys.exit(1) - else: - print("User", user, "already exists.") - sys.exit(1) - -elif(action == "delete"): - if (princ is None): - print("No such user in database:", user) - sys.exit(1) - else: - # User exists, try to remove it. - try: - kadm.delprinc(user) - print("User " + user + " deleted.") - sys.exit(0) - except Exception as e: - print("Delprinc failed:", e) - sys.exit(1) - -else: - # The first argument should be add or delete - print("Not a valid action: \"" + action + "\". Should be \"add\" or \"delete\".") - sys.exit(1) - -# Finish. -sys.exit(0) diff --git a/1time_scripts/remove_user_1time.py b/1time_scripts/remove_user_1time.py deleted file mode 100644 index adf9159043df7b5659929a232feba285021e4b59..0000000000000000000000000000000000000000 --- a/1time_scripts/remove_user_1time.py +++ /dev/null @@ -1,28 +0,0 @@ -import ldap -import ldap.modlist as modlist -import settings - -l = None -# Connect to LDAP using python-LDAP -try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) - - l = ldap.initialize(settings.LDAP_HOST) - l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) -except ldap.LDAPError as le: - print ("LDAP Connection Error - %s", le) - if l: - l.unbind() - -try: - groupDN = "gidNumber=19527" + "," + settings.groupsDN - - l.delete_s(groupDN) - - #personDN = "uid=s_annam" + "," + settings.peopleDN - #l.delete_s(personDN) - -except ldap.LDAPError as le: - print ("LDAP Error -- %s",le) - diff --git a/1time_scripts/supr_SUA_check_1time.py b/1time_scripts/supr_SUA_check_1time.py deleted file mode 100644 index d008107dcb9ee4a668d8088fbbd1081d28f4a71b..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_SUA_check_1time.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import settings -import requests - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import (setup_log, sendMail) - -logger = setup_log("SUPR_SUA", "logs/supr_sua_check.log") - -# Message to be sent to User -def sendUserMail(m, proj_name): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are a member of Swestore project -- " + proj_name + " in SUPR. \n \n" - msgTxt += "We have noticed that you have not signed SNIC User Agreement, SUA. \n" - msgTxt += "Due to a oversight from our side, access to Swestore projects were granted even when this SUA wasn't signed. \n \n" - msgTxt += "To be able to use Swestore in the future, it is important that SUA is accepted.\n" - msgTxt += "Please login to SUPR (https://supr.snic.se/login). Go to Personal Information and sign the SUA using Federated Identity. \n\n" - msgTxt += "In case of any issues or clarifications, please mail support@swestore.se. \n\n" - msgTxt += "Regards,\n" + "SWESTORE Support Team" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Notification to Sign SNIC User Agreement (SUA) in SUPR") - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Compose query from the below options - params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id} - - res = supr_connection.get("project/search/", params = params) - - for p in res.matches: - - for m in p.members: - if m.user_agreement_version and m.user_agreement_accepted: - logger.info(m.centre_person_id + " SUA is signed and accepted") - else: - logger.info(m.centre_person_id + " SUA is not signed and accepted") - print(m.centre_person_id + " SUA is not signed and accepted") - #sendUserMail(m, p.name) - -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) -except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - sys.exit(1) - diff --git a/1time_scripts/supr_account_1time.py b/1time_scripts/supr_account_1time.py deleted file mode 100644 index 3e3699741aefc6d228bd0b8346c84bb1ee021be0..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_account_1time.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import settings -import requests - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import setup_log - -logger = setup_log("SUPR_ACCOUNT", "logs/supr_account_creation.log") - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Compose query from the below options - params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id} - - res = supr_connection.get("project/search/", params = params) - - for p in res.matches: - - resourceIDList = [] - resourceList = [] - - for rp in p.resourceprojects: - if str(rp.resource.id) in [settings.dcache_resource_id, settings.irods_resource_id]: - resourceIDList.append(str(rp.resource.id)) - resourceList.append(rp.resource) - - for m in p.members: - - if m.centre_person_id and m.user_agreement_version and m.user_agreement_accepted: - for resource in resourceList: - d = {'username' : m.centre_person_id, - 'person_id' : m.id, - 'resource_id' : resource.id, - 'button_text' : "Reset Password", - 'status' : 'enabled'} - try: - account = supr_connection.post("account/create/", data = d) - logger.info("Account for Person with SUPR ID :: %s for resource -- %s created", m.id, resource.name) - except supr.SUPRHTTPError as e: - print e - # We want to show the text received if we get an HTTP Error - logger.error("HTTP error in creating account to SUPR - %s :: %s", e.status_code, e) - #ERR_MJR_MAIL += "Error occured in creating account to SUPR - " + e.text + "\n" - #ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + str(attrsPerson['uid']) + "\t Module :: addPerson \n" - #err_mjr_cnt += 1 - except ConnectionError as ce: - #ERR_MJR_MAIL += "Error occured in creating account to SUPR due to ConnectionError- " + str(ce) + "\n" - logger.error("Connection to SUPR failed - %s" %str(ce)) - - -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) -except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - sys.exit(1) - diff --git a/1time_scripts/supr_account_button_1time.py b/1time_scripts/supr_account_button_1time.py deleted file mode 100644 index 698dc1c7705f9728399e2d781bb2309e29280abf..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_account_button_1time.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import settings -import requests - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import setup_log - -logger = setup_log("SUPR_ACCOUNT", "logs/supr_account_button.log") - - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Compose query from the below options - params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id} - - res = supr_connection.get("project/search/", params = params) - - for p in res.matches: - - for m in p.members: - for account in m.accounts: - if not account.button_text: - print account - d = {'button_text' : "Reset Password"} - try: - #account = supr_connection.post("account/"+str(account.id)+"/update/", data = d) - logger.info("Account for Person with SUPR ID :: %s updated testing", m.id) - except supr.SUPRHTTPError as e: - print e - except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - - -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) -except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - sys.exit(1) diff --git a/1time_scripts/supr_cert_check_1time.py b/1time_scripts/supr_cert_check_1time.py deleted file mode 100644 index f235e13abdb8b5bd4ecdb4822dc38dd76c1a0976..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_cert_check_1time.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import settings -import requests - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import (setup_log, sendMail) - -logger = setup_log("SUPR_cert", "logs/supr_cert_check.log") - -# Message to be sent to User -def sendUserMail(m, proj_name): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are a member of Swestore project -- " + proj_name + " in SUPR. \n \n" - msgTxt += "We have noticed that you have not uploaded Client Certificate in SUPR. \n" - msgTxt += "To be able to use Swestore (dCache), uploading Client Certificate in SUPR is mandatory.\n" - msgTxt += "Please login to SUPR (https://supr.snic.se/login). Go to Personal Information and upload Client Certificate. \n\n" - msgTxt += "In case of any issues or clarifications, please mail support@swestore.se. \n\n" - msgTxt += "Regards,\n" + "SWESTORE Support Team" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Notification to upload Client Certificate in SUPR for Swestore Access") - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Compose query from the below options - params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id, 'resource_id': settings.dcache_resource_id} - - res = supr_connection.get("project/search/", params = params) - - for p in res.matches: - - for m in p.members: - if m.subject: - logger.info(m.centre_person_id + " certificate present in SUPR") - else: - logger.info(m.centre_person_id + " certificate not present in SUPR") - print(m.centre_person_id + " certificate not present in SUPR") - sendUserMail(m, p.name) - -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) -except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - sys.exit(1) diff --git a/1time_scripts/supr_ipa_1time.py b/1time_scripts/supr_ipa_1time.py deleted file mode 100644 index a38e4d254cac0b3a01c65806cc05a201c719b881..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_ipa_1time.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- - -import ipahttp -import logging -import sys -import supr -import settings -import requests - -from requests import ConnectionError -logging.basicConfig() -requests.packages.urllib3.disable_warnings() - - -from supr_common import (asciify, - sendMail, - setup_log, - temp_password) - -logger = setup_log("IPA_SET_PWD", "logs/ipa_set_pwd_1time_2.log") - - - -# Function to add new Person to FREEIPA -def addPersontoFreeIPA(m): - try: - uidNumber = str(settings.uidNumberStart + m.id) - user = m.centre_person_id - opts = {"givenname": m.first_name, - "sn": m.last_name, - "mail" : m.email, - "uidnumber": uidNumber, - "userpassword":temp_password(), - } - result = ipa.user_add(user, opts) - logger.info(user + " added to IPA") - - except Exception as e: - logger.error("Error in addPersontoFreeIPA Module for %s :: %s", str(uidNumber), e) - - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Compose query from the below options - params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id} - - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sendMail("HTTP error from SUPR - " + e.text, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") - sys.exit(1) -except ConnectionError as ce: - logger.error("Connection to SUPR failed - %s" %str(ce)) - sendMail("Connection to SUPR failed - " + str(ce), settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") - sys.exit(1) - -# Connect to FreeIPA -try: - ipa = ipahttp.ipa(settings.IPA_HOST) - ipa.login(settings.IPA_ADMIN_USER, settings.IPA_ADMIN_PWD) -except Exception as e: - logger.error("FreeIPA Connection Error - %s", e) - sendMail("Error occured in FreeIPA Connection - " + str(e), settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, "IPA Connection Error") - sys.exit(1) - -# Loop through the results from the search in SUPR -for p in res.matches: - for m in p.members: - user = m.centre_person_id - principal = user+ "@SWESTORE.SE" - - if not (m.user_agreement_version and m.user_agreement_accepted): - logger.info(str(m.id) + " --- user agreement not signed") - - reply = ipa.user_find(user) - if reply['result']['result']: - #ipa.passwd(principal,temp_password()) - logger.info(str(m.id) + " --- " + m.centre_person_id + " --- 1111") - else: - #addPersontoFreeIPA(m) - if (m.user_agreement_version and m.user_agreement_accepted): - logger.info(user + " user agreement accepted but not added to IPA") - else: - logger.info(user + " user agreement not signed") diff --git a/1time_scripts/supr_irods_kerberos_1time.py b/1time_scripts/supr_irods_kerberos_1time.py deleted file mode 100644 index 4fba29bb3c139ceb8166f20234460eacd423bf3e..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_irods_kerberos_1time.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import os - -from irods.session import iRODSSession -from irods.exception import * -import settings - -from supr_common import (asciify, - setup_log) - -logging.basicConfig() -# logging configuration -logger = setup_log("IRODS_PDC_KERBEROS", "logs/irods_set_pdc_kerberos_1time.log") - -# Compose query from the below options -params = {'full_person_data': '1','all_centre_person_ids':'1', 'resource_centre_id': settings.resource_centre_id, 'resource_id': settings.irods_resource_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - - -sess = None - -try: - - # Connection to a server with the default values - sess = iRODSSession(host=settings.IRODS_HOST, - port=settings.IRODS_PORT, - user=settings.IRODS_ADMIN_USER, - password=settings.IRODS_ADMIN_PWD, - zone=settings.IRODS_ZONE) - - memberList = [] - - for p in res.matches: - - for m in p.members: - - userName = None - if m.centre_person_id: - userName = str(m.centre_person_id).strip() - - if userName and (userName not in memberList): - - try: - user = sess.users.get(userName) - if user: - memberList.append(userName) - - if m.centre_person_ids: - pdc_kerberos_principal = None - - for cpid in m.centre_person_ids: - if cpid.centre.id == settings.PDC_centre_id: - - pdc_kerberos_principal = cpid.centre_person_id + "@" + settings.PDC_kerberos - #print pdc_kerberos_principal - - if (not user.dn) or (user.dn and pdc_kerberos_principal not in user.dn): - #print user.dn - sess.users.modify(userName, 'addAuth', pdc_kerberos_principal) - logger.info(pdc_kerberos_principal + " -- PDC Kerberos principal added to irods user -- " + userName) - else: - logger.info(pdc_kerberos_principal + " -- PDC Kerberos principal already added to irods user -- " + userName) - - except UserDoesNotExist: - logger.info(userName + " user does not exist in irods") - - else: - logger.info(userName + " -- user already checked") - -except iRODSException as ie: - logger.error("Error during iRODS Connection: %s", repr(ie)) - -except Exception as e: - logger.error("Error during Execution: %s", e) -finally: - if sess: - sess.cleanup() - diff --git a/1time_scripts/supr_irods_pirc_pwd_1time.py b/1time_scripts/supr_irods_pirc_pwd_1time.py deleted file mode 100644 index 629733a9781cef3eda5e55b217571d1632b003ec..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_irods_pirc_pwd_1time.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import os - -from irods.session import iRODSSession -from irods.exception import * -import settings - -from supr_common import (asciify, - sendMail, - setup_log, - temp_password) - -logging.basicConfig() -# logging configuration -logger = setup_log("IRODS_SET_PWD", "logs/irods_set_pwd_1time.log") - -# Compose query from the below options -params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id, 'resource_id': settings.irods_resource_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - - -sess = None - -try: - - # Connection to a server with the default values - sess = iRODSSession(host=settings.IRODS_HOST, - port=settings.IRODS_PORT, - user=settings.IRODS_ADMIN_USER, - password=settings.IRODS_ADMIN_PWD, - zone=settings.IRODS_ZONE) - - memberList = ['s_dejvi', 's_ilako'] - - for p in res.matches: - - for m in p.members: - - userName = str(m.centre_person_id).strip() - - if userName and (userName not in memberList): - - principal = userName+ "@SWESTORE.SE" - - try: - user = sess.users.get(userName) - if user: - memberList.append(userName) - sess.users.modify(userName, 'password', temp_password()) - logger.info(userName + " -- temp password added to irods") - - if (not user.dn) or (user.dn and principal not in user.dn): - sess.users.modify(userName, 'addAuth', principal) - logger.info(userName + " -- principal added to irods") - else: - logger.info(userName + " -- principal already added to irods") - - if m.subject and not m.subject == "": - certi_subj = str((m.subject).encode('utf-8')) - - if user.dn and certi_subj not in user.dn: - sess.users.modify(userName, 'addAuth', certi_subj) - logger.info(userName + " certificate added to irods auth") - else: - logger.info(userName + " -- certificate already added to irods") - - except UserDoesNotExist: - print userName + "does not exist in irods" - logger.info(userName + " user does not exist in irods") - - else: - logger.info(userName + " -- temp password already added to irods") - -except iRODSException as ie: - logger.error("Error during iRODS Connection: %s", repr(ie)) - -except Exception as e: - logger.error("Error during Execution: %s", e) -finally: - if sess: - sess.cleanup() diff --git a/1time_scripts/supr_irods_yubikey_1time.py b/1time_scripts/supr_irods_yubikey_1time.py deleted file mode 100644 index 638cc89bf856fbbc0cd74d4ba15b7d76d29821e7..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_irods_yubikey_1time.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import ldap -import ldap.modlist as modlist -import logging -import sys -import supr -import smtplib -import os - -from email.mime.text import MIMEText - -import settings - -from supr_common import (asciify, - sendMail, - setup_log, - temp_password) - -logging.basicConfig() -# logging configuration -logger = setup_log("Yubikey_Mail", "logs/yubikey_mail_1time.log") - -# Compose query from the below options -params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id, 'resource_id': settings.irods_resource_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - - -sess = None - -# Message to be sent to User -def sendUserMail(m, proj_name): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are a member of Swestore/iRODS project -- " + proj_name + " in SUPR. \n\n" - - msgTxt += "We would like to inform that going forward SNIC/iRODS will be using password authentication and yubikey would be retired. \n" - msgTxt += "Please click on the following link to set password -- http://auth1.swestore.se/ipa/supr/supr-auth1.cgi \n" - msgTxt += "You will be redirected to SUPR authentication page for confirmation. \n" - msgTxt += "Once authenticated, you can set a password for iRODS. \n \n" - msgTxt += "We also request you to mail us back the yubikey to the following address -- \n \n" - msgTxt += "Krishnaveni Chitrapu \n" - msgTxt += "Swestore/iRODS Support Team \n" - msgTxt += "National Supercomputer Centre \n" - msgTxt += "Linköping University \n" - msgTxt += "581 83 Linköping, Sweden \n \n" - - msgTxt += "For more information on connecting and using snic-irods,\n" - msgTxt += "please refer to http://snicdocs.nsc.liu.se/wiki/Swestore-irods \n \n" - msgTxt += "Regards,\n" + "Swestore/iRODS Support Team" - - msgTxt = msgTxt.decode('utf-8') - - sendMail(msgTxt, settings.IRODS_FROM_ADDRS, m.email, "IRODS - Yubikey authentication replaced with password authentication") - -try: - - memberList = [] - for p in res.matches: - proj_name = ((p.directory_name).encode('utf-8')).lower() - for m in p.members: - - if m.id not in memberList: - - memberList.append(m.id) - sendUserMail(m,proj_name) - logger.info("mail sent to -- " + str(m.id)) - - else: - logger.info("mail already sent to -- " + str(m.id)) - -except Exception as e: - logger.error("Error during Execution: %s", e) -finally: - if sess: - sess.cleanup() diff --git a/1time_scripts/supr_swestore_init.py b/1time_scripts/supr_swestore_init.py deleted file mode 100644 index 00a81007e5682d325125d24f947ef65d7556cdc8..0000000000000000000000000000000000000000 --- a/1time_scripts/supr_swestore_init.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import ldap -import ldap.modlist as modlist - -from settings import * - -# Connect to LDAP using python-LDAP -try: - #ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) - #l = ldap.initialize(LDAP_HOST) - l = ldap.open(LDAP_HOST) - l.simple_bind_s(LDAP_ADMIN, LDAP_PASSWORD) - - attrs = {} - attrs['objectclass'] = ['top','organization','dcObject'] - attrs['o'] = 'Swestore' - - ldif = modlist.addModlist(attrs) - l.add_s(baseDN,ldif) - - attrs = {} - attrs['objectclass'] = ['top','organizationalUnit'] - attrs['ou'] = 'Groups' - - ldif = modlist.addModlist(attrs) - l.add_s(groupsDN,ldif) - - attrs = {} - attrs['objectclass'] = ['top','organizationalUnit'] - attrs['ou'] = 'People' - - ldif = modlist.addModlist(attrs) - l.add_s(peopleDN,ldif) - - l.unbind_s() - -except ldap.LDAPError, e: - print e diff --git a/1time_scripts/update_group_ldap.py b/1time_scripts/update_group_ldap.py deleted file mode 100644 index d25bfd680b81d8b585feb88eeda152ce7a1a4e24..0000000000000000000000000000000000000000 --- a/1time_scripts/update_group_ldap.py +++ /dev/null @@ -1,43 +0,0 @@ -import ldap -import ldap.modlist as modlist -import settings - -l = None -# Connect to LDAP using python-LDAP -try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) - - l = ldap.initialize(settings.LDAP_HOST) - l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) -except ldap.LDAPError as le: - print ("LDAP Connection Error - %s", le) - if l: - l.unbind() - -try: - attrsGroup = {} - #groupDN = "gidNumber=12806" + "," + settings.groupsDN - attrsGroup['objectclass'] = ['Swestore','posixgroup'] - attrsGroup['cn'] = 'reference_4' - attrsGroup['description'] = ['6806', '9948'] - attrsGroup['piMemberID'] = '32851' - attrsGroup['memberUID'] = ['s_jenme', 's_jesno', 's_gerro', 's_chawa'] - attrsGroup['resourceID'] = ['31'] - attrsGroup['projectEndDate'] = '2019-11-01' - attrsGroup['lastModifiedTime'] = '2018-10-30 16:50:36' - - #ldif = modlist.addModlist(attrsGroup) - #l.add_s(groupDN,ldif) - - groupDN = "gidNumber=16575" + "," + settings.groupsDN - #l.delete_s(groupDN) - oldMemberUid = [(ldap.MOD_DELETE, 'memberUid', '')] - newMemberUid = [(ldap.MOD_ADD, 'memberUid', '32691' )] - - self.l.modify_s(groupDN,oldMemberUid) - self.l.modify_s(groupDN,newMemberUid) - -except ldap.LDAPError as le: - print ("LDAP Error -- %s",le) - diff --git a/README.md b/README.md index 180c0b1b2291faf32b127c9474bfa6623e7253f2..c528335e9aa3318405f7186691d9f4bbd8670e01 100644 --- a/README.md +++ b/README.md @@ -3,42 +3,40 @@ This is NAISS SUPR LDAP integration, a collection of scripts to synchronize and update user and project information between SUPR and the Swestore LDAP. -# Development +The upstream repository for this repo is: +https://gitlab.liu.se/swestore/supr-ldap-integration -## Dependencies +modified_time.txt, its needed to bring the projects and persons from SUPR +from last updated time..i.e. if the last script ended now, modified_time.txt +wil be updated with that timestamp so that next time when the script runs, +it will only fetch projects and persons from that timestamp -- python2 -- python-virtualenv -- openldap@2.4 -- cyrus-sasl -- mit-krb5 -In addition, development libraries for python2 are necessary. +The main entry point is supr_swestore_main.py. -## Virtualenv +# Installation -The development tooling are reliant on a tool called virtualenv, which -creates links to a installed version of python and also allows for -installing packages local to the project. +## System Dependencies -First create the virtual environment: +- python3 +- ldap3 +- urllib3 +- python-kadmin +- openldap +- openldap-dev +- cyrus-sasl +- mit-krb5 -```sh -virtualenv -p python2 . -``` +## Installing python dependencies -In order to enable it run the shell appropriate script found in the -newly created bin directory, for example: +To install python dependencies have to be installed. -```sh -source bin/activate -``` + python3 -m pip install -r requirements.txt -## Installing python dependencies +Then you should be ready: + + python3 supr_swestore_main.py -To install python dependencies have to be installed. Make sure that -you have ran the script in bin/activate first. +# More information -```sh -python -m pip install -r requirements.txt -``` +- https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments diff --git a/cronscript.sh b/cronscript.sh deleted file mode 100755 index 6301e2c165196b977d0168539c98aed25875e08b..0000000000000000000000000000000000000000 --- a/cronscript.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -#exit 0 #(krishnaveni: 2022-08-18 till auth1 is fixed due to CVE-2022-2414) - -# Source init scripts. -. /etc/profile -LD_LIBRARY_PATH="/supr/lib64:/opt/rh/python27/root/usr/lib64" -export LD_LIBRARY_PATH - -# Build virtual environment and call python script. -cd /supr -source bin/activate -python supr_swestore_main.py -if [ $? -ne 0 ] -then - echo "Python script failed" -fi -deactivate diff --git a/del_scripts/delete_proj_persons_ldap.py b/del_scripts/delete_proj_persons_ldap.py deleted file mode 100644 index 7992a5df043902fca0dbdaf90af8c4b6bcd9b6ef..0000000000000000000000000000000000000000 --- a/del_scripts/delete_proj_persons_ldap.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import ldap -import ldap.modlist as modlist -import sys - -import settings - - -# LDAP search scope and other variables -searchScope = ldap.SCOPE_SUBTREE -retrievedAttrs = ["description"] - -# Delete Persons from LDAP and iRODS that are not in SUPR -def deletePersons(): - try: - # Get All Persons from LDAP - filter = "uidNumber=*" - ldap_result_id = l.search(settings.peopleDN, searchScope, filter, retrievedAttrs) - result_type, ldap_persons = l.result(ldap_result_id) - - # Loop through LDAP results - for person in ldap_persons: - l.delete_s(person[0]) - - except ldap.LDAPError as le: - print("LDAP Error in deletePersonsFromLDAP Module - %s", le) - -# Delete Projects from LDAP and iRODS that are not in SUPR -def deleteProjects(): - try: - # Get All Projects from LDAP - filter = "gidNumber=*" - ldap_result_id = l.search(settings.groupsDN, searchScope, filter, retrievedAttrs) - result_type, ldap_groups = l.result(ldap_result_id) - - for group in ldap_groups: - l.delete_s(group[0]) - - except ldap.LDAPError as le: - print("LDAP Error in deleteProjectsFromLDAP Module - %s", le) - - -# Connect to LDAP using python-LDAP -ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) -ldap.set_option(ldap.OPT_X_TLS_CERTFILE,settings.TLS_CERTFILE) -ldap.set_option(ldap.OPT_X_TLS_KEYFILE,settings.TLS_KEYFILE) -ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND) - -l = ldap.initialize(settings.LDAP_HOST) - -try: - l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) - - # delete Persons From LDAP - deletePersons() - - # delete Projects From LDAP - deleteProjects() - -except ldap.LDAPError as le: - print("LDAP Connection Error - %s", le) -finally: - if l: - l.unbind() diff --git a/del_scripts/delete_project_pirc.py b/del_scripts/delete_project_pirc.py deleted file mode 100644 index 3c6f390de29fe9cabb6009a9e15ee44370e14292..0000000000000000000000000000000000000000 --- a/del_scripts/delete_project_pirc.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import smtplib -import os - -from email.mime.text import MIMEText -from irods import * -from settings import * -from subprocess import call, check_output - -# logging configuration -logging.basicConfig(filename = DELETE_LOG_FILE, - filemode = LOG_FILE_MODE, - format = LOG_FILE_FORMAT, - datefmt = LOG_FILE_DATEFORMAT, - level = logging.DEBUG) - -# Compose query from the below options -params = {'full_person_data': '1','resource_centre_id': resource_centre_id, 'resource_id': irods_resource_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = SUPR_API_USER_NAME, password = SUPR_API_PASSWORD) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logging.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - -try: -sess = None -coll = None -group = None - -try: - - # Connection to a server with the default values - sess = iRODSSession(host=settings.IRODS_HOST, - port=settings.IRODS_PORT, - user=settings.IRODS_ADMIN_USER, - password=settings.IRODS_ADMIN_PWD, - zone=settings.IRODS_ZONE) - - try: - c = sess.collections.get(settings.IRODS_DIR) - self.logger.info("Client Connection to iRODS successful \n") - except CollectionDoesNotExist: - self.logger.error(settings.IRODS_DIR + " does not exist ") - self.ERR_MJR_MAIL += settings.IRODS_DIR + " does not exist " + "\n" - self.err_mjr_cnt += 1 - - try: - userGroup = sess.user_groups.get("users") - except UserGroupDoesNotExist: - self.logger.error(" users group does not exist ") - self.ERR_MJR_MAIL += " users group does not exist " + "\n" - self.err_mjr_cnt += 1 - - for p in res.matches: - - proj_name = ((p.directory_name).encode('utf-8')).lower() - group = sess.user_groups.get(proj_name) - - for m in p.members: - if m.centre_person_id: - userName = str(m.centre_person_id).strip() - - user = sess.users.get(userName) - if group: - if user and group.hasmember(userName): - group.removemember(userName) - logging.info(userName + " user deleted from " + proj_name + " group") - else: - logging.info(userName + " user already deleted from " + proj_name + " group") - - if userGroup: - if user and userGroup.hasmember(userName): - userGroup.removemember(userName) - logging.info(userName + " user deleted from user group") - else: - logging.info(userName + " user already deleted from users group") - - if user: - sess.users.remove(userName) - logging.info(userName + " user deleted.") - else: - logging.info(userName + " user already deleted") - - if group: - sess.user_groups.remove(proj_name) - sess.collections.remove(proj_name) - logging.info(proj_name + " group deleted") - else: - logging.info(proj_name + " group already deleted") - -except Exception as e: - logging.error("Error during Execution: %s", e) -finally: - if sess: - sess.cleanup() - diff --git a/del_scripts/delete_project_pyrods.py b/del_scripts/delete_project_pyrods.py deleted file mode 100644 index 6ada05da1389b2e539cb8e9f14d897f3486b1e30..0000000000000000000000000000000000000000 --- a/del_scripts/delete_project_pyrods.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import logging -import sys -import supr -import smtplib -import os - -from email.mime.text import MIMEText -from irods import * -from settings import * -from subprocess import call, check_output - -# logging configuration -logging.basicConfig(filename = IRODS_LOG_FILE, - filemode = LOG_FILE_MODE, - format = LOG_FILE_FORMAT, - datefmt = LOG_FILE_DATEFORMAT, - level = logging.DEBUG) - -# Compose query from the below options -params = {'full_person_data': '1','resource_centre_id': resource_centre_id, 'resource_id': irods_resource_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = SUPR_API_USER_NAME, password = SUPR_API_PASSWORD) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logging.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - -try: - envVal = obfiGetEnvKey() - obi_password = obfiEncode(IRODS_ADMIN_PWD, envVal) - - # Connection to a server with the default values - conn, errMsg = rcConnect(IRODS_HOST, IRODS_PORT, IRODS_ADMIN_USER, IRODS_ZONE) - status = clientLoginWithObfPassword(conn, obi_password) - - c = irodsCollection(conn, IRODS_DIR) - userGroup = getGroup(conn, "users") - - for p in res.matches: - - proj_name = ((p.directory_name).encode('utf-8')).lower() - group = getGroup(conn, proj_name) - - for m in p.members: - - user = getUser(conn,str(m.centre_person_id)) - if group: - if user and (user.getId() in (groupuser.getId() for groupuser in group.getMembers())): - group.rmUser(str(m.centre_person_id)) - logging.info(str(m.centre_person_id) + " user deleted from " + proj_name + " group") - else: - logging.info(str(m.centre_person_id) + " user already deleted from " + proj_name + " group") - - if userGroup: - if user and (user.getId() in (groupuser.getId() for groupuser in userGroup.getMembers())): - userGroup.rmUser(str(m.centre_person_id)) - logging.info(str(m.centre_person_id) + " user deleted from user group") - else: - logging.info(str(m.centre_person_id) + " user already deleted from users group") - - if user: - deleteUser(conn, str(m.centre_person_id)) - logging.info(str(m.centre_person_id) + " user deleted.") - else: - logging.info(str(m.centre_person_id) + " user already deleted") - - if getGroup(conn, proj_name): - group = deleteGroup(conn, proj_name) - logging.info(proj_name + " group deleted") - else: - logging.info(proj_name + " group already deleted") - - if proj_name in c.getSubCollections(): - c.deleteCollection(proj_name) - logging.info(IRODS_DIR + proj_name + " directory deleted") - else: - logging.info(IRODS_DIR + proj_name + " directory already deleted") - -except Exception as e: - logging.error("Error during Execution: %s", e) -finally: - conn.disconnect() diff --git a/modified_time.txt b/modified_time.txt index 481e41570214b7fbdcd4273002e2eeb900b8ef79..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/modified_time.txt +++ b/modified_time.txt @@ -1 +0,0 @@ -2023-03-30 13:30:02 \ No newline at end of file diff --git a/python3-update.md b/python3-update.md deleted file mode 100644 index a20bb23b78045caf669cd69766cd2d7273ecf4ab..0000000000000000000000000000000000000000 --- a/python3-update.md +++ /dev/null @@ -1,59 +0,0 @@ -Supr-ldap-integration Python3 Update Plan -========================================= - -This explains preliminary plans to update the supr-integration scripts to -python3. A repo of the code is available here: -https://gitlab.liu.se/swestore/supr-ldap-integration. The master branch is -the old python2 version. The branch with the work in progress update is -python3. - -A partially updated version is checked out at ldaptest:/opt/. I lack -sufficient knowledge to even test it so progress has stalled. - -The Current Deployed Version -============================ - -The version thats currently deployed has had a few minor changes. The code -is currently deployed to ldaptest and ldap1 in the directory /supr. Changes -since last year (2022) include: - -- Created a upstream git repository. -- Merged changes between the versions available on the two servers. -- Update the email template being sent out to new users to use current links. -- Removed all references to IPA and IRODS, as they are no longer used. - -The Update Plan -=============== - -Here are a few things that I think should change: - -- Update to python3, python2 has been deprecated for a while now. -- Have a better way of deploying the scripts. -- Have some way of managing dependencies. - -Deploy Scripts In a Better Way ------------------------------- - -I currently apply changes by pushing to the gitlab repository and then pull -the changes from the ldap_master servers. This still feels frail but is -better than copying files over. - -I have a few ideas on how this could be better: - -- Use puppet to automatically install the code -- Create a .rpm-package with the code - -Dependency Management ---------------------- - -Another related issue is how to manage dependencies, currently the code -relies on a virtual-env to install dependencies. This works but has turned -out to be tricky to automate. - -An alternative could be to if one were to install it through the package -manager to declare dependencies that way. Or if puppet is used to deploy, -then dependencies could be installed that way, with or without virtual-envs. - -I also believe that the file supr.py belongs to another package but has been -included by copying it into the repo. It would be good to include it as a -proper dependency instead. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 99ad7f05191daefb2f219949d13c2bee2276553f..0000000000000000000000000000000000000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -python-ldap -requests -python-kadmin==0.1.2+twtr # Busted diff --git a/settings-default.py b/settings-default.py index 4adbb6613c339a415f5954f52051940f135b78b7..16eafbd4a341273b88b6e60135c44446c71d658c 100644 --- a/settings-default.py +++ b/settings-default.py @@ -1,55 +1,55 @@ #!/usr/bin/python #! -*- coding: utf-8 -*- -# Settings File for supr_swestore -# Copy this file to settings.py - import datetime -SUPR_API_USER_NAME = "" -SUPR_API_PASSWORD = "" -SUPR_BASE_URL = "" +# Settings File for supr_swestore -# LDAP HOST -HOST_NAME = "" -LDAP_PORT = "" -LDAP_HOST = "ldaps://" + HOST_NAME + ":" + LDAP_PORT +# SUPR API USER NAME +SUPR_API_USER_NAME = +# SUPR API PASSWORD +SUPR_API_PASSWORD = +# SUPR API URL +SUPR_BASE_URL = +# LDAP HOST +HOST_NAME = +LDAP_PORT = +LDAP_HOST = +#LDAP_HOST = "ldapi:///" # LDAP BIND DN -baseDN = "" -LDAP_ADMIN = "" -LDAP_PASSWORD = "" +baseDN = "dc=swestore-ldap" +LDAP_ADMIN = "cn=admin," + baseDN +# LDAP BIND PASSWORD +LDAP_PASSWORD = # TLS Certificate Paths -TLS_CACERTDIR = "/etc/openldap/certs/" -TLS_CACERTFILE = "" -TLS_CERTFILE = "" -TLS_KEYFILE = "" +#TLS_CACERTDIR = "/etc/openldap/certs/" +TLS_CACERTFILE = "/etc/grid-security/certificates/TERENA-eScience-SSL-CA-3.pem" +TLS_CERTFILE = "/etc/grid-security/supr-cert.pem" +TLS_KEYFILE = "/etc/grid-security/supr-key.pem" # LDAP DN -groupsDN = "ou=Groups," + baseDN +groupsDN = "ou=Groups," + baseDN peopleDN = "ou=People," + baseDN uidNumberStart = 30000 gidNumberStart = 6000 # Centre Resource ID in SUPR for Swestore resource_centre_id = 9 -PDC_centre_id = 7 - -# PDC Kerberos tag -PDC_kerberos = "" # dcache Resource ID in SUPR for Swestore -dcache_resource_id = "" +dcache_resource_id = '31' # Kerberos settings -keytab = "" -adminprincipal = "" - +keytab = +adminprincipal = + # Get a date object today = datetime.date.today().strftime("%Y-%m-%d") -BASEDIR = "" +BASEDIR = "/supr/" +LOG_DIR = BASEDIR+ "logs/" DELETE_LOG_FILE = BASEDIR + "logs/delete_" + str(today) + ".log" LOG_FILE = BASEDIR + "logs/ldap_" + str(today) + ".log" LOG_FILE_MODE = 'a' @@ -57,7 +57,7 @@ LOG_FILE_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' LOG_FILE_DATEFORMAT = '%H:%M:%S' # DCache Admin Mail Ids to send mail -DCACHE_ADMIN_MAIL = "" +DCACHE_ADMIN_MAIL = 'dcache-admin@swestore.se' # Send Mail Attributes SMTP_HOST = 'localhost' diff --git a/supr_common.py b/supr_common.py index de971acd038bf05d135af204b821ba4e15589def..ce3f7913ee2a659deb422c95c6f7b42762483bb0 100644 --- a/supr_common.py +++ b/supr_common.py @@ -1,39 +1,42 @@ #!/usr/bin/python -#! -*- coding: utf-8 -*- +# ! -*- coding: utf-8 -*- -import ldap import logging import smtplib -import os, random, string +import os +import random +import string from email.mime.text import MIMEText from email.header import Header from unicodedata import decomposition -from settings import (LOG_FILE, +from settings import (LOG_DIR, + LOG_FILE, LOG_FILE_FORMAT, LOG_FILE_DATEFORMAT, SMTP_HOST, SMTP_PORT, - ) + ) + # Function to convert non ascii characters to ascii. # This is used for creating user IDs (uids) def asciify(string): # ASCIIfy u2a = { - u'æ' : u'ae', - u'Æ' : u'AE', - u'ø' : u'o', - u'Ø' : u'O', - u'ß' : u'ss', - u'þ' : u'th', - u'ð' : u'd', - u'´' : u"'" - } + 'æ': 'ae', + 'Æ': 'AE', + 'ø': 'o', + 'Ø': 'O', + 'ß': 'ss', + 'þ': 'th', + 'ð': 'd', + '´': "'" + } '''"ASCIIfy" a Unicode string by stripping all umlauts, tildes, etc.''' - temp = u'' + temp = '' for char in string: # Special case a few characters that don't decompose if char in u2a: @@ -42,24 +45,21 @@ def asciify(string): decomp = decomposition(char) if decomp: - temp += unichr(int(decomp.split()[0], 16)) + temp += chr(int(decomp.split()[0], 16)) else: temp += char return temp -# Function to setup Log Functionality for each module or Class -# Individual classes can configure accordingly + def setup_log(logger_name, log_file, level=logging.INFO): - # logging configuration - #logging.basicConfig(level=logging.INFO, - # format=LOG_FILE_FORMAT, - # datefmt=LOG_FILE_DATEFORMAT, - # stream=log_file, - # filemode='w') + """ Setup Log Functionality for each module or Class. + Individual classes can configure accordingly. + """ + os.makedirs(LOG_DIR, exist_ok=True) - logger = logging.getLogger(logger_name) + logger = logging.getLogger(logger_name) - hdlr = logging.FileHandler(log_file) + hdlr = logging.FileHandler(log_file) formatter = logging.Formatter(LOG_FILE_FORMAT, LOG_FILE_DATEFORMAT) hdlr.setFormatter(formatter) logger.setLevel(level) @@ -67,12 +67,13 @@ def setup_log(logger_name, log_file, level=logging.INFO): return logger + # logging configuration log_main = setup_log('SUPR_COMMON', LOG_FILE) + # Function to send mail to Admins for daily logs and other important errors. def sendMail(msgtext, from_address, to_address, subject): - if msgtext: msg = MIMEText(msgtext, 'plain', 'utf-8') msg['Subject'] = Header(subject, 'utf-8') @@ -83,7 +84,7 @@ def sendMail(msgtext, from_address, to_address, subject): s = None try: s = smtplib.SMTP(SMTP_HOST, SMTP_PORT) - #s.starttls() + # s.starttls() s.sendmail(from_address, to_address, msg.as_string()) except smtplib.SMTPException as se: @@ -92,6 +93,7 @@ def sendMail(msgtext, from_address, to_address, subject): if s: s.quit() + # Function to get generate temporary password def temp_password(): length = 13 diff --git a/supr_irods_pirc.py b/supr_irods_pirc.py deleted file mode 100644 index 98fd46c60d18bd87379cdbc0620abf430c10caca..0000000000000000000000000000000000000000 --- a/supr_irods_pirc.py +++ /dev/null @@ -1,438 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- - -import logging -import sys -import settings -from irods.session import iRODSSession -from irods.access import iRODSAccess -from irods.exception import * - -from supr_common import (sendMail, - setup_log, - temp_password) - -class SUPR_IRODS: - - def __init__(self, irods_projects, irods_persons_modified): - - if irods_projects or irods_persons_modified: - - # Setting irods_projects - self.irods_projects = irods_projects - self.sess = None - - # Get Logging File Handler - self.logger = setup_log(self.__class__.__name__, settings.IRODS_LOG_FILE) - - # Variables needed for calculating number of projects and persons created - # that are used to sendMail to Admins - self.add_proj_cnt = 0 - self.err_proj_cnt = 0 - self.add_grp_cnt = 0 - self.mod_grp_cnt = 0 - self.err_grp_cnt = 0 - self.err_grp_mod_cnt = 0 - self.add_pers_cnt = 0 - self.err_pers_cnt = 0 - self.sua_pers_cnt = 0 - self.err_mjr_cnt = 0 - - # Variables needed for Message Text of projects and persons created - # that are used to sendMail to Admins - self.ADD_PERS_MAIL = "The Following Persons have been Added on " + settings.today + "\n" - self.ADD_PERS_MAIL += "---------------------------------------------------- \n" - - self.SUA_PERS_MAIL = "The Following Persons have not signed SUA and hence not added on " + settings.today + "\n" - self.SUA_PERS_MAIL += "---------------------------------------------------- \n" - - self.ADD_PROJ_MAIL = "The Following Projects have been Added on " + settings.today + "\n" - self.ADD_PROJ_MAIL += "----------------------------------------------------- \n" - - self.ADD_GRP_MAIL = "The Following Groups have been Added on " + settings.today + "\n" - self.ADD_GRP_MAIL += "----------------------------------------------------- \n" - - self.MOD_GRP_MAIL = "The Following Groups have been Modified on " + settings.today + "\n" - self.MOD_GRP_MAIL += "----------------------------------------------------- \n" - - self.ERR_PROJ_MAIL = "Error in creating the following Projects on " + settings.today + "\n" - self.ERR_PROJ_MAIL += "------------------------------------------------------- \n" - - self.ERR_GRP_MAIL = "Error in creating the following Groups on " + settings.today + "\n" - self.ERR_GRP_MAIL += "---------------------------------------------------- \n" - - self.ERR_GRP_MOD_MAIL = "Error in modifying the following Groups on " + settings.today + "\n" - self.ERR_GRP_MOD_MAIL += "---------------------------------------------------- \n" - - self.ERR_PERS_MAIL = "Error in creating the following Persons on " + settings.today + "\n" - self.ERR_PERS_MAIL += "------------------------------------------------------- \n" - - self.ERR_MJR_MAIL = "Major Error Occured on " + settings.today + "\n" - self.ERR_MJR_MAIL += "---------------------------------- \n" - - self.msgtext = "" - - try: - # Connection to a server with the default values - self.sess = iRODSSession(host=settings.IRODS_HOST, - port=settings.IRODS_PORT, - user=settings.IRODS_ADMIN_USER, - password=settings.IRODS_ADMIN_PWD, - zone=settings.IRODS_ZONE) - except iRODSException as ie: - self.logger.error("Error during iRODS Connection: %s", repr(ie)) - self.ERR_MJR_MAIL += "Error occured in iRODS Connection - " + repr(ie) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_SUBJECT) - sys.exit(1) - - except Exception as e: - self.logger.error("Error during iRODS Connection: %s", repr(e)) - self.ERR_MJR_MAIL += "Error occured in iRODS Connection - " + repr(e) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_SUBJECT) - sys.exit(1) - finally: - if self.sess: - self.sess.cleanup() - - # Call to AddProjects Function - if irods_projects: - self.addProjects() - - addUsers = [] - cantAddUsers = [] - - if irods_persons_modified: - for m in irods_persons_modified: - self.addUser(m[0], m[1], addUsers, cantAddUsers ) - - if addUsers: - self.ADD_GRP_MAIL += "\t Group Name :: " + m[1] + "\t Persons Added :: " + ", ".join(addUsers) + "\n" - self.add_grp_cnt += 1 - - if cantAddUsers: - self.ERR_GRP_MOD_MAIL += "\t Group Name :: " + m[1] + "\t Persons Couldnot be Added :: " + ", ".join(cantAddUsers) + "\n" - self.err_grp_mod_cnt += 1 - - # Call to sendMail() Function - if self.err_mjr_cnt: - self.msgtext += str(self.ERR_MJR_MAIL) + "\n" - if self.err_pers_cnt: - self.msgtext += str(self.ERR_PERS_MAIL) + "\n" - if self.err_proj_cnt: - self.msgtext += str(self.ERR_PROJ_MAIL) + "\n" - if self.err_grp_cnt: - self.msgtext += str(self.ERR_GRP_MAIL) + "\n" - if self.err_grp_mod_cnt: - self.msgtext += str(self.ERR_GRP_MOD_MAIL) + "\n" - if self.add_proj_cnt: - self.msgtext += str(self.ADD_PROJ_MAIL) + "\n" - if self.add_grp_cnt: - self.msgtext += str(self.ADD_GRP_MAIL) + "\n" - if self.add_pers_cnt: - self.msgtext += str(self.ADD_PERS_MAIL) + "\n" - if self.sua_pers_cnt: - self.msgtext += str(self.SUA_PERS_MAIL) + "\n" - if self.mod_grp_cnt: - self.msgtext += str(self.MOD_GRP_MAIL) + "\n" - if self.msgtext: - sendMail(self.msgtext, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_SUBJECT) - - # Function to add Users in irods and Assign Users to Groups - def addUser(self,m,proj_name,addUsers,cantAddUsers): - - uidNumber = str(settings.uidNumberStart + m.id) - - if m.centre_person_id and not (m.centre_person_id == uidNumber): - - userName = str(m.centre_person_id).strip() - certi_subj = ""; - - if m.subject and not m.subject == "": - certi_subj = str((m.subject).encode('utf-8')) - try: - user = self.sess.users.get(userName) - newUser = False - - # Add Certificate subject to irods - if (not user.dn) or (user.dn and certi_subj not in user.dn): - - if not certi_subj == "": - self.sess.users.modify(userName, 'addAuth', certi_subj) - self.logger.info(userName + " certificate added to irods auth") - - # Add PDC Kerberos principal to irods - if m.centre_person_ids: - for cpid in m.centre_person_ids: - - if cpid.centre.id == settings.PDC_centre_id: - pdc_kerberos_principal = cpid.centre_person_id + "@" + settings.PDC_kerberos - - if pdc_kerberos_principal not in user.dn: - self.sess.users.modify(userName, 'addAuth', pdc_kerberos_principal) - self.logger.info(pdc_kerberos_principal + " -- PDC Kerberos principal added to irods user -- " + userName) - else: - self.logger.info(pdc_kerberos_principal + " -- PDC Kerberos principal already exists for irods user -- " + userName) - else: - self.logger.info("No PDC Kerberos principal exists for irods user -- " + userName) - - self.logger.info(userName + " user already exists") - - except UserDoesNotExist: - try: - user = self.sess.users.create(userName, "rodsuser") - self.logger.info(userName + " user created") - newUser = True - - # Add temporary user password to irods - self.sess.users.modify(userName, 'password', temp_password()) - self.logger.info(userName + " temporary initial password added to irods") - - # Add Certificate Subject to irods - if not certi_subj == "": - self.sess.users.modify(userName, 'addAuth', certi_subj) - self.logger.info(userName + " certificate added to irods auth") - - # Add Kerberos Prinicipal to irods - kerberos_principal = userName+"@SWESTORE.SE" - self.sess.users.modify(userName, 'addAuth', kerberos_principal) - self.logger.info(kerberos_principal + " -- SWESTORE Kerberos principal added to irods user -- " + userName) - - # Add PDC Kerberos principal to irods - if m.centre_person_ids: - for cpid in m.centre_person_ids: - - if cpid.centre.id == settings.PDC_centre_id: - pdc_kerberos_principal = cpid.centre_person_id + "@" + settings.PDC_kerberos - self.sess.users.modify(userName, 'addAuth', pdc_kerberos_principal) - self.logger.info(pdc_kerberos_principal + " -- PDC Kerberos principal added to irods user -- " + userName) - - self.ADD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + userName + "\t Person Name :: " + str((m.first_name).encode('utf-8')) + " " + str((m.last_name).encode('utf-8')) + "\n" - self.add_pers_cnt += 1 - - except Exception as e: - self.logger.error(str(m.centre_person_id) + " user could not be created due to " + repr(e)) - self.ERR_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + userName + "\t Person Name :: " + str((m.first_name).encode('utf-8')) + " " + str((m.last_name).encode('utf-8')) + "\n" - self.err_pers_cnt += 1 - - group = self.sess.user_groups.get(proj_name) - if group: - # Add the users to the group - if user: - if group.hasmember(userName): - self.logger.info(userName + " user already exists in " + proj_name + " group") - else: - try: - group.addmember(userName) - addUsers.append(userName) - self.logger.info(userName + " user added to " + proj_name + " group") - self.sendUserMail(m, proj_name, newUser) - except Exception as e: - cantAddUsers.append(userName) - self.logger.error(userName + " user could not be added to " + proj_name + " group due to " + repr(e)) - - else: - cantAddUsers.append(userName) - self.logger.error(userName + " user was not created. Hence could not be added to " + proj_name) - - else: - self.logger.error(proj_name + " group does not exist") - - userGroup = self.sess.user_groups.get("users") - if userGroup: - # Add the users to the usergroup - if userGroup.hasmember(userName): - self.logger.info(userName + " user already exists in users group \n") - - else: - userGroup.addmember(userName) - self.logger.info(userName + " user added to users group \n") - else: - self.logger.error("users group does not exist") - self.ERR_GRP_MAIL += "users group does not exist \n" - self.err_grp_cnt += 1 - - - # Function to add Projects and Users and Assign Users to Groups - def addProjects(self): - coll = None - group = None - - try: - - try: - c = self.sess.collections.get(settings.IRODS_DIR) - self.logger.info("Client Connection to iRODS successful \n") - except CollectionDoesNotExist: - try: - c = self.sess.collections.create(settings.IRODS_DIR) - except Exception as e: - self.logger.error(settings.IRODS_DIR + " could not be created due to " + repr(e)) - self.ERR_MJR_MAIL += settings.IRODS_DIR + " could not be created " + "\n" - self.err_mjr_cnt += 1 - - try: - userGroup = self.sess.user_groups.get("users") - except UserGroupDoesNotExist: - try: - userGroup = self.sess.user_groups.create("users") - except Exception as e: - self.logger.error(" users group could not be created due to " + repr(e)) - self.ERR_MJR_MAIL += " users group could not be created " + "\n" - self.err_mjr_cnt += 1 - - for p in self.irods_projects: - - proj_name = ((p.directory_name).encode('utf-8')).lower() - newGroup = None - - # Creation of projects. It is created as collection - try: - coll = self.sess.collections.get(settings.IRODS_DIR + "/" + proj_name ) - self.logger.info(settings.IRODS_DIR + "/" + proj_name + " directory already exists") - - except CollectionDoesNotExist: - try: - coll = self.sess.collections.create(settings.IRODS_DIR + "/" + proj_name) - self.logger.info(settings.IRODS_DIR + "/" + proj_name + " directory created") - self.ADD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + proj_name + "\n" - self.add_proj_cnt += 1 - - except Exception as e: - self.logger.error(settings.IRODS_DIR + proj_name + " directory could not be created due to " + repr(e)) - self.ERR_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + proj_name + "\n" - self.err_proj_cnt += 1 - - # Creation of groups. It is created as group in PiRC - try: - group = self.sess.user_groups.get(proj_name) - newGroup = False - self.logger.info(proj_name + " group already exists \n") - - except UserGroupDoesNotExist: - try: - group = self.sess.user_groups.create(proj_name) - newGroup = True - self.logger.info(proj_name + " group created \n") - - except Exception as e: - self.logger.error(proj_name + " group could not be created due to " + repr(e)) - self.ERR_GRP_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\n" - self.err_grp_cnt += 1 - - removedUsers = [] - cantRemoveUsers = [] - - # Remove the users from group that have been removed from project in SUPR - if group: - for groupuser in group.members: - userName = str(groupuser.name) - - if userName not in (str(m.centre_person_id).strip() for m in p.members): - - try: - group.removemember(userName) - removedUsers.append(userName) - self.logger.info(userName + " user removed from " + proj_name + " group") - - except Exception as e: - cantRemoveUsers.append(userName) - self.logger.error(userName + " user could not be removed from " + proj_name + " group due to :: " + repr(e)) - - if removedUsers: - self.MOD_GRP_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons Removed :: " + ", ".join(removedUsers) + "\n" - self.mod_grp_cnt += 1 - if cantRemoveUsers: - self.ERR_GRP_MOD_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons Couldnot be Removed :: " + ", ".join(cantRemoveUsers) + "\n" - self.err_grp_mod_cnt += 1 - - addUsers = [] - cantAddUsers = [] - suaNotSigned = [] - - for m in p.members: - if m.user_agreement_version and m.user_agreement_accepted: - self.addUser(m,proj_name,addUsers,cantAddUsers) - else: - suaNotSigned.append(str(m.id)) - - if addUsers and not newGroup: - self.MOD_GRP_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons Added :: " + ", ".join(addUsers) + "\n" - self.mod_grp_cnt += 1 - - if addUsers and newGroup: - self.ADD_GRP_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons Added :: " + ", ".join(addUsers) + "\n" - self.add_grp_cnt += 1 - - if cantAddUsers: - self.ERR_GRP_MOD_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons Couldnot be Added :: " + ", ".join(cantAddUsers) + "\n" - self.err_grp_mod_cnt += 1 - - if suaNotSigned: - #self.SUA_PERS_MAIL += "SUPR ID :: " + str(p.id) + "\t Group Name :: " + proj_name + "\t Persons SUA Not signed :: " + ", ".join(suaNotSigned) + "\n" - self.sua_pers_cnt += 0 - - # update the Ownership of the collection from admin to the group - if newGroup: - try: - access = iRODSAccess("own", settings.IRODS_DIR + "/" + proj_name, proj_name, settings.IRODS_ZONE) - self.sess.permissions.set(access,recursive=True) - self.logger.info("Ownership added to " + proj_name + "\n") - - except Exception as e: - self.logger.error("Ownership could not be added to " + proj_name + " due to " + repr(e)) - self.ERR_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Ownership could not be added to Group :: " + proj_name + "\n" - self.err_proj_cnt += 1 - - # update the Inheritance of the collection - if newGroup: - try: - access = iRODSAccess("inherit", settings.IRODS_DIR+ "/" + proj_name, proj_name, settings.IRODS_ZONE) - self.sess.permissions.set(access,recursive=True) - self.logger.info("Inheritance enabled to " + proj_name + "\n") - - except Exception as e: - self.logger.error("Inheritance could not be enabled to " + proj_name + " due to " + repr(e)) - self.ERR_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Inheritance could not be added to Group :: " + proj_name + "\n" - self.err_proj_cnt += 1 - - except iRODSException as ie: - self.logger.error("Error during iRODS Connection: %s", repr(ie)) - self.ERR_MJR_MAIL += "Error occured in iRODS Connection - " + repr(ie) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_SUBJECT) - sys.exit(1) - - except Exception as e: - self.logger.error("Error during iRODS Connection: %s", repr(e)) - self.ERR_MJR_MAIL += "Error occured in iRODS Connection - " + repr(e) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_SUBJECT) - sys.exit(1) - finally: - if self.sess: - self.sess.cleanup() - - # Message to be sent to User - def sendUserMail(self, m, proj_name, newUser): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are added as a member to Swestore/iRODS project -- " + proj_name + " in SUPR. \n\n" - msgTxt += "Your username is " + str(m.centre_person_id) + "\n" - msgTxt += "Your project path is " + settings.IRODS_DIR + "/" + proj_name + "\n \n" - msgTxt += "The username is automatically generated using the firstname and lastname.\n \n" - - if newUser: - msgTxt += "Please click on the following link to set password for irods -- http://auth1.swestore.se/ipa/supr/supr-auth1.cgi" + "\n" - msgTxt += "You will be redirected to SUPR authentication page for confirmation." + "\n" - msgTxt += "Once authenticated, you can set a password for iRODS." + "\n" - else: - msgTxt += "Kindly use the password set by you earlier" + "\n" - - - msgTxt += "For more information on connecting and using snic-irods,\n" - msgTxt += "please refer to http://snicdocs.nsc.liu.se/wiki/Swestore-iRODS \n \n" - msgTxt += "Regards,\n" + "Swestore/iRODS Support Team" - - sendMail(msgTxt, settings.IRODS_FROM_ADDRS, m.email, settings.IRODS_USR_SUBJECT) diff --git a/supr_ldap.py b/supr_ldap.py new file mode 100644 index 0000000000000000000000000000000000000000..b418a6fa7fd1ba96d8831f7cf2192738346c8d35 --- /dev/null +++ b/supr_ldap.py @@ -0,0 +1,811 @@ +"""Main handler for supr and ldap connections.""" + +import kadmin +import ssl +import subprocess +import sys +from textwrap import dedent + +import ldap3 +from ldap3 import Server, Connection, Tls, ALL, SUBTREE +from requests import ConnectionError + +import settings +import supr + +from supr_common import (asciify, + sendMail, + setup_log, ) + + +class SUPR_LDAP: + """Handle the connection to supr and ldap. (?)""" + + def __init__(self, all_projects, persons_modified, supr_connection): + + if all_projects or persons_modified: + + # Get Logging File Handler + self.logger = setup_log(self.__class__.__name__, settings.LOG_FILE) + + # LDAP connection + self.server = None + self.connection = None + + # Get supr_connection + self.supr_connection = supr_connection + + # LDAP search scope and other variables + self.searchScope = SUBTREE + self.retrievedAttrs = None + + # Variables needed for calculating number of projects and + # persons created that are used to sendMail to Admins + self.add_proj_cnt = 0 + self.mod_proj_cnt = 0 + self.err_proj_cnt = 0 + + self.add_pers_cnt = 0 + self.mod_pers_cnt = 0 + self.err_pers_cnt = 0 + self.sua_pers_cnt = 0 + + self.krb_pers_cnt = 0 + self.err_kerb_cnt = 0 + + self.err_mjr_cnt = 0 + self.msgtext = "" + + # Variables needed for Message Text of projects and persons created + # that are used to sendMail to Admins + self.ADD_PERS_MAIL = dedent(f"""\ + Following Persons have been added to LDAP on {settings.today} + ------------------------------------------------------------- + """) + + self.MOD_PERS_MAIL = "Following Persons have been modified to LDAP on " + settings.today + "\n" + self.MOD_PERS_MAIL += "----------------------------------------------------------------- \n" + + self.SUA_PERS_MAIL = ("Following Persons have not signed SUA and hence not added to LDAP on " + + settings.today + "\n") + self.SUA_PERS_MAIL += "---------------------------------------------------------------------- \n" + + self.KRB_PERS_MAIL = "Following Persons have been added to Kerberos " + settings.today + "\n" + self.KRB_PERS_MAIL += "------------------------------------------------------- \n" + + self.ADD_PROJ_MAIL = "Following Projects have been added to LDAP on " + settings.today + "\n" + self.ADD_PROJ_MAIL += "----------------------------------------------------- \n" + + self.MOD_PROJ_MAIL = "Following Projects have been modified on " + settings.today + "\n" + self.MOD_PROJ_MAIL += "----------------------------------------------------- \n" + + self.ERR_PROJ_MAIL = "Error in creating the following Projects in LDAP on " + settings.today + "\n" + self.ERR_PROJ_MAIL += "------------------------------------------------------- \n" + + self.ERR_PERS_MAIL = "Error in creating the following Persons in LDAP on " + settings.today + "\n" + self.ERR_PERS_MAIL += "------------------------------------------------------ \n" + + self.ERR_KERB_MAIL = "Error in creating the following Persons in Kerberos on " + settings.today + "\n" + self.ERR_KERB_MAIL += "------------------------------------------------------ \n" + + self.ERR_MJR_MAIL = "Major Error occurred on " + settings.today + "\n" + self.ERR_MJR_MAIL += "---------------------------------- \n" + + # Connect to LDAP using LDAP3 + try: + tls_config = Tls(local_private_key_file=settings.TLS_KEYFILE, + local_certificate_file=settings.TLS_CERTFILE, + validate=ssl.CERT_NONE, + ca_certs_file=settings.TLS_CACERTFILE) + + self.server = Server(settings.LDAP_HOST, use_ssl=True, get_info=ALL, tls=tls_config) + + self.connection = Connection(server=self.server, user=settings.LDAP_ADMIN, + password=settings.LDAP_PASSWORD, + auto_bind="DEFAULT", + auto_referrals=True, + lazy=False, + client_strategy="SAFE_SYNC") + self.connection.bind() + self.connection.start_tls() + + except Exception as le: + self.logger.error("LDAP Connection Error - %s", le) + if self.connection: + self.connection.unbind() + + self.ERR_MJR_MAIL += "Error occurred in LDAP Connection - " + str(le) + "\n" + self.err_mjr_cnt += 1 + sys.exit(1) + + # Call to addUpdateProjects() Function + if all_projects: + # Assigning the all_projects from supr_swestore_main + self.all_projects = all_projects + self.addUpdateProjects() + + # Call to updateDeleteProjects() Function + if persons_modified: + # Assigning the persons_modified from supr_swestore_main + self.persons_modified = persons_modified + self.updateDeletePersons() + + # Call to sendMail() Function + if self.err_mjr_cnt: + self.msgtext += str(self.ERR_MJR_MAIL) + "\n" + if self.err_proj_cnt: + self.msgtext += str(self.ERR_PROJ_MAIL) + "\n" + if self.err_pers_cnt: + self.msgtext += str(self.ERR_PERS_MAIL) + "\n" + if self.add_proj_cnt: + self.msgtext += str(self.ADD_PROJ_MAIL) + "\n" + if self.mod_proj_cnt: + self.msgtext += str(self.MOD_PROJ_MAIL) + "\n" + if self.add_pers_cnt: + self.msgtext += str(self.ADD_PERS_MAIL) + "\n" + if self.sua_pers_cnt: + self.msgtext += str(self.SUA_PERS_MAIL) + "\n" + + if self.krb_pers_cnt: + self.msgtext += str(self.KRB_PERS_MAIL) + "\n" + + if self.mod_pers_cnt: + self.msgtext += str(self.MOD_PERS_MAIL) + "\n" + if self.msgtext: + sendMail(self.msgtext, + settings.FROM_ADDRS, + settings.DCACHE_ADMIN_MAIL, + settings.LDAP_SUBJECT) + + def sendUserMail(self, m, proj_name, sua_accepted): + """Mail to be sent to User""" + + msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" + msgTxt += ("You are receiving this mail as you are added as a member to Swestore project -- " + proj_name + + " in SUPR.\n\n") + + if not sua_accepted: + msgTxt += "We have noticed that you have not signed the NAISS User Agreement.\n" + msgTxt += "Before access to Swestore is granted, the NAISS User Agreement must be read and accepted.\n" + msgTxt += ("Login to SUPR (https://supr.naiss.se/login), go to Personal Information and sign the " + "NAISS User Agreement using Federated Identity. \n\n") + + msgTxt += "For information on how to set your password, please see the following documentation :-\n" + msgTxt += "https://docs.swestore.se/access/\n\n" + + msgTxt += "Please refer to the documentation for more information on Swestore:-\n" + msgTxt += "https://docs.swestore.se/\n\n" + + msgTxt += "In case of any issues or clarifications, please use the support form on\n" + msgTxt += "https://supr.naiss.se/support/ or email support@swestore.se.\n\n" + msgTxt += "Regards,\nSwestore Support Team\n" + + #self.logger.info(msgTxt) + + sendMail(msgTxt, 'support@swestore.se', m.email, "Information to access Swestore") + + def getUID(self, m): + """Generate userId or uid for new Person from first name and last + name using various combinations""" + + guesses = [] + firstname = (m.first_name).replace(" ", "").lower() + lastname = (m.last_name).replace(" ", "").lower() + + if (len(firstname) < 3 and len(lastname) < 3): + uid = "s_" + asciify(firstname + lastname) + guesses.append(str(uid)) + else: + for (flen, llen, swap) in ((3, 2, False), + (2, 3, False), + (3, 2, True), + (2, 3, True), + (1, 4, False), + (4, 1, False), + (1, 4, True), + (4, 1, True), + (0, 5, False), + (5, 0, False)): + if (len(firstname) < flen or len(lastname) < llen): + continue + if swap: + uid = "s_" + asciify(lastname[:llen] + firstname[:flen]) + guesses.append(str(uid)) + else: + uid = "s_" + asciify(firstname[:flen] + lastname[:llen]) + guesses.append(str(uid)) + + # Check if the uid already exists in LDAP + self.logger.debug("Person with SUPR ID :: %s login guesses -- %s ", m.id, str(guesses)) + + for login in guesses: + + try: + filter = "(uid=" + login + ")" + self.logger.info("getUID filter - %s", str(filter)) + retrievedAttrs = ['uid'] + + result_data = self.connection.search(search_base=settings.peopleDN, search_filter=filter, + search_scope=self.searchScope, attributes=retrievedAttrs) + + self.logger.info("getUID result_data - %s", str(result_data)) + if (result_data and not result_data[0]): + return login + + except Exception as e: + self.logger.error("getUID LDAP Search Error - %s", e) + + # No guess possible + return str(guesses[0] + m.id) + + def searchPerson(self, uidNumber): + """Search Person based on uidNumber """ + try: + # Check if the member already exists in LDAP + filter = "(uidNumber=" + uidNumber + ")" + result_data = self.connection.search(search_base=settings.peopleDN, search_filter=filter, + search_scope=self.searchScope, attributes= ldap3.ALL_ATTRIBUTES) + + self.logger.info("searchPerson result_data full -- " + str(result_data) + " --- " + str(result_data[0]) + " --- " + str(result_data[2])) + + if (result_data[0] and result_data[2] and result_data[2][0] and result_data[2][0]['attributes']): + self.logger.info("searchPerson result_data[2][0] -- " + str(result_data[2][0]) + " --- " + str(result_data[2][0]['attributes'])) + return result_data[2][0]['attributes'] + else: + return [] + except Exception as le: + self.logger.error("LDAP Error in searchPerson Module for %s :: %s", str(uidNumber), le) + self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchPerson \n" + self.err_pers_cnt += 1 + return [] + + def searchMemberUid(self, uidNumber): + """Search MemberUid based on uidNumber in Groups for SUP not signed persons""" + + try: + # Check if the member already exists in LDAP + filter = "(memberUid=" + uidNumber + ")" + retrievedAttrs = ['gidNumber', 'resourceID', 'cn'] + + result_data = self.connection.search(search_base=settings.groupsDN, search_filter=filter, + search_scope=self.searchScope, attributes=retrievedAttrs) + + self.logger.info("searchMemberUid result_data full -- " + str(result_data) + " --- " + str(result_data[0]) + " --- " + str(result_data[2])) + + if (result_data[0] and result_data[2] and result_data[2][0] and result_data[2][0]['attributes']): + self.logger.info("searchMemberUid result_data[2][0] -- " + str(result_data[2][0]) + " --- " + str(result_data[2][0]['attributes'])) + return result_data[2][0]['attributes'] + else: + return [] + except Exception as le: + self.logger.error("LDAP Error in searchMemberUid Module for %s :: %s", str(uidNumber), le) + self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchMemberUid \n" + self.err_pers_cnt += 1 + return [] + + def createPersonAttrs(self, m, uidNumber): + """Return a Person Attributes dictionary""" + + attrsPerson = {} + attrsPerson['objectclass'] = ['Swestore', 'inetorgperson', 'posixaccount'] + attrsPerson['description'] = str(m.id) + attrsPerson['uidNumber'] = uidNumber + attrsPerson['gidNumber'] = uidNumber + attrsPerson['gn'] = str(m.first_name) + attrsPerson['sn'] = str(m.last_name) + attrsPerson['cn'] = str(m.first_name + " " + m.last_name) + attrsPerson['mail'] = str(m.email) + if m.subject: + attrsPerson['subject'] = str(m.subject) + else: + attrsPerson['subject'] = "/" + + attrsPerson['lastModifiedTime'] = str(m.modified) + attrsPerson['homeDirectory'] = "/" + + # Will be updated to the correct yubikey value once yubikey is + # integrated into SUPR (Not needed as of now) + attrsPerson['yubikey'] = "yubikey" + + # Need to check if centre_person_id comes from SUPR. If it clashes + # with other UIDs then an alert mail needs to be sent to Admin about + # the same. + if m.centre_person_id: + attrsPerson['uid'] = str(m.centre_person_id) + else: + attrsPerson['uid'] = str(self.getUID(m)) + + # attrsPerson = {key:[v.encode("utf-8") if type(v) == str else v for v in values] + # for key, values in attrsPerson.items()} + + return attrsPerson + + def personChanged(self, result_data, attrsPerson): + """Check if Person Data has changed""" + self.logger.info("personChanged result_data -- " + str(result_data)) + if ((result_data.get('description', False) + and result_data.get('description', '')[0] != attrsPerson['description'])): + return True + if ((result_data.get('givenName', False) + and result_data.get('givenName', '')[0] != attrsPerson['gn'])): + return True + if ((result_data.get('sn', False) + and result_data.get('sn', '')[0] != attrsPerson['sn'])): + return True + if ((result_data.get('cn', False) + and result_data.get('cn', '')[0] != attrsPerson['cn'])): + return True + if ((result_data.get('mail', False) + and result_data.get('mail', '')[0] != attrsPerson['mail'])): + return True + if ((result_data.get('subject') is None and attrsPerson['subject']) + or (result_data.get('subject') and result_data.get('subject', '')[0] + != attrsPerson['subject'])): + return True + if ((result_data.get('uid', False) + and result_data.get('uid', '')[0] != attrsPerson['uid'])): + return True + + return False + + def addPerson(self, m, uidNumber, resourceIDList): + """Add person (to ldap?)""" + + try: + attrsPerson = self.createPersonAttrs(m, uidNumber) + self.logger.info("chking addPerson attrsPerson -- " + str(attrsPerson)) + # personDN = "uidNumber=" + uidNumber + "," + peopleDN + personDN = "uid=" + str(attrsPerson['uid']) + "," + settings.peopleDN + self.logger.info("chking addPerson personDN -- " + str(personDN)) + + # person_dn = dn.str2dn("uid=" + str(attrs_person['uid']) + "," + settings.peopleDN) + result = self.connection.add(personDN, attributes=attrsPerson) + self.logger.info("addPerson result --" + str(result)) + + self.logger.info("\n Person with SUPR ID SUP is signed :: %s and added to LDAP -- %s", m.id, str(uidNumber)) + + if settings.dcache_resource_id in resourceIDList: + self.ADD_PERS_MAIL += ("SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + + "\t Person Name :: " + attrsPerson['cn'] + "\n") + self.add_pers_cnt += 1 + + if m.centre_person_id: + self.logger.info("Person with SUPR ID :: %s centre_person_id already exists -- %s", m.id, + m.centre_person_id) + else: + # Updating the centre_person_id to SUPR + d = {'centre_person_id': attrsPerson['uid']} + self.logger.info("centre_person_id d -- " + str(d)) + + + try: + person = self.supr_connection.post("person/%s/update/" % m.id, data=d) + m.centre_person_id = attrsPerson['uid'] + self.logger.info("Centre_Person_id for Person with SUPR ID :: %s updated to SUPR -- %s", str(m.id), + attrsPerson['uid']) + except supr.SUPRHTTPError as e: + # We want to show the text received if we get an HTTP Error + self.logger.error("HTTP error in updating centre_person_id to SUPR - %s :: %s" % str(e.status_code) %str(e)) + self.ERR_MJR_MAIL += "Error occurred in updating centre_person_id (uid) to SUPR - " + str(e) + "\n" + self.ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson[ + 'uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\t Module :: addPerson \n" + self.err_mjr_cnt += 1 + except ConnectionError as ce: + self.ERR_MJR_MAIL += ("Error occurred in updating centre_person_id (uid) to SUPR due to " + "ConnectionError- ") + str(ce) + "\n" + self.logger.error("Connection to SUPR failed - %s", str(ce)) + + for resourceid in resourceIDList: + d = {'username': m.centre_person_id, + 'person_id': m.id, + 'resource_id': resourceid, + 'status': 'enabled', + 'button_text': 'Change password'} + self.logger.info("account create d -- " + str(d)) + try: + account = self.supr_connection.post("account/create/", data=d) + self.logger.info("Account for Person with SUPR ID :: %s for resource -- %s created", m.id, + resourceid) + except supr.SUPRHTTPError as e: + if int(e.status_code) == 409: + self.logger.info("Account already exists in SUPR - " + str(m.centre_person_id)) + else: + # We want to show the text received if we get an HTTP Error + self.logger.error("HTTP error in creating account to SUPR - %s :: %s", str(e.status_code), str(e)) + self.ERR_MJR_MAIL += "Error occurred in creating account to SUPR - " + str(e) + "\n" + self.ERR_MJR_MAIL += ("SUPR ID :: " + str(m.id) + "\t username(uid) :: " + + str(attrsPerson['uid']) + "\t Module :: addPerson \n") + self.err_mjr_cnt += 1 + except ConnectionError as ce: + self.ERR_MJR_MAIL += ("Error occurred in creating account to SUPR due to ConnectionError- " + + str(ce) + "\n") + self.logger.error("Connection to SUPR failed - %s", str(ce)) + + # Adding Project for every Person + self.addPersonAsProject(attrsPerson) + + # Adding Person to Kerberos + self.addPersontoKerberos(m, attrsPerson) + + except Exception as le: + self.logger.error("LDAP Error in addPerson Module for %s :: %s", str(uidNumber), le) + self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: addPerson \n" + self.err_pers_cnt += 1 + + def addPersontoKerberos(self, m, attrsPerson): + """Add a new person to Kerberos, if able + + Uses external `kadmin` program. + + :param m: Person to add + :type m: Ldap person object + :param attrsPerson: Person attributes to add to kerberos + :type attrsPerson: Dictionary + :returns: None + """ + # Kadmin init or "login" + try: + kadm = kadmin.init_with_keytab(settings.adminprincipal, settings.keytab) + + user = attrsPerson['uid'] + princ = kadm.getprinc(user) + + if (princ is None): + kadm.addprinc(user, None) + + self.logger.info("Person with SUPR ID :: %s added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) + self.KRB_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" + self.krb_pers_cnt += 1 + else: + self.logger.info("Person with SUPR ID :: %s already added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) + #sys.exit(1) + + except Exception as e: + self.logger.error("Error in addPersontoKerberos Module for %s :: %s", str(attrsPerson['uid']), e) + self.ERR_PERS_MAIL += "uidNumber :: " + str(attrsPerson['uid']) + "\t Module :: addPersontoKerberos \n" + self.err_pers_cnt += 1 + sys.exit(1) + + def updateDeletePersons(self): + """Update Person Data or delete merged Persons""" + + self.logger.info("updateDeletePersons -- " + str(self.persons_modified)) + gidNumbers = [] + uidNumber = None + try: + for m in self.persons_modified: + + uidNumber = str(settings.uidNumberStart + m.id) + result_data = self.searchPerson(uidNumber) + self.logger.info("updateDeletePersons searchPerson result_data -- " + str(result_data)) + + if ((not result_data) and (not m.merged_ids)): + + # check for uidnumber in memberUids in groups + gidNumbers = self.searchMemberUid(uidNumber) + self.logger.info("gidNumbers -- " + str(gidNumbers)) + + if gidNumbers: + if (m.user_agreement_version and m.user_agreement_accepted): + + for gidNumber in [gidNumbers]: + self.logger.info("gidNumber -- " + str(gidNumber)) + gid = str(gidNumber['gidNumber']) + resourceIDList = gidNumber['resourceID'] + self.logger.info("resourceIDList : %s ", str(resourceIDList)) + + proj_name = gidNumber['cn'][0] + + self.addPerson(m, uidNumber, resourceIDList) + + groupDN = "gidNumber=" + gid + "," + settings.groupsDN + + oldMemberUid = {'memberUid': [(ldap3.MODIFY_DELETE, str(uidNumber))]} + newMemberUid = {'memberUid': [(ldap3.MODIFY_ADD, str(m.centre_person_id))]} + + result = self.connection.modify(groupDN, changes=oldMemberUid) + result1 = self.connection.modify(groupDN, changes=newMemberUid) + + self.logger.info("Person with SUPR ID :: %s SUP is signed and will be updated to LDAP.", str(m.id)) + + else: + self.logger.info("Person with SUPR ID :: %s not needed in LDAP. Just ignore it.", str(m.id)) + else: + + for merge_id in m.merged_ids: + mergeUidNumber = str(settings.uidNumberStart + merge_id) + result_data_mrg = self.searchPerson(mergeUidNumber) + self.logger.info("updateDeletePerson result_data_mrg --- " + str(result_data_mrg)) + + if (not result_data_mrg): + self.logger.info("Person with SUPR ID :: %s has already been deleted from LDAP since its " + + "merged with SUPR ID :: %s ", str(merge_id), str(m.id)) + else: + personDN = "uid=" + result_data_mrg['uid'][0] + "," + settings.peopleDN + groupDN = "gidNumber=" + mergeUidNumber + "," + settings.groupsDN + + self.logger.info("updateDeletePerson personDN --- " + str(personDN)) + self.logger.info("updateDeletePerson groupDN --- " + str(groupDN)) + + result = self.connection.delete(personDN) + self.logger.info("updateDeletePerson result personDN delete 1 --- " + str(result)) + + + self.logger.info("Person with SUPR ID :: %s deleted from LDAP since its merged with " + + "SUPR ID :: %s ", str(merge_id), str(m.id)) + + self.MOD_PERS_MAIL += ("SUPR Person ID :: " + str(merge_id) + " merged with SUPR Person ID " + + " :: " + str(m.id) + "\n") + self.mod_pers_cnt += 1 + + # Deleting the corresponding Project as well + result = self.connection.delete(groupDN) + self.logger.info("updateDeletePerson result groupDN delete 1 --- " + str(result)) + + self.logger.info("Project with ID :: %s deleted from LDAP since its person is also deleted " + + ":: %s ", str(merge_id), str(merge_id)) + + attrsPerson = self.createPersonAttrs(m, uidNumber) + + self.logger.info("updateDeletePerson attrsPerson -- " + str(attrsPerson)) + + personDN = "uid=" + str(attrsPerson['uid']) + "," + settings.peopleDN + + self.logger.info("updateDeletePerson personDN -- " + str(personDN)) + + if (result_data and self.personChanged(result_data, attrsPerson)): + + result = self.connection.delete(personDN) + self.logger.info("updateDeletePerson personChanged result delete 1 --- " + str(result)) + + result1 = self.connection.add(personDN, attributes=attrsPerson) + self.logger.info("Person with SUPR ID :: %s modified to LDAP -- %s", str(m.id), str(attrsPerson['uidNumber'])) + + self.MOD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + str(attrsPerson['uid']) + "\t Person Name :: " + str(attrsPerson['cn']) + "\n" + self.mod_pers_cnt += 1 + + else: + self.logger.info("Person with SUPR ID :: %s - No changes since last time \n", str(m.id)) + + except Exception as le: + self.logger.error("LDAP Error in updateDeletePersons Module for %s :: %s", str(uidNumber), str(le)) + self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module Name :: updateDeletePerson \n" + self.err_pers_cnt += 1 + + def searchProject(self, gidNumber, pid, cn): + """Search Project based on gidNumber """ + try: + # Check if the project already exists in LDAP + filter = "(|(&(cn=" + cn + ")(description=" + pid + "))(gidNumber=" + gidNumber + "))" + + self.logger.info("searchProject filter -- " + str(filter)) + + result_data = self.connection.search(search_base=settings.groupsDN, search_filter=filter, + search_scope=self.searchScope, attributes=ldap3.ALL_ATTRIBUTES) + # result_data = self.connection.entries + + self.logger.info("searchProject result full -- " + str(result_data[2])) + + for res in result_data[2]: + self.logger.info("result -- " + str(res)) + if str(cn) == str(res['attributes']['cn'][0]): + return res + + except Exception as le: + self.logger.error("LDAP Error in searchProject Module for %s :: %s", str(gidNumber), le) + self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: searchProject \n" + self.err_proj_cnt += 1 + return [] + + def addUpdateProjects(self): + """Add or Update Projects""" + + for p in self.all_projects: + + attrsGroup = {} + memberUIDList = [] + resourceIDList = [] + removeResourceIDList = [] + suaNotSigned = [] + sua_accepted = None + + for rp in p.resourceprojects: + if str(rp.resource.id) == settings.dcache_resource_id: + resourceIDList.append(str(rp.resource.id)) + else: + removeResourceIDList.append(str(rp.resource.id)) + + for m in p.members: + # Generate uidNumber for new Person + # ( Example 30023 - 30000 is the start range and 23 is the person id from SUPR ) + uidNumber = str(settings.uidNumberStart + m.id) + result_data = self.searchPerson(uidNumber) + self.logger.info("addUpdateProjects searchPerson result_data -- " + str(result_data)) + result_data_mid = self.searchMemberUid(uidNumber) + self.logger.info("addUpdateProjects searchPerson result_data_mid -- " + str(result_data_mid)) + + if ((not result_data) and (not result_data_mid)): + + if (m.user_agreement_version and m.user_agreement_accepted): + self.logger.info("addUpdateProjects m.id -- " + str(m.id) + " merged_ids -- " + str(m.merged_ids)) + + if m.merged_ids: + self.persons_modified = [m] + self.updateDeletePersons() + + self.addPerson(m, uidNumber, resourceIDList) + sua_accepted = True + + # To send user mail regarding user certificate registration in SUPR for dcache projects + if settings.dcache_resource_id in resourceIDList: + self.sendUserMail(m, p.directory_name, sua_accepted) + self.logger.info("Person with SUPR ID :: %s SUP is signed and added to LDAP.",str(m.id)) + else: + sua_accepted = False + suaNotSigned.append(str(m.id)) + # To send user mail regarding SUA in SUPR for all projects + self.sendUserMail(m, p.directory_name, sua_accepted) + self.logger.info("Person with SUPR ID :: %s SUP is not signed and will not be added to LDAP.",str(m.id)) + + # Add UidNumber as MemberUid in Group fo SUP not signed + m.centre_person_id = uidNumber + + elif (result_data and result_data['uid'] and result_data['uid'][0]): + self.logger.info("result_data['uid'][0] -- " + str(result_data['uid'][0])) + m.centre_person_id = result_data['uid'][0] + + self.logger.info("Person with SUPR ID :: %s - Already added to LDAP", m.id) + + elif result_data_mid: + m.centre_person_id = uidNumber + + if not m.centre_person_id: + m.centre_person_id = uidNumber + + memberUIDList.append(str(m.centre_person_id)) + + if (suaNotSigned and (settings.dcache_resource_id in resourceIDList)): + self.SUA_PERS_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + str(p.directory_name) + + "\t Persons SUA Not signed :: " + ", ".join(suaNotSigned) + "\n") + self.sua_pers_cnt += 1 + + # Generate gidNumber for new Project + # ( Example 6012 - 6000 is the start range and 12 is the project id from SUPR ) + gidNumber = str(settings.gidNumberStart + p.id) + + groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN + attrsGroup['objectclass'] = ['Swestore', 'posixgroup'] + attrsGroup['description'] = [str(p.id)] + attrsGroup['piMemberID'] = str(settings.uidNumberStart + p.pi.id) + attrsGroup['memberUID'] = [str(m) for m in memberUIDList] + attrsGroup['resourceID'] = [str(r) for r in resourceIDList] + attrsGroup['projectEndDate'] = str(p.end_date) + attrsGroup['lastModifiedTime'] = str(p.modified) + + if p.directory_name: + attrsGroup['cn'] = str(p.directory_name) + + try: + result_data = self.searchProject(gidNumber, str(p.id), str(attrsGroup['cn'])) + self.logger.info("attrsGroup 1-- %s ", str(attrsGroup)) + self.logger.info("result_data 1-- %s ", str(result_data)) + + # Load data into LDAP + if (not result_data): + # ldif = modlist.addModlist(attrsGroup) + + if settings.dcache_resource_id in resourceIDList: + result = self.connection.add(groupDN, attributes=attrsGroup) + + self.logger.info("Project with SUPR ID :: %s added to LDAP -- %s \n", p.id, gidNumber) + + self.ADD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + p.directory_name + + "\t Persons Added :: " + ", ".join(memberUIDList) + "\n") + self.add_proj_cnt += 1 + + else: + if (result_data and result_data['attributes'] and result_data['attributes']['lastModifiedTime'] and + (result_data['attributes']['lastModifiedTime'][0] != attrsGroup['lastModifiedTime'])): + + addUsers = list(set(memberUIDList).difference(set(result_data['attributes']['memberUid']))) + removeUsers = list(set(result_data['attributes']['memberUid']).difference(set(memberUIDList))) + suprIds = result_data['attributes']['description'] + + self.logger.info("lastModifiedTime 1 --- " + str(result_data['attributes']['lastModifiedTime'][0]) + " ---- " + str(attrsGroup['lastModifiedTime'])) + self.logger.info("suprIds 1 --- " + str(suprIds)) + + if p.continuation_name: + gidNumber = str(result_data['attributes']['gidNumber']) + self.logger.info("gidNumber continuation --- " + str(gidNumber)) + groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN + if str(p.id) not in suprIds: + attrsGroup['description'] = suprIds + [str(p.id)] + else: + attrsGroup['description'] = suprIds + + self.logger.info("attrsGroup 2 -- %s ", str(attrsGroup)) + + for id in suprIds: + grpId = settings.gidNumberStart + int(id) + grpDn = "gidNumber=" + str(grpId) + "," + settings.groupsDN + result = self.connection.delete(grpDn) + self.logger.info("addUpdateProjects delete grpDn delete 1 -- %s ", str(result)) + #result = self.connection.modify(settings.groupsDN, {'gidNumber': [(ldap3.MODIFY_DELETE, str(grpId))]}) + #self.logger.info("addUpdateProjects result grpDN delete 2 --- " + str(result)) + + # ldif = modlist.addModlist(attrsGroup) + if settings.dcache_resource_id in resourceIDList: + result = self.connection.add(groupDN, attributes=attrsGroup) + self.logger.info("addUpdateProjects result grpDN add --- " + str(result)) + + self.logger.info("Project with SUPR ID :: %s modified to LDAP -- %s ", p.id, gidNumber) + + if p.continuation_name: + self.MOD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + + "\t Continuation project for SUPR ID(s) :: " + ", ".join(suprIds) + + "\n") + self.mod_proj_cnt += 1 + + newCn = False + if attrsGroup['cn'] != result_data['attributes']['cn'][0]: + self.MOD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t New Project Name :: " + + attrsGroup['cn'] + "\t Old Project Name :: " + + result_data['attributes']['cn'][0] + "\n") + self.mod_proj_cnt += 1 + newCn = True + + if removeUsers and (settings.dcache_resource_id in resourceIDList): + self.MOD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + + "\t Persons Removed :: " + ", ".join(removeUsers) + "\n") + self.mod_proj_cnt += 1 + + if addUsers and (settings.dcache_resource_id in resourceIDList): + self.MOD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + + "\t Persons Added :: " + ", ".join(addUsers) + "\n") + self.mod_proj_cnt += 1 + + if not (removeUsers or addUsers or p.continuation_name or newCn): + self.MOD_PROJ_MAIL += ("SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + + "\n") + self.mod_proj_cnt += 1 + + else: + self.logger.info("Project with SUPR ID :: %s - No changes since last time \n", p.id) + + except Exception as le: + self.logger.error("LDAP Error in addUpdateProjects Module for %s :: %s", str(gidNumber), le) + self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addUpdateProjects \n" + self.err_proj_cnt += 1 + + def addPersonAsProject(self, attrsPerson): + """For every Person add a corresponding Project with uidNumber as + gidNumber""" + + attrsGroup = {} + attrsGroup['cn'] = attrsPerson['uid'] + attrsGroup['description'] = attrsPerson['description'] + attrsGroup['piMemberID'] = attrsPerson['uidNumber'] + attrsGroup['memberUID'] = [attrsPerson['uid']] + attrsGroup['objectclass'] = ['Swestore', 'posixgroup'] + + gidNumber = attrsPerson['uidNumber'] + attrsGroup['gidNumber'] = gidNumber + groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN + + try: + result_data = self.searchProject(gidNumber, attrsGroup['description'], attrsGroup['cn']) + + # Load data into LDAP + if (not result_data): + # ldif = modlist.addModlist(attrsGroup) + result = self.connection.add(groupDN, attributes=attrsGroup) + self.logger.info("Person-Project with ID :: %s added to LDAP -- %s", attrsPerson['description'], + attrsGroup['gidNumber']) + + else: + self.logger.info("Person-Project with ID :: %s - already added", attrsPerson['description']) + + except Exception as le: + self.logger.error("LDAP Error in addPersonAsProject Module for %s :: %s", str(gidNumber), le) + self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addPersonAsProject \n" + self.err_proj_cnt += 1 diff --git a/supr_ldap_ipa_krb.py b/supr_ldap_ipa_krb.py deleted file mode 100644 index 6a773c251a2c85ed25d0aab26b810c556bc6f97b..0000000000000000000000000000000000000000 --- a/supr_ldap_ipa_krb.py +++ /dev/null @@ -1,787 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- - -import kadmin -import ldap -import ldap.modlist as modlist -import logging -import sys -import supr -import settings -import requests - -# (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) -#import supr_irods_pirc - - -from python_freeipa import ClientMeta -from python_freeipa import exceptions - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import (asciify, - sendMail, - setup_log, - temp_password) - -class SUPR_LDAP: - - def __init__(self, all_projects, persons_modified, supr_connection): - - if all_projects or persons_modified: - - # Get Logging File Handler - self.logger = setup_log(self.__class__.__name__, settings.LOG_FILE) - self.l = None - - self.ipa = None - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - #self.irods_projects = [] - #self.irods_persons_modified = [] - - # Get supr_connection - self.supr_connection = supr_connection - - # LDAP search scope and other variables - self.searchScope = ldap.SCOPE_SUBTREE - self.retrievedAttrs = None - - # Variables needed for calculating number of projects and persons created - # that are used to sendMail to Admins - self.add_proj_cnt = 0 - self.mod_proj_cnt = 0 - self.err_proj_cnt = 0 - - self.add_pers_cnt = 0 - self.mod_pers_cnt = 0 - self.err_pers_cnt = 0 - self.sua_pers_cnt = 0 - - self.ipa_pers_cnt = 0 - self.krb_pers_cnt = 0 - - self.err_mjr_cnt = 0 - self.msgtext = "" - - # Variables needed for Message Text of projects and persons created - # that are used to sendMail to Admins - self.ADD_PERS_MAIL = "The Following Persons have been Added on " + settings.today + "\n" - self.ADD_PERS_MAIL += "---------------------------------------------------- \n" - - self.MOD_PERS_MAIL = "The Following Persons have been Modified on " + settings.today + "\n" - self.MOD_PERS_MAIL += "---------------------------------------------------- \n" - - self.SUA_PERS_MAIL = "The Following Persons have not signed SUA and hence not Added on " + settings.today + "\n" - self.SUA_PERS_MAIL += "---------------------------------------------------------------------------- \n" - - self.IPA_PERS_MAIL = "The Following Persons have been Added to IPA " + settings.today + "\n" - self.IPA_PERS_MAIL += "------------------------------------------------------- \n" - - self.KRB_PERS_MAIL = "The Following Persons have been Added to Kerberos " + settings.today + "\n" - self.KRB_PERS_MAIL += "------------------------------------------------------- \n" - - self.ADD_PROJ_MAIL = "The Following Projects have been Added on " + settings.today + "\n" - self.ADD_PROJ_MAIL += "----------------------------------------------------- \n" - - self.MOD_PROJ_MAIL = "The Following Projects have been Modified on " + settings.today + "\n" - self.MOD_PROJ_MAIL += "----------------------------------------------------- \n" - - self.ERR_PROJ_MAIL = "Error in creating the following Projects on " + settings.today + "\n" - self.ERR_PROJ_MAIL += "------------------------------------------------------- \n" - - self.ERR_PERS_MAIL = "Error in creating the following Persons on " + settings.today + "\n" - self.ERR_PERS_MAIL += "------------------------------------------------------ \n" - - self.ERR_MJR_MAIL = "Major Error Occured on " + settings.today + "\n" - self.ERR_MJR_MAIL += "---------------------------------- \n" - - # Connect to LDAP using python-LDAP - try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) - - self.l = ldap.initialize(settings.LDAP_HOST) - self.l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) - except ldap.LDAPError as le: - self.logger.error("LDAP Connection Error - %s", le) - if self.l: - self.l.unbind() - - self.ERR_MJR_MAIL += "Error occured in LDAP Connection - " + str(le) + "\n" - self.err_mjr_cnt += 1 - sys.exit(1) - - # Connect to FreeIPA - try: - - self.ipa = ClientMeta(settings.IPA_HOST) - self.ipa.login(settings.IPA_ADMIN_USER, settings.IPA_ADMIN_PWD) - ClientMeta.log = setup_log("IPA_ADD_USER", settings.LOG_FILE) - self.logger.info("Connected to IPA \n") - - except exceptions.FreeIPAError as e: - self.logger.error("FreeIPA Connection Error - %s", e) - self.ERR_MJR_MAIL += "Error occured in FreeIPA Connection - " + str(e) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, settings.LDAP_SUBJECT) - sys.exit(1) - - - # Call to addUpdateProjects() Function - if all_projects: - # Assigning the all_projects from supr_swestore_main - self.all_projects = all_projects - self.addUpdateProjects() - - # Call to updateDeleteProjects() Function - if persons_modified: - # Assigning the persons_modified from supr_swestore_main - self.persons_modified = persons_modified - self.updateDeletePersons() - - # Call to sendMail() Function - if self.err_mjr_cnt: - self.msgtext += str(self.ERR_MJR_MAIL) + "\n" - if self.err_proj_cnt: - self.msgtext += str(self.ERR_PROJ_MAIL) + "\n" - if self.err_pers_cnt: - self.msgtext += str(self.ERR_PERS_MAIL) + "\n" - if self.add_proj_cnt: - self.msgtext += str(self.ADD_PROJ_MAIL) + "\n" - if self.mod_proj_cnt: - self.msgtext += str(self.MOD_PROJ_MAIL) + "\n" - if self.add_pers_cnt: - self.msgtext += str(self.ADD_PERS_MAIL) + "\n" - if self.sua_pers_cnt: - self.msgtext += str(self.SUA_PERS_MAIL) + "\n" - - if self.ipa_pers_cnt: - self.msgtext += str(self.IPA_PERS_MAIL) + "\n" - - if self.krb_pers_cnt: - self.msgtext += str(self.KRB_PERS_MAIL) + "\n" - - if self.mod_pers_cnt: - self.msgtext += str(self.MOD_PERS_MAIL) + "\n" - if self.msgtext: - sendMail(self.msgtext, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, settings.LDAP_SUBJECT) - - # (Krishnaveni: 2022-03-03 commenting out as irods is no longer in production) - # Call to function to create iRODS Users and Projects - - #if self.irods_projects: - # self.irods_projects.sort(key = lambda p: p.id) - # supr_irods_pirc.SUPR_IRODS(self.irods_projects, []) - - - # Mail to be to be sent to User for Password Setting (Not needed anymore) - def sendIPAMail(self,m): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - #msgTxt += "You are receiving this mail as you are added as a member to Swestore project -- " + proj_name + " in SUPR. \n\n" - msgTxt += "To set password to access Swestore/dCache, login to portal - http://auth1.swestore.se/ipa/supr/supr-auth1.cgi \n" - msgTxt += "First time, you will be redirected to SUPR for confirmation and then you can set a password which you can use to login to Swestore/iRods \n" - msgTxt += "To know more on how to set password in IPA please refer to the following links :- \n" - - msgTxt += "http://snicdocs.nsc.liu.se/wiki/Swestore#Using_Swestore \n\n" - - msgTxt += "In case of any issues or clarifications, please mail support@swestore.se. \n\n" - msgTxt += "Regards,\n" + "Swestore Support Team" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Information to access Swestore") - - - # Mail to be to be sent to User - def sendUserMail(self,m, proj_name, sua_accepted): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are added as a member to Swestore project -- " + proj_name + " in SUPR. \n \n" - - if not sua_accepted: - msgTxt += "We have noticed that you have not signed the SNIC User Agreement.\n" - msgTxt += "Before access to Swestore is granted, the SNIC User Agreement must be read and accepted.\n" - msgTxt += "Login to SUPR (https://supr.snic.se/login), go to Personal Information and sign the SNIC User Agreement using Federated Identity. \n\n" - else: - if not m.subject: - msgTxt += "Please register your eScience client certificate in SUPR if available. \n" - msgTxt += "Login to SUPR (https://supr.snic.se/login), go to Personal Information, click Register Client Certificate and follow the instructions.\n" - msgTxt += "Or set password by logging into SUPR and Navigating to Accounts page. \n" - msgTxt += "Please wait for up to 10 minutes for this information to be distributed to Swestore. \n\n" - msgTxt += "To know more on how to access Swestore, please refer to the following links :- \n" - msgTxt += "http://snicdocs.nsc.liu.se/wiki/Swestore \n" - msgTxt += "http://snicdocs.nsc.liu.se/wiki/Swestore#Using_Swestore \n\n" - - msgTxt += "In case of any issues or clarifications, please mail support@swestore.se. \n\n" - msgTxt += "Regards,\n" + "Swestore Support Team" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Information to access Swestore") - - - # Generate userId or uid for new Person from first name and last name - # using various combinations - def getUID(self,m): - guesses = [] - firstname = ((m.first_name).replace(" ", "")).lower() - lastname = (m.last_name).replace(" ", "").lower() - - if (len(firstname) < 3 and len(lastname) < 3): - uid = "s_" + asciify(u'' + firstname + lastname) - guesses.append(str(uid)) - else: - for (flen, llen, swap) in ((3,2, False), - (2,3, False), - (3,2, True), - (2,3, True), - (1,4, False), - (4,1, False), - (1,4, True), - (4,1, True), - (0,5, False), - (5,0, False), - ): - if (len(firstname) < flen or len(lastname) < llen): - continue - if swap: - uid = "s_" + asciify(u'' + lastname[:llen] + firstname[:flen]) - guesses.append(str(uid)) - else: - uid = "s_" + asciify(u'' + firstname[:flen] + lastname[:llen]) - guesses.append(str(uid)) - - # Check if the uid already exists in LDAP - self.logger.debug("Person with SUPR ID :: %s login guesses -- %s ", m.id, guesses) - - for login in guesses: - - filter = "uid=" + login - ldap_result_id = self.l.search(settings.peopleDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id, 0) - - if (not result_data): - return login - - # No guess possible - return str(guesses[0]+m.id) - - # Function to search Person based on uidNumber - def searchPerson(self,uidNumber): - - try: - # Check if the member already exists in LDAP - filter = "(uidNumber=" + uidNumber+")" - - ldap_result_id = self.l.search(settings.peopleDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id, 0) - self.logger.info("searchPerson -- " + str(result_type) + "--- " + str(result_data)) - return result_data - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchPerson Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchPerson \n" - self.err_pers_cnt += 1 - return [] - - # Function to search MemberUid based on uidNumber in Groups for SUP not signed persons - def searchMemberUid(self,uidNumber): - - try: - # Check if the member already exists in LDAP - filter = "(memberUid=" + uidNumber+")" - retrievedAttrs = ['gidNumber', 'resourceID', 'cn'] - - ldap_result_id = self.l.search(settings.groupsDN, self.searchScope, filter, retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id) - self.logger.info("chk 111 -- " + str(result_type) + " --- " + str(result_data)); - return result_data - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchMemberUid Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchMemberUid \n" - self.err_pers_cnt += 1 - return [] - - - # Function to create Person Attributes - def createPersonAttrs(self,m,uidNumber): - - attrsPerson = {} - attrsPerson['objectclass'] = ['Swestore','inetorgperson','posixaccount'] - attrsPerson['description'] = str(m.id) - attrsPerson['uidNumber'] = uidNumber - attrsPerson['gidNumber'] = uidNumber - attrsPerson['gn'] = str((m.first_name).encode('utf-8')) - attrsPerson['sn'] = str((m.last_name).encode('utf-8')) - attrsPerson['cn'] = str((m.first_name + " " + m.last_name).encode('utf-8')) - attrsPerson['mail'] = str((m.email).encode('utf-8')) - attrsPerson['subject'] = str((m.subject).encode('utf-8')) - attrsPerson['lastModifiedTime'] = str(m.modified) - attrsPerson['homeDirectory'] = "/" - - # Will be updated to the correct yubikey value once yubikey is integrated into SUPR (Not needed as of now) - attrsPerson['yubikey'] = "yubikey" - - # Need to check if centre_person_id comes from SUPR. If it clashes with other UIDs - # then an alert mail needs to be sent to Admin about the same. - if m.centre_person_id: - attrsPerson['uid'] = str(m.centre_person_id) - else: - attrsPerson['uid'] = self.getUID(m) - - return attrsPerson - - # Function to check Person Data has changed - def personChanged(self,result_data, attrsPerson): - - if ((result_data[0][1].get('description',False) and result_data[0][1].get('description', '')[0] != attrsPerson['description'])): - return True - if ((result_data[0][1].get('givenName',False) and result_data[0][1].get('givenName','')[0] != attrsPerson['gn'])): - return True - if ((result_data[0][1].get('sn',False) and result_data[0][1].get('sn', '')[0] != attrsPerson['sn'])): - return True - if ((result_data[0][1].get('cn',False) and result_data[0][1].get('cn', '')[0] != attrsPerson['cn'])): - return True - if ((result_data[0][1].get('mail',False) and result_data[0][1].get('mail', '')[0] != attrsPerson['mail'])): - return True - if ((result_data[0][1].get('subject') == None and attrsPerson['subject']) or - (result_data[0][1].get('subject') and result_data[0][1].get('subject', '')[0] != attrsPerson['subject'])): - return True - if ((result_data[0][1].get('uid',False) and result_data[0][1].get('uid', '')[0] != attrsPerson['uid'])): - return True - - return False - - # Function to add new Person - def addPerson(self,m,uidNumber,resourceIDList): - - try: - attrsPerson = self.createPersonAttrs(m,uidNumber) - self.logger.info ("chking addPerson attrsPerson -- " + str(attrsPerson)) - #personDN = "uidNumber=" + uidNumber + "," + peopleDN - personDN = "uid=" + attrsPerson['uid'] + "," + settings.peopleDN - self.logger.info ("chking addPerson personDN -- " + str(personDN)) - - ldif = modlist.addModlist(attrsPerson) - self.l.add_s(personDN,ldif) - - self.logger.info("\n Person with SUPR ID SUP is signed :: %s and added to LDAP -- %s", m.id, str(uidNumber)) - - if settings.dcache_resource_id in resourceIDList: - self.ADD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.add_pers_cnt += 1 - - if m.centre_person_id: - self.logger.info("Person with SUPR ID :: %s centre_person_id already exists -- %s", m.id, m.centre_person_id) - else: - # Updating the centre_person_id to SUPR - d = {'centre_person_id' : attrsPerson['uid']} - - try: - person = self.supr_connection.post("person/%s/update/" % m.id, data = d) - m.centre_person_id = attrsPerson['uid'] - self.logger.info("Centre_Person_id for Person with SUPR ID :: %s updated to SUPR -- %s", m.id, attrsPerson['uid']) - except supr.SUPRHTTPError as e: - # We want to show the text received if we get an HTTP Error - self.logger.error("HTTP error in updating data to SUPR - %s :: %s" % e.status_code % e.text) - self.ERR_MJR_MAIL += "Error occured in updating centre_person_id (uid) to SUPR - " + e.text + "\n" - self.ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\t Module :: addPerson \n" - self.err_mjr_cnt += 1 - except ConnectionError as ce: - self.ERR_MJR_MAIL += "Error occured in updating centre_person_id (uid) to SUPR due to ConnectionError- " + str(ce) + "\n" - self.logger.error("Connection to SUPR failed - %s" %str(ce)) - - for resourceid in resourceIDList: - d = {'username' : m.centre_person_id, - 'person_id' : m.id, - 'resource_id' : resourceid, - 'status' : 'enabled', - 'button_text' : 'Change password', - } - try: - account = self.supr_connection.post("account/create/", data = d) - self.logger.info("Account for Person with SUPR ID :: %s for resource -- %s created", m.id, resourceid) - except supr.SUPRHTTPError as e: - # We want to show the text received if we get an HTTP Error - self.logger.error("HTTP error in creating account to SUPR - %s :: %s", e.status_code, e.text) - self.ERR_MJR_MAIL += "Error occured in creating account to SUPR - " + e.text + "\n" - self.ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + str(attrsPerson['uid']) + "\t Module :: addPerson \n" - self.err_mjr_cnt += 1 - except ConnectionError as ce: - self.ERR_MJR_MAIL += "Error occured in creating account to SUPR due to ConnectionError- " + str(ce) + "\n" - self.logger.error("Connection to SUPR failed - %s" %str(ce)) - - - # Adding Project for every Person - self.addPersonAsProject(attrsPerson) - - self.addPersontoFreeIPA(m,attrsPerson) - - # Adding Person to Kerberos - self.addPersontoKerberos(m,attrsPerson) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addPerson Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: addPerson \n" - self.err_pers_cnt += 1 - - # Function to add new person to Kerberos - def addPersontoKerberos(self,m,attrsPerson): - - # Kadmin init or "login" - try: - kadm = kadmin.init_with_keytab(settings.adminprincipal, settings.keytab) - - user = attrsPerson['uid'] - princ = kadm.getprinc(user) - - if (princ is None): - kadm.addprinc(user, None) - - self.logger.info("Person with SUPR ID :: %s added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) - self.KRB_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.krb_pers_cnt += 1 - else: - self.logger.info("Person with SUPR ID :: %s already added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) - sys.exit(1) - - except Exception as e: - self.logger.error("Error in addPersontoKerberos Module for %s :: %s", str(attrsPerson['uid']), e) - self.ERR_PERS_MAIL += "uidNumber :: " + str(attrsPerson['uid']) + "\t Module :: addPersontoKerberos \n" - self.err_pers_cnt += 1 - - - # Function to add new person to ipa - def addPersontoFreeIPA(self,m,attrsPerson): - - try: - user = attrsPerson['uid'] - givenname = attrsPerson['gn'] - sn = attrsPerson['sn'] - cn = attrsPerson['gn'] - uidnumber = attrsPerson['uidNumber'] - userpassword = temp_password() - - opts = {"givenname": attrsPerson['gn'], - "sn": attrsPerson['sn'], - "mail" : attrsPerson['mail'], - "uidnumber":attrsPerson['uidNumber'], - "userpassword":temp_password(), - } - result = self.ipa.user_add(user, givenname, sn, cn, o_uidnumber=uidnumber, o_userpassword=userpassword) - result = self.ipa.group_add_member('irodsusers', o_user=user, o_group='user') - #self.sendIPAMail(m) - - self.logger.info("Person with SUPR ID :: %s added to IPA -- %s", m.id, str(attrsPerson['uidNumber'])) - self.IPA_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.ipa_pers_cnt += 1 - - except exceptions.FreeIPAError as e: - self.logger.error("Error in addPersontoFreeIPA Module for %s :: %s", str(attrsPerson['uid']), e) - self.ERR_PERS_MAIL += "uidNumber :: " + str(attrsPerson['uid']) + "\t Module :: addPersontoFreeIPA \n" - self.err_pers_cnt += 1 - - - # Function to update Person Data or delete merged Persons - def updateDeletePersons(self): - - self.logger.info("updateDeletePersons -- " + str(self.persons_modified)) - gidNumbers = [] - try: - for m in self.persons_modified: - - uidNumber = str(settings.uidNumberStart + m.id) - result_data = self.searchPerson(uidNumber) - self.logger.info("updateDeletePersons searchPerson result_data -- " + str(result_data)) - - if ((not result_data) and (not m.merged_ids)): - - # check for uidnumber in memberUids in groups - gidNumbers = self.searchMemberUid(uidNumber) - self.logger.info("gidNumbers -- " + str(gidNumbers)) - - if gidNumbers: - if (m.user_agreement_version and m.user_agreement_accepted): - - for gidNumber in gidNumbers: - - gid = gidNumber[1].get('gidNumber')[0] - resourceIDList = gidNumber[1].get('resourceID') - self.logger.info("resourceIDList : %s ", resourceIDList) - - proj_name = gidNumber[1].get('cn')[0] - - self.addPerson(m,uidNumber,resourceIDList) - - groupDN = "gidNumber=" + gid + "," + settings.groupsDN - oldMemberUid = [(ldap.MOD_DELETE, 'memberUid', str(uidNumber))] - newMemberUid = [(ldap.MOD_ADD, 'memberUid', str(m.centre_person_id))] - - self.l.modify_s(groupDN,oldMemberUid) - self.l.modify_s(groupDN,newMemberUid) - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - # code for adding SUA approved person to irods - - #if settings.irods_resource_id in resourceIDList: - # self.irods_persons_modified.append([m, proj_name]) - - self.logger.info("Person with SUPR ID :: %s SUP is signed and will be updated to LDAP.", m.id) - - else: - self.logger.info("Person with SUPR ID :: %s not needed in LDAP. Just ignore it.", m.id) - else: - - for merge_id in m.merged_ids: - mergeUidNumber = str(settings.uidNumberStart + merge_id) - result_data_mrg = self.searchPerson(mergeUidNumber) - - if(not result_data_mrg): - self.logger.info("Person with SUPR ID :: %s has already been deleted from LDAP since its merged with SUPR ID :: %s ", merge_id, m.id) - else: - personDN = "uid=" + result_data_mrg[0][1].get('uid')[0] + "," + settings.peopleDN - groupDN = "gidNumber=" + mergeUidNumber + "," + settings.groupsDN - - self.l.delete_s(personDN) - self.logger.info("Person with SUPR ID :: %s deleted from LDAP since its merged with SUPR ID :: %s ", merge_id, m.id) - - self.MOD_PERS_MAIL += "SUPR Person ID :: " + str(merge_id) + " merged with SUPR Person ID :: " + str(m.id) + "\n" - self.mod_pers_cnt += 1 - - # Deleting the corresponding Project as well - self.l.delete_s(groupDN) - self.logger.info("Project with ID :: %s deleted from LDAP since its person is also deleted :: %s ", merge_id, merge_id) - - attrsPerson = self.createPersonAttrs(m,uidNumber) - - personDN = "uid=" + attrsPerson['uid'] + "," + settings.peopleDN - - if(result_data and self.personChanged(result_data,attrsPerson)): - self.l.delete_s(personDN) - ldif = modlist.addModlist(attrsPerson) - self.l.add_s(personDN,ldif) - self.logger.info("Person with SUPR ID :: %s modified to LDAP -- %s", m.id, attrsPerson['uidNumber']) - - self.MOD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.mod_pers_cnt += 1 - - else: - self.logger.info("Person with SUPR ID :: %s - No changes since last time \n", m.id) - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - #if self.irods_persons_modified: - # supr_irods_pirc.SUPR_IRODS([], self.irods_persons_modified) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in updateDeletePersons Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module Name :: updateDeletePerson \n" - self.err_pers_cnt += 1 - - # Function to search Project based on gidNumber - def searchProject(self,gidNumber,cn): - - try: - # Check if the project already exists in LDAP - filter = "(|(cn=" + cn + ")(gidNumber=" + gidNumber + "))" - - ldap_result_id = self.l.search(settings.groupsDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id) - self.logger.info("result_data full -- " + str(result_data)) - - for result in result_data: - self.logger.info("result -- " + str(result[1]['cn'][0])) - if str(cn) == str(result[1]['cn'][0]): - return [result] - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchProject Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: searchProject \n" - self.err_proj_cnt += 1 - return [] - - # Function to add / update Projects - def addUpdateProjects(self): - - for p in self.all_projects: - - attrsGroup = {} - memberUIDList = [] - resourceIDList = [] - suaNotSigned = [] - sua_accepted = None - - for rp in p.resourceprojects: - if (str(rp.resource.id) in [settings.dcache_resource_id, settings.irods_resource_id]): - resourceIDList.append(str(rp.resource.id)) - - for m in p.members: - # Generate uidNumber for new Person - # ( Example 30023 - 30000 is the start range and 23 is the person id from SUPR ) - uidNumber = str(settings.uidNumberStart + m.id) - result_data = self.searchPerson(uidNumber) - self.logger.info("addUpdateProjects searchPerson result_data -- " + str(result_data)) - result_data_mid = self.searchMemberUid(uidNumber) - self.logger.info("addUpdateProjects searchPerson result_data_mid -- " + str(result_data_mid)) - - if ((not result_data) and (not result_data_mid)): - - if (m.user_agreement_version and m.user_agreement_accepted): - self.logger.info("addUpdateProjects m.id -- " + str(m.id) + " merge_ids -- " + str(m.merge_ids)) - - if m.merge_ids: - self.persons_modified = [m] - self.updateDeletePersons() - - self.addPerson(m,uidNumber,resourceIDList) - sua_accepted = True - - # To send user mail regarding user certificate registration in SUPR for dcache projects - if settings.dcache_resource_id in resourceIDList: - self.sendUserMail(m, p.directory_name, sua_accepted) - else: - sua_accepted = False - suaNotSigned.append(str(m.id)) - # To send user mail regarding SUA in SUPR for all projects - self.sendUserMail(m, p.directory_name, sua_accepted) - self.logger.info("Person with SUPR ID :: %s SUP is not signed and will not be added to LDAP.", m.id) - - # Add UidNumber as MemberUid in Group fo SUP not signed - m.centre_person_id = uidNumber - - elif (result_data and result_data[0][1].get('uid')[0]): - m.centre_person_id = result_data[0][1].get('uid')[0] - #self.sendIPAMail(m) - - self.logger.info("Person with SUPR ID :: %s - Already added to LDAP", m.id) - - elif result_data_mid: - m.centre_person_id = uidNumber - - if not m.centre_person_id: - m.centre_person_id = uidNumber - - memberUIDList.append(str(m.centre_person_id)) - - if (suaNotSigned and (settings.dcache_resource_id in resourceIDList)): - self.SUA_PERS_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + str(p.directory_name) + "\t Persons SUA Not signed :: " + ", ".join(suaNotSigned) + "\n" - self.sua_pers_cnt += 1 - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - # Add irods projects to a list - - #if settings.irods_resource_id in resourceIDList: - # self.irods_projects.append(p) - - # Generate gidNumber for new Project - # ( Example 6012 - 6000 is the start range and 12 is the project id from SUPR ) - gidNumber = str(settings.gidNumberStart + p.id) - - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - attrsGroup['objectclass'] = ['Swestore','posixgroup'] - attrsGroup['description'] = [str(p.id)] - attrsGroup['piMemberID'] = str(settings.uidNumberStart + p.pi.id) - attrsGroup['memberUID'] = memberUIDList - attrsGroup['resourceID'] = resourceIDList - attrsGroup['projectEndDate'] = str(p.end_date) - attrsGroup['lastModifiedTime'] = str(p.modified) - - - if p.directory_name: - attrsGroup['cn'] = str((p.directory_name).encode('utf-8')) - - try: - result_data = self.searchProject(gidNumber, attrsGroup['cn']) - self.logger.info("attrsGroup 1-- %s ", str(attrsGroup)) - self.logger.info("result_data 1-- %s ", str(result_data)) - - # Load data into LDAP - if (not result_data): - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - self.logger.info("Project with SUPR ID :: %s added to LDAP -- %s \n", p.id, gidNumber) - - if settings.dcache_resource_id in resourceIDList: - self.ADD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + p.directory_name + "\t Persons Added :: " + ", ".join(memberUIDList) + "\n" - self.add_proj_cnt += 1 - - else: - if (result_data and ('lastModifiedTime' in result_data[0][1]) and (result_data[0][1]['lastModifiedTime'][0] != attrsGroup['lastModifiedTime'])): - - addUsers = list(set(memberUIDList).difference(set(result_data[0][1]['memberUid']))) - removeUsers = list(set(result_data[0][1]['memberUid']).difference(set(memberUIDList))) - suprIds = result_data[0][1]['description'] - - if p.continuation_name: - gidNumber = result_data[0][1]['gidNumber'][0] - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - if str(p.id) not in suprIds: - attrsGroup['description'] = suprIds + [str(p.id)] - else: - attrsGroup['description'] = suprIds - - self.logger.info("attrsGroup 2 -- %s ", str(attrsGroup)) - self.l.delete_s(groupDN) - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - - self.logger.info("Project with SUPR ID :: %s modified to LDAP -- %s ", p.id, gidNumber) - - if p.continuation_name: - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Continuation project for SUPR ID(s) :: " + ", ".join(suprIds) + "\n" - self.mod_proj_cnt += 1 - - newCn = False - if attrsGroup['cn'] != result_data[0][1]['cn'][0]: - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t New Project Name :: " + attrsGroup['cn'] + "\t Old Project Name :: " + result_data[0][1]['cn'][0] + "\n" - self.mod_proj_cnt += 1 - newCn = True - - if removeUsers and (settings.dcache_resource_id in resourceIDList): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Persons Removed :: " + ", ".join(removeUsers) + "\n" - self.mod_proj_cnt += 1 - - if addUsers and (settings.dcache_resource_id in resourceIDList): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Persons Added :: " + ", ".join(addUsers) + "\n" - self.mod_proj_cnt += 1 - - if not (removeUsers or addUsers or p.continuation_name or newCn): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\n" - self.mod_proj_cnt += 1 - - else: - self.logger.info("Project with SUPR ID :: %s - No changes since last time \n", p.id) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addUpdateProjects Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addUpdateProjects \n" - self.err_proj_cnt += 1 - - - # For every Person add a corresponding Project with uidNumber as gidNumber - def addPersonAsProject(self,attrsPerson): - - attrsGroup = {} - attrsGroup['cn'] = attrsPerson['uid'] - attrsGroup['description'] = attrsPerson['description'] - attrsGroup['piMemberID'] = attrsPerson['uidNumber'] - attrsGroup['memberUID'] = [attrsPerson['uid']] - attrsGroup['objectclass'] = ['Swestore','posixgroup'] - - gidNumber = attrsPerson['uidNumber'] - attrsGroup['gidNumber'] = gidNumber - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - - try: - result_data = self.searchProject(gidNumber, attrsGroup['cn']) - - # Load data into LDAP - if (not result_data): - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - self.logger.info("Person-Project with ID :: %s added to LDAP -- %s", attrsPerson['description'], attrsGroup['gidNumber']) - - else: - self.logger.info("Person-Project with ID :: %s - already added", attrsPerson['description']) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addPersonAsProject Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addPersonAsProject \n" - self.err_proj_cnt += 1 diff --git a/supr_ldap_krb.py b/supr_ldap_krb.py deleted file mode 100644 index 1ad5ac59eec6b10857d858d3c8ed6106a22ca99b..0000000000000000000000000000000000000000 --- a/supr_ldap_krb.py +++ /dev/null @@ -1,794 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- - -import kadmin -import ldap -import ldap.modlist as modlist -import logging -import sys -import supr -import settings -import requests - -# (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) -#import supr_irods_pirc - -# (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) -#from python_freeipa import ClientMeta -#from python_freeipa import exceptions - -from requests import ConnectionError -requests.packages.urllib3.disable_warnings() - -from supr_common import (asciify, - sendMail, - setup_log, - temp_password) - -class SUPR_LDAP: - - def __init__(self, all_projects, persons_modified, supr_connection): - - if all_projects or persons_modified: - - # Get Logging File Handler - self.logger = setup_log(self.__class__.__name__, settings.LOG_FILE) - self.l = None - - # (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - #self.ipa = None - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - #self.irods_projects = [] - #self.irods_persons_modified = [] - - # Get supr_connection - self.supr_connection = supr_connection - - # LDAP search scope and other variables - self.searchScope = ldap.SCOPE_SUBTREE - self.retrievedAttrs = None - - # Variables needed for calculating number of projects and persons created - # that are used to sendMail to Admins - self.add_proj_cnt = 0 - self.mod_proj_cnt = 0 - self.err_proj_cnt = 0 - - self.add_pers_cnt = 0 - self.mod_pers_cnt = 0 - self.err_pers_cnt = 0 - self.sua_pers_cnt = 0 - - #(Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - #self.ipa_pers_cnt = 0 - - self.krb_pers_cnt = 0 - - self.err_mjr_cnt = 0 - self.msgtext = "" - - # Variables needed for Message Text of projects and persons created - # that are used to sendMail to Admins - self.ADD_PERS_MAIL = "The Following Persons have been Added on " + settings.today + "\n" - self.ADD_PERS_MAIL += "---------------------------------------------------- \n" - - self.MOD_PERS_MAIL = "The Following Persons have been Modified on " + settings.today + "\n" - self.MOD_PERS_MAIL += "---------------------------------------------------- \n" - - self.SUA_PERS_MAIL = "The Following Persons have not signed SUA and hence not Added on " + settings.today + "\n" - self.SUA_PERS_MAIL += "---------------------------------------------------------------------------- \n" - - # (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - #self.IPA_PERS_MAIL = "The Following Persons have been Added to IPA " + settings.today + "\n" - #self.IPA_PERS_MAIL += "------------------------------------------------------- \n" - - self.KRB_PERS_MAIL = "The Following Persons have been Added to Kerberos " + settings.today + "\n" - self.KRB_PERS_MAIL += "------------------------------------------------------- \n" - - self.ADD_PROJ_MAIL = "The Following Projects have been Added on " + settings.today + "\n" - self.ADD_PROJ_MAIL += "----------------------------------------------------- \n" - - self.MOD_PROJ_MAIL = "The Following Projects have been Modified on " + settings.today + "\n" - self.MOD_PROJ_MAIL += "----------------------------------------------------- \n" - - self.ERR_PROJ_MAIL = "Error in creating the following Projects on " + settings.today + "\n" - self.ERR_PROJ_MAIL += "------------------------------------------------------- \n" - - self.ERR_PERS_MAIL = "Error in creating the following Persons on " + settings.today + "\n" - self.ERR_PERS_MAIL += "------------------------------------------------------ \n" - - self.ERR_MJR_MAIL = "Major Error Occured on " + settings.today + "\n" - self.ERR_MJR_MAIL += "---------------------------------- \n" - - # Connect to LDAP using python-LDAP - try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER) - - self.l = ldap.initialize(settings.LDAP_HOST) - self.l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) - except ldap.LDAPError as le: - self.logger.error("LDAP Connection Error - %s", le) - if self.l: - self.l.unbind() - - self.ERR_MJR_MAIL += "Error occured in LDAP Connection - " + str(le) + "\n" - self.err_mjr_cnt += 1 - sys.exit(1) - - """ - # (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - # Connect to FreeIPA - try: - - self.ipa = ClientMeta(settings.IPA_HOST) - self.ipa.login(settings.IPA_ADMIN_USER, settings.IPA_ADMIN_PWD) - ClientMeta.log = setup_log("IPA_ADD_USER", settings.LOG_FILE) - self.logger.info("Connected to IPA \n") - - except exceptions.FreeIPAError as e: - self.logger.error("FreeIPA Connection Error - %s", e) - self.ERR_MJR_MAIL += "Error occured in FreeIPA Connection - " + str(e) + "\n" - self.err_mjr_cnt += 1 - sendMail(self.ERR_MJR_MAIL, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, settings.LDAP_SUBJECT) - sys.exit(1) - """ - - # Call to addUpdateProjects() Function - if all_projects: - # Assigning the all_projects from supr_swestore_main - self.all_projects = all_projects - self.addUpdateProjects() - - # Call to updateDeleteProjects() Function - if persons_modified: - # Assigning the persons_modified from supr_swestore_main - self.persons_modified = persons_modified - self.updateDeletePersons() - - # Call to sendMail() Function - if self.err_mjr_cnt: - self.msgtext += str(self.ERR_MJR_MAIL) + "\n" - if self.err_proj_cnt: - self.msgtext += str(self.ERR_PROJ_MAIL) + "\n" - if self.err_pers_cnt: - self.msgtext += str(self.ERR_PERS_MAIL) + "\n" - if self.add_proj_cnt: - self.msgtext += str(self.ADD_PROJ_MAIL) + "\n" - if self.mod_proj_cnt: - self.msgtext += str(self.MOD_PROJ_MAIL) + "\n" - if self.add_pers_cnt: - self.msgtext += str(self.ADD_PERS_MAIL) + "\n" - if self.sua_pers_cnt: - self.msgtext += str(self.SUA_PERS_MAIL) + "\n" - - # (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - #if self.ipa_pers_cnt: - # self.msgtext += str(self.IPA_PERS_MAIL) + "\n" - - if self.krb_pers_cnt: - self.msgtext += str(self.KRB_PERS_MAIL) + "\n" - - if self.mod_pers_cnt: - self.msgtext += str(self.MOD_PERS_MAIL) + "\n" - if self.msgtext: - sendMail(self.msgtext, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, settings.LDAP_SUBJECT) - - # (Krishnaveni: 2022-03-03 commenting out as irods is no longer in production) - # Call to function to create iRODS Users and Projects - - #if self.irods_projects: - # self.irods_projects.sort(key = lambda p: p.id) - # supr_irods_pirc.SUPR_IRODS(self.irods_projects, []) - - - # Mail to be to be sent to User for Password Setting (Not needed anymore) - def sendIPAMail(self,m): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - #msgTxt += "You are receiving this mail as you are added as a member to Swestore project -- " + proj_name + " in SUPR. \n\n" - msgTxt += "To set password to access Swestore/dCache, login to portal - http://auth1.swestore.se/ipa/supr/supr-auth1.cgi \n" - msgTxt += "First time, you will be redirected to SUPR for confirmation and then you can set a password which you can use to login to Swestore/iRods \n" - msgTxt += "To know more on how to set password in IPA please refer to the following links :- \n" - - msgTxt += "http://snicdocs.nsc.liu.se/wiki/Swestore#Using_Swestore \n\n" - - msgTxt += "In case of any issues or clarifications, please mail support@swestore.se. \n\n" - msgTxt += "Regards,\n" + "Swestore Support Team" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Information to access Swestore") - - - # Mail to be to be sent to User - def sendUserMail(self,m, proj_name, sua_accepted): - - msgTxt = "Dear " + m.first_name + " " + m.last_name + ",\n \n" - msgTxt += "You are receiving this mail as you are added as a member to Swestore project -- " + proj_name + " in SUPR.\n\n" - - if not sua_accepted: - msgTxt += "We have noticed that you have not signed the NAISS User Agreement.\n" - msgTxt += "Before access to Swestore is granted, the NAISS User Agreement must be read and accepted.\n" - msgTxt += "Login to SUPR (https://supr.naiss.se/login), go to Personal Information and sign the NAISS User Agreement using Federated Identity. \n\n" - - msgTxt += "For information on how to set your password, please see the following documentation :-\n" - msgTxt += "https://docs.swestore.se/access/\n\n" - - msgTxt += "Please refer to the documentation for more information on Swestore:-\n" - msgTxt += "https://docs.swestore.se/\n\n" - - msgTxt += "In case of any issues or clarifications, please use the support form on\n" - msgTxt += "https://supr.naiss.se/support/ or email support@swestore.se.\n\n" - msgTxt += "Regards,\nSwestore Support Team\n" - - sendMail(msgTxt, 'support@swestore.se', m.email, "Information to access Swestore") - - - # Generate userId or uid for new Person from first name and last name - # using various combinations - def getUID(self,m): - guesses = [] - firstname = ((m.first_name).replace(" ", "")).lower() - lastname = (m.last_name).replace(" ", "").lower() - - if (len(firstname) < 3 and len(lastname) < 3): - uid = "s_" + asciify(u'' + firstname + lastname) - guesses.append(str(uid)) - else: - for (flen, llen, swap) in ((3,2, False), - (2,3, False), - (3,2, True), - (2,3, True), - (1,4, False), - (4,1, False), - (1,4, True), - (4,1, True), - (0,5, False), - (5,0, False), - ): - if (len(firstname) < flen or len(lastname) < llen): - continue - if swap: - uid = "s_" + asciify(u'' + lastname[:llen] + firstname[:flen]) - guesses.append(str(uid)) - else: - uid = "s_" + asciify(u'' + firstname[:flen] + lastname[:llen]) - guesses.append(str(uid)) - - # Check if the uid already exists in LDAP - self.logger.debug("Person with SUPR ID :: %s login guesses -- %s ", m.id, guesses) - - for login in guesses: - - filter = "uid=" + login - ldap_result_id = self.l.search(settings.peopleDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id, 0) - - if (not result_data): - return login - - # No guess possible - return str(guesses[0]+m.id) - - # Function to search Person based on uidNumber - def searchPerson(self,uidNumber): - - try: - # Check if the member already exists in LDAP - filter = "(uidNumber=" + uidNumber+")" - - ldap_result_id = self.l.search(settings.peopleDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id, 0) - self.logger.info("searchPerson -- " + str(result_type) + "--- " + str(result_data)) - return result_data - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchPerson Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchPerson \n" - self.err_pers_cnt += 1 - return [] - - # Function to search MemberUid based on uidNumber in Groups for SUP not signed persons - def searchMemberUid(self,uidNumber): - - try: - # Check if the member already exists in LDAP - filter = "(memberUid=" + uidNumber+")" - retrievedAttrs = ['gidNumber', 'resourceID', 'cn'] - - ldap_result_id = self.l.search(settings.groupsDN, self.searchScope, filter, retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id) - self.logger.info("chk 111 -- " + str(result_type) + " --- " + str(result_data)); - return result_data - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchMemberUid Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: searchMemberUid \n" - self.err_pers_cnt += 1 - return [] - - - # Function to create Person Attributes - def createPersonAttrs(self,m,uidNumber): - - attrsPerson = {} - attrsPerson['objectclass'] = ['Swestore','inetorgperson','posixaccount'] - attrsPerson['description'] = str(m.id) - attrsPerson['uidNumber'] = uidNumber - attrsPerson['gidNumber'] = uidNumber - attrsPerson['gn'] = str((m.first_name).encode('utf-8')) - attrsPerson['sn'] = str((m.last_name).encode('utf-8')) - attrsPerson['cn'] = str((m.first_name + " " + m.last_name).encode('utf-8')) - attrsPerson['mail'] = str((m.email).encode('utf-8')) - attrsPerson['subject'] = str((m.subject).encode('utf-8')) - attrsPerson['lastModifiedTime'] = str(m.modified) - attrsPerson['homeDirectory'] = "/" - - # Will be updated to the correct yubikey value once yubikey is integrated into SUPR (Not needed as of now) - attrsPerson['yubikey'] = "yubikey" - - # Need to check if centre_person_id comes from SUPR. If it clashes with other UIDs - # then an alert mail needs to be sent to Admin about the same. - if m.centre_person_id: - attrsPerson['uid'] = str(m.centre_person_id) - else: - attrsPerson['uid'] = self.getUID(m) - - return attrsPerson - - # Function to check Person Data has changed - def personChanged(self,result_data, attrsPerson): - - if ((result_data[0][1].get('description',False) and result_data[0][1].get('description', '')[0] != attrsPerson['description'])): - return True - if ((result_data[0][1].get('givenName',False) and result_data[0][1].get('givenName','')[0] != attrsPerson['gn'])): - return True - if ((result_data[0][1].get('sn',False) and result_data[0][1].get('sn', '')[0] != attrsPerson['sn'])): - return True - if ((result_data[0][1].get('cn',False) and result_data[0][1].get('cn', '')[0] != attrsPerson['cn'])): - return True - if ((result_data[0][1].get('mail',False) and result_data[0][1].get('mail', '')[0] != attrsPerson['mail'])): - return True - if ((result_data[0][1].get('subject') == None and attrsPerson['subject']) or - (result_data[0][1].get('subject') and result_data[0][1].get('subject', '')[0] != attrsPerson['subject'])): - return True - if ((result_data[0][1].get('uid',False) and result_data[0][1].get('uid', '')[0] != attrsPerson['uid'])): - return True - - return False - - # Function to add new Person - def addPerson(self,m,uidNumber,resourceIDList): - - try: - attrsPerson = self.createPersonAttrs(m,uidNumber) - self.logger.info ("chking addPerson attrsPerson -- " + str(attrsPerson)) - #personDN = "uidNumber=" + uidNumber + "," + peopleDN - personDN = "uid=" + attrsPerson['uid'] + "," + settings.peopleDN - self.logger.info ("chking addPerson personDN -- " + str(personDN)) - - ldif = modlist.addModlist(attrsPerson) - self.l.add_s(personDN,ldif) - - self.logger.info("\n Person with SUPR ID SUP is signed :: %s and added to LDAP -- %s", m.id, str(uidNumber)) - - if settings.dcache_resource_id in resourceIDList: - self.ADD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.add_pers_cnt += 1 - - if m.centre_person_id: - self.logger.info("Person with SUPR ID :: %s centre_person_id already exists -- %s", m.id, m.centre_person_id) - else: - # Updating the centre_person_id to SUPR - d = {'centre_person_id' : attrsPerson['uid']} - - try: - person = self.supr_connection.post("person/%s/update/" % m.id, data = d) - m.centre_person_id = attrsPerson['uid'] - self.logger.info("Centre_Person_id for Person with SUPR ID :: %s updated to SUPR -- %s", m.id, attrsPerson['uid']) - except supr.SUPRHTTPError as e: - # We want to show the text received if we get an HTTP Error - self.logger.error("HTTP error in updating data to SUPR - %s :: %s" % e.status_code % e.text) - self.ERR_MJR_MAIL += "Error occured in updating centre_person_id (uid) to SUPR - " + e.text + "\n" - self.ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\t Module :: addPerson \n" - self.err_mjr_cnt += 1 - except ConnectionError as ce: - self.ERR_MJR_MAIL += "Error occured in updating centre_person_id (uid) to SUPR due to ConnectionError- " + str(ce) + "\n" - self.logger.error("Connection to SUPR failed - %s" %str(ce)) - - for resourceid in resourceIDList: - d = {'username' : m.centre_person_id, - 'person_id' : m.id, - 'resource_id' : resourceid, - 'status' : 'enabled', - 'button_text' : 'Change password', - } - try: - account = self.supr_connection.post("account/create/", data = d) - self.logger.info("Account for Person with SUPR ID :: %s for resource -- %s created", m.id, resourceid) - except supr.SUPRHTTPError as e: - # We want to show the text received if we get an HTTP Error - self.logger.error("HTTP error in creating account to SUPR - %s :: %s", e.status_code, e.text) - self.ERR_MJR_MAIL += "Error occured in creating account to SUPR - " + e.text + "\n" - self.ERR_MJR_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + str(attrsPerson['uid']) + "\t Module :: addPerson \n" - self.err_mjr_cnt += 1 - except ConnectionError as ce: - self.ERR_MJR_MAIL += "Error occured in creating account to SUPR due to ConnectionError- " + str(ce) + "\n" - self.logger.error("Connection to SUPR failed - %s" %str(ce)) - - - # Adding Project for every Person - self.addPersonAsProject(attrsPerson) - - # Adding Person to FreeIPA (Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos) - # self.addPersontoFreeIPA(m,attrsPerson) - - # Adding Person to Kerberos - self.addPersontoKerberos(m,attrsPerson) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addPerson Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module :: addPerson \n" - self.err_pers_cnt += 1 - - # Function to add new person to Kerberos - def addPersontoKerberos(self,m,attrsPerson): - - # Kadmin init or "login" - try: - kadm = kadmin.init_with_keytab(settings.adminprincipal, settings.keytab) - - user = attrsPerson['uid'] - princ = kadm.getprinc(user) - - if (princ is None): - kadm.addprinc(user, None) - - self.logger.info("Person with SUPR ID :: %s added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) - self.KRB_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.krb_pers_cnt += 1 - else: - self.logger.info("Person with SUPR ID :: %s already added to Kerberos -- %s", m.id, str(attrsPerson['uidNumber'])) - sys.exit(1) - - except Exception as e: - self.logger.error("Error in addPersontoKerberos Module for %s :: %s", str(attrsPerson['uid']), e) - self.ERR_PERS_MAIL += "uidNumber :: " + str(attrsPerson['uid']) + "\t Module :: addPersontoKerberos \n" - self.err_pers_cnt += 1 - - """ - # Krishnaveni: 2022-11-21 commented out as IPA is replaced by Kerberos - # Function to add new person to ipa - def addPersontoFreeIPA(self,m,attrsPerson): - - try: - user = attrsPerson['uid'] - givenname = attrsPerson['gn'] - sn = attrsPerson['sn'] - cn = attrsPerson['gn'] - uidnumber = attrsPerson['uidNumber'] - userpassword = temp_password() - - opts = {"givenname": attrsPerson['gn'], - "sn": attrsPerson['sn'], - "mail" : attrsPerson['mail'], - "uidnumber":attrsPerson['uidNumber'], - "userpassword":temp_password(), - } - result = self.ipa.user_add(user, givenname, sn, cn, o_uidnumber=uidnumber, o_userpassword=userpassword) - result = self.ipa.group_add_member('irodsusers', o_user=user, o_group='user') - #self.sendIPAMail(m) - - self.logger.info("Person with SUPR ID :: %s added to IPA -- %s", m.id, str(attrsPerson['uidNumber'])) - self.IPA_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.ipa_pers_cnt += 1 - - except exceptions.FreeIPAError as e: - self.logger.error("Error in addPersontoFreeIPA Module for %s :: %s", str(attrsPerson['uid']), e) - self.ERR_PERS_MAIL += "uidNumber :: " + str(attrsPerson['uid']) + "\t Module :: addPersontoFreeIPA \n" - self.err_pers_cnt += 1 - """ - - - # Function to update Person Data or delete merged Persons - def updateDeletePersons(self): - - self.logger.info("updateDeletePersons -- " + str(self.persons_modified)) - gidNumbers = [] - try: - for m in self.persons_modified: - - uidNumber = str(settings.uidNumberStart + m.id) - result_data = self.searchPerson(uidNumber) - self.logger.info("updateDeletePersons searchPerson result_data -- " + str(result_data)) - - if ((not result_data) and (not m.merged_ids)): - - # check for uidnumber in memberUids in groups - gidNumbers = self.searchMemberUid(uidNumber) - self.logger.info("gidNumbers -- " + str(gidNumbers)) - - if gidNumbers: - if (m.user_agreement_version and m.user_agreement_accepted): - - for gidNumber in gidNumbers: - - gid = gidNumber[1].get('gidNumber')[0] - resourceIDList = gidNumber[1].get('resourceID') - self.logger.info("resourceIDList : %s ", resourceIDList) - - proj_name = gidNumber[1].get('cn')[0] - - self.addPerson(m,uidNumber,resourceIDList) - - groupDN = "gidNumber=" + gid + "," + settings.groupsDN - oldMemberUid = [(ldap.MOD_DELETE, 'memberUid', str(uidNumber))] - newMemberUid = [(ldap.MOD_ADD, 'memberUid', str(m.centre_person_id))] - - self.l.modify_s(groupDN,oldMemberUid) - self.l.modify_s(groupDN,newMemberUid) - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - # code for adding SUA approved person to irods - - #if settings.irods_resource_id in resourceIDList: - # self.irods_persons_modified.append([m, proj_name]) - - self.logger.info("Person with SUPR ID :: %s SUP is signed and will be updated to LDAP.", m.id) - - else: - self.logger.info("Person with SUPR ID :: %s not needed in LDAP. Just ignore it.", m.id) - else: - - for merge_id in m.merged_ids: - mergeUidNumber = str(settings.uidNumberStart + merge_id) - result_data_mrg = self.searchPerson(mergeUidNumber) - - if(not result_data_mrg): - self.logger.info("Person with SUPR ID :: %s has already been deleted from LDAP since its merged with SUPR ID :: %s ", merge_id, m.id) - else: - personDN = "uid=" + result_data_mrg[0][1].get('uid')[0] + "," + settings.peopleDN - groupDN = "gidNumber=" + mergeUidNumber + "," + settings.groupsDN - - self.l.delete_s(personDN) - self.logger.info("Person with SUPR ID :: %s deleted from LDAP since its merged with SUPR ID :: %s ", merge_id, m.id) - - self.MOD_PERS_MAIL += "SUPR Person ID :: " + str(merge_id) + " merged with SUPR Person ID :: " + str(m.id) + "\n" - self.mod_pers_cnt += 1 - - # Deleting the corresponding Project as well - self.l.delete_s(groupDN) - self.logger.info("Project with ID :: %s deleted from LDAP since its person is also deleted :: %s ", merge_id, merge_id) - - attrsPerson = self.createPersonAttrs(m,uidNumber) - - personDN = "uid=" + attrsPerson['uid'] + "," + settings.peopleDN - - if(result_data and self.personChanged(result_data,attrsPerson)): - self.l.delete_s(personDN) - ldif = modlist.addModlist(attrsPerson) - self.l.add_s(personDN,ldif) - self.logger.info("Person with SUPR ID :: %s modified to LDAP -- %s", m.id, attrsPerson['uidNumber']) - - self.MOD_PERS_MAIL += "SUPR ID :: " + str(m.id) + "\t username(uid) :: " + attrsPerson['uid'] + "\t Person Name :: " + attrsPerson['cn'] + "\n" - self.mod_pers_cnt += 1 - - else: - self.logger.info("Person with SUPR ID :: %s - No changes since last time \n", m.id) - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - #if self.irods_persons_modified: - # supr_irods_pirc.SUPR_IRODS([], self.irods_persons_modified) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in updateDeletePersons Module for %s :: %s", str(uidNumber), le) - self.ERR_PERS_MAIL += "uidNumber :: " + str(uidNumber) + "\t Module Name :: updateDeletePerson \n" - self.err_pers_cnt += 1 - - # Function to search Project based on gidNumber - def searchProject(self,gidNumber,cn): - - try: - # Check if the project already exists in LDAP - filter = "(|(cn=" + cn + ")(gidNumber=" + gidNumber + "))" - - ldap_result_id = self.l.search(settings.groupsDN, self.searchScope, filter, self.retrievedAttrs) - result_type, result_data = self.l.result(ldap_result_id) - self.logger.info("result_data full -- " + str(result_data)) - - for result in result_data: - self.logger.info("result -- " + str(result[1]['cn'][0])) - if str(cn) == str(result[1]['cn'][0]): - return [result] - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in searchProject Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: searchProject \n" - self.err_proj_cnt += 1 - return [] - - # Function to add / update Projects - def addUpdateProjects(self): - - for p in self.all_projects: - - attrsGroup = {} - memberUIDList = [] - resourceIDList = [] - suaNotSigned = [] - sua_accepted = None - - for rp in p.resourceprojects: - if (str(rp.resource.id) in [settings.dcache_resource_id, settings.irods_resource_id]): - resourceIDList.append(str(rp.resource.id)) - - for m in p.members: - # Generate uidNumber for new Person - # ( Example 30023 - 30000 is the start range and 23 is the person id from SUPR ) - uidNumber = str(settings.uidNumberStart + m.id) - result_data = self.searchPerson(uidNumber) - self.logger.info("addUpdateProjects searchPerson result_data -- " + str(result_data)) - result_data_mid = self.searchMemberUid(uidNumber) - self.logger.info("addUpdateProjects searchPerson result_data_mid -- " + str(result_data_mid)) - - if ((not result_data) and (not result_data_mid)): - - if (m.user_agreement_version and m.user_agreement_accepted): - self.logger.info("addUpdateProjects m.id -- " + str(m.id) + " merged_ids -- " + str(m.merged_ids)) - - if m.merged_ids: - self.persons_modified = [m] - self.updateDeletePersons() - - self.addPerson(m,uidNumber,resourceIDList) - sua_accepted = True - - # To send user mail regarding user certificate registration in SUPR for dcache projects - if settings.dcache_resource_id in resourceIDList: - self.sendUserMail(m, p.directory_name, sua_accepted) - else: - sua_accepted = False - suaNotSigned.append(str(m.id)) - # To send user mail regarding SUA in SUPR for all projects - self.sendUserMail(m, p.directory_name, sua_accepted) - self.logger.info("Person with SUPR ID :: %s SUP is not signed and will not be added to LDAP.", m.id) - - # Add UidNumber as MemberUid in Group fo SUP not signed - m.centre_person_id = uidNumber - - elif (result_data and result_data[0][1].get('uid')[0]): - m.centre_person_id = result_data[0][1].get('uid')[0] - #self.sendIPAMail(m) - - self.logger.info("Person with SUPR ID :: %s - Already added to LDAP", m.id) - - elif result_data_mid: - m.centre_person_id = uidNumber - - if not m.centre_person_id: - m.centre_person_id = uidNumber - - memberUIDList.append(str(m.centre_person_id)) - - if (suaNotSigned and (settings.dcache_resource_id in resourceIDList)): - self.SUA_PERS_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + str(p.directory_name) + "\t Persons SUA Not signed :: " + ", ".join(suaNotSigned) + "\n" - self.sua_pers_cnt += 1 - - # (Krishnaveni: 2022-03-03 commented out as irods is no longer in production) - # Add irods projects to a list - - #if settings.irods_resource_id in resourceIDList: - # self.irods_projects.append(p) - - # Generate gidNumber for new Project - # ( Example 6012 - 6000 is the start range and 12 is the project id from SUPR ) - gidNumber = str(settings.gidNumberStart + p.id) - - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - attrsGroup['objectclass'] = ['Swestore','posixgroup'] - attrsGroup['description'] = [str(p.id)] - attrsGroup['piMemberID'] = str(settings.uidNumberStart + p.pi.id) - attrsGroup['memberUID'] = memberUIDList - attrsGroup['resourceID'] = resourceIDList - attrsGroup['projectEndDate'] = str(p.end_date) - attrsGroup['lastModifiedTime'] = str(p.modified) - - if p.directory_name: - attrsGroup['cn'] = str((p.directory_name).encode('utf-8')) - - try: - result_data = self.searchProject(gidNumber, attrsGroup['cn']) - self.logger.info("attrsGroup 1-- %s ", str(attrsGroup)) - self.logger.info("result_data 1-- %s ", str(result_data)) - - # Load data into LDAP - if (not result_data): - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - self.logger.info("Project with SUPR ID :: %s added to LDAP -- %s \n", p.id, gidNumber) - - if settings.dcache_resource_id in resourceIDList: - self.ADD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + p.directory_name + "\t Persons Added :: " + ", ".join(memberUIDList) + "\n" - self.add_proj_cnt += 1 - - else: - if (result_data and ('lastModifiedTime' in result_data[0][1]) and (result_data[0][1]['lastModifiedTime'][0] != attrsGroup['lastModifiedTime'])): - - addUsers = list(set(memberUIDList).difference(set(result_data[0][1]['memberUid']))) - removeUsers = list(set(result_data[0][1]['memberUid']).difference(set(memberUIDList))) - suprIds = result_data[0][1]['description'] - - if p.continuation_name: - gidNumber = result_data[0][1]['gidNumber'][0] - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - if str(p.id) not in suprIds: - attrsGroup['description'] = suprIds + [str(p.id)] - else: - attrsGroup['description'] = suprIds - - self.logger.info("attrsGroup 2 -- %s ", str(attrsGroup)) - self.l.delete_s(groupDN) - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - - self.logger.info("Project with SUPR ID :: %s modified to LDAP -- %s ", p.id, gidNumber) - - if p.continuation_name: - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Continuation project for SUPR ID(s) :: " + ", ".join(suprIds) + "\n" - self.mod_proj_cnt += 1 - - newCn = False - if attrsGroup['cn'] != result_data[0][1]['cn'][0]: - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t New Project Name :: " + attrsGroup['cn'] + "\t Old Project Name :: " + result_data[0][1]['cn'][0] + "\n" - self.mod_proj_cnt += 1 - newCn = True - - if removeUsers and (settings.dcache_resource_id in resourceIDList): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Persons Removed :: " + ", ".join(removeUsers) + "\n" - self.mod_proj_cnt += 1 - - if addUsers and (settings.dcache_resource_id in resourceIDList): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\t Persons Added :: " + ", ".join(addUsers) + "\n" - self.mod_proj_cnt += 1 - - if not (removeUsers or addUsers or p.continuation_name or newCn): - self.MOD_PROJ_MAIL += "SUPR ID :: " + str(p.id) + "\t Project Name :: " + attrsGroup['cn'] + "\n" - self.mod_proj_cnt += 1 - - else: - self.logger.info("Project with SUPR ID :: %s - No changes since last time \n", p.id) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addUpdateProjects Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addUpdateProjects \n" - self.err_proj_cnt += 1 - - - # For every Person add a corresponding Project with uidNumber as gidNumber - def addPersonAsProject(self,attrsPerson): - - attrsGroup = {} - attrsGroup['cn'] = attrsPerson['uid'] - attrsGroup['description'] = attrsPerson['description'] - attrsGroup['piMemberID'] = attrsPerson['uidNumber'] - attrsGroup['memberUID'] = [attrsPerson['uid']] - attrsGroup['objectclass'] = ['Swestore','posixgroup'] - - gidNumber = attrsPerson['uidNumber'] - attrsGroup['gidNumber'] = gidNumber - groupDN = "gidNumber=" + gidNumber + "," + settings.groupsDN - - try: - result_data = self.searchProject(gidNumber, attrsGroup['cn']) - - # Load data into LDAP - if (not result_data): - ldif = modlist.addModlist(attrsGroup) - self.l.add_s(groupDN,ldif) - self.logger.info("Person-Project with ID :: %s added to LDAP -- %s", attrsPerson['description'], attrsGroup['gidNumber']) - - else: - self.logger.info("Person-Project with ID :: %s - already added", attrsPerson['description']) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in addPersonAsProject Module for %s :: %s", str(gidNumber), le) - self.ERR_PROJ_MAIL += "gidNumber :: " + str(gidNumber) + "\t Module :: addPersonAsProject \n" - self.err_proj_cnt += 1 diff --git a/supr_swestore_main.py b/supr_swestore_main.py index cb4829eaa201e927a29ec92e48820327ce3c3e5e..75077e04622a85907c7cde849c589045e01d63e1 100644 --- a/supr_swestore_main.py +++ b/supr_swestore_main.py @@ -5,9 +5,7 @@ import logging import sys import supr import settings -#import supr_ldap_ipa_krb as supr_ldap -#(Krishnaveni: 2022-11-28 switch to this once IPA is decommissioned) -import supr_ldap_krb as supr_ldap +import supr_ldap from datetime import datetime from requests import ConnectionError @@ -19,7 +17,7 @@ log_main = setup_log('SUPR_SWESTORE', settings.LOG_FILE) # getting modified_since time from file try: - with open("modified_time.txt", "r") as f: + with open("/supr/modified_time.txt", "r") as f: t = f.readline() if t: @@ -28,8 +26,8 @@ try: log_main.info("Modified Since : %s" %t) except IOError as ie: - log_main.error("Error occured in reading modified_time.txt file :: " + ie) - sendMail(ie.text, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR SWESTORE MAIN") + log_main.error("Error occured in reading modified_time.txt file :: " + str(ie)) + sendMail(str(ie), settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR SWESTORE MAIN") # Search in SUPR try: @@ -39,10 +37,7 @@ try: base_url = settings.SUPR_BASE_URL) today_date = datetime.strptime(t, "%Y-%m-%d %H:%M:%S").date() - #print today_date - # Compose query from the below options - #params = {'id': 10181, 'full_person_data': '1', 'all_centre_person_ids':'1', 'resource_centre_id': settings.resource_centre_id } # Changing query into two parts to solve continuation projects start date problem params = {'full_person_data': '1', 'all_centre_person_ids':'1', 'resource_centre_id': settings.resource_centre_id, 'start_date': today_date, 'end_date_gt': today_date} @@ -85,12 +80,12 @@ try: res = supr_connection.get("person/search/", params = params) except supr.SUPRHTTPError as e: # Logging Errors from SUPR - log_main.error("HTTP error from SUPR - %s" %e.text) - sendMail("HTTP error from SUPR - " + e.text, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") + log_main.error("HTTP error from SUPR - %s" %str(e)) + sendMail("HTTP error from SUPR - " + str(e), settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") sys.exit(1) except ConnectionError as ce: - log_main.error("Connection to SUPR failed - %s" %ce.text) - sendMail("Connection to SUPR failed - " + ce.text, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") + log_main.error("Connection to SUPR failed - %s" %str(ce)) + sendMail("Connection to SUPR failed - " + str(ce), settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, "SUPR - SWESTORE Connection Error") sys.exit(1) # Getting the updated Person profiles using modified_since @@ -111,10 +106,10 @@ if all_projects or persons_modified: try: #t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") t = res.began - with open("modified_time.txt", "w") as f: + with open("/supr/modified_time.txt", "w") as f: f.write(t) log_main.info("Updated Modified Since to: %s \n" %t) except IOError as ie: - log_main.error("Error occured in updating modified_time.txt file :: " + ie + "\n") + log_main.error("Error occured in updating modified_time.txt file :: " + str(ie) + "\n") sys.exit(1) diff --git a/weekly_cleanup.py b/weekly_cleanup.py deleted file mode 100755 index a869ce9c85040ee628aab40cddd5c845464988e1..0000000000000000000000000000000000000000 --- a/weekly_cleanup.py +++ /dev/null @@ -1,287 +0,0 @@ -#!/usr/bin/python -#! -*- coding: utf-8 -*- -import irods -import ldap -import ldap.modlist as modlist -import logging -import sys -import supr -import smtplib - -from email.mime.text import MIMEText -import settings - -from supr_common import (sendMail, - setup_log) - -class WEEKLY_CLEANUP: - def __init__(self, supr_persons, supr_groups): - - # Get Logging File Handler - self.logger = setup_log(self.__class__.__name__, settings.DELETE_LOG_FILE) - - self.l = None - self.conn = None - self.supr_persons = supr_persons - self.supr_groups = supr_groups - - # Variables needed for calculating number of projects and persons created - # that are used to sendMail to Admins - self.del_ldap_proj_cnt = 0 - self.del_irods_proj_cnt = 0 - - self.del_ldap_pers_cnt = 0 - self.del_irods_pers_cnt = 0 - - self.err_ldap_proj_cnt = 0 - self.err_ldap_pers_cnt = 0 - self.err_ldap_mjr_cnt = 0 - self.err_irods_mjr_cnt = 0 - self.ldap_msg_text = "" - self.irods_msg_text = "" - - # Variables needed for Message Text of projects and persons created - # that are used to sendMail to Admins - self.DEL_LDAP_PROJ_MAIL = "The Following Projects have been deleted from LDAP on " + settings.today + "\n" - self.DEL_LDAP_PROJ_MAIL += "----------------------------------------------------------- \n" - - self.DEL_LDAP_PERS_MAIL = "The Following Persons have been deleted from LDAP on " + settings.today + "\n" - self.DEL_LDAP_PERS_MAIL += "----------------------------------------------------------- \n" - - self.DEL_IRODS_PROJ_MAIL = "The Following Projects have been deleted from SUPR on " + settings.today + "\n" - self.DEL_IRODS_PROJ_MAIL += "----------------------------------------------------------- \n" - - self.DEL_IRODS_PERS_MAIL = "The Following Persons have been deleted from SUPR on " + settings.today - self.DEL_IRODS_PERS_MAIL += "\n" + "----------------------------------------------------- \n" - - self.ERR_LDAP_PROJ_MAIL = "Error in deleting the following Projects from LDAP on " + settings.today + "\n" - self.ERR_LDAP_PROJ_MAIL += "------------------------------------------------------- \n" - - self.ERR_LDAP_PERS_MAIL = "Error in deleting the following Persons from LDAP on " + settings.today + "\n" - self.ERR_LDAP_PERS_MAIL += "------------------------------------------------------ \n" - - self.ERR_LDAP_MJR_MAIL = "Major Error Occured on " + settings.today + "\n" - self.ERR_LDAP_MJR_MAIL += "---------------------------------- \n" - - self.ERR_IRODS_MJR_MAIL = "Major Error Occured on " + settings.today + "\n" - self.ERR_IRODS_MJR_MAIL += "---------------------------------- \n" - - - # LDAP search scope and other variables - self.searchScope = ldap.SCOPE_SUBTREE - - # Connect to LDAP using python-LDAP - try: - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE,settings.TLS_CACERTFILE) - ldap.set_option(ldap.OPT_X_TLS_CERTFILE,settings.TLS_CERTFILE) - ldap.set_option(ldap.OPT_X_TLS_KEYFILE,settings.TLS_KEYFILE) - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_DEMAND) - - self.l = ldap.initialize(settings.LDAP_HOST) - #l = ldap.open(settings.LDAP_HOST) - self.l.simple_bind(settings.LDAP_ADMIN, settings.LDAP_PASSWORD) - - except ldap.LDAPError as le: - self.logger.error("LDAP Connection Error - %s", le) - self.ERR_LDAP_MJR_MAIL += "Error occured in LDAP Connection - " + str(le) + "\n" - self.err_ldap_mjr_cnt += 1 - - if self.l: - self.l.unbind() - sys.exit(1) - - # Connect to iRODS using pyRODS - try: - self.envVal = irods.obfiGetEnvKey() - self.obi_password = irods.obfiEncode(settings.IRODS_ADMIN_PWD, self.envVal) - # Connection to a server with the default values - self.conn, self.errMsg = irods.rcConnect(settings.IRODS_HOST, settings.IRODS_PORT, settings.IRODS_ADMIN_USER, settings.IRODS_ZONE) - if self.conn: - self.status = irods.clientLoginWithObfPassword(self.conn, self.obi_password) - self.irods_projects = irods.irodsCollection(self.conn, settings.IRODS_DIR) - self.userGroup = irods.getGroup(self.conn, "users") - else: - raise irods.IrodsException(self.errMsg.status) - - except irods.IrodsException as ie: - self.logger.error("Error during iRODS Connection: %s", ie) - self.ERR_IRODS_MJR_MAIL += "Error occured in iRODS Connection - " + str(ie) + "\n" - self.err_irods_mjr_cnt += 1 - - if self.conn: - self.conn.disconnect() - sys.exit(1) - - self.deletePersons() - self.deleteProjects() - - # Call to sendMail() Function for LDAP - if self.err_ldap_mjr_cnt: - self.ldap_msg_text += str(self.ERR_LDAP_MJR_MAIL) + "\n" - if self.err_ldap_proj_cnt: - self.ldap_msg_text += str(self.ERR_LDAP_PROJ_MAIL) + "\n" - if self.err_ldap_pers_cnt: - self.ldap_msg_text += str(self.ERR_LDAP_PERS_MAIL) + "\n" - - if self.del_ldap_proj_cnt: - self.ldap_msg_text += str(self.DEL_LDAP_PROJ_MAIL) + "\n" - if self.del_ldap_pers_cnt: - self.ldap_msg_text += str(self.DEL_LDAP_PERS_MAIL) + "\n" - - if self.ldap_msg_text: - sendMail(self.ldap_msg_text, settings.FROM_ADDRS, settings.DCACHE_ADMIN_MAIL, settings.LDAP_DEL_SUBJECT) - - - # Call to sendMail() Function for iRODS - if self.err_irods_mjr_cnt: - self.irods_msg_text += str(self.ERR_IRODS_MJR_MAIL) + "\n" - - if self.del_irods_proj_cnt: - self.irods_msg_text += str(self.DEL_IRODS_PROJ_MAIL) + "\n" - if self.del_irods_pers_cnt: - self.irods_msg_text += str(self.DEL_IRODS_PERS_MAIL) + "\n" - - if self.irods_msg_text: - sendMail(self.irods_msg_text, settings.FROM_ADDRS, settings.IRODS_ADMIN_MAIL, settings.IRODS_DEL_SUBJECT) - - - # Delete Persons from LDAP and iRODS that are not in SUPR - def deletePersons(self): - - try: - # Get All Persons from LDAP - filter = "uidNumber=*" - retrievedAttrs = ['description', 'uid','uidNumber'] - ldap_result_id = self.l.search(settings.peopleDN, self.searchScope, filter, retrievedAttrs) - result_type, ldap_persons = self.l.result(ldap_result_id) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in deletePersons Module search - %s", le) - self.ERR_LDAP_MJR_MAIL += "Error occured in deletePersons Module search LDAP - " + str(le) + "\n" - self.err_ldap_mjr_cnt += 1 - - # Loop through LDAP results - for person in ldap_persons: - - # Check if the ldap Person exists in SUPR - if person[1]['description'][0] in self.supr_persons: - self.logger.info("SUPR Person ID %s exists. Need not delete from LDAP", person[1]['description'][0]) - else: - try: - self.l.delete_s(person[0]) - self.logger.info("SUPR Person ID %s doesnot exist. Deleted from LDAP", person[1]['description'][0]) - - self.DEL_LDAP_PERS_MAIL += "SUPR ID :: " + str(person[1]['description'][0]) + "\t" + "username(uid) :: " + str(person[1]['uid'][0]) - self.del_ldap_pers_cnt += 1 - except ldap.LDAPError as le: - self.logger.error("LDAP Error in deletePersons Module delete for %s :: %s", str(person[1]['uidNumber'][0]), le) - self.ERR_LDAP_PERS_MAIL += "SUPR ID :: " + str(person[1]['description'][0]) + "\t" + "username(uid) :: " + str(person[1]['uid'][0]) - self.err_ldap_pers_cnt += 1 - - try: - # write code to disable person from iRODS - if self.conn and irods.getUser(self.conn, str(person[1]['uid'][0])): - # disable user from iRODS - self.logger.info("SUPR Person ID %s doesnot exist. Disable from iRODS", person[1]['description'][0]) - - self.DEL_IRODS_PERS_MAIL += "SUPR ID :: " + str(person[1]['description'][0]) + "\t" + "username(uid) :: " + str(person[1]['uid'][0]) - self.del_irods_pers_cnt += 1 - except irods.IrodsException as ie: - self.logger.error("Error during iRODS Connection: %s", ie) - - - # Delete Projects from LDAP and iRODS that are not in SUPR - def deleteProjects(self): - - try: - # Get All Projects from LDAP - filter = "gidNumber=*" - retrievedAttrs = ['description','gidNumber', 'cn'] - ldap_result_id = self.l.search(settings.groupsDN, self.searchScope, filter, retrievedAttrs) - result_type, ldap_groups = self.l.result(ldap_result_id) - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in deleteProjects Module search - %s", le) - self.ERR_LDAP_MJR_MAIL += "Error occured in deleteProjects Module search LDAP - " + str(le) + "\n" - self.err_ldap_mjr_cnt += 1 - - for group in ldap_groups: - # Checking for projects in SUPR - proj_supr_id = str(group[1]['description'][0]) - proj_name = str(group[1]['cn'][0]) - - if group[0].find("gidNumber=5") < 0: - - if proj_supr_id in self.supr_groups: - self.logger.info("SUPR Project ID %s exists. Not needed to delete from LDAP", group[1]['description'][0]) - else: - try: - self.l.delete_s(group[0]) - self.logger.info("SUPR Project ID %s doesnot exist. Deleted from LDAP", group[1]['description'][0]) - self.DEL_LDAP_PROJ_MAIL += "SUPR ID :: " + proj_supr_id + "\t" + "Project Name :: " + proj_name - self.del_ldap_proj_cnt += 1 - - except ldap.LDAPError as le: - self.logger.error("LDAP Error in deleteProjects Module delete for %s :: %s", str(group[1]['gidNumber'][0]), le) - self.ERR_LDAP_PROJ_MAIL += "SUPR ID :: " + proj_supr_id + "\t" + "Project Name :: " + proj_name - self.err_ldap_proj_cnt += 1 - - try: - # write code to disable project from iRODS - #if proj_name in c.getSubCollections(): - # disable project - # write code to disable group from iRODS - if self.conn and irods.getGroup(self.conn, proj_name): - # disable group - self.DEL_IRODS_PROJ_MAIL += "SUPR ID :: " + proj_supr_id + "\t" + "Project Name :: " + proj_name - self.del_irods_proj_cnt += 1 - except irods.IrodsException as ie: - self.logger.error("Error during iRODS Connection: %s", ie) - - - # Checking for Projects created for each Person - else: - if proj_supr_id in self.supr_persons: - self.logger.info("LDAP Person ID %s exists. Not needed to delete from LDAP", group[1]['description'][0]) - else: - try: - self.l.delete_s(group[0]) - self.logger.info("LDAP Person ID %s doesnot exist. Deleted from LDAP", group[1]['description'][0]) - except ldap.LDAPError as le: - self.logger.error("LDAP Error in deleteProjects Module - %s", le) - -# Compose query from the below options -params = {'full_person_data': '1','resource_centre_id': settings.resource_centre_id} - -# Search in SUPR -try: - # Prepare a SUPR connection object - supr_connection = supr.SUPR(user = settings.SUPR_API_USER_NAME, - password = settings.SUPR_API_PASSWORD, - base_url = settings.SUPR_BASE_URL) - - # Get All Projects - res = supr_connection.get("project/search/", params = params) - -except supr.SUPRHTTPError as e: - # Logging Errors from SUPR - logger.error("HTTP error from SUPR - %s" %e.text) - sys.exit(1) - -# Loop through the results from the search in SUPR -supr_groups = [] -supr_persons = [] -for p in res.matches: - - # Add Projects to SUPR - if str(p.id) not in supr_groups: - supr_groups.append(str(p.id)) - - for m in p.members: - if str(m.id) not in supr_persons: - supr_persons.append(str(m.id)) - -# Instantiating and Calling the class -if supr_groups or supr_persons: - WEEKLY_CLEANUP(supr_persons, supr_groups) -