Example External User Sync Script

Example synchronization script for use with the Perforce IPLM LDAP integration. 

Example External User Synchronization Script

Note: requires a simple wrapper script to pass in arguments.
Example External User Synchronization Script
#!/usr/bin/python

import ldap
import logging
import json
import sys
import os

log = logging.getLogger()

# global variable to keep track of user information
users_seen = {}
users_list = []


def get_member_name(member):
    username = member[1]['AccountName'][0]
    if username.startswith('_'):
        return
    if 'confrm' in username.lower():
        return
    if not username in users_seen:
        users_seen[username] = 1
        users_list.append({
            'username': username,
            'fullname': member[1]['fullName'][0],
            'email': member[1]['mail'][0],
        })
    return username


def get_group_members(l, group):
    member_list = []
    try:
        cn = group[0]
        base = 'OU=Users,OU=Corp,DC=mycompany,DC=com'
        attribs = ['AccountName', 'fullName', 'mail']
        filter = '(&(objectCategory=person)(objectClass=user)(AccountName=*)(fullName=*)(mail=*)(memberOf:5.3.175.123456.2.5.1972:=%s))' % cn
        members = l.search_s(base, ldap.SCOPE_SUBTREE, filter, attribs)
        for member in members:
            username = get_member_name(member)
            if username:
                member_list.append(username)
    except ldap.LDAPError, error_message:
        log.debug(error_message)
    return member_list


def get_group_list(l, group):
    try:
        base = 'OU=Groups,OU=%s,DC=mycompany,DC=com' % group
        attribs = ['name', 'member']
        filter = '(&(objectClass=group)(|(name=cad*)(name=*.sg)(name=*.ro))(member=*))'
        groups = l.search_s(base, ldap.SCOPE_SUBTREE, filter, attribs)
        return groups
    except ldap.LDAPError, error_message:
        log.debug(error_message)
 
def ldap_query(args):
    try:
        l = ldap.open(args.ldap_host)
        l.simple_bind_s(args.ldap_username, args.ldap_password)
        log.debug('successfully bound to %s ldap server', args.ldap_host)

        # Actual LDAP configurations will vary with each setup, this is
        # provided as an example that will need to be customized to
        # be used with a particular LDAP setup.

        # get a list of groups and users
        group_list = []
        for group in ['Corp', 'LINUX']:
            members = []
            groups = get_group_list(l, group)
            for group in groups:
                members = get_group_members(l, group)
                if members:
                    groupname = group[1]['name'][0]
                    if len(groupname) < 30:
                        group_list.append({
                            'groupname': groupname,
                            'members': sorted(set(members))
                        })

        # build json string
        auth_list = {
            'users': users_list,
            'groups': group_list
        }
        indent = None
        if args.loglevel == logging.DEBUG:
            indent = 2
        print json.dumps(auth_list, indent=indent)

    except ldap.LDAPError, error_message:
        log.debug(error_message)
 
# Main: PI requirements state that the sync script should take no arguments
# this script is set up to take arguments so a simple wrapper script is
# required to call this script.
if __name__ == '__main__':

    # setup argument parser
    import argparse
    parser = argparse.ArgumentParser(description='piweb ldap sync interface')

    # try to load default argument values
    try:
        config = os.path.expanduser('/mdx/config/Perforce IPLM/piweb_ldap.json')
        with open(config, 'r') as f:
            defaults = json.load(f)
            parser.set_defaults(**defaults)
    except IOError:
        pass

    # add ldap arguments
    parser.add_argument('--ldap_host', help='ldap hostname (default: %(default)s)')
    parser.add_argument('--ldap_username', help='ldap service account username')
    parser.add_argument('--ldap_password', help='ldap service account password')

    # debugging flag for logging
    parser.add_argument('-v', '--verbose', action='store_const', dest='loglevel',
                        const=logging.DEBUG, default=logging.INFO,
                        help='enable debugging messages')

    # parse command line arguments
    args = parser.parse_args()

    # setup logging
    log.setLevel(logging.DEBUG)
    handler = logging.StreamHandler(sys.stdout)
    fmt = logging.Formatter(fmt='%(levelname)s: %(message)s')
    handler.setFormatter(fmt)
    handler.setLevel(args.loglevel)
    log.addHandler(handler)
    log.debug('argv: %s', ' '.join(sys.argv))

    # execute command
    sys.exit(ldap_query(args))