Zoho Banner September 2011

Archive for the 'Active Directory' Category

What’s in a name?

 

I’ve been working with the Windows Server 2008 R2 Active Directory cmdlets quite a bit recently.  If you’ve come from a background of using ADFIND, the cmdlets take a bit of getting used, but for me it’s definitely been worth the time spent.  One thing that frustrates me a little is that the names used by the cmdlets for AD attributes tend to vary greatly.  Not only is there inconsistency between cmdlets that stem from different modules and snap-ins, but also between the cmdlets and the traditional UI tools.  The table below shows some examples:

 

AD Users and Computers

ldapDisplayName

AD cmdlet property name

Exchange 2010 cmdlet property name

Telephone Number

telephoneNumber

OfficePhone

Phone

E-mail

mail

EmailAddress

WindowsEmailAddress

P.O. Box

postofficeBox

POBox

PostOfficeBox

 

I guess the Microsoft Product Groups try to protect the long-suffering customer from the obscurity of some of the attribute LDAP display names by giving them friendly names.  This approach would work well if there were universal consistency, but it not it just becomes confusing.  My preference is always to use the ldapDisplayName values whenever possible – and certainly always with the AD cmdlets, e.g.

Get-ADUser –LDAPFilter “(samaccountname=bobm)”

If in doubt however, refer to the object model:

get-help about_ActiveDirectory_ObjectModel

Tony

The books that keep on giving

Good books continue to deliver value long after the publication date.  Here’s an example of how they helped repair a broken bed support recently.

img_2631_small.jpg

(with apologies to Gil Kirkpatrick, whose Active Directory Programming book has been a huge help to me over the last 10 years).

PS. Details of how exactly the bed was broken are not available at this time.

Powershell script to find objects using objectGUID value

The objectGUID attribute is a little tricky to work with, especially if you want to use it as part of an LDAP filter.  This is because the value in stored within the directory as an octet string - essentially an array of one-byte characters.  This syntax is not especially user-friendly, which is why it is typically displayed (by tools such as LDP.EXE and the AD Powershell cmdlets) in a registry string format, e.g. “af97d4c7-5f17-4ce2-9245-687d410b4b20″Another way of displaying the value is using a hex string format, e.g. “C7D497AF175FE24C9245687D410B4B20″.  If you’re into migrations using Quest Migration Manager for AD, the hex string representation is used for the matching attribute value (using either extenstionAttribute15 or adminDisplayName).  As you can see, the two representations are similar, but have a slightly different ordering of the bytes.

You’d think that you would be able to use one of these two string representations of the objectGUID as part of an LDAP search filter, wouldn’t you?  Well, no, that would be too helpful.  Instead, you need a slightly modified version of the hex string, i.e. “\C7\D4\97\AF\17\5F\E2\4C\92\45\68\7D\41\0B\4B\20″.   The search filter syntax would look like this “(objectGUID=\C7\D4\97\AF\17\5F\E2\4C\92\45\68\7D\41\0B\4B\20)”

The script below accepts either of the two string formats as input and prompts you for the naming context in which to search for the object represented by the objectGUID attribute.

#########################################################
#
# Name: Get-ADObjectFromGUID.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 24/08/2010
# Comment: PowerShell script to search for an AD object
# using 'objectGUID' as the LDAP search filter
#
#########################################################

# Import the AD module
ipmo ActiveDirectory

# Get the objectGUID value
$Input1 = @'
    Please enter the objectGUID value in one
    of the two following formats:

    Registry string format, e.g.
        bb67681f-0ac1-471a-bf3d-f7f4c4cb1290
    or
    Hex string format, e.g.
        455E54E9D58B0F4B8F389E4982791D40

'@

$strGUID = Read-Host $Input1

# Present Menu
[string] $menu = @'
    Choose the AD partition to search within
    1. Current Domain
    2. Configuration
    3. Schema
    4. Other

'@

$a = Read-Host $menu
switch ($a)
{
    1 { $SearchBase = (Get-ADRootDSE).defaultNamingContext }
    2 { $SearchBase = (Get-ADRootDSE).configurationNamingContext }
    3 { $SearchBase = (Get-ADRootDSE).schemaNamingContext }
    4 { $SearchBase = Read-Host "Enter the search base: " }

}

if ($strGUID.length -eq 36)
{
    # We have a string in registry format and need to convert it to Hex string
    $strHex = -join (([guid]$strGUID).tobytearray() | %{$_.tostring("X").padleft(2,"0")})
}
elseif ($strGUID.length -eq 32)
{
    # We have a string in Hex format - no need to modify
    $strHex = $strGUID
}
else
{
    # Unrecognised string format
    Write-host "Unrecognised string format - remove any leading or trailing spaces and try again"
    Break
}

# We need to modify the Hex string to allow it to be used as a filter
$strSearch = $strHex -replace '(..)','\$1'

# Go ahead and search for the object
Get-ADObject -LDAPFilter "(objectGUID=$strSearch)" -SearchBase $SearchBase -Properties * | fl

