Import users from an LDAP directory to IBM Security Access Manager

Use Python to easily find and import user accounts into IBM Security Access Manager with no scripting experience required

Systems administrators frequently need a way to import existing user accounts from an LDAP repository into IBM Security Access Manager. In this article, get started with an import script written in Python that you can use to read users in an LDAP repository, then import them using the IBM Security Access Manager pdadmin command.

Share:

Ori Pomerantz (orip@us.ibm.com), Technical Enablement Specialist, IBM

author photoOri Pomerantz has been securing computer networks and teaching other people how he does it since 1995. Since joining IBM in 2003, he has written and taught classes on several IBM Security products, including IBM Security Identity Manager.



15 October 2013

Also available in Russian

Identity and Access Management

Learn more about identity and access management tools in IBM's "Identity and Access Management Buyer's Guide."

IBM security products are often implemented as brownfield developments, meaning they are built for an environment where some similar application already exists. IBM Security Access Manager is such a product, being frequently deployed into environments where a Lightweight Directory Access Protocol (LDAP) directory server is already in place. In that case, system administrators need to know how to import user entries from the LDAP directory server into IBM Security Access Manager.

Figure 1 shows a system architecture where IBM Security Access Manager has been introduced to an existing system that includes an LDAP directory server and back-end applications.

Figure 1. A directory server architecture with IBM Security Access Manager
A system architecture connecting an LDAP respository to IBM Security Access Manager

In this article, I present a Python script (see Download) you can use from the command-line to automatically find and import new users from an LDAP repository tree into IBM Security Access Manager. Note that this article assumes that you are familiar with IBM Security Access Manager and the Lightweight Directory Access Protocol. You needn't be familiar with Python to use the import script.

About Python

Python is a scripting language that is a standard part of most Linux® distributions. If your installation of IBM Security Access Manager is running on Windows®, you can download Python to follow the demonstration here. See Resources to learn more about Python.

The import script

In this section, I introduce and explain some elements and stages of the import script, which you may download at any time. Note that the script relies on IBM Security Access Manager's pdadmin command, so you must run it on a computer with the IBM Security Access Manager runtime environment installed.

Figure 2 is a flow diagram showing the major progressions of the script.

Figure 2. The major stages of the script
A flow diagram showing the stages of the import script.

Listing 1 shows the import script.

Listing 1. The import script
#! /usr/bin/python

# Authentication
ldap_dn = "cn=root"
ldap_pwd = "object00"
ldap_server = "localhost"
sameb_uid = "sec_master"
sameb_pwd = "object00"

# The part of the LDAP tree where you expect users
ldap_base = "o=xyz"

# The part of the LDAP tree where the SAMeb 
# configuration is located
ldap_sameb_base = "secAuthority=Default"

# Internal configuration
ldap_user_file = "ldap_users"
uid_file = "uid_file"

from subprocess import call

call("ldapsearch -LLL -D " + ldap_dn + " -w " + ldap_pwd 
	+ " -b " + ldap_base + " -h " + ldap_server
	" objectclass=inetOrgPerson dn >" + ldap_user_file,
		shell=True)

ldap_users = open(ldap_user_file, "r")

for line in ldap_users:
	if len(line) > 1:
		dn = line[4:-1]
		ret_val = call("ldapsearch -D " + ldap_dn +
			" -w " + ldap_pwd + " -h " + ldap_server +
			" -b " + ldap_sameb_base + " secDN=" + dn + 
			" | grep numEntries > /dev/null",
			shell=True)
		if (ret_val == 1):
			print "Need to import " + dn
			call("ldapsearch -D " + ldap_dn +
				" -w " + ldap_pwd + 
				" -h " + ldap_server + " -b " + dn +
				" objectClass=inetOrgPerson uid " + 
				"| grep uid: >" + uid_file, 
				shell=True)
			uid_f = open(uid_file, "r")
			uid = uid_f.read()
			uid_f.close()
			uid = uid[5:-1]
			call("pdadmin -a " + sameb_uid + " -p " +
				sameb_pwd + " user import " + uid + 
				" " + dn,
				shell=True);
			call("pdadmin -a " + sameb_uid + " -p " +
				sameb_pwd + " user modify " + uid + 
				"account-valid yes ",
				shell=True);

In the next section, I won't explain every part of the script, just its major features. It is helpful if you are familiar with Python, but not necessary. I'll explain the relevant aspects of Python syntax for each setting and also show you where you would need to modify it for your own use.


Script settings

Normally, Python lines that start with a number sign (#) are comments. This line in Listing 1 is a special case, however. The UNIX® convention is that files that start with a number sign followed by an exclamation point (#!) use the rest of the line as the name of the interpreter that will run the file. In this case, the following code is the path for the Python interpreter. You would modify it as needed for your environment.

#! /usr/bin/python

The next code snip contains the LDAP server's logon, password, and server host name information. Modify it as needed for your own system.

# Authentication
ldap_dn = "cn=root"
ldap_pwd = "object00"
ldap_server = "localhost"

Next, the script passes logon and password information to IBM Security Access Manager. Modify these parts for your environment.

sameb_uid = "sec_master"
sameb_pwd = "object00"

The next part is the branch of the LDAP tree that has user information. Figure 3 shows an example of the location of users in the LDAP tree. Modify as needed for your configuration.

Figure 3. LDAP tree with users
A diagram of a branch in the LDAP tree.
# The part of the LDAP tree where you expect users
ldap_base = "ou=people,o=xyz"

Filtering user accounts

In addition to locating users in the LDAP tree, the script must limit itself to users who are not already in IBM Security Access Manager. To filter out those users, the script needs to know the location in the LDAP tree of the IBM Security Access Manager configuration. As shown below, the default location is secAuthority=Default. You can change this default setting when you first configure the policy server.

# The part of the LDAP tree where the SAMeb
# configuration is located
ldap_sameb_base = "secAuthority=Default"

Figure 4 shows the LDAP tree with the default location of the IBM Security Access Manager configuration.

Figure 4. LDAP tree with secAuthority=Default
A diagram of the LDAP tree with ISAM defaults.

Toward the end of the script you see the files used as intermediate storage for the output of commands used to obtain user information. Unless you have a reason to run multiple instances of the script at once, you shouldn't need to change the following file names:

# Internal configuration
ldap_user_file = "ldap_users"
uid_file = "uid_file"

Script functions

The next part of the script uses the parameters declared above to actually read users from LDAP and import them into IBM Security Access Manager.

The script uses Python's subprocess.call function to run shell commands. The following line imports the function so that it is available:

from subprocess import call

The next line calls ldapsearch to find the list of users.

call("ldapsearch -LLL -D " + ldap_dn + " -w " + ldap_pwd
        + " -b " + ldap_base + " -h " + ldap_server
        " objectclass=inetOrgPerson dn >" + ldap_user_file,
        shell=True)

With the default configuration, the lines above run the following shell command. This command searches for entities of type inetOrgPerson, which is used to represent people. It reads only their distinguished name and sends the output to a file called ldapusers:

ldapsearch -LLL -D cn=root -w object00 -b ou=people,o=xyz
        -h localhost objectclass=inetOrgPerson dn > ldapusers

Next, the script opens the ldapusers file and reads it, line by line. Note that Python handles blocks by indentation; so everything that is indented at least once from this point onward is done once per user.

ldap_users = open(ldap_user_file, "r")
for line in ldap_users:

Note: The lines in ldapusers are of the form: dn: cn=jdoe,ou=users,o=xyz . The first four characters are dn: followed by a space. The actual distinguished name starts in the fifth character, which is number 4 when counting from zero.

Half of the lines in ldapusers are blank. The other half start with dn: . This code fragment ignores the blank lines and discards the first four characters of the other lines. Because Python blocks are designated by indentation, the rest of the script runs only for lines that are not blank.

if len(line) > 1:
        dn = line[4:-1]

Checking for existing accounts

As previously noted, it's important to ensure that you don't duplicate existing accounts when you import users from the LDAP repository into IBM Security Access Manager. User entries in IBM Security Access Manager have a secDN attribute with the value of the original distinguished name. The following code segment uses ldapsearch to look for an entry with the appropriate secDN value.

ret_val = call("ldapsearch -D " + ldap_dn +
        " -w " + ldap_pwd +
        " -h " + ldap_server +
        " -b " + ldap_sameb_base + " secDN=" + dn +
        " | grep numEntries > /dev/null",
        shell=True)

A return value of 1 indicates that grep failed, meaning that no LDAP entry matches the filter. In that case, the script imports the user, creating a new LDAP entity for the IBM Security Access Manager user information.

if (ret_val == 1):
        print "Need to import " + dn

Importing a new user

To import a user into IBM Security Access Manager you must specify the user's UID, the identifier that he or she uses to log on. The following lines retrieve that value:

call("ldapsearch -D " + ldap_dn +
        " -w " + ldap_pwd +
        " -h " + ldap_server +
        " -b " + dn +
        " objectClass=inetOrgPerson uid " +
        "| grep uid: >" + uid_file,
        shell=True)

This line reads the first line of the file:

   uid_f = open(uid_file, "r")
     uid = uid_f.read()
     uid_f.close()

Note that the above line specifies that the first five characters (uid: ) should be discarded. The remaining characters represent the actual attribute value.

uid = uid[5:-1]

Creating new accounts

Finally, the script creates the new accounts in IBM Security Access Manager using pdadmin:

call("pdadmin -a " + sameb_uid + " -p " +
        sameb_pwd + " user import " + uid +
        " " + dn,
        shell=True);
call("pdadmin -a " + sameb_uid + " -p " +
        sameb_pwd + " user modify " + uid +
        "account-valid yes ", shell=True)

Note that the script needs to issue the second command (user modify >uid< account-valid yes) because users created or imported by pdadmin are inactive by default.


In conclusion

In this article, I've introduced you to a Python script that makes it easy to import new users to IBM Security Access Manager. While the script doesn't provide all the flexibility of IBM Tivoli Directory Integrator, or the functionality of IBM Security Identity Manager (see Resources), it does have the advantage of being free.

Acknowledgments

I would like to thank Windayani Achmad Zaenullah for identifying the need for this article and Lance Clinton for reviewing it. Any remaining mistakes are my fault.


Download

DescriptionNameSize
Import python scriptautomatic_import_src.zip  ( HTTP | FTP | Download Director Help )---

Resources

Learn

Get products and technologies

  • IBM Tivoli Directory Integrator: Download a free trial version of IBM Tivoli Directory Integrator v7.1 and find out how you use it to enable consistent data across multiple identity or generic data resources.
  • IBM Security Identity Manager: Automate the creation, modification, recertification, and termination of user privileges throughout the user lifecycle.
  • Download Python.

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Security on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Security
ArticleID=947978
ArticleTitle=Import users from an LDAP directory to IBM Security Access Manager
publish-date=10152013