LDIF

 < Day Day Up > 



We were introduced to LDIF (LDAP data interchange format) in Chapter 2, when we played around with some of the LDAP command lines. We learned that LDIF is a way of representing the directory in a human-readable format. However, some questions remained open. For example, how do we use special characters required in some languages, such as the "umlaut" characters in German or binary data? In this section, we take a deeper look at the LDIF format.

The initial use of the LDIF format was for the University of Michigan Project, where LDIF was used to describe the entries held in the directory. Exhibit 18 shows a piece of our example directory dumped as an LDIF file. As you can see, it is the same format the command-line tool "ldapmodify -a" uses as input to load bulk data into the directory. The LDIF format is defined in RFC 2849, "The LDAP Data Interchange Format (LDIF) — Technical Specification." The file format now has two different purposes:

start figure

 dn: o=LdapAbc.org objectClass: top objectClass: organization o: LdapAbc.org dn: ou=IT,o=LdapAbc.org objectClass: top objectClass: organizationalUnit ou: IT dn: ou=HR,o=LdapAbc.org objectClass: top objectClass: organizationalUnit ou: HR dn: ou=Marketing, o=LdapAbc.org objectClass: top objectClass: organizationalUnit ou: Marketing dn: ou=Research, o=LdapAbc.org objectClass: top objectClass: organizationalUnit ou: Research dn: uid=RVoglmaier,ou=IT,o=LdapAbc.org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Reinhard Erich Voglmaier sn: Voglmaier givenName: Reinhard Erich ou: IT uid: RVoglmaier mail: RVoglmaier@LdapAbc.org 

end figure

Exhibit 18: A Piece of the Example Directory in LDIF Format

  • Description of directory entries

  • Update of directory entries

File Format

As the name suggests, LDIF is a data interchange format that provides a description of directory entries. Because LDIF is an ASCII format, the data can be exported easily from one directory and imported into another. With the data in ASCII format, the database can easily be transported over different architectures, e.g., from a directory running on Win2000 to UNIX. Furthermore, you can dump data from a legacy system or, indeed, from any repository, convert it into LDIF, and then import it into a directory.

The second purpose of LDIF is to describe the changes to be made to a directory. We used this capability in Chapter 2 when we applied the "ldapmodify" utility to change the directory. Exhibit 19 shows an example. Because there is a one-to-one relationship between the operations on the directory and the change-records defined in LDIF, you can use LDIF to describe the changes to be made to the directory.

start figure

 dn: uid=JParker, ou=IT, o=LdapAbc.org changetype: modify replace: mail mail: Jparker1@LdapAbc.org dn: uid=MJohnson, ou=Marketing, o=LdapAbc.org changetype: delete 

end figure

Exhibit 19: Example of LDIF File with Change Description

It is clear that the formats for the "description" and "update description" differ slightly. In the following, we will examine both formats in greater detail.

Description of Directory Entries

The LDIF file contains a dump of a number of entries. Each entry consists of a number of records, and each record is listed separately on a new line. Every entry consists of three parts:

  • The distinguished name that uniquely identifies the entry

  • The object class or object classes the entry belongs to

  • The attributes with their respective value or values

Exhibit 18 shows a real-life example of directory entries. Exhibit 20 is a formal representation of what an LDIF file describing directory entries should look like.

start figure

 dn: <Distinguished Name> objectClass: <ObjectClass> objectClass: <ObjectClass> ?.. <attribute name>: <attribute value> ??. 

end figure

Exhibit 20: Formal Definition of LDIF File— Description of Entries

There are a few exceptions to the described format of an LDIF file. For example, even though each record is separated by a new line, an attribute value could occupy more than one line. In this case, a white space at the beginning of a line indicates the continuation of the previous line. In LDAP parlance, this is called a "folded-attribute value." See Exhibit 21 for an entry containing a record with a folded-attribute value.

start figure

 version: 1 dn:cn=Barbara Jensen, ou=Product Development, dc=airius, dc=com objectclass:top objectclass:person objectclass:organizationalPerson cn:Barbara Jensen cn:Barbara J Jensen cn:Babs Jensen sn:Jensen uid:bjensen telephonenumber:+1 408 555 1212 description:Babs is a big sailing fan, and travels extensively   in search of perfect sailing conditions. title:Product Manager, Rod and Reel Division 

end figure

