Archive | Active Directory RSS feed for this section

Key Management Service (KMS) Commands Everyone Must Know

There are several commands I use often with Microsoft’s Key Management Service.  Normally, when a server is joined to the domain, there is almost never an issue with KMS.  That’s because KMS advertises through DNS, and if a server is joined to the domain, it’s likely pointed at the right DNS servers to pick up the KMS advertisement.

However, sometimes I have a server in the DMZ that is not domain joined, and is also not using AD-based DNS servers.  Alternatively, I might have a server on the local IT network, and even be using the AD-based DNS servers, but through a combination of sysprep, not being domain-joined, being off for a while or a whole host of other related circumstances it’s just not picking up the KMS advertisement.

The first command specifies a specific KMS server and port, which works great in the first circumstance:

slmgr.vbs /skms <value>:<port>

Note that the default port of KMS is TCP 1688

…for the second situation, oftimes you just need to clear KMS so that it gets set back to automatic:

slmgr.vbs /ckms

…and other times, you may have used a retail key during installation, and need to get it set back to a specific volume license key, in that situation, use:

slmgr.vbs /ipk [Volume License Key]

Finally, the following command will show you a nice screen shot of what is actually happening with activation and if there are any problems with activation:

Slmgr.vbs /ato

That’s it!  Between those three commands you can likely get any modern windows client/server to pick up the KMS instance on your domain and know exactly what’s going on with it.

Advertisements

Active Directory: Right-Click to Update Employee ID & Employee Number in Active Directory Users & Computers

Due to a recent acquisition, I needed to give the helpdesk a good way to update the employeeID and employeeNumber fields in the properties of various user accounts.  As these two properties are not natively accessible from Active Directory Users & Computers, my choice was to either give them access to ADSI Edit (love them, but not going to happen) or figure out a way to add those fields to ADUC.

I ended up finding an elegant way to add them as choices when right-clicking on a user account (just like you would to reset a password).  This is a simple, quick way to extend functionality without trying to write a .Net app (something I suck at).

First, you’ll create two files names employeeID.vbs and employeeNumber.vbs (code at the end of this article).  While you could place these scripts anywhere, I found it handy to add them to directory called aduc in the Netlogon directory for our domain:

\\domain\sysvol\DOMAIN\scripts\aduc

This gives everyone access to them.  Keep in mind that while a user will have access to them, they won’t do them any good unless they have permissions to modify directory objects.

Second, you need to open ADSI Edit and edit the following key:

CN=user-Display,CN=409, CN=DisplaySpecifiers, CN=Configuration

Look for the adminContextMenu and add the following to it.  Be careful here and make sure it is exactly as it is shown below, spaces and all:


2, Employee &ID, \\DOMAIN\sysvol\DOMAIN\scripts\aduc\employeeID.vbs
3, Employee &Number, \\DOMAIN\sysvol\DOMAIN\scripts\aduc\employeeNumber.vbs

Remember to replace DOMAIN with your actual domain name.

Once that key is updated, you’ll need to wait a bit for replication to occur if you have a wide area network.

That’s it, now just launch a fresh copy of Active Directory Users & Computers, right click on a user account, and you should see “Employee ID” and “Employee Number” listed.

If you get a pop up script warning when you click on one of them, you’ll need to add your Active Directory domain name to your list of Intranet sites in Internet Explorer (Security Tab in Internet Options, Local Intranet properties, then click Advanced to add the domain name).

Here are the scripts.  Enjoy!


=================employeeID.vbs=================
 Option Explicit
 Dim wshArguments, objUser, objSchemaEmployeeID, strCurrentID, strEmployeeID, intMaxLen
 On Error Resume Next
 Set wshArguments = WScript.Arguments
 Set objUser = GetObject(wshArguments(0))
 Set objSchemaEmployeeID = GetObject(LDAP://schema/employeeID)
 intMaxLen = objSchemaEmployeeID.MaxRange
 If objUser.employeeID  "" Then
 strCurrentID = objUser.employeeID
 Else
 strCurrentID = "empty"
 End If
 strEmployeeID = InputBox( _
 "The current Employee ID is " & strCurrentID & vbCrLf & _
 vbCrLf & _
 "Enter the new Employee ID (1 through " & intMaxLen & " chars)", _
 Right(objUser.Name, Len(objUser.Name) - 3) & " Employee ID", _
 objUser.employeeID)
 If strEmployeeID = "" Then WScript.Quit 'User clicked Cancel
 If Len(strEmployeeID) > intMaxLen Then
 MsgBox "The new Employee ID was too long and it was not saved.", _
 vbCritical, "Error Occurred"
 Else
 Err.Clear
 objUser.employeeID = strEmployeeID
 objUser.SetInfo
 If Err Then MsgBox "The new Employee ID was not saved.", _
 vbCritical, "Error Occurred"
 End If
 ===============================================

 


==============employeeNumber.vbs===============
 Option Explicit
 Dim wshArguments, objUser, objSchemaEmployeeNumber, strCurrentID, strEmployeeNumber, intMaxLen
 On Error Resume Next
 Set wshArguments = WScript.Arguments
 Set objUser = GetObject(wshArguments(0))
 Set objSchemaEmployeeNumber = GetObject(LDAP://schema/EmployeeNumber)
 intMaxLen = objSchemaEmployeeNumber.MaxRange
 If objUser.EmployeeNumber  "" Then
 strCurrentID = objUser.EmployeeNumber
 Else
 strCurrentID = "empty"
 End If
 strEmployeeNumber = InputBox( _
 "The current Employee Number is " & strCurrentID & vbCrLf & _
 vbCrLf & _
 "Enter the new Employee Number (1 through " & intMaxLen & " chars)", _
 Right(objUser.Name, Len(objUser.Name) - 3) & " Employee Number", _
 objUser.EmployeeNumber)
 If strEmployeeNumber = "" Then WScript.Quit 'User clicked Cancel
 If Len(strEmployeeNumber) > intMaxLen Then
 MsgBox "The new Employee Number was too long and it was not saved.", _
 vbCritical, "Error Occurred"
 Else
 Err.Clear
 objUser.EmployeeNumber = strEmployeeNumber
 objUser.SetInfo
 If Err Then MsgBox "The new Employee Number was not saved.", _
 vbCritical, "Error Occurred"
 End If
 ===============================================

Active Directory: Using DSQuery/DSMod to add Service Account to Multiple Groups Based on Description

Due to a regulatory change in our organization, we had to slim down the Domain Admins groups to almost no one, and we were required to remove all service accounts from Domain Admins as well.

Fortunately for us, we had, for quite some time, been creating a specific domain security group for each server and then adding “administrative” user accounts to those groups to assign access to the right people (as not everyone needs to administrate every server).

Unfortunately we didn’t necessarily do the same for service accounts.

One service account, our ePOAgent account for McAfee Anti-Virus, needed to be assigned to all of the server-specific security groups but, for compliance reasons, not be assigned to any other groups.

As we had all of our security groups in one OU, this was a little problematic, but fortunately DSQuery gives us a switch to handle this since we use accurate and consistent descriptions when we create accounts/groups.  Writing a quick command completed the task.

The following DSQuery/DSMod command will do the following:

  • Search a specific OU for security groups that have “Server Administrators:” as the first part of their Description (-desc)
  • Search greater than the default 100 objects (-limit)
  • Continue processing even if one of the groups already has our ePOAgent account in it (-c)
  • Add the ePOAgent account to each group (-addmbr)

Here’s the command:


dsquery group "OU=Security Groups,DC=ad,DC=harness,DC=net" -desc "Server Administrators:*" -limit 1000 | dsmod group -addmbr "CN=ePOAgent,OU=Service Accounts,DC=ad,DC=harness,DC=net" -c

The DS commands in Windows 2008 make life  whole lot easier when working with large collections of objects, particularly if they’re all jumbled together in one OU.  In my case, I had 500+ objects to identify, sort through, and add an account to.  One simple command later I’m done and can move on to something more interesting. : )

Active Directory: Project Plan to Clean and Organize Group Policies

A healthy Group Policy deployment is an essential part of any well run Active Directory infrastructure. In a lot of organizations, Group Policy Objects come to be over several years, administrators and acquisitions. As such, over time the rationale for creating those policies and the methodology applied varies greatly from policy to policy.

By adopting standards for GPO creation and applying them consistently going forward, Group Policies should become much easier to administrate leading to a healthier and more secure network infrastructure.
After recently being tasked to examine our organization’s current Group Policies in place, I developed the following logical plan to reduce the number of GPO’s, apply standards and, where applicable, consolidation.

This plan that I have developed covers five phases:

Phase 1: Removal of Empty Organizational Units in Legacy OU’s

Phase 2: Backup and Removal of Inactive Group Policy Objects

Phase 3: Verify Functionality of Active Group Policy Objects

Phase 4: Rename Active Group Policy Objects

Phase 5: Logically Consolidate Active Group Policy Objects

For us, Group Policy objects had come into existence over a period of years, and at one point almost everyone had rights to create new Group Policy objects… so it was really a mess. Our department did a hostile takeover of everything to do with Active Directory not too long ago, and so organizing and securing it became a top priority.

At the completion of this process the Group Policy implementation at your organization should be much more consistent and easier to manage (I reduced our GPOs by over half… we started with 150 of them). In addition, you’ll have a backup of all Group Policies you have removed “just in case.”

Hopefully, you can use this plan on your own network to clean up your Group Policy objects and begin to apply some consistency to your Active Directory infrastructure.

Phase 1: Removal of Empty Organizational Units
Many organizations create numerous organizational units over time that ultimately get emptied out, but never removed. Therefore, there may be Group Policies that were created specifically for these now empty OUs. By removing these organizational units as the first phase, we can identify a greater percentage of Group Policy Objects that are not currently in use.

Now, I know it’s tempting to try and clean up all of your organizational units at this time… but that should really be a project in and of itself. As this project is principally concerned with Group Policy Objects, only those OUs that are completely empty and unnecessary should be removed.

While it would probably be a simple matter to identify some additional, occupied OUs that could have their objects migrated elsewhere, it would distract from the primary goal of cleaning up our Group Policy Objects.

Phase 2: Backup and Removal of Inactive Group Policy Objects
If you’re reading this, you probably now have several Group Policy Objects that are not currently linked to any Organizational Units and that are not in use in the enterprise.

In Group Policy Management, it is a simple matter to back up an individual policy (just right click on the policy and choose “Back up”). In case any of these policies prove to be needed in the future, every policy should be backed up into a named folder prior to its removal.

Once you have the policy backed up and have verified it does not apply to any OUs, just right click and select delete.

Phase 3: Verify Functionality of Active Group Policy Objects
Some Group Policy Objects may be applied to occupied Organizational Units, but may no longer be functional for a variety of reasons.

For example, we had a Group Policy Object that at one time apparently installed winsnare.msi on Domain Controllers and Servers. However, the install point it referenced no longer exists on our network, therefore the GPO is no longer functional.

Once verified as non-functional, these Group Policy Objects can be removed as well… they’re not doing anything anyway.

The Group Policy Object must be 100% non-functional to be removed during this phase. If any portion of the Group Policy Object is currently functional it should remain intact during this particular phase. The goal of this project and its five phases is to avoid any unnecessary disruption while significantly decreasing and organizing the Group Policy objects.

Phase 4: Rename Active Group Policy Objects
A standard naming scheme for your Group Policy Objects is essential. If you’re like most organizations, you’ll have a ton of GPO’s and if they don’t have a consistent naming scheme it makes it very difficult to accurately identify why a particular policy exists and who it is meant for.

A simple naming scheme should therefore be constructed and applied to the existing group policies to remedy this. More importantly, this standard should be followed from this point forward.

The following scheme illustrates how proper naming can assist an administrator in maintaining a relevant and efficient Group Policy infrastructure.

[Region Code] [Targeted Object] [Policy Category] [Additional Information]

Region Code – Such as NA, EMEA, etc., this indicates who the GPO was created for.

Targeted Object – Such as user, computer, or server, this indicates the type of object the GPO applies to.

Policy Category – Such as WSUS, Display Settings, or Default, this indicates what type of policies are being applied.

Additional Information – Such as Install, Change, or Access, this would be any relevant information that may assist an administrator in identifying what this policy does.

Renaming a Group Policy is safe, it’s just a friendly name, and the computers on your network actually use the SID of the GPO to identify it, which isn’t changing. So, no worried, feel free to rename them at will.

Phase 5: Consolidate Active Group Policy Objects
While not advocating monolithic Group Policy Objects that contain all settings in one object or single-function Group Policy Objects that only contain one policy setting, there are many instances where multiple Group Policy Objects could logically be combined into one object.

In order to determine when it is appropriate to consolidate multiple GPO’s into a single GPO, the following criteria should be used:

  • Multiple GPO’s perform the same function
    • Note: This should be easier to identify once a standard naming scheme is developed and applied
  • Multiple GPO’s apply complementary settings
    • For example, if two GPO’s provide complimentary (not contradictory) settings for Windows System Update Services, then those two GPOs should be combined.

Consolidation should be considered on a case-by-case basis as there are no hard and fast rules for consolidation.

Active Directory: Using the Command Line for Group Management

DSGet displays the selected properties of a specific object in the directory, while DSQuery finds groups in the directory that match the search criteria that you specify. You can then use DSMod to modify an existing object of a specific type in the directory.

DSQuery, DSMod, and DSGet are three command-line tools that are built into Windows Server 2008. It is available if you have the Active Directory Domain Services (AD DS) server role installed. To use them, you must run the commands from an elevated command prompt. To open an elevated command prompt, click Start, right-click Command Prompt, and then click Run as administrator.

A couple of quick reminders about using command line tools:

1. If a value that you supply contains spaces, use quotation marks around the text
2. If you enter multiple values, the values must be separated by spaces

While Active Directory Users & Computers works great, there are always some situations in which command line entry is much quicker as you can specify arguments. These are two situations that I have had to consider recently:

Add specific named user to multiple security groups based on defined criteria
As an example, say I want to add a specific user named Jane Doe to all modify- level security groups, which I can identify as I’ve used “- M” in all of the group names. As I have used consistent naming conventions and have a proper OU structure in place, I can do all of this for the username Jane Doe by typing the following command:


dsquery group "OU=Security Groups,DC=domain,DC=net" -name “- M” | dsmod group -addmbr "CN=Jane Doe,CN=Users,DC=domain,DC=net"

This command works as expected because I’ve used “- M” at the end of all of my security groups that have modify rights to the resource they protect. Consistency pays off when managing large Active Directory infrastructures.

To dissect this command a bit, I’m basically saying “Find all groups under the Security Groups OU that have – M in their name. Then (after the ) modify those groups by adding Jane Doe.”

Add members of one security group to another security group
You can also use DSGet in order to get all members of one group, which then allows you to use DSMod to add them to another group. This can be useful if your organization expands and you need to extend the number of security groups you have.


dsget group "CN=US INFOSEC,OU=Security Groups,DC=domain,DC=net" -members | dsmod group "CN=GERMANY INFOSEC,OU=Security Groups,DC=domain,DC=net" –addmbr

Narratively (I think better in the narrative), this command says “Get all of the users in the US INFOSEC security group and the (after the ) add them to the GERMANY INFOSEC security group.”

Add users based on filtered criteria to existing security group
This one came up for me recently. I needed to find all users in our domain based on an Active Directory attribute (in my case, the description field). In this instance, I was looking for the existence of one word (we’ll use ENSIGN in this example) in the description field and I needed to search our entire user OU structure. I used a * at the beginning and end of “ENSIGN” so that it would look for the word anywhere in the description field. Here are the four ways it could have been written:

  • ENSIGN Ensign is the ONLY word in the description field
  • *ENSIGN The description field ENDS with Ensign
  • ENSIGN* The description field STARTS with Ensign
  • *ENSIGN* Ensign APPEARS anywhere in the description field

By specifying the top level OU I wanted to search, DSQuery will automatically search all sub OUs. In my case, I knew it was going to return A LOT of results, so I used the –limit at the end of the command. By default, DSQuery will only return 100 results, I needed thousands.


dsquery user ou=OUR DOMAIN USERS,dc=domain,dc=net –desc *ENSIGN* -limit 10000 | dsmod group "cn=NEWBIE GROUP,ou=OUR DOMAIN GROUPS,dc=domain,dc=net" –addmbr

So, we’re basically saying “Get up to 10,000 users with the word Ensign anywhere in their description field and add them to the Newbie Group security group.”

…Finally
Issues commands from the command line can save you tons of time. In my case, I had to create a scheduled task in Task Scheduler to perform that last example every four hours to make 100% sure any new users were put in to that group if that criteria were met.

I realize it may seem trivial, but when you’re working with thousands and thousands of accounts in a high security environment, using the command line, specifying criteria, and then scheduling it to run on a routine basis can 100% assure you that requirements are being met.

Active Directory Architecture: Read-Only Domain Controllers

Recently we had a situation come up where it was necessary to provide a domain controller in a unique location. This was a “one off” scenario for us; this location was in a third-world country (not unique) and connected with a government controlled crappy DSL line (very unique) and physical security of the equipment could not yet be guaranteed (very, very unique). Nevertheless, we had to provide a local domain controller (as always, like… right now) for a variety of reasons.

While the personnel onsite were our personnel, the overwhelming majority were new to the company.

As we have recently begun migrating all of our domain controllers to Microsoft Windows Server 2008 R2, a read-only domain controller was the perfect fit (actually, the perfect fit would have been better bandwidth and App-V in a country with plumbing).

Read Only Domain Controllers (RODC’s) allow for granular control of the password database; that is you can choose which accounts are cached locally, and which accounts must transverse the WAN for authentication. In addition, the local Active Directory database is read-only. Modifications to it are not replicated to the other domain controllers.

This is important in a situation where physical security cannot be guaranteed initially (as in our case) or network bandwidth is less than ideal (also in our case). If an interested party (and there are a lot) obtained physical access to a standard domain controller, it is possible (alright, easy) to decrypt the Active Directory database and obtain all passwords… this would be particularly devastating if they were able to obtain the passwords for accounts with admin access.

In cases where bandwidth is a concern, the updates that are pushed to a Read Only domain controller are much smaller as they do not contain all account information.

Deploying an RODC is actually quite simple and not much different than a standard domain controller.

First, you need to prepare your domain for the addition of a RODC. Assuming you already have a Windows 2008-based domain controller, you need to run the following command in order to prep the directory:

Adprep /rodcprep

Adprep.exe is located on your Windows Server 2008 CD under the Support Tools directory. It doesn’t take very long to run and is a relatively safe operation (though, by nature, I’m pretty paranoid about anything that makes modifications to the schema).

Now, you’re ready to promote a domain controller as a new RODC. Assuming you have a prepped Windows Server 2008 box by selecting the Active Directory Domain Services role in Server Manager, just run dcpromo as always. Ideally, select “Advanced Mode” on the first screen so that you can configure the password replication policy and other settings during the AD DS installation.

As you pass through the promotion screens, simply select “Read-only domain controller” (RODC) on the same screen where you select the DNS Server and Global Catalog options. I think making the RODC a DNS server is important, but making it a Global Catalog is a matter of debate.

When you get to the password replication screen, you are presented with a number of options. By default, no passwords will be replicated except those accounts that are members of the “Read-Only Domain Controllers” group. I think that unless there is an exceptional circumstance, it is best to leave this be.

Now, add the accounts for the local users at that site to the Read-Only Domain Controllers group. This will allow them to log on locally without their credentials traversing the WAN. It’s important to note that if a user is not a member of this group, and the site link is terminated due to WAN issues, they will not be able to log on at that site until WAN access is restored.

It’s important to note that the following operations will fail if the WAN link is terminated for any reason:

  • Password changes
  • Attempts to join a computer to the domain
  • Computer rename operations
  • Authentications attempts for accounts whose credentials are not cached on the RODC
  • Group Policy updates that an administrator might attempt by running the gpupdate /force command

However, these operations will still succeed even with the WAN link terminated:

  • Authentication and logon attempts, if the credentials for the resource and the requester are already cached
  • Local RODC server administration performed by a delegated RODC server administrator

Read-only Domain Controllers give the Active Directory Architect an important tool in intelligent AD design… allowing them to further refine their architecture when heightened consideration must be given to security and bandwidth.

Hopefully, this article has given you a “real world” introduction to RODC’s. I highly encourage any administrator to thoroughly review Microsoft’s Read-only Domain Controllers Step-by-Step Guide.

Active Directory Architecture: How to Migrate DHCP from Windows Server 2003 to Windows Server 2008 R2

As part of a global initiative to migrate to a Windows Server 2008-based architecture, I have to migrate DHCP at numerous sites from Windows Server 2003 to Windows Server 2008 R2.

This procedure is covered in the Microsoft DHCP Server Migration Guide, but as usual it is all encompassing and covers sever different scenarios. I’ve decided to write a quick blog entry on (probably) the most common scenario… starting with a Windows Server 2003 (source server) and migrating to Windows Server 2008 R2 (destination server).

Fortunately, Microsoft created a tool set to make the migration of various domain services from 2003 to 2008 relatively easy. The Server Migration Tools can be used to migrate server roles, features, operating system settings, and other data and shares to computers that are running Windows Server® 2008 R2.

The first step is to prepare an installation package of the Server Migration Tools for a Windows Server 2003 environment. To do so, follow these steps:

  1. Log in to your new Windows Server 2008 R2 server
  2. Open a command prompt (make sure to Run as Administrator)
  3. Navigate to %Windir%\System32\ServerMigrationTools
    a. If your source server is Windows 2003 x86, run the following command – SmigDeploy.exe /package /architecture X86 /os WS03 /path c:\DHCPMig
    b. If your source server is Windows 2003 x64, run the following command – SmigDeploy.exe /package /architecture amd64 /os WS03 /path c:\DHCPMig
  4. Copy C:\DHCPMig to your Windows Server 2003 Source Server

We now need to get the Windows Server Migration Tools package registered (installed) on the Windows 2003 source server. To do so, ensure the Microsoft .NET Framework 2.0 and PowerShell 1.0 or later is installed on your 2003 server and follow these steps:

  1. Log in to your Windows Server 2003 source server
  2. Open a command prompt
  3. Navigate to the only sub-directory of the DHCPMig folder you created in the step above.=
  4. Type the following: .\smigdeploy.exe

The “.\” tells Windows to run that command as a PowerShell command.

With the Server Migration Tools now installed, it’s time to actually export our DHCP server instance. To do so, follow these steps:

  1. Go to Start – All Programs – Administrative Tools – Windows Server Migration Tools and click on Windows Server Migration Tools. This opens a specific Windows PowerShell instance with the Migration Tools applet already loaded.
  2. Run the following command to export all DHCP settings- Export-SmigServerSetting -featureID DHCP -User All -Group -IPConfig -path c:\DHCPMig –Verbose
  3. It will prompt for a password to secure the file it is about to create. Choose a password and try not to forget it 🙂
  4. Now that DHCP is backed up to a file, you need to delete DHCP authorization from the source server so that it does not hand out any additional addresses. To do so, type the following command in the same PowerShell session: Netsh DHCP delete server
  5. Copy the svrmig.mig file that was created in step two to the same directory (I use c:\DHCPmig) on the destination server.

We now get to bring our new Windows Server 2008 R2 DHCP server to life, and to do so, do the following:

  1. Go to Start – All Programs – Administrative Tools – Windows Server Migration Tools and right-click on Windows Server Migration Tools and select “Run as Administrator.” This opens a specific Windows PowerShell instance with the Migration Tools applet already loaded.
  2. Run the following command to import all DHCP settings: Import-SmigServerSetting -featureid DHCP -Group -Force -path c:\dhcpmig -Verbose
    NOTE: If you do not already have DHCP installed, it will be installed by running this command. However, you may have to reboot and then run this command again to finish the migration
  3. Type in the password you set when exporting the settings from the source server.
  4. Run this command to start the DHCP Server: Start-Service DHCPServer
  5. Run this command to authorize the new DHCP Server: netsh DHCP add server

That’s it! You have now successfully migrated DHCP from your Windows Server 2003 source server to your new Windows Server 2008 R2 destination server.

Active Directory Architecture: Real World Site Link Benefits & Configuration

I rarely used site links until recently, as the majority of my customers had a single site and didn’t need them. When I did need them, I was only proficient with the basics of setting up Active Directory Sites and, by extension, Active Directory Site Links.

Recently, Site Links have become a major part of my life. Seems silly, I know, but when you’re dealing with a global network with thousands of users and hundreds of servers, it’s critical to get them right and to maintain them. Site Links are definitely not fire and forget. Bandwidth and latency change over time, and it’s important to revisit them every quarter.

I’m faced with an interesting challenge because, due to uber-high security, I’m not “in the know” when it comes to how each physical site is connected to the rest of the network. I’ve been told “it’s sufficient” and little else. So, I had to figure it out on my own. More on that in a minute.

As a refresher, I want to be sure and cover what a site is exactly in Active Directory as well as define a site link.

On the surface, it’s actually very simple. In Active Directory Sites & Services, you create a subnet and then create a site, assigning that subnet to a site which is generally (but not always) related to a physical site. Once you have a site set up, you assign domain controllers to sites. All other servers and workstations then know (via the subnet) which domain controllers they should authenticate against.

Site Links are also created in Active Directory Sites & Services and provide information as to how and when the Active Directory database should be copied.

When you’re dealing with thousands and thousands of computer objects, your Active Directory database can get quite large and probably changes more often than you would think (a LOT of information that changes often is stored in Active Directory and it’s getting more robust as Microsoft transitions more and more data to Active Directory). That large database needs to be copied (often) to all other domain controllers in your domain. If you have lots of sites, you should have lots of domain controllers, and that’s a lot or replication.

Windows Active Directory does set up default site connectors, but they are worthless as they do not take into account latency or bandwidth between sites which just encourages chaos.

With Site Links though, you are able to direct that replication so that it happens when and how you want it to happen.

Back to the network I am currently working with. We don’t know what my bandwidth between sites is, and I don’t know what kind of media it rides on or how it gets there… that’s top secret info, even if we do think we need to know to do our job right.

So, we had to improvise. We simply logged on to each DC and pinged all other DC’s and recorded the latency, making a manual Visio map (did I mention we also cannot install any third party software, so we’re kind of stuck with what is built in to Windows). After that, we did tracert’s between all sites to get an idea of the how traffic was routed. Finally, we did some arbitrary data copies between DCs to get an idea of how much bandwidth we were dealing with.

It’s messy, but it works in a pinch when you can’t get details as to bandwidth, latency, media or even if you’re dealing with a carrier or a private network.

Now that we know what servers talk to each other best, we can set up our Site Links. Site Links are actually quite simple to set up, you simply specify two servers and the “cost” of that connection. The lower the cost, the more likely Windows will elect to use that link when replicating Active Directory Changes. In addition, you can specify a schedule as to when information is replicated. You don’t want it so often that it chokes the network, but you don’t want it so seldom that it presents an unacceptable security risk.

So, say you had multiple sites in the US, Japan, Germany, Guam, Columbia and some parts of Asia with lots of sand. All of those sites connect to each other with different degrees of latency and bandwidth. Germany & the US connect nice and quick, but Asia is a slow, slow link (probably satellite) to Asia, but some sites in Asia actually connect reasonably fast to one another, just not outside the country.

With a Site Link then, we can replicate changes to one domain controller in Asia, and then set up Site Links so that all other domain controllers in Asia first attempt to get their replica’s from that primary site. This allows the Active Directory architect to intelligently route what can be significant traffic along the most efficient route.

Now, multiply that times dozens and dozens of sites and you can see how even a small mistake could result in choking off parts of the network every time Active Directory replication occurs, just like clockwork.

In summary, never underestimate any part of a Windows Active Directory network or assume that “out-of-the-box” is just fine. It’s not… you really, really need to pay attention to the details in order to ensure proper operation, security and service availability.

Active Directory Architecture: How to Search for old Security Groups

Recently I was asked to get a grasp on an organizations Active Directory and make any recommendations on how to clean it up or improve upon its structure.

Task #1 for me was getting a handle on the security groups in place. Security (and Distribution) Groups are often neglected. They are set up by someone, somewhere, sometime and then typically forgotten. As time passes and users are copied to create new users, these security groups can become security holes as rights are given to people unintentionally.

For this particular organization, this was no easy challenge as they had thousands of undocumented groups. Where would I ever even begin to start?

I was fortunate in the fact that this particular organization does not copy users to create new users. All users are created from scratch and then added to the appropriate groups on an as needed basis (which, by the way, is a good security principle to follow). Since we know that Microsoft Windows Active Directory tracks when objects are modified, all I had to do was extract that information and then sort on the last modified date.

The modified date is a good indicator to determine if a security group is in active use. In large organizations, there is a substantial amount of employee turnover or employees being promoted or moved around. If a security group has not been modified in 18 months or more, it’s likely it is no longer necessary. Microsoft has a good article on this:

http://technet.microsoft.com/en-us/library/cc779808%28WS.10%29.aspx

In order to get that info though, I needed a way to export all of the security groups and pull their modified dates. You can do this through LDAP queries, (per that Microsoft article) but I wanted something a little more robust. I ended up finding this script thatqueries Active Directory to get a list of all user groups, the date it was created and last modified, and then writes the output to a CSV file.

In my case, it returned 7021 security groups. Unfortunately, I also discovered that the script returned no OU’s to tell me where those 7021 groups actually were… which effectively made it pretty useless as I was now dealing with thousands of groups that had not been modified in some time. Knowing which OU they were in, I could at least send a list to the various department heads asking them to audit and verify which groups were still necessary.

So, I modified the script a little (I have pasted the code below) so that it would also return the OU’s by also querying the distinguishedName property. It’s still 7021, but at least now I have it narrowed down just a bit further. : )

