Monitoring FSMO Role Modifications

In my first article about using Windows Management Instrumentation (WMI) to monitor data in Active Directory (AD), I discussed three new WMI providers that let you monitor AD group modifications. I explained how WMI represents AD information (see "Using WMI to Monitor AD," April 2004, InstantDoc ID 41835), and I presented a scripting technique to monitor AD groups. In this article, I leverage that information to create a way to monitor modifications made to the five Flexible Single-Master Operation (FSMO) roles so that administrators can be notified when someone moves one of the five FSMO roles from one server to another.

Accessing FSMO Role Information The FSMO roles are the five crucial roles that one or more AD domain controllers (DCs) perform. For more information about FSMO roles, see "Determining Operations Masters in a Win2K Forest and Domain," February 2002, InstantDoc ID 23403.

The logic and coding techniques for monitoring the FSMO roles are similar to those I describe in the earlier article about monitoring AD groups, except that accessing the FSMO information isn't as straightforward as accessing the AD group information. To access the FSMO role information, you must concurrently access the three AD naming contexts (NCs), which requires a specific WMI setup at the level of the root\directory\LDAP namespace. By default, AD providers access AD information in the default NC, which is the Windows domain in which the accessed DC resides. However, the attributes containing the FSMO information are spread among all three AD NCs, so to monitor all FSMO roles, you must access the configuration and schema NCs too.

Table 1 lists the FSMO roles, their respective NC locations, and other important information about them. Each of the FSMO roles is stored in a different AD object class, whose WMI form appears in the WMI Class column in Table 1. The FSMO role is always stored in an attribute called fSMORoleOwner, which corresponds to a WMI property called ds_fSMORoleOwner. For those who prefer Active Directory Service Interfaces (ADSI) programming to WMI programming, the TechNet script at http://www.microsoft.com/technet/community/scriptcenter/compmgmt/scrcm24.mspx illustrates how to use ADSI to retrieve the FSMO information by accessing the Lightweight Directory Access Protocol (LDAP) objects listed in the AD Object DN column in Table 1. The TechNet script first retrieves the Schema Master FSMO role, then the Domain Naming Master, the PDC Emulator, the RID Master, and finally the Infrastructure Master. If you look at this code, you'll see that all FSMO roles are contained in an attribute called fSMORoleOwner, which contains the distinguished name (DN) of the DC that hosts these FSMO roles. This DN changes when someone has moved the FSMO to another DC. Thus, to detect an FSMO role modification, you simply have to monitor for DN changes contained in the FSMORoleOwner attribute. You can access the same information that the TechNet script does by using WMI; the challenge resides in accessing the configuration and schema NCs, which contain, respectively, the Domain Naming Master role (i.e., the LDAP crossRefContainer object) and the Schema Master role (i.e., the LDAP dMD object).

To enable WMI to access the crossRefContainer LDAP object in the configuration NC and the dMD LDAP object in the schema NC, you must first create an instance of the DN_Class and DSClass_To_DNInstance WMI classes in the root\directory\LDAP namespace. The DN_Class class encapsulates the DN of the NC that contains the FSMO role. The DSClass_To_DNInstance class associates a WMI class that represents the object that you want to find in an AD NC with an instance of that NC.

You can create these class instances by using a Managed Object Format (MOF— the native WMI file format for classes and class instances in the WMI repository) file, which the code in Listing 1 shows. As the code at callout A in Listing 1 shows, to locate a WMI ds_crossRefContainer instance in the configuration NC, you first create an instance of DN_Class that defines the NC, then you create an instance of DSClass_To_DNInstance and initialize its properties as follows:

The DSClass property is assigned the ds_crossRefContainer class instance name.

The RootDNForSearchAndQuery property is assigned the WMI path of the WMI instance that represents the configuration NC. The instance that represents the configuration NC is created from the DN_Class class described earlier.

As the code at callout B in Listing 1 shows, the MOF file uses the same creation and initialization process for the ds_dMD class, whose instance is in the AD schema NC.

Before you can monitor the FSMO roles, you need to load the MOF file into the Common Information Model (CIM) repository, which you can do by using WMI's MofComp utility. MofComp parses a file that contains MOF statements and adds the classes and class instances defined in the file to the CIM repository. To load the code that Listing 1 shows into the CIM repository, type the following command:

MofComp ForestFSMO.mof

Note that you don't have to specify the WMI namespace root\directory\LDAP in the command line to load the MOF file definition into the right location of the CIM repository. The MOF file explicitly defines the namespace, as the #pragma namespace command in Listing 1 shows, so the namespace is optional on the command line.

Monitoring FSMO Roles The script I created for the FSMO role-monitoring task, FSMOMonitor.wsf, is available at the Windows Scripting Solutions Web site. (Go to http://www.winnetmag.com/windowsscripting, enter InstantDoc ID 42101 in the InstantDoc ID text box, then click the 42101.zip hotlink.) Listing 2 shows an FSMOMonitor.wsf excerpt that implements the logic of the FSMO-role—monitoring technique. The logic and structure is similar to the group-monitoring code from the earlier article, so I won't repeat all the details here but will instead comment on some of the differences.

One major difference is the number of WMI Query Language (WQL) event queries the code submits. Instead of executing one such query, FSMOMonitor.wsf executes five WQL event queries (one per FSMO role). The WQL queries all have the same structure. To detect whether the examined AD object has had a change related to an FSMO role modification, the WQL event query compares the object property DS_fSMORoleOwner before the change (PreviousInstance.DS_fSMORoleOwner) with the object property DS_fSMORoleOwner after the change (TargetInstance.DS_fSMORoleOwner). Figure 1 shows the WQL event queries the script uses for the different FSMO roles.

After establishing a WMI connection, the script submits the five WQL event queries to WMI, as the code at callout B in Listing 2 shows. Note that each WQL query uses a WMI context object because the same event subroutine is used to capture all WMI events. The context is stored in a SWbemNamedValueSet object created at the beginning of the script. One SWbemNamedValueSet object is created per FSMO role, as the code at callout A in Listing 2 shows. You can get more information about the SWbemNamedValueSet object from http://msdn.microsoft.com/library/en-us/wmisdk/wmi/swbemnamedvalueset.asp. Before submitting each WQL event query, the code initializes each SWbemNamedValueSet object with a value specific to the monitored FSMO role. The subroutine that handles the WMI events has the same logic and structure as the code I used in the AD group-monitoring article except that the code first extracts the WMI context to determine which FSMO role the received event relates to, as the code at callout C in Listing 2 shows. The script then displays a message about the FSMO role that has been modified.

In the Real World In this article and "Using WMI to Monitor AD," I've shown that by leveraging the support of the three WMI AD providers, you can monitor AD for FSMO-role and group modifications. Although Microsoft might provide a different way to perform AD monitoring in future releases, the WMI AD providers are the only interfaces available for that purpose today. You can also track user creations and deletions in the same way. Thus, you could set up a two-forest Microsoft Exchange Server environment in which the mailbox forest is provisioned (i.e., a mailbox is created) when you create a user account in the account forest. Similarly, you could configure the mailbox forest to be deprovisioned (i.e., the mailbox deleted) when you delete a user account from the account forest. This setup requires more WMI and ADSI coding, but the two code samples I discussed in these two articles could serve as the foundation of this two-forest provisioning and deprovisioning script. Now the sky and your imagination are the limits! To your keyboards