Theo Chatzimichos 5f6f74
#!/usr/bin/python3
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
# For description and usage, see the argparse options at the end of the file
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
from ldap3 import Server, Connection, ALL
Theo Chatzimichos 4f2316
from get_roles import get_roles, get_roles_of_one_minion
Theo Chatzimichos 5f6f74
import argparse
Theo Chatzimichos 5f6f74
import os
Theo Chatzimichos 5f6f74
import sys
Theo Chatzimichos 5f6f74
import yaml
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
def get_admins_of_a_role(admins, role):
Theo Chatzimichos 5f6f74
    results = {}
Theo Chatzimichos 5f6f74
    all_roles = get_roles()
Theo Chatzimichos 5f6f74
    if role not in all_roles:
Theo Chatzimichos 5f6f74
        print('Role not found')
Theo Chatzimichos 5f6f74
        sys.exit(1)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    conn.search('cn=groups,cn=compat,%s' % BASE_DN, '(cn=%s-admins)' % role, attributes=['cn', 'memberUid'])
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    try:
Theo Chatzimichos 5f6f74
        members = conn.entries[0].memberUid
Theo Chatzimichos 5f6f74
    except IndexError:
Theo Chatzimichos 5f6f74
        return results
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    for sls in os.listdir('pillar/id'):
Theo Chatzimichos 4f2316
        minion = sls.split('_')[0]
Theo Chatzimichos 4f2316
        roles = get_roles_of_one_minion(minion)
Theo Chatzimichos 5f6f74
        if role in roles:
Theo Chatzimichos 5f6f74
            for member in members:
Theo Chatzimichos 5f6f74
                results[member] = admins[member]
Theo Chatzimichos 4f2316
                results[member]['roles'].append('%s (%s)' % (minion, role))
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    return results
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
def get_admins_of_a_server(admins, server):
Theo Chatzimichos 5f6f74
    results = {}
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    try:
Theo Chatzimichos 4f2316
        roles = get_roles_of_one_minion(server)
Theo Chatzimichos 5f6f74
    except FileNotFoundError:
Theo Chatzimichos 5f6f74
        print('Server not found')
Theo Chatzimichos 5f6f74
        sys.exit(1)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    if roles:
Theo Chatzimichos 5f6f74
        for role in roles:
Theo Chatzimichos 5f6f74
            for admin, data in admins.items():
Theo Chatzimichos 5f6f74
                for group in data['groups']:
Theo Chatzimichos 5f6f74
                    if group.split('_')[0] == role:
Theo Chatzimichos 5f6f74
                        results[admin] = data
Theo Chatzimichos 5f6f74
                        results[admin]['roles'].append('%s (%s)' % (server, role))
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    return results
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
def output_to_pillar():
Theo Chatzimichos 5f6f74
    with open('pillar/generated/role/monitoring.sls', 'w') as f:
Theo Chatzimichos 5f6f74
        for admin, data in admins.items():
Theo Chatzimichos 5f6f74
            del data['roles']
Theo Chatzimichos 5f6f74
        yaml.dump({'profile': {'monitoring': {'contacts': admins}}}, f, default_flow_style=False)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
def output_nice(results):
Theo Chatzimichos 5f6f74
    RESULT_TMPL = '{:^30} {separ} {:^20} {separ} {:^30} {separ} {:^30}'
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
    print(RESULT_TMPL.format('SERVER (ROLE)', 'USERNAME', 'REAL NAME', 'EMAIL', separ='|'))
Theo Chatzimichos 5f6f74
    print(RESULT_TMPL.format('', '', '', '', separ='+').replace(' ', '-'))
Theo Chatzimichos 5f6f74
    for admin, data in sorted(results.items()):
Theo Chatzimichos 5f6f74
        for role in data['roles']:
