Compare AD against snapshots

Wouldn’t it be cool to learn all the changes made to Active Directory recently? All the accounts added and removed, all the ones modified including the old and the new values for each modified property? Below is a script that does exactly that: creates snapshots of your AD and allows to compare your live environments against them.

Yeah, I know that there are commercial products doing that (and even allowing rollbacks) and that AD auditing in Windows 2008 is now almost there natively but hey this is a PowerShell blog. ;)

The basic idea behind the script below is:

  1. We have a set of properties which we want to track.
  2. Let’s retrieve them and export to an XML file. That will be our snapshot.
  3. At any time we can then load the snapshot and compare it against what is currently in the AD.

Here’s the code. Not perfect – feel free to improve it at the code repository – but works for me! ;)

###############################################################################
# Compare-AD - a set of functions (and sample code using them) to create 
# snapshots of user accounts in the current Active Directory domain
# save them in an xml file, and then compare live AD environment
# against that XML
#
# (C) Dmitry Sotnikov
# http://dmitrysotnikov.wordpress.com/2008/10/14/compare-ad-against-snapshotscompare-ad-against-snapshots
# 
###############################################################################

# Requires QAD cmdlets
if ((Get-PSSnapin "Quest.ActiveRoles.ADManagement" `
            -ErrorAction SilentlyContinue) -eq $null) {
    Add-PSSnapin "Quest.ActiveRoles.ADManagement"
}


###############################################################################
# Functions
###############################################################################

# Retrives all AD users from the current domain and stores the selected 
# set of properties (passed as an array of strings in the $properties parameter)
# as an xml file by the path passed as $path
# See sample use below
function New-Snapshot {
    param($path, $properties)
    Get-QADUser -SizeLimit 0 -DontUseDefaultIncludedProperties `
        -IncludedProperties $properties | 
            Select $properties | Export-Clixml $path
}

# Load the snapshot and compare it against current AD domain
function Compare-ActiveDirectory {
    param($path, $properties)
    
    # $old is the snapshot, $new is the current environment data
    $old = Import-Clixml $path
    $new = Get-QADUser -SizeLimit 0 -DontUseDefaultIncludedProperties `
        -IncludedProperties $properties | 
            Select $properties

    # First lets report the ones which got created or deleted
    $diff = Compare-Object $old $new -Property Name
    $created = , ($diff | where { $_.SideIndicator -eq "=>" })
    $deleted = , ($diff | where { $_.SideIndicator -eq "<=" })
    
    if ( $created.Count -gt 0 ) {
        "New accounts:"
        $created | Format-Table Name
    }
    
    if ( $deleted.Count -gt 0 ) {
        "Deleted accounts:"
        $deleted | Format-Table Name
    }
    
    # Now let's load the accounts in a hash-table so it is easier to locate them
    $hash = @{}
    $new | ForEach-Object { $hash[$_.DistinguishedName] = $_ }
    
    # Let's enumerate the accounts and their properties and report any changes
    "Modified objects:"
    foreach ( $snapshot in $old ) {
        $current = $hash[$snapshot.DistinguishedName]
        if ( $current -and 
            ($current.ModificationDate -ne $snapshot.ModificationDate )) {
@"

Object $($snapshot.distinguishedname)
Modified at $($current.ModificationDate)
                
Property`tOld Value`tNew Value
========`t=========`t=========
"@
            foreach ($property in $properties) {
                if ( ($property -ne "ModificationDate") -and 
                    ($snapshot.$property -ne $current.$property )) {
                "$property`t$($snapshot.$property)`t$($current.$property)"
                }
            }
        }
    }
}

###############################################################################
# Common parameters
###############################################################################

# These are the properties to be compared
# Make sure they include Name, DistinguishedName, and ModificationDate
# Remove the TS attributes if your system requirements for retrieving those
# are not met: 
# http://dmitrysotnikov.wordpress.com/2008/07/23/system-requirements-for-powershell-terminal-services-management/
$Members_to_Compare = @( "Name", "DistinguishedName", "ModificationDate", 
    "AccountIsDisabled", "AccountIsLockedOut", "AccountName", 
    "CanonicalName", "City", "Company", "Department", "Description", 
    "DisplayName", "Email", "Fax",
    "FirstName", "HomeDirectory", "HomeDrive", "HomePhone", "Initials", 
    "LastName", "LdapDisplayName", "LogonName", "LogonScript", "Manager", 
    "MobilePhone", "Notes", "Office", "Pager", 
    "ParentContainerDN", "PasswordNeverExpires", 
    "PhoneNumber", "PostalCode", "PostOfficeBox", "ProfilePath", 
    "SamAccountName", "StateOrProvince", "StreetAddress", "Title", 
    "TsAllowLogon", "TsBrokenConnectionAction", "TsConnectClientDrives", 
    "TsConnectPrinterDrives", "TsDefaultToMainPrinter", "TsHomeDirectory", 
    "TsHomeDrive", "TsInitialProgram", "TsMaxConnectionTime", 
    "TsMaxDisconnectionTime", "TsMaxIdleTime", "TsProfilePath", 
    "TsReconnectionAction", "TsRemoteControl", "TsWorkDirectory", 
    "UserPrincipalName", "WebPage" )

# Path to the snapshot file
$SnapshotPath = "c:\snapshot.xml"

###############################################################################
# Sample usage
###############################################################################

# Create a snapshot
New-Snapshot -Path $SnapshotPath -Properties $Members_to_Compare

# Make some changes
New-QADUser -Name "Lawrence Alford"  -ParentContainer mydomain.local/test
Set-QADUser "Jennifer Clarke" -PhoneNumber "(249) 111-22-33"
Set-QADUser "Ernest Cantrell" -City "San Francisco"
Remove-QADObject "Andreas Bold"  -Force

# Let's see if we find them
Compare-ActiveDirectory -Path $SnapshotPath -Properties $Members_to_Compare

Tags: , , , , ,

About these ads

0 Responses to “Compare AD against snapshots”



  1. Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




My Recent Tweets

Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

October 2008
M T W T F S S
« Sep   Nov »
 12345
6789101112
13141516171819
20212223242526
2728293031  

Follow

Get every new post delivered to your Inbox.

Join 93 other followers

%d bloggers like this: