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
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.
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
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
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.
Normally, Python lines that start with a number sign (
#) are comments.
This line in Listing 1 is a special case, however. The
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.
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
# 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
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"
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
inetOrgPerson, which is used to
represent people. It reads only their distinguished name and sends the
output to a file called
ldapsearch -LLL -D cn=root -w object00 -b ou=people,o=xyz -h localhost objectclass=inetOrgPerson dn > ldapusers
Next, the script opens the
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:
. The first four characters are
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
secDN attribute with the value of the
original distinguished name. The following code segment uses
ldapsearch to look for an entry with the
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
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
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 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.
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.
|Import python script||automatic_import_src.zip ( HTTP | FTP | Download Director Help )||---|
- "IBM Security Access Manager unboxed" (developerWorks, January 2013): Get up and running with IBM Security Access Manager for Web. This series of four videos demonstrates how to install the virtual machine, configure the command-line interface, and create a reverse proxy.
- IBM Identity Management and Access Management Solutions: Get an overview of IBM security solutions for identity and access management.
"Application development in Python with ibm_db:" Get started with Python functions for accessing and manipulating data in an IBM data server database via the
- "Discover Python, Part 8: Reading and writing data using Python's input and output functionality" (developerWorks, January 2006): Learn more about the many uses of Python.
- Introduction to Computer Science: Try a free online course teaching new programmers how to write a web crawler using Python.
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.
Dig deeper into Security on developerWorks
Get samples, articles, product docs, and community resources to help build, deploy, and manage your cloud apps.
Experiment with new directions in software development.
Software development in the cloud. Register today to create a project.
Evaluate IBM software and solutions, and transform challenges into opportunities.