|[ Team LiB ]|
4.5 Adding the Initial Directory Entries
A directory without data isn't of much use. There are two ways to add information to your directory; which method to use depends on the directory's state. First, slapadd and the other slap* commands were presented in Chapter 3 as database maintenance tools. They allow an administrator to import entries directly into the database files and export the entire directory as an LDIF file. They work directly with the database, and don't interact with slapd at all. Second, the OpenLDAP distribution includes a number of tools, such as ldapmodify, that can update a live directory using the LDAPv3 network operations. These tools access the directory through the server.
What are the advantages and disadvantages of these approaches? The offline tools can be much faster; furthermore, there are circumstances when you can't start the server without first adding data (for example, when restoring the directory's contents from a backup). The disadvantage of the offline tools, of course, is that they must be run locally on the server.
In contrast to the offline tools, the LDAP client utilities are more flexible and allow a directory administrator greater control by forcing user authentication and by using access control lists on directory entries. A good rule of thumb is that the slap* tools are used for getting your LDAP server online, and the ldap* tools are for day-to-day administration of the directory.
The tools for offline manipulation of directory information are slapadd, slapcat, slapindex, and slappasswd (covered in Chapter 3). The slapadd tool determines which files and indexes to update based on the slapd.conf file. Because it is possible for a given configuration file to define more than one database partition, slapadd provides options for specifying a database partition by either the directory suffix (-b suffix) or the numbered occurrence (-n integer) in slapd.conf. Referring to a particular database using a numbered instance is confusing and error-prone. It is far more intuitive to refer to the same database by using the directory suffix. Note that the -b and -n options are mutually exclusive. A summary of the various slapadd command-line options is provided in Table 4-2.
The slapcat utility dumps the contents of an entire directory (including persistent operational attributes such as modifyTimeStamp) in LDIF format. The command-line options for slapcat are identical to the options for slapadd (Table 4-2), except that the -l switch specifies an output filename instead of an input filename. In the absence of this switch, slapcat writes all entries to standard output. slapcat can provide a useful means of backing up the directory. Unlike the actual DBM datafiles, which are machine- and version-dependent, LDIF is very portable and allows easier editing in case of corrupted data. I don't mean to discourage you from backing up the DBM files, but you could do worse than backing up the directory in both forms.
The slapindex command can be used to regenerate the indexes for a bdb backend. This might be necessary if a new index was added to slapd.conf after the directory was populated with entries. The slapindex tool shares the same command-line options as slapadd, with the exception of -l. The -l option isn't used for slapindex because neither an input nor an output file is needed.
To start populating your directory, create a file containing the LDIF entries of the top-level nodes. These LDIF entries build the root node and the people organizational unit.
## Build the root node. dn: dc=plainjoe,dc=org dc: plainjoe objectClass: dcObject objectClass: organizationalUnit ou: PlainJoe Dot Org ## Build the people ou. dn: ou=people,dc=plainjoe,dc=org ou: people objectClass: organizationalUnit
Assuming that these entries are stored in a file named /tmp/top.ldif, you can add them to the directory by executing:
root# slapadd -v -l /tmp/top.ldif added: "dc=plainjoe,dc=org" (00000001) added: "ou=people,dc=plainjoe,dc=org" (00000002)
The output indicates that the entries were added successfully.
4.5.1 Verifying the Directory's Contents
After the directory server has started, you can use ldapsearch to query the server. ldapsearch allows you to dig through your directory, test for the existence of data, and test whether access control has been set up correctly.
OpenLDAP's ldapsearch began life as a simple wrapper for the LDAP search operation. The list of search possibilities is lengthy; I won't cover it until Chapter 5. For now, I will focus on very simple searches that assure you the directory is up and running correctly. In its simplest form, a query requires the following information:
We'll start with a "Show me everything" search. Here, you ask the directory to return all entries that have a value for the objectClass attribute (which is all entries).
$ ldapsearch -x -b "dc=plainjoe,dc=org" "(objectclass=*)" version: 2 # # filter: (objectclass=*) # requesting: ALL # # plainjoe,dc=org dn: dc=plainjoe,dc=org dc: plainjoe.org objectClass: dcObject objectClass: organizationalUnit ou: PlainJoe Dot Org # people,dc=plainjoe,dc=org dn: ou=people,dc=plainjoe,dc=org ou: people objectClass: organizationalUnit # Search result search: 2 result: 0 Success # numResponses: 3 # numEntries: 2
The surprising thing about this command is that it doesn't explicitly contain most of the items that I said were necessary for any search. In fact, the only two items that we can clearly see are the search base and the search filter. What's going on? Let's look at the missing items one at a time:
The default values for many LDAP client parameters can be controlled via the system-wide ldap.conf configuration file (located in the same directory as slapd.conf) or the user-specific version in $HOME/.ldaprc. For more details, refer to the ldap.conf(5) manpage. Our examples explicitly list all parameters required by the command-line tools unless the compile-time defaults can be used, which was the case in the previous ldapsearch listing.
4.5.2 Updating What Is Already There
Eventually, the information stored in a directory will need to be updated or deleted. While a directory isn't designed to be updated as frequently as a database, there are very few applications in which the data never changes. This section covers how to update the data in the directory using ldapmodify. The name ldapmodify is a little misleading; this utility can add new entries and delete or update existing entries using some of the advanced features of LDIF for its input language.
The following LDIF listing defines two entries that we will add to our directory:
## filename: /tmp/users.ldif ## LDIF entry for "Gerald W. Carter" dn: cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org cn: Gerald W. Carter sn: Carter mail: email@example.com mail: firstname.lastname@example.org labeledURI: http://www.plainjoe.org/ roomNumber: 1234 Dudley Hall departmentNumber: Engineering telephoneNumber: 222-555-2345 pager: 222-555-6789 mobile: 222-555-1011 objectclass: inetOrgPerson ## LDIF entry for "Jerry Carter" dn: cn=Jerry Carter,ou=people,dc=plainjoe,dc=org cn: Jerry Carter sn: Carter mail: email@example.com telephoneNumber: 555-123-1234 objectclass: inetOrgPerson
The following command shows how to add these entries to the directory while it is running. Because write privileges are required to add new entries, ldapmodify binds to the directory using the credentials from the rootdn and rootpw slapd.conf parameters.
$ ldapmodify -D "cn=Manager,dc=plainjoe,dc=org" -w secret \ > -x -a -f /tmp/users.ldif adding new entry "cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org" adding new entry "cn=Jerry Carter,ou=people,dc=plainjoe,dc=org"
The output indicates that both entries were added successfully. The -D, -w, and -x options to ldapmodify should be familiar; they specify the DN to use for the modification, specify the password for the modification, and request simple authentication, respectively. This leaves only two new options to discuss:
ldap_add: Invalid syntax additional info: value contains invalid data
There are two common causes of this error message. You may have forgotten to include all the necessary schema files in slapd.conf, or you may have extra whitespace at the end of line in the LDIF file. The set list command in vi can help you track down extra whitespace.
Refer again to Table 4-3 for a list of the common options for all of these ldap client tools. Table 4-5 lists those options specific to ldapmodify and ldapadd. Note that ldapadd and ldapmodify are the same executable; ldapadd is only a hard link to ldapmodify. The commands differ only in their default behavior, which depends on the name by which the program was invoked.
Now let's see how a modification works. Suppose you want to add a URL to the entry for cn=Jerry Carter,ou=people,dc=plainjoe,dc=org. To add a URL, use the labeledURI attribute:
In addition, you should delete the firstname.lastname@example.org email address for "Gerald W. Carter" because it has become invalid. You can place both changes in a single LDIF file:
## /tmp/update.ldif ## Add a web page location to Jerry Carter. dn: cn=Jerry Carter,ou=people,dc=plainjoe,dc=org changetype: modify add: labeledURI labeledURI: http://www.plainjoe.org/~jerry/ ## Remove an email address from Gerald W. Carter. dn: cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org changetype: modify delete: mail mail: email@example.com
This LDIF file tells ldapmodify what changes to make. We'll invoke ldapmodify with the verbose (-v) option so you can follow the update operations more closely. The -a option isn't needed because you're not adding new entries.
$ ldapmodify -D "cn=Manager,dc=plainjoe,dc=org" -w secret > -x -v -f /tmp/update.ldif ldap_initialize( <DEFAULT> ) add labeledURI: http://www.plainjoe.org/~jerry/ modifying entry "cn=Jerry Carter,ou=people,dc=plainjoe,dc=org" modify complete delete mail: firstname.lastname@example.org modifying entry "cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org" modify complete
Notice that the LDIF file is parsed sequentially from the top. Therefore, later LDIF entries can modify entries created previously in the file. You can also create an LDIF file with entries having different changetype values. For example, the follow LDIF file adds an entry for user Peabody Soup, adds a new telephoneNumber to Jerry Carter's entry, and finally deletes the previously created entry for Peabody Soup.
## /tmp/changetypes.ldif ## Add entry for Peabody Soup. dn: cn=Peabody Soup,ou=people,dc=plainjoe,dc=org changetype: add cn: Peabody Soup sn: Soup objectclass: inetOrgPerson ## Add new telephoneNumber for Jerry Carter. dn: cn=Jerry Carter,ou=people,dc=plainjoe,dc=org changetype: modify delete: telephoneNumber telephoneNumber: 555-123-1234 - add: telephoneNumber telephoneNumber: 234-555-6789 ## Remove the entry for Peabody Soup. dn: cn=Peabody Soup,ou=people,dc=plainjoe,dc=org changetype: delete
A couple of facts about this LDIF file are worth mentioning:
The modify changetype supports add and delete keywords for adding and deleting attribute values. In order to delete the value of an attribute, the delete: must immediately be followed by an attributetype:value pair. It's necessary to specify the value you're deleting because some attributes can hold multiple values. Specifying which value to remove eliminates any ambiguity about what you want to do. When the last value of an attribute is removed from an entry, that attribute is no longer present in the entry.
Here's how to apply this second set of changes to the directory. Again, we've specified the -v option to see how ldapmodify processes the LDIF file.
$ ldapmodify -D "cn=Manager,dc=plainjoe,dc=org" -w secret -x -v -f /tmp/changetype.ldif ldap_initialize( <DEFAULT> ) add cn: Peabody Soup add sn: Soup add objectclass: inetOrgPerson adding new entry "cn=Peabody Soup,ou=people,dc=plainjoe,dc=org" modify complete delete telephoneNumber: 555-123-1234 add telephoneNumber: 234-555-6789 modifying entry "cn=Jerry Carter,ou=people,dc=plainjoe,dc=org" modify complete deleting entry "cn=Peabody Soup,ou=people,dc=plainjoe,dc=org" delete complete
Modifying the RDN of an entry takes a little more thought than adding an entry or changing an attribute of an entry. If the entry is not a leaf node, changing its RDN orphans the children in the directory because the DN of their parent has changed. You should make sure that you don't leave orphaned nodes in the directory—you should move the nodes with their parent or give them a new parent. With that in mind, let's think about how to change the RDN of the entry:
dn: cn=Jerry Carter,ou=people,dc=plainjoe,dc=org
from cn: Jerry Carter to cn: Gerry Carter. Here's the LDIF file that makes the changes:
## /tmp/modrdn.ldif ## Change the RDN from "Jerry Carter" to "Gerry Carter." dn: cn=Jerry Carter,ou=people,dc=plainjoe,dc=org changetype: modrdn newrdn: cn=Gerry Carter deleteoldrdn: 1
$ ldapmodrdn \ > "cn=Jerry Carter,ou=people,dc=plainjoe,dc=org" \ > "cn=Gerry Carter"
Not counting the DN of the entry to be changed and the new RDN value, the ldapmodrdn tool has three command-line options besides those common to the other OpenLDAP client tools (Table 4-3). These additional options are listed in Table 4-6.
If an entire subtree of the directory needs to be moved, a better solution may be to export the subtree to an LDIF file, modify all occurrences of the changed attribute in all the DNs, and finally re-add the subtree to the new location. Once the information has been entered correctly into a location, you can then use a recursive ldapdelete to remove the old subtree.
ldapdelete possesses all of the command-line options common to ldapsearch and ldapmodify. The only new option is -r (recursive), which deletes all entries below the one specified on the command line, in addition to the named entry. Note that this deletion is not atomic; entries are deleted individually. The following command deletes the entire ou=people subtree:
$ ldapdelete -D "cn=Manager,dc=plainjoe,dc=org" -w secret -x \ > -r -v "ou=people,dc=plainjoe,dc=org" ldap_initialize( <DEFAULT> ) deleting entry "ou=people,dc=plainjoe,dc=org" deleting children of: ou=people,dc=plainjoe,dc=org deleting children of: cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org removing cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org cn=Gerald W. Carter,ou=people,dc=plainjoe,dc=org removed deleting children of: cn=Gerry Carter,ou=people,dc=plainjoe,dc=org removing cn=Gerry Carter,ou=people,dc=plainjoe,dc=org cn=Gerry Carter,ou=people,dc=plainjoe,dc=org removed Delete Result: Success (0)
Now that you have a working directory, a good exercise would be to experiment with various ACLs to restrict access to certain attributes. This exercise will also help you become more comfortable with the tools presented in this chapter. Use the slapcat tool to dump the directory to an LDIF file and start over from scratch until you are comfortable with adding, deleting, and modifying entries. The next chapter explores creating a distributed directory, replicating information to multiple servers, more searching techniques, and some advanced ACL configurations.
|[ Team LiB ]|