Accomplishing the impossible
Many books and articles about the Active Directory (AD) schema—even from Microsoft—state that deleting classes or attributes from the AD schema is impossible. The supposed inability to delete from the schema presents problems for AD administrators because testing new schema extensions is difficult and removing unwanted extensions is unachievable. Suppose you want to test the schema-extension process in a test forest. If you encounter an error while testing the extensions, you'll want to retest them. However, because you can't delete them, you find that you must rebuild the forest. Or suppose you add extensions in a production forest that turn out to be faulty. You'd like to simply delete them, but you can't.
Now is the time to dispel the myth that deleting from the schema is impossible. Let's take a look at how to enable schema deletions and what precautions you must take before doing so.
A Little Background
The AD schema defines how AD represents and structures data. A basic understanding of the schema is essential for any AD administrator. A couple of excellent starting points for learning more about the schema are "Diving into the AD Schema," September 2001, http://www.winnetmag.com, InstantDoc ID 21839, and "Extending the AD Schema," November 2001, http://www.winnetmag.com, InstantDoc ID 22540.
Over the past couple of years, more and more applications have become directory-aware and are requiring that data reside in AD. In most cases, these applications require that you extend the AD schema to include custom classes and attributes. When you store data in AD, applications can use AD's distributed, multimaster architecture so that a separate replication mechanism isn't necessary for transferring data between application servers. Storing information in AD also makes the application data more accessible to end users and other applications.
Many IT departments extend the schema for their own use. For example, organizations that have a "white pages" application that internally publishes employee or customer information might need to extend the schema to support specific attributes that don't exist in the default AD schema. Suppose you need to add building name to each employee's user object. Because the default AD schema doesn't contain a building attribute, you must either create a new attribute or use an existing unused attribute for that purpose. The AD schema contains many useful attributes and classes, but most vendors and large organizations will need to add others to fully meet their applications' requirements. To make the most of AD's capabilities, you need to extend the schema.
Because extending the schema is such an essential task in AD, the ability to delete schema extensions can be extremely beneficial. Many people were disappointed that Microsoft neglected to support a means to delete schema extensions in Windows 2000. In Microsoft's defense, deleting attributes or classes from the schema is a highly sensitive operation that, if performed inappropriately, can have disastrous consequences in your AD environment.
If you delete a class and objects of that class still exist, AD might end up in an inconsistent state or objects might exist without a class definition. Although AD's multimaster replication architecture is beneficial, that architecture complicates the implementation of a robust schema-deletion process. You have no way to guarantee that an object isn't using a class or attribute before you delete that object. After you delete a class or attribute on a domain controller (DC), an application could create an object that uses that class or attribute on a DC that has yet to receive the deletion update.
Although Microsoft doesn't support the deletion of classes or attributes, you can deactivate them, much as you can disable a user account. The object will still exist in AD, but you can't use it to instantiate other objects and you can't use it in other class definitions. In Microsoft .NET, Microsoft has taken the deactivation functionality a step further by letting you redefine (i.e., recreate, as opposed to reactivate) deactivated classes or attributes, if necessary.
Benefits of Deleting from the Schema
You might wonder why deleting from the schema is important, particularly considering that Microsoft provides the deactivate function. The two most significant reasons why you might need to delete from the schema are to test new schema extensions and to remove unused classes and attributes.
Anyone who has developed schema extensions for AD understands that testing new extensions can be a painful process. Without the ability to remove schema extensions, the only way to repeatedly test modifications to extensions or the extension process itself is to use a different forest each time or rebuild the already-extended forest. For application developers, this process can be tedious.
A third benefit of deleting from the schema is to remove extensions that decommissioned applications have created. In most enterprises, applications come and go for a variety of reasons. More than likely, an application for which you've extended the schema will eventually be decommissioned or no longer used. Deleting from the schema lets you remove all traces of the application's existence in AD. Cleaning up the schema will become even more important over time, as the number of stale classes and attributes grows.
When you delete from the schema, you do so at your own risk. The schema-deletion process is still relatively untested, and problems might surface after further testing. Therefore, you need to take several precautions before you begin deleting from the schema.
Deleting from the Schema
Enabling schema deletions is a simple two-step process. First, you must modify the ACL on the Schema container (i.e., cn=Schema,cn=Configuration,ForestDN, where ForestDN is your forest's distinguished name—DN) to permit deletion of child objects. Second, you must enable schema updates.
Modify the ACL. Members of the Schema Admins group can use the Microsoft Management Console (MMC) ADSI Edit snap-in to modify the ACL. By default, neither Enterprise Admins nor Domain Admins members have the necessary rights to modify permissions on the Schema container.
In ADSI Edit, add an entry (if one doesn't already exist) for the Schema container that you want to edit in the forest. Expand the Schema container entry and right-click the folder labeled with the Schema container's DN, as Figure 1 shows. Click Properties and go to the Security tab. Select the group (e.g., Schema Admins) to which you want to grant the ability to delete from the schema. Then, under Permissions, select the Allow check box for Delete All Child Objects, as Figure 2 shows.
After you click OK, the permissions to delete from the schema will be enabled. You can also use the MMC Schema snap-in to perform this procedure, and you can use the Dsacl utility (available in the Support Tools kit) to automate it, if necessary.
Enable schema updates. Any type of schema update, including deletions, can be done only on the DC that has the Schema Flexible Single-Master Operation (FSMO) role and only after the registry has been updated on that DC to enable schema updates. The HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters registry subkey must have the value Schema Update Allowed (of type REG_DWORD) set to 1. To update this value, you can use a registry editor or select the Allow Schema Updates check box in the Schema snap-in.
You can delete schema objects in several ways. For example, you can use ADSI Edit or Ldp to delete them directly, as you would any other type of object. However, you have some restrictions regarding what objects you can delete and in what order you can delete them. For example, you can't delete an attribute if it's defined as part of the mayContain or mustContain attributes of a class, and you can't delete a class if it's defined as part of the subClassOf attribute for another class.
Deletions in Action
Possibly the most beneficial use of schema deletions is for testing or developing schema extensions in a test forest. You might need to extend and reextend the schema to test the extensions. The approach I recommend for extending the schema is to use LDAP Data Interchange Format (LDIF) files, which Internet Engineering Task Force (IETF) Request for Comments (RFC) 2849 describes. LDIF files are human-readable and have a well-defined format. Using LDIF files to update the schema gives you a simple, self-documenting schema-tracking mechanism that you can easily store and archive. Listing 1, page 67, shows a sample LDIF file called add.ldf that creates a new auxiliary class (xyz-ITUser) and two attributes (xyz-ITDeptName and xyz-ITBldg-Name). You can use the xyz-ITUser class to extend the user class to contain the two new attributes. This approach is common for extending an existing object class, such as user.
The code at callouts A and B in Listing 1 create the xyz-ITBldgName and xyz-ITDeptName attributes, respectively. The lines at callout C in Listing 1 update the schema cache. This cache update is necessary so that the xyz-ITBldgName and xyz-ITDeptName attributes can be specified as part of the xyz-ITUser class at callout D in Listing 1. The remainder of the file updates the schema cache, thereby committing the new class immediately.
You can use the Ldifde utility, available on any Win2K machine, to import and export LDIF files. To import the schema extensions from Listing 1, use the following command:
The -i switch enables import mode, the -v switch enables verbose output, and the -f switch specifies the filename of the LDIF file to import. To perform a similar test in your environment, replace DC=xyz,DC=com throughout Listing 1 with the DN of the forest you want to test. If you aren't running the Ldifde utility on the Schema FSMO DC, you'll need to use the -s switch to specify the host name of that DC.
Now that you have an LDIF file to add the schema extensions, you can create another LDIF file—delete.ldf—which contains the commands necessary to delete the extensions. Listing 2 contains the LDIF content necessary to delete the class and attributes that the code in Listing 1 created. Because of the deletion restrictions I mentioned earlier, you must delete the xyz-ITUser class (at callout A in Listing 2) before you can delete the attributes (at callouts B and C in Listing 2). Again, you can use Ldifde to run the LDIF file against a DC and remove the schema extensions:
As with Listing 1, you'll need to replace DC=xyz,DC=com throughout Listing 2 with the DN of the forest you're testing against.
Of course, LDIF isn't the only way to add, modify, or delete schema extensions. You can use ADSI Edit to perform such actions manually, or you can use Perl, VBScript, and other languages to do so programmatically.
The ability to delete from the schema opens up new possibilities for application developers and schema administrators, who typically need to build a new forest each time they test schema extensions. Deleting from the schema also lets administrators remove unused classes or attributes that might exist from a decommissioned application. However, doing so in a production forest requires extensive testing because it might produce undocumented side effects.