Theo Chatzimichos 5f6f74
            print(RESULT_TMPL.format(role, admin, data['name'], data['mail'], separ='|'))
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
BASE_DN = 'dc=infra,dc=opensuse,dc=org'
Theo Chatzimichos 5f6f74
admins = {}
Theo Chatzimichos 5f6f74
EXCLUDE_ACCOUNTS = ['admin', 'guest', 'mufasa', 'monitor', 'wiki']
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
parser = argparse.ArgumentParser('Collects the admins of a server or of a role, and returns them in a nice output, or as a python dictionary or a yaml hash')
Theo Chatzimichos 5f6f74
parser.add_argument('-o', '--out', choices=['nice', 'yaml', 'python', 'pillar'], help='Select the output format. Options: nice (the default nice output), python (as a python dictionary), yaml (as a yaml hash), pillar (write them to pillar/generated/role/monitoring.sls)')
Theo Chatzimichos 5f6f74
parser.add_argument('-r', '--role', nargs=1, help='Collect the admins of a given role')
Theo Chatzimichos 5f6f74
parser.add_argument('-s', '--server', nargs=1, help='Collect the admins of a given server')
Theo Chatzimichos 5f6f74
args = parser.parse_args()
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
ldap_server = Server('freeipa.infra.opensuse.org', get_info=ALL)
Theo Chatzimichos 5f6f74
conn = Connection(ldap_server)
Theo Chatzimichos 5f6f74
conn.open()
Theo Chatzimichos 5f6f74
ldap_exclude_accounts = ''
Theo Chatzimichos 5f6f74
for account in EXCLUDE_ACCOUNTS:
Theo Chatzimichos 5f6f74
    ldap_exclude_accounts += '(uid=%s)' % account
Theo Chatzimichos 5f6f74
conn.search('cn=users,cn=accounts,%s' % BASE_DN, '(&(uid=*)(!(|%s)))' % ldap_exclude_accounts, attributes=['uid', 'gecos', 'mail'])
Theo Chatzimichos 5f6f74
all_admins_from_ldap = conn.entries
Theo Chatzimichos 5f6f74
for admin in all_admins_from_ldap:
Theo Chatzimichos 5f6f74
    admins[admin.uid[0]] = {'name': admin.gecos[0], 'mail': admin.mail[0], 'groups': [], 'roles': []}
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
conn.search('cn=groups,cn=compat,%s' % BASE_DN, '(cn=*-admins)', attributes=['cn', 'memberUid'])
Theo Chatzimichos 5f6f74
all_admin_groups_from_ldap = conn.entries
Theo Chatzimichos 5f6f74
for group in all_admin_groups_from_ldap:
Theo Chatzimichos 5f6f74
    members = group.memberUid
Theo Chatzimichos 5f6f74
    for member in members:
Theo Chatzimichos 5f6f74
        group_str = str(group.cn).replace('-', '_')[:-1]
Theo Chatzimichos 5f6f74
        admins[str(member)]['groups'].append(group_str)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
if args.out == 'pillar':
Theo Chatzimichos 5f6f74
    output_to_pillar()
Theo Chatzimichos 5f6f74
    sys.exit(0)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
if args.role:
Theo Chatzimichos 5f6f74
    results = get_admins_of_a_role(admins, args.role[0])
Theo Chatzimichos 5f6f74
elif args.server:
Theo Chatzimichos 5f6f74
    results = get_admins_of_a_server(admins, args.server[0])
Theo Chatzimichos 5f6f74
else:
Theo Chatzimichos 5f6f74
    parser.print_help()
Theo Chatzimichos 5f6f74
    sys.exit(1)
Theo Chatzimichos 5f6f74
Theo Chatzimichos 5f6f74
if results:
Theo Chatzimichos 5f6f74
    if args.out == 'yaml':
Theo Chatzimichos 5f6f74
        print(yaml.dump(results, default_flow_style=False))
Theo Chatzimichos 5f6f74
    elif args.out == 'python':
Theo Chatzimichos 5f6f74
        print(results)
Theo Chatzimichos 5f6f74
    else:
Theo Chatzimichos 5f6f74
        output_nice(results)