3 minute read

This post is an update on my previous post Connect to IBM’s LDAP, Bluepages, with Python. Much like the previous post, this will be done using Bluepages, IBM’s LDAP. Any results from the queries will be anonymized.

Note, if you’re having trouble getting this to work, I’d recommend using ldapsearch first to iron out any issues with your query as it’ll be faster to iterate over the CLI. Check out Common ldapsearch queries for IBM Bluepages to get started.

This post will include sample code for five operations:

Bluepages LDAP schema and properties

Let’s go over some basics about the LDAP properties first.

  • LDAP URL: ldap://bluepages.ibm.com
  • Base user DN: ou=bluepages,o=ibm.com
  • Base group DN: ou=memberlist,ou=ibmgroups,o=ibm.com

In Python we can we initialize this as:

import ldap

ldap_uri = 'ldap://bluepages.ibm.com'
user_base = 'ou=bluepages,o=ibm.com'
group_base = 'ou=memberlist,ou=ibmgroups,o=ibm.com'
conn = ldap.initialize(ldap_uri)

Searching for a user by email

To start, we will find a user by email. The important part is the search filter.

(email=stevemar@ca.ibm.com)

Written in Python, we can find a user by email with the following code:

search_filter = "(email=stevemar@ca.ibm.com)"
result = conn.search_s(user_base, ldap.SCOPE_SUBTREE, search_filter)
userDN = result[0][0]

The result variable will be a tuple. The first part of the tuple contains the DN and the second part contains user properties, like email, phone number, job title, etc.

[
  ('uid=123456789,c=ca,ou=bluepages,o=ibm.com',
  {
    'uid': [b '123456789'], 'emailAddress': [b 'stevemar@ca.ibm.com'], 'mobile': [b '1-416-555-1234'],
	  'jobResponsibilities': [b 'STSM, Developer Advocacy'], 'passwordIsExpired': [b 'false']
  })
]

The userDN variable will be a string:

"uid=123456789,c=ca,ou=bluepages,o=ibm.com"

Finding groups that a user is a member of

For the rest of the examples we’ll use the same userDN from above. The important part is the search filter.

"(&(objectClass=groupOfUniqueNames)(uniqueMember=%s))"

Written in Python, we can find the groups that a user is a member of with the following code:

search_filter="(&(objectClass=groupOfUniqueNames)(uniqueMember=%s))" % userDN
results = conn.search_s(group_base, ldap.SCOPE_SUBTREE, search_filter, ['cn'])
groupCN = (results[0][1]['cn'][0]).decode('utf-8')

The results variable will be a list. Each entry is a group DN, with the cn added as that is part of the attribute list to be returned in the search query.

[
  ('cn=devteam,ou=memberlist,ou=ibmgroups,o=ibm.com', {'cn': [b 'devteam']}),
  ('cn=prodteam,ou=memberlist,ou=ibmgroups,o=ibm.com', {'cn': [b 'prodteam']}),
  ('cn=stagingteam,ou=memberlist,ou=ibmgroups,o=ibm.com', {'cn': [b 'stagingteam']})
]

The groupDN variable will simply be the short name, watch out for bytes being returned, you’ll need to decode it:

"devteam"

Finding members of a group

For the rest of the examples we’ll use the same groupDN from above. The important part is the search filter.

(&(objectClass=groupOfUniqueNames)(cn=%s))

Written in Python, we can find the members of a group with the following code. Each entry is a user DN, returned in a uniqueMember attribute as that is part of the attribute list to be returned in the search query.

search_filter="(&(objectClass=groupOfUniqueNames)(cn=%s))" % groupCN
results = conn.search_s(group_base, ldap.SCOPE_SUBTREE, search_filter, ['uniqueMember'])
member_list = results[0][1]['uniqueMember']

The results variable will be a tuple. The first part of the tuple is the group DN, the second part of the tuple is a list of DNs for each member in the group.

[
  ('cn=devteam,ou=memberlist,ou=ibmgroups,o=ibm.com',
  {
    'uniqueMember':[
      b 'uid=987654321,c=us,ou=bluepages,o=ibm.com',
      b 'uid=111333667,c=us,ou=bluepages,o=ibm.com'
    ]
  })
]

The member_list is snipped from the uniqueMember part of the result. We’ll iterate over that list.

Looking up a user based on DN

To look up information about a user, when we have their DN, is just one call. The important part is to change the search from the base_user_search to the userDN. We can also pass in the following search filter so we get information about the user:

(objectClass=*)

Written in Python, we can iterate over a list of members in a group and get each user’s email address. Again, watch out for data returned in bytes.

search_filter = "(objectClass=*)"
member_list = results[0][1]['uniqueMember']
member_emails = []
for member in member_list:
    memberDN = member.decode('utf-8')
    result = conn.search_s(memberDN, ldap.SCOPE_BASE, search_filter)
    member_emails.append((result[0][1]['mail'][0]).decode('utf-8'))

The member_emails variable will be a list of emails, nothing too fancy.

['stevemar@ca.ibm.com', 'jedi@us.ibm.com']

Authenticating a user

The last part is authenticating a user, this is easy if we have a DN.

password = "ThisIsSecure!"
conn.simple_bind_s(userDN, password)

Wrapping up

To sum things up…

  • Finding a user by email: (email=stevemar@ca.ibm.com)
  • Finding groups a user is a member of: (&(objectClass=groupOfUniqueNames)(uniqueMember=uid=123456789,c=ca,ou=bluepages,o=ibm.com))
  • Finding users in a group: (&(objectClass=groupOfUniqueNames)(cn=devteam))
  • Finding a user by DN: (objectClass=*)

Updated: