Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Sends an email report with any changes made to Active Directory Sites and Subnets. Run regularly with automation.
######################################################################################
## ##
## This script compares the current list of AD sites and subnets with a cached list ##
## If anything has changed, the cached list will be updated and the changes emailed ##
## ##
######################################################################################
################
## PARAMETERS ##
################
# Location of cache files
$ADSitesFile = "G:\Scheduled Task Scripts\Cache Files\ADSites.csv"
$ADSubnetsFile = "G:\Scheduled Task Scripts\Cache Files\ADSubnets.csv"
# Email parameters
$EmailParams = @{
smtpserver = "contoso-com.mail.protection.outlook.com"
To = "SCCMAdmins@contoso.com"
From = "SCCMReports@contoso.com"
Subject = "Active Directory Site and Subnet Changes"
}
# Html CSS style
$Style = @"
<style>
table {
border-collapse: collapse;
}
td, th {
border: 1px solid #ddd;
padding: 8px;
}
th {
padding-top: 12px;
padding-bottom: 12px;
text-align: left;
background-color: #4286f4;
color: white;
}
</style>
"@
#################
## MAIN SCRIPT ##
#################
# ArrayLists to hold the data
$ADSites = [System.Collections.ArrayList]::new()
$ADSubnets = [System.Collections.ArrayList]::new()
# Retrieve the list of AD sites for the current forest
$Sites = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites
# Retrieve the AD subnets for each AD site and convert to a custom object
foreach ($ADSite in $Sites)
{
[void]$ADSites.Add(
[PSCustomObject]@{
'AD Site' = $ADSite.Name
}
)
Foreach ($Subnet in $ADSite.Subnets)
{
[void]$ADSubnets.Add(
[pscustomobject]@{
Name = $Subnet.Name
Site = $Subnet.Site
Location = $Subnet.Location
}
)
}
}
# Test whether the cached lists exist, if not create them assuming first run
If (!(Test-Path $ADSitesFile))
{
$ADSites | Sort 'AD Site' | Export-Csv -Path $ADSitesFile -NoTypeInformation -Force
}
If (!(Test-Path $ADSubnetsFile))
{
$ADSubnets | Sort Name | Export-Csv -Path $ADSubnetsFile -NoTypeInformation -Force
}
# Load in the cached lists
$ADSitesCached = Import-Csv -Path $ADSitesFile
$ADSubnetsCached = Import-Csv -Path $ADSubnetsFile
# More ArrayLists to hold the data
$ADSitesAdded = [System.Collections.ArrayList]::new()
$ADSitesRemoved = [System.Collections.ArrayList]::new()
$ADSubnetsAdded = [System.Collections.ArrayList]::new()
$ADSubnetsRemoved = [System.Collections.ArrayList]::new()
$ADSubnetsModified = [System.Collections.ArrayList]::new()
# New AD sites
Foreach ($Item in $ADSites)
{
If($Item.'AD Site' -notin $ADSitesCached.'AD Site')
{
[void]$ADSitesAdded.Add($Item)
}
}
# Removed AD Sites
Foreach ($Item in $ADSitesCached)
{
If($Item.'AD Site' -notin $ADSites.'AD Site')
{
[void]$ADSitesRemoved.Add($Item)
}
}
# IP subnet where AD Site has changed, or new IP subnet added
Foreach ($Item in $ADSubnets)
{
$Sub = $ADSubnetsCached.Where({$_.Name -eq $Item.Name})
If ($Sub)
{
If ($Sub.Site -ne $Item.Site)
{
[void]$ADSubnetsModified.Add(
[PSCustomObject]@{
Name = $Item.Name
OldSite = $Sub.Site
NewSite = $Item.Site
}
)
}
}
Else
{
[void]$ADSubnetsAdded.Add($Item)
}
}
# IP subnet removed
Foreach ($Item in $ADSubnetsCached)
{
$Sub = $ADSubnets.Where({$_.Name -eq $Item.Name})
If ($Sub){}
Else
{
[void]$ADSubnetsRemoved.Add($Item)
}
}
# Prepare the HTML
If ($ADSitesAdded.Count -ge 1)
{
$HTML1 = $ADSitesAdded |
ConvertTo-Html -Head $Style -Property 'AD Site' -Body "<h2>The following AD Sites have been ADDED in Active Directory</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String
}
If ($ADSitesRemoved.Count -ge 1)
{
$HTML2 = $ADSitesRemoved |
ConvertTo-Html -Head $Style -Property 'AD Site' -Body "<h2>The following AD Sites have been REMOVED from Active Directory</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String
}
If ($ADSubnetsAdded.Count -ge 1)
{
$HTML3 = $ADSubnetsAdded |
ConvertTo-Html -Head $Style -Property Name,Site,Location -Body "<h2>The following IP Subnets have been ADDED in Active Directory</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String
}
If ($ADSubnetsRemoved.Count -ge 1)
{
$HTML4 = $ADSubnetsRemoved |
ConvertTo-Html -Head $Style -Property Name,Site,Location -Body "<h2>The following IP Subnets have been REMOVED from Active Directory</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String
}
If ($ADSubnetsModified.Count -ge 1)
{
$HTML5 = $ADSubnetsModified |
ConvertTo-Html -Head $Style -Property Name,OldSite,NewSite -Body "<h2>The AD Site for the following IP Subnets has been MODIFIED in Active Directory</h2>" -CssUri "http://www.w3schools.com/lib/w3.css" |
Out-String
}
$HTML = $HTML1 + $HTML2 + $HTML3 + $HTML4 + $HTML5
# Send the email report and update the cached lists if required
If ($HTML.Length -ge 1)
{
Try
{
Send-MailMessage -Body $HTML @EmailParams -BodyAsHtml -Priority High -ErrorAction Stop
}
Catch
{
$_
Break
}
$ADSites | Sort 'AD Site' | Export-Csv -Path $ADSitesFile -NoTypeInformation -Force
$ADSubnets | Sort Name | Export-Csv -Path $ADSubnetsFile -NoTypeInformation -Force
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.