Exhibit 21: LDIF File with a Record Containing a Folded-Attribute Value (Example Copied from RFC 2849)

You also could have an entry containing binary data. Such data has to be encoded using base-64 encoding. There are libraries available for base-64 encoding for most programming and scripting languages. An entry containing a photo would look like the example in Exhibit 22. Instead of encoding the JPEG photo using base-64, you could also include an external file in the LDIF file. Exhibit 23 shows an example.

start figure

 dn: uid=JMiller,ou=IT,o=LdapAbc.org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Johann Miller sn: Miller givenName: Johann ou: IT jpegPhoto::V2hhdCBhIGNhcmVmdWwgcmVhZGVyIHlvdSBhcmUhICBUa  GlzIGlzIGJhc2UtNjQtZW5jb2RIZCBiZWNhdXNlIGl0IGhhcyBhIGNvbnRl  VyIGluIGl0IChhIENSKS4NICBCeSB0aGUgd2F5LCB5b3Ugc2hvdWxkIH  JlYWxseSBnZXQgyb2wgY2hhcmFjdGb3V0IGlvcmUu uid: JMiller mail: JMiller@LdapAbc.org 

end figure

Exhibit 22: LDIF File with a Record Containing a Base-64-Encoded Attribute Value

start figure

 dn: uid=JMiller,ou=IT,o=LdapAbc.org objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Johann Miller sn: Miller givenName: Johann ou: IT jpegPhoto: < file:///opt/directory/photos/jmiller.jpg uid: JMiller mail: JMiller@LdapAbc.org 

end figure

Exhibit 23: LDIF File with a Record Including a File Containing the Attribute Value

You can also use attributes with language-specific values. These attribute values then have to be UTF-8 encoded. UTF-8 (Unicode Transformation Format-8) is an encoding that produces human-readable strings. It is a standard encoding system defined by the Unicode Consortium. Users in the United States will seldom be bothered with data in different character sets. Luckily, the ASCII characters in UTF-8 are represented with the same 7-bit code as in ASCII. If you need more information, see RFC 2253, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names." For more information about the LDIF syntax, refer to RFC 2849, "The LDAP Data Interchange Format (LDIF) — Technical Specification."

Update of Directory Entries

Now let us have a look at the update description, the second form of an LDIF file. This second form describes the modification applied or to be applied to a directory. It reflects the actions upon the directory described by the functional model (see the functional model in Chapter 3 for additional details). The syntax of this LDIF format is quite similar to the one previously described. The encoding rules are the same, so they will not be repeated here.

Recall that the functional model knows three types of functions:

  1. Interrogation operations: search, compare

  2. Update operations: add, delete, modify DN, modify

  3. Authentication and control operations: bind, unbind, abandon

The functions used by the LDIF format are the update operations, i.e.,

  • The add function

  • The delete function

  • The modifyDN function

  • The modify function

The general syntax of these operations is:

 dn: <Distinguished Name> changetype: <Type of Operation> <attribute name>: <attribute value> <attribute value>... ... 

Let us see one example for each of these operations to get a better idea of what they look like. Here we use "Barbara Jensen" as an example, also called "Babs," which is also used for examples in the RFCs and in the LDAP literature.

The Add Function

The changeType "add" indicates that a new entry is to be added to the directory.

Syntax —

 dn: <Distinguished Name> changetype: add <attribute name>: <attribute value> <attribute value>... ... 

Example —

 dn: uid=BJensen, ou=IT,o=LdapAbc.org changetype: add objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson cn: Barbara Jensen cn: Babs Jensen sn: Jensen givenName: Barbara ou: IT jpegPhoto: < file:///opt/ directory/photos/BJensen.jpg uid: BJensen mail: Bjensen@LdapAbc.org 

The Delete Function

The changeType "delete" indicates that the entry with the DN has to be deleted from the directory.

Syntax —

 dn: <Distinguished Name> changetype: delete 

Example —

 dn: uid=CMiller, ou=IT,o=LdapAbc.org changetype: delete 

The modifyDN Function

The modifyDN function can:

  • Change only the RDN

  • Move the entry in the directory information tree

  • Both of the above

Note that in LDAP (v2), the moving of entries in the DIT is not allowed. You have to delete the old entry and create a new one instead of moving it.

