Next / Previous / Contents / TCC Help System / NM Tech homepage

13. genAllUsers(): Find all the users in LDAP

homelist2
# - - -   g e n A l l U s e r s

def genAllUsers():
    '''Generate the LDAP entries for all real user accounts.

      [ generate a sequence of WebUser instances representing all
        users in LDAP_SERVER ]
    '''

First, we bind to the LDAP server. Anonymous binding is sufficient to get the account information we want. See Section 7.3, “LDAP_SERVER.

homelist2
    #-- 1 --
    # [ LDAP_SERVER names an accessible LDAP server ->
    #     anon  :=  an LDAP object representing an anonymous bind
    #               to LDAP_SERVER ]
    try:
        anon  =  ldap.initialize ( LDAP_SERVER )
        anon.bind ( "", "", ldap.AUTH_SIMPLE )
    except ldap.LDAP_Error, detail:
        fatal("Couldn't bind to the LDAP server.")

Next, we use the LDAP module's search function to search first-level children of the node specified by ACCOUNTS_DN. The filterstr argument filters out entries that have no uid attribute. The attrlist argument requests that only the attributes named in the list are returned. See Section 7.4, “ACCOUNTS_DN, Section 7.1, “UID_ATTR, and Section 7.2, “GECOS_ATTR.

homelist2
    #-- 2 --
    # [ anon is a bound LDAP object ->
    #     ldapResult  :=  a list of LDAP result tuples for
    #         a search of the immediate children of ACCOUNTS_DN that
    #         have a UID_ATTR attribute, containing the UID_ATTR and
    #         GECOS_ATTR attributes ]
    ldapResult  =  anon.search_s ( ACCOUNTS_DN, ldap.SCOPE_ONELEVEL,
        filterstr="(%s=*)" % UID_ATTR,
        attrlist=[UID_ATTR, GECOS_ATTR] )

The structure of ldapResult is described by this excerpt from LDAP programming with Python:

Each result tuple is of the form (dn, attrs), where dn is a string containing the DN (distinguished name) of the entry, and attrs is a dictionary containing the attributes associated with the entry. The keys of attrs are strings, and the associated values are lists of strings.

So to produce the return value, we pull out the second element of each tuple in ldapResult to get the attribute map, then form a tuple from the first element of the list for each attribute we want.

Two more complications. Some LDAP entries don't have a GECOS field. In that case we just skip that entry. Also, in the Bad Old Days, there was a convention that GECOS fields contained not just the name, but three more fields separated by commas. So we use only the part of the GECOS field up to the first comma, if there is one.

homelist2
    #-- 3 --
    # [ ldapResult is an LDAP-search-format result list ->
    #     generate a sequence of WebUser instances representing
    #     the usernames and GECOS fields made from ldapResult ]
    for  dn, attrs in ldapResult:
        uid  =  attrs[UID_ATTR][0]
        try:
            rawGecos  =  attrs[GECOS_ATTR][0]
            commaPos = rawGecos.find(",")
            if commaPos >= 0:
                gecos = rawGecos[:commaPos]
            else:
                gecos = rawGecos
            yield WebUser(uid, gecos)
        except KeyError:
            pass

    #-- 4 --
    raise StopIteration