$ /some-path/compare_ipa_dsee_groups.py -h usage: compare_ipa_dsee_groups.py [-h] (-a | -u USER) [-t | -r] Compare IPA and DSEE groups (all or specific user) optional arguments: -h, --help show this help message and exit -a, --all Compare groups of all IPA users -u USER, --user USER Compare groups of specified IPA user login -t, --table Output is a table on the screen -r, --raw Raw output (default) Brought to you by ZD
This is table output.$ /some-path/ipa/compare_ipa_dsee_groups.py -u zdudic zdudic CA-LDAP: 485400023(userg_sa) userg_some_org, userg_pdu, userg_netdisco DSEE: 10(staff) labrm tech
This is cronjob, that creates html page (only when query all users).$ /some-path/compare_ipa_dsee_groups.py -t -u zdudic Obtaining Kerberos ticket-granting ticket for admin (IPA Administrator) Check if admin has kerberos ticket OK, admin has kerberos ticket +--------+-----------------------+-------------------------------------------+--------------------+-------------------+ | User | IPA primary group | IPA other groups | DSEE primary group | DSEE other groups | +--------+-----------------------+-------------------------------------------+--------------------+-------------------+ | zdudic | 485400023(userg_sa) | userg_some_org, userg_pdu, userg_netdisco | 10(staff) | labrm tech | | | | | | | +--------+-----------------------+-------------------------------------------+--------------------+-------------------+
55 15 * * * /some-path/compare_ipa_dsee_groups.py -a --html >/dev/null
#!/some-path/python3.5 # list users' IPA and DSEE groups # ------------------------------ import sys import ldap import argparse import subprocess import logging, logging.handlers from time import gmtime, strftime import datetime from prettytable import PrettyTable # variables # Bold text: \033[1m ... \033[0m BOLD = "\033[1m" END = "\033[0m" html_output = "/some-nfs-share/users_dsee_ipa_groups.html" ipa_server = "ipa-server.domain.com" dsee_server = "dsee-server.domain.com" # -- argument work parser = argparse.ArgumentParser( description="Compare IPA and DSEE groups (all or specific user)", epilog='Brought to you by ZD') who = parser.add_mutually_exclusive_group(required=True) who.add_argument("-a", "--all", help="Compare groups of all IPA users", action="store_true") who.add_argument("-u", "--user", help="Compare groups of specified IPA user login") output = parser.add_mutually_exclusive_group() output.add_argument("-t", "--table", help="Output is a table on the screen", action="store_true") output.add_argument("-r", "--raw", help="Raw output (default)", action="store_true") parser.add_argument("--html", help=argparse.SUPPRESS, action="store_true") args = parser.parse_args() allusers=args.all user=args.user tableoutput=args.table rawoutput=args.raw htmloutput=args.html def admin_kinit(): """ Obtain and cache Kerberos ticket-granting ticket for admin admin is IPA administrator account """ try: print("Obtaining Kerberos ticket-granting ticket for admin (IPA Administrator)") subprocess.call(['sudo -u admin kinit -kt /homelocal/admin/.ipa/admin.kt admin'], shell=True) except subprocess.CalledProcessError as err: print("Admin account (IPA Administrator) cannot obtain Kerberos ticket-granting ticket" ) sys.exit("subprocess.CalledProcessError: {0}".format(err)) def admin_kerberos_ticket(): """ Does admin have valid kerberos ticket? """ return True if subprocess.call(['sudo', '-u', 'admin', 'klist', '-s']) == 0 else False def does_user_exist_in_ipa(): """ Check if IPA account exists """ return True if subprocess.call(["sudo -u admin ipa user-find --login %s >/dev/null" % user], shell=True) == 0 else False def get_all_ipa_users(): """ Get list of all IPA users """ ipa_service_accounts = "admin|amandabackup|jenbuild|passwordreset|satools" global all_ipa_users try: all_ipa_users_output = subprocess.check_output(['sudo -u admin ipa user-find | grep \"User login\" | awk \'{print $3}\' \ | egrep -ve \'%s\'' % ipa_service_accounts], shell=True) except subprocess.SubprocessError as err: print("Can't get list of all IPA users") sys.exit("SubprocessError: {0}".format(err)) all_ipa_users = all_ipa_users_output.decode().split("\n") #print(all_ipa_users) all_ipa_users.pop() # remove last '' from list #print(all_ipa_users.pop()) # remove last '' from list #print(all_ipa_users) def get_user_ipa_primary_group(user): """ Get user's IPA primary group command: id user | awk '{print $2}' | awk -F= '{print $2}' """ global ipa_primarygroup try: ipa_primarygroup = subprocess.check_output(['id %s | awk \'{print $2}\' |awk -F= \'{print $2}\'' % user], shell=True) except subprocess.CalledProcessError as err: print("Can't get IPA primary group for %s" % user) sys.exit("subprocess.CalledProcessError: {0}".format(err)) def get_user_ipa_all_group(user): """ Get user's IPA all groups, including primary one """ global ipa_allgroups try: ipa_allgroups = subprocess.check_output(['sudo -u admin ipa user-show %s | grep "Member of groups" \ | awk \'{for (i=4; i<=NF; i++) printf $i""FS}\'' % user], shell=True) except subprocess.CalledProcessError as err: print("Can't get all IPA groups for %s" % user) sys.exit("subprocess.CalledProcessError: {0}".format(err)) def get_user_dsee_primary_group(user): """ Get user's DSEE primary group """ global dsee_primarygroupName global dsee_primarygroupID baseDN = "l=continent,dc=domain,dc=com" searchScope = ldap.SCOPE_SUBTREE # subtree search retrieveAttributes = None searchFilter = "uid=" + user try: ldapobject = ldap.initialize('ldap://' + dsee_server) ldapobject.protocol_version = ldap.VERSION3 l_search = ldapobject.search(baseDN, searchScope, searchFilter, retrieveAttributes) result_status, result_data = ldapobject.result(l_search, 0) #print(result_data) dsee_primarygroupID = result_data[0][1]["gidNumber"][0].decode() except ldap.LDAPError as err: print("Can't get DSEE primary group GID for %s" % user) sys.exit("ldap.LDAPError: {0}".format(err)) try: dsee_primarygroupName = subprocess.check_output(['ldapsearch -LLL -h %s -x -b "ou=groups,dc=domain,dc=com" "(gidNumber=%s)" \ | grep ^cn | awk \'{print $2}\'' % (dsee_server, dsee_primarygroupID)], shell=True) except subprocess.CalledProcessError as err: print("Can't get DSEE primary group name for %s" % user) sys.exit("subprocess.CalledProcessError: {0}".format(err)) def get_user_dsee_other_group(user): """ Get user's DSEE other groups, primary one is not included. command: ldapsearch -LLL -h dsee-server -x -b "ou=groups,dc=domain,dc=com" \ | "(memberUid=zdudic)" cn | grep ^cn | awk '{print $2}' | tr '\n' ',' """ global dsee_other_groups try: dsee_other_groups = subprocess.check_output(['ldapsearch -LLL -h %s -x -b "ou=groups,dc=domain,dc=com" "(memberUid=%s)" \ | grep ^cn | awk \'{print $2}\' \ | tr \'\n\' \' \' ' % (dsee_server, user)], shell=True) except subprocess.CalledProcessError as err: print("Can't get other DSEE groups for %s" % user) sys.exit("subprocess.CalledProcessError: {0}".format(err)) def table_output_one_user(user, ipa_primarygroup, ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups): """ Creates a table with results for only one user """ x = PrettyTable() x.field_names = ["User", "IPA primary group", "IPA other groups", "DSEE primary group", "DSEE other groups"] x.add_row([user, ipa_primarygroup, ipa_allgroups.decode(), dsee_primarygroupID + "(" + dsee_primarygroupName.decode().strip() + ")", dsee_other_groups.decode()]) print(x) def write_to_html_file(file_name, text): """ Write stdout to html file Arguments: file name and text """ original = sys.stdout sys.stdout = open(file_name, 'w+') print("<html>") print("<h2> Users' groups </h2>") print(strftime("Generated on: %b %d %Y")) print(text) print("</html>") sys.stdout.close() sys.stdout = original def raw_output(user, ipa_primarygroup, ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups): """ Creates a raw output of result """ print(BOLD + user + " IPA: " + ipa_primarygroup.strip() + END + " " + ipa_allgroups.decode() + BOLD + " DSEE: " + dsee_primarygroupID + "(" + dsee_primarygroupName.decode().strip() + ")" + END + " " + dsee_other_groups.decode()) if __name__ == '__main__': admin_kinit() print("Check if admin has kerberos ticket") if not admin_kerberos_ticket(): sys.exit("Admin doesn't have a kerberos ticket!") print("OK, admin has kerberos ticket") # query for only one user if user: # exit if user is not present in IPA if not does_user_exist_in_ipa(): sys.exit("User %s %s %s is not present in IPA, exiting!" % (BOLD, user, END)) get_user_ipa_primary_group(user) get_user_ipa_all_group(user) get_user_dsee_primary_group(user) get_user_dsee_other_group(user) if tableoutput: table_output_one_user(user, ipa_primarygroup.decode(), ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups) elif rawoutput: raw_output(user, ipa_primarygroup.decode(), ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups) else: # raw is also default raw_output(user, ipa_primarygroup.decode(), ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups) # query for all users if allusers: get_all_ipa_users() if tableoutput: x = PrettyTable() x.field_names = ["User", "IPA primary group", "IPA other groups", "DSEE primary group", "DSEE other groups"] x.align["User"] = "l" x.align["IPA primary group"] = "l" x.align["IPA other groups"] = "l" x.align["DSEE primary group"] = "l" x.align["DSEE other groups"] = "l" for user in all_ipa_users: get_user_ipa_primary_group(user) get_user_ipa_all_group(user) get_user_dsee_primary_group(user) get_user_dsee_other_group(user) x.add_row([user, ipa_primarygroup.decode(), ipa_allgroups.decode(), dsee_primarygroupID + "(" + dsee_primarygroupName.decode().strip() + ")", dsee_other_groups.decode()]) print(x) elif rawoutput: for user in all_ipa_users: get_user_ipa_primary_group(user) get_user_ipa_all_group(user) get_user_dsee_primary_group(user) get_user_dsee_other_group(user) raw_output(user, ipa_primarygroup.decode(), ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups) elif htmloutput: # hidden html output only for all users x = PrettyTable() x.field_names = ["User", "IPA primary group", "IPA other groups", "DSEE primary group", "DSEE other groups"] for user in all_ipa_users: get_user_ipa_primary_group(user) get_user_ipa_all_group(user) get_user_dsee_primary_group(user) get_user_dsee_other_group(user) x.add_row([user, ipa_primarygroup.decode(), ipa_allgroups.decode(), dsee_primarygroupID + "(" + dsee_primarygroupName.decode().strip() + ")", dsee_other_groups.decode()]) write_to_html_file(html_output, x.get_html_string(attributes={"border":"1"})) else: # raw is also default for user in all_ipa_users: get_user_ipa_primary_group(user) get_user_ipa_all_group(user) get_user_dsee_primary_group(user) get_user_dsee_other_group(user) raw_output(user, ipa_primarygroup.decode(), ipa_allgroups, dsee_primarygroupID, dsee_primarygroupName, dsee_other_groups) sys.exit(0)