# End

You can download the script here: get-adobjectfromguid.zip

Teched 2011 New Zealand - Powershell files

As promised, here are the Powershell data files from my Teched NZ 2011 demos.  I’ve also included the FSMO role mover script.

te_2011.zip

Let me know if you have any questions. Enjoy!

How to find duplicate sAMAccountNames between two forests

When preparing for a migration of AD objects from one forest to another it is useful to know if any of the names are going to conflict.  There are, as you probably know, a number of different naming attributes in AD, but the one most likely to cause problems in the event of a conflict is sAMAccountName.  This is because sAMAccountName is used for domain logon (assuming UPN is not used).  If you know which names conflict between source and target you can plan changes before you get into the migration itself.

I’ve written a couple of small scripts to detect sAMAccountName conflicts.  I’ve used two scripts instead of one as there is not always trust connectivity between the two forests.  The first script (SourceUsersToCSV) is run in the source domain and basically just dumps all the user sAMaccountName attribute values to a file.  The second script (DupeCheckFromCSV) is run in the target domains and reads the exported file information line-by-line and checks to see if there are any conflicts in the target domain.  If a conflict is found the sAMAccountName is written to a file.

Enjoy!

#########################################################
#
# Name: SourceUsersToCSV.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 14/07/2011
# Comment: PowerShell script to export AD user info
# to CSV to support search for duplicate users
#
#
#########################################################

### --- Varible Definitions ---

$DOMAIN = "source.com"
$EXPFILE = "C:\util\CSV\domain_export.csv"
$sourceOU = "OU=MyUsers,DC=source,DC=com"
$filter = "(&(objectClass=user)(!iscriticalsystemobject=TRUE))"

### --- Main ---

# Export Source AD User info to file