Simply copy and paste this code into notepad and save it as GroupAge_AD.vbs. Run it from a command prompt as you would a .bat file and it will create a file called ADGroups_Age.csv in the same directory as the .vbs script.


'==========================================================================
 ' Name: GroupAge_AD.vbs
 ' Author: Jose Cruz (merlinpr) & modified by Rebecca Harness
 ' Date: 11/04/2009 with modifications on 07/18/2010
 ' Desc: Queries Active Directory for all group objects and writes the date
 ' when it was created and last modified to a CSV file. Modified to add distinguishedName
 '==========================================================================

'On Error Resume Next

Const ADS_SCOPE_SUBTREE = 2

Set RootDSE = GetObject("LDAP://RootDSE")
 domainContainer = rootDSE.Get("defaultNamingContext")

Set objConnection = CreateObject("ADODB.Connection")
 Set objCommand = CreateObject("ADODB.Command")
 objConnection.Provider = "ADsDSOObject"
 objConnection.Open "Active Directory Provider"
 Set objCommand.ActiveConnection = objConnection

objCommand.Properties("Page Size") = 1000
 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE

objCommand.CommandText = _
 "SELECT Name, whenChanged, distinguishedName, whenCreated FROM 'LDAP://" & domainContainer & "' WHERE objectCategory='group'"
 Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst

Set objFSO = CreateObject("Scripting.FileSystemObject")
 Set objLogFile = objFSO.CreateTextFile("ADGroups_Age.csv", _
 ForWriting, True)

Do Until objRecordSet.EOF
 objLogFile.Write objRecordSet.Fields("Name").Value & ","
 objLogFile.Write objRecordSet.Fields("whenCreated").Value & ","
 objLogFile.Write objRecordSet.Fields("whenChanged").Value & ","
 objLogFile.Write objRecordSet.Fields("distinguishedName").Value
 objLogFile.Writeline
 objRecordSet.MoveNext
 Loop

objLogFile.Close
 objRecordset.Close
 objConnection.Close