At the time of this writing, Net::LDAP 0.29 was the latest version, so the script ImportLdapFile.pl, which Listing 1 shows, uses this version. To determine which Net::LDAP version (if any) is installed on your machine, run the command
perl -MNet::LDAP -e "print
$Net::LDAP::VERSION"
(Although this command appears on two lines here, you would enter it on one line on the command line. The same holds true for the other multiline commands in this article.)
Understanding the Script
ImportLdapFile.pl provides a template from which you can learn the basic steps to extend the schema by importing an LDIF file. This script handles input from the command line, retrieves the Schema container's DN, verifies the LDIF file's schema extensions to ensure the file imports correctly, and imports the file.
Step 1: Handling command-line input. The code at callout A in Listing 1 makes sure that users provide four parameters when they launch the script from the command line. The first parameter must be the name or IP address of the DC that has the Schema Flexible Single-Master Operation (FSMO) role. The second parameter must be the user principal name (UPNe.g., administrator@rallencorp.com) or DN (e.g., cn=administrator,cn=users,dc=rallencorp,dc=com) of a user in the Schema Admins group. The third parameter must be the user's password. The fourth parameter must be the path to the LDIF file. When all four parameters are present, the script stores them in the $server, $user, $passwd, and $ldif_file variables, respectively. If one or more parameters are missing, the script returns an error message and quits.
Step 2: Getting the Schema container's DN. Using the name and password specified on the command line, the code at callout B employs the Net::LDAP module to connect and bind to the specified server. The script then performs a search against the RootDSE object to retrieve the schemaNamingContext attribute's value, which is the Schema container's DN.
Step 3: Verifying the schema extensions. The code at callout C uses the retrieved DN to open and read the specified LDIF file, then verifies the schema extensions. The script opens the file with the Net::LDAP::LDIF module's new() method, which takes three parameters. The first parameter is the path to the LDIF file, which the $ldif_file variable provides in this case. The second parameter indicates whether to read ("r") or write ("w") to the file. ImportLdapFile.pl is configured to read the LDIF file because the script is importing the file's contents. If you write a script to export an LDIF file's contents, you would use "w" as the parameter. The third parameter, called onerror, determines what happens if the Net::LDAP::LDIF module's read_entry() method (which the script uses to read the LDIF file) encounters an error. The script sets onerror to 'undef', which means that the read_entry() method will return the value undef if it encounters an error. If you prefer to have the script print out an error message and terminate if an error occurs, you can set onerror to 'die'. If you want the script to only print out an error message, you can set onerror to 'warn'.
After opening the LDIF file, the script uses the read_entry() method in a while loop to read each LDIF entry. If the script finds an error while reading an entry, the script exits the loop. When no error occurs, the script performs a search in AD. When the LDIF entry's changetype line specifies add, the search verifies that the object to be added doesn't already exist. If the entry exists, the script reports an error. When the changetype line specifies modify or delete, the search verifies the existence of the object to be modified or deleted. If the object doesn't exist, the script reports an error.
The Net::LDAP::LDIF module's eof() method returns true when the loop reaches the end of the file. At that point, assuming that no errors occurred, the script prints the message Verification complete. If errors occurred, the script aborts.
Step 4: Importing the LDIF file. When the verification process in Step 3 is successful, ImportLdapFile.pl imports the LDIF file in AD, as the code at callout D shows. Like the verification code, the import code uses the new() method to open the LDIF file and uses the read_entry() method in a while loop to read each entry in the file. When no read errors occur, the script calls the update() method. This method submits class and attribute additions and modifications to the AD schema. The while loop continues until the end of the file unless the code() method returns a value, indicating that an error occurred during the update process. In that case, the script aborts.
If you want to use ImportLdapFile.pl to import an LDIF file like that in Figure 1, I highly recommend that you do so in a test forest first. You should never use LDIF or any other tool to extend the schema in a production forest until you thoroughly test the schema extensions. To import the LDIF file in Figure 1 into your forest, you need to customize that file, including replacing dc=rallencorp,dc=com in the DN with your forest's root domain.
You don't need to customize any code in ImportLdapFile.pl because you specify all the customized information on the command line. For example, the following command imports the LDIF file C:\myldif.ldf into the schema on a DC named dc01 while running under the administrator user account, which has the password xyz123:
perl ImportLdapFile.pl dc01
administrator@rallencorp.com
xyz123 c:\myldif.ldf
After the script successfully finishes, you should verify the changes in AD. You can view the classes and attributes you added or modified in the Microsoft Management Console (MMC) Schema Manager snap-in.
The Basics and Beyond
You should now understand the LDIF basics and how to use the Net::LDAP modules to automate importing LDIF files to extend the schema. With this basic understanding, you can adapt ImportLdapFile.pl to meet your needs. For example, you might make the verification portion of the script more robust by adding more elaborate checks. Or you might expand the script's capabilities through such tools as the Schema Manager snap-in or the Ldifde utility. Ultimately, by automating the schema verification and extension process, you should have more peace of mind about extending the schema and allowing applications to take advantage of AD's power.