if(@(get-module `
| where-object {$_.Name -eq "ActiveDirectory"} ).count -eq 0) {import-module ActiveDirectory}

$objSourceDC = Get-ADDomainController -Discover -DomainName $DOMAIN
$sourceDC = [string]$objSourceDC.HostName
$UserInfo = '' | Select 'UsrsAMAccountName'
$AllUsers = @()
$MyUsers = Get-ADUser -LDAPFilter $filter -Server $sourceDC -SearchBase $sourceOU
foreach($User in $MyUsers) {
    $UserInfo.'UsrsAMAccountName' = $User.sAMAccountname
    $AllUsers += $UserInfo | Select 'UsrsAMAccountName'
}
$AllUsers | Export-Csv $EXPFILE -NoTypeInformation
#########################################################
#
# Name: DupeCheckfromCSV.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 14/07/2011
# Comment: PowerShell script to import AD User info
# from CSV to check for duplicates
#
#########################################################

### Set Global variables

$domain = "target.com"
$impfile = "C:\util\CSV\Domain_Export.csv"
$EXPFILE = "C:\util\CSV\Duplicate_Users.csv"
$dc = Get-ADDomainController -Discover -DomainName $domain
$targetdc = [string]$dc.HostName
$arrSrcSAMs=@()
$arrTarSAMs = @()
$arrDupeUsers = @()

### Load the CSV file and extract the source domain unique User names

$colsrcUsers = import-csv $impfile #| select UsrSAMAccountName

foreach ($srcUser in $colsrcUsers)
	{
		$srcSAM = $srcUser.UsrSAMAccountName
		$arrsrcSAMs += $srcSAM
	}    

# Check for empty file
if ($colsrcUsers.Count -eq 0)
    {
        write-host "No Users found in CSV import file!"
        break
    }

### Enumerate Users in the local (target) domain 

$coltarUsers = Get-ADUser -Filter '*' -Server $targetDC -Properties samaccountname

foreach ($tarUser in $coltarUsers)
	{
		$tarSAM = [string]$tarUser.samaccountname
		$arrTarSAMs += $tarSAM
	}    

### Find Users to Add or Modify

foreach ($tarUser in $arrTarSAMs)
	{
		if ($arrSrcSAMs -contains $tarUser)
		{
			write-host "Duplicate User found for " $tarUser
			$arrDupeUsers += $tarUser
		}
		else
		{
			write-host "No Duplicate found for " $tarUser
		}
	}

### Add new Users to target and apply the membership

$arrDupeUsers | out-file $EXPFILE

How to clear group membership with Powershell

Something I often recommend to my customers is keep the membership of the Enterprise Admins and Schema Admins groups empty and only populate them (temporarily) when required.  The privileges assigned to these groups are obviously high and removing the members reduces the potential for costly mistakes and/or compromise. 

Here’s a quick Powershell snippet that will perform the removal:

$grps = "Enterprise Admins", "Schema Admins"
foreach ($grp in $grps) {
Get-ADGroupMember -Identity $grp `
| %{Remove-ADGroupMember -Identity $grp -Members $_ -Confirm:$false}
}

This is something that you could consider running as a scheduled task to ensure the memberships are kept clear.

How to find the renamed domain Built-In Administrator account with Powershell

Many organisations choose to rename the Built-in Administrator account for the domain for security reasons.  Whether or not renaming the account provides any real protection is the matter of some debate.  What is clear is that any hacker worth his or her salt is not going to be fooled by the rename, because the account has a well known security identifer:

SID: S-1-5-21domain-500

I was working on something the other day and needed to find the Built-in Administrator account using Powershell.  It wasn’t quite as straightforward as I thought it would be.  Anyway, here’s what I came up with:

$BA = (Get-ADDomain).domainsid
$BA = $BA.ToString() + "-500"
Get-ADUser -Identity $BA

As you can see it basically involves grabbing the domain SID, adding on the well-known identifier “-500″ and then searching for the account based on the concatenanted string. 

I can’t help thinking there must be an easier method, so if you have one please post a comment here.

Quest OnDemand Recovery for AD

 

On and off over the past couple of days I’ve been trialling one of Quest’s cloud services – OnDemand Recovery for AD.  The other service that Quest currently offers in the Microsoft space is Log Management, which allows the collection, storage and forensic analysis of Windows Event Log data. 

For those of you familiar with Quest’s Recovery Manager for AD, the OnDemand version has similarities, but quite a few differences too.  You can find a useful table comparing the feature sets of the two products here.

The basic concept behind OnDemand Recovery for AD is that by subscribing to a cloud service to support the recovery of AD objects you avoid having to deploy and manage infrastructure components within your environment.  At USD0.60 per user per month the service is likely to attract SMB customers, but is unlikely to tempt large enterprises that typically have existing, comprehensive backup and recovery solutions.

The first thing that popped into my head when I looked at the feature set was why anyone would subscribe to the service when Windows Server 2008 R2 AD includes the AD Recycle Bin (for free).  The Recycle Bin combined with the “Protection from accidental deletion” feature (introduced in Windows Server 2008 AD) can provide a reasonably comprehensive toolset for protection and deleted object recovery.  After spending some time looking at Quest’s product it struck me that OnDemand Recovery for AD has two significant advantages over the native Microsoft toolset:

  1. Ease of use.  The OnDemand web interface is very straightforward to set up and operate.  A child could do it.  The same cannot be said of the AD Recycle Bin, which requires that you know your way around Powershell AD cmdlets.
  2. Ability to restore objects to a previous state.  The AD Recycle Bin is great for restoring deleted objects, but doesn’t let you revert an existing, non-deleted object back to a previous state.  For example, let’s say you run a script that accidentally changes the telephoneNumber attribute of 5000 users to “911”.  In this scenario you can’t use the AD Recycle Bin to change the numbers back because the objects have been modified, not deleted.  You would typically need to go through the process of an authoritative restore of those objects from backup – a time consuming task that carries an element of risk.  With OnDemand Recovery for AD you could have those 5000 user objects reverted to their previous state within a couple of minutes.  I have included screenshots below to illustrate just how simple this is.

From your OnDemand Recovery for AD home page select “Restore”

rmadod0a

Choose the backup that contains the content that you would like to revert to.

rmadod1

The OnDemand software then compares the current state of AD objects with those in the backup set and then displays any differences.

rmadod2

In this example, two objects with differences are detected.  One is a modification (update) and the other is a deletion.  In this example, I selected the modified object (Autumn Metzler).

rmadod3a

After clicking Finish you see the restore operation in progress.

rmadod4

And that’s it! Ok, in this example I only worked with one object, but the principle is the same for multiple objects and the OnDemand product allows you to multi-select objects that you want to restore.

On balance I think Quest’s OnDemand Recovery for AD service is going to be a good choice for SMBs that are looking for a simple and easy-to-use product for quick AD object recovery.

I’ve only scratched the surface of the product’s capabilities here.  If you want to learn more I recommend giving the product a trial (very simple to setup) and perusing the following document:

Protect Your Data with Quest OnDemand Recovery for Active Directory

Quest ActiveRoles Quick Connect Express: GAL Sync Step-by-step Guide

A couple of weeks ago I blogged about using Quest’s ActiveRoles Quick Connect Express for Exchange 2010 Global Address List synchronisation (GAL Sync).  Since then I’ve written a step-by-step guide which will hopefully help others who want to use this very useful freeware utility.  You can download the guide (pdf format) here:

GAL Sync with ActiveRoles Quick Connect Express - Step-by-Step Guide v1

I have also updated the Powershell script that exposes the provisioned Contact objects in the target GAL.  You can download the script here:

ConfigureContacts.ps1

If you have any feedback on the guide please post a comment here or contact me directly (tony@activedir.org)

ActiveDir.org reaches a decade

10 years ago today I started ActiveDir.org and the AD discussions mailing list is still going strong!  Thanks to everyone who has made it a success over the years and especially to Martin Tuip who helped me get set up and Matty Holland who does all the development work.

It makes me feel quite old!

Next Page »