Syntax —

 dn: <Distinguished Name> changetype: moddn [newsuperior: <Distinguished Name of new superior>] [deleteoldrdn:] (0 | 1) [newrdn: <new RDN>] 

Examples — Let us assume that Barbara Jensen moves from IT to Marketing. This calls for a change of the DN, a new superior entry, and removal of the old entry. The resultant changes in the LDIF file are as follows:

 dn: uid=BJensen, ou=IT, o=LdapAbc.org changetype: moddn newrdn: uid=Bjensen newsuperior: ou=Marketing, o=LdapAbc.org deleteoldrdn: 1 

The new DN of Barbara Jensen is now: uid = Bjensen, ou = Marketing, o = LdapAbc.org

Now let us see an example where the RDN changes. For example, we have a new person that would have a uid in conflict with an existing one. Let us assume there will be a new person — Joseph Smith, uid = JSmith — and that there is already a uid "JSmith" from a person "James Smith." Let us further assume that the IT department will avoid future conflicts by naming the new JSmith as JSmith1 and the original as JSmith0. To make the change in the directory, we would say:

 dn: JSmith, ou=Marketing, o=LdapAbc.org changetype: moddn deleteoldrdn: 1 newrdn: JSmithl 

One word about renaming an entry that has children. This action would require renaming an entire subtree. If you would like to do this via ldapmodify, you have to do this in three steps:

  1. Create a new entry with the new DN

  2. Change the RDN of all children

  3. Delete the old DN

Again, an example makes this clear. Let us assume that Human Resources is to be changed to HR (perhaps to avoid typos).

 dn: ou=HR, o=LdapAbc.org changetype: add objectclass: top objectclass: organizationalUnit ou: HR dn: PSmith, ou=Human Resources, o=LdapAbc.org changetype: modrdn newrdn: PSmith deleteoldrdn: 1 newsuperior: ou=HR, o=LdapAbc.org dn: ou=Human Resources, o=LdapAbc.org changetype: delete 

The second step you have to do for all children. If the children have further children, you have to create down the hierarchy all entries having children, rename the children, and delete the old entries. If you have an extensive subtree, this can become painful. The alternative is to export the whole directory, rename all "ou = Human Resources" into "ou = HR," physically delete the old directory files, and import the new directory. We will see more about this in Chapter 7, "LDAP Directory Server Administration."

The Modify Function

The modify function changes the attributes of an entry in the directory. Thus, there are three different types of modification:

  1. Add an attribute

  2. Delete an attribute

  3. Replace an attribute

Syntax —

 dn: <Distinguished Name> changetype: modify <modify type> <attribute> [<attribute name> <attribute value> ? ] 

Examples — The following example shows the addition of a mobile attribute to the entry with distinguished name JSmith1, ou = Marketing, o = LdapAbc.org.

 dn: JSmithl, ou=Marketing, o=LdapAbc.org changetype: modify add: mobile mobile: 0170 64738 8374 377 

The following would change the new assigned number:

 dn: JSmith1, ou=Marketing, o=LdapAbc.org changetype: modify replace: mobile mobile: 0170 64738 8374 477 

The following would delete the number again:

 dn: JSmithl, ou=Marketing, o=LdapAbc.org changetype: modify delete: mobile 

LDIF: Conclusion, an Example in Perl

One common task is synchronizing the directory with a database or some other data source. The data source provides a listing of all entries, and this list can be used to update the directory so that the LDAP database reflects the new data.

The first approach is to look up every entry to see if it exists and verify that the values are still the same. This entails sending all the data over the network to the directory so that the values can be compared with those held in the directory. If the number of employees in your enterprise is not too high (several hundred), this could be a reasonable solution. However, it can be problematic if there are any restrictions on the queries you can make against the directory.

Another alternative is to obtain a dump of the entries in a plain file, e.g., database.txt. When the sync request arrives, you rename the old file database.old.txt and produce, via the diff system call or a customized utility, an instruction list that updates the directory. This instruction list can then be printed out in the LDIF format. In order to do this you need three functions:

  1. deleteEntry: Deletes an entry from the directory

  2. addEntry: Adds a new entry to the directory

  3. modEntry: Modifies an entry in the database

The Perl functions shown in Exhibit 24 generate an LDIF file that reflects these changes in the directory. The first function that we need is the addEntry function, which takes an associative array as a parameter. The array contains the attribute names as keys.

start figure

 sub addEntry {      my ($EntryPtr) = $_ ;      my %Entry = %{EntryPtr} ;      my @objectClasses = ("top,""organizationalPerson","inetOrgPerson");      printf("dn: uid = %s, ou=%s, o=%s\n",$Entry{uid}, $Entry{ou}, $Entry{o}) ;      printf("changetype: add\n");      foreach $class (@objectClasses) {           printf("objectClass: %s\n",$class);      }      printf("sn: %s\n",$Entry{sn});      printf("cn: %s %s\n",$Entry{givenName}, $Entry{sn});      printf("givenName: %s\n", $Entry{givenName});      printf("ou: %s\n",$Entry{ou});      printf("telephoneNumber: %s\n", $Entry{phone});      printf("mail: %s\n",$Entry{mail});      printf("uid: %s\n",$Entry{uid}) ;      printf("\n\n"); } 

end figure

Exhibit 24: Perl Function that Produces LDIF Output to Add an Entry into the Directory

The second function that we need is the delEntry function. The simplest of the three, it is as follows:

 sub delEntry {           my ($EntryPtr) = $_ ;           %Entry = %{$EntryPtr} ;       printf("dn: uid = %s, ou=%s, o=%s\n",$Entry{uid}, $Entry{ou}, $Entry{o}) ;           printf("changetype: delete\n"): } 

The third function, modEntry, is something different. To handle all possible situations while keeping the code simple, it first deletes the entry and then adds the entry with the new values:

 sub modEntry {           my ($EntryPtr) = $_ ;           delEntry($EntryPtr);           addEntry($EntryPtr) ; } 

What is missing is a program uniting all of these operations: First, we define the values needed for all three functions, in this case only the name of the enterprise. The program then loads the ASCII file of the directory data in an associative array. Then we execute a function that looks to see whether the values of the attributes in the entries and the database are the same. For each "yes," it deletes the corresponding row in the associative array. If there is a discrepancy, it calls the function "modEntry" to resolve the discrepancy and then deletes the row in the associative array. If there is no line corresponding to the entry, it calls the function "addEntry." After processing all entries, the program looks to see whether there are any rows remaining in the associative array. If there are, then this indicates that some of the entries have been deleted in the data source. To deal with these lines, the program then calls the "delEntry" function. Exhibit 25 shows the code to perform all of these functions.

start figure

 %DirectoryEntries = getDirectoryEntries(); %NewEntries = getNewEntries(); foreach $dn (keys %NewEntries)) {         if (! $DirectoryEntries{$dn}) {              addEntry($DirectoryEntries{$dn}) ;         } else {              if ( $DirectoryEntries{$dn} == $NewEntries{$dn}) {                   delete($DirectoryEntries{$dn}) ,              } else {                   modEntry($DirectoryEntries{$dn}) ;                   delete($DirectoryEntries{$dn}) ;              }         } } foreach $dn (keys % DirectoryEntries) {              delEntry($NewEntries($dn)) ; } putDirectoryEntries(%NewEntries); 

end figure

Exhibit 25: Main Perl Function to Produce LDIF Output

The functions still missing are getDirectoryEntries and its counterpart putDirectoryEntries. These could be functions that simply write down and read the entries in the form "key: value." The key is then used for the lookup. Another function that is missing is the one that produces the NewEntries hash or associative array, which should have the same syntax as the two previously mentioned functions. It could also be interesting to use objects instead of these hashes. In this case, the addEntry, delEntry, and modEntry functions could be implemented as methods.

The program logic also works if we simply install all entries new from scratch. In this case, the hash DirectoryEntries is empty, so the statement:

 if (! $DirectoryEntries{$dn} 

is always true and the entry is added.

The program produces a file in the LDIF format that can be used to update the directory with the command "ldapmodify."

Just for completeness, the Net::LDAP package has an object called Net::LDAP::LDIF that reads and writes a complete LDIF file in a single step. Have a look at the Web site dedicated to the perl package or consult the documentation delivered with the software distribution. Software and documention are available at the Net::LDAP project site: http://perl-ldap.sourceforge.net.



 < Day Day Up > 



The ABCs of LDAP. How to Install, Run, and Administer LDAP Services
The ABCs of LDAP: How to Install, Run, and Administer LDAP Services
ISBN: 0849313465
EAN: 2147483647
Year: 2003
Pages: 149

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net