# encoding: ascii
# api: powershell
# title: Security group monitor
# description: This script takes a list of Active Directory security group membership from XML, checks a baseline, and emails results. Code can be taken from this to create the baseline XML as well. Thanks to Koldkutspecial for fixing empty group membership bug.
# version: 0.1
# type: script
# author: Steve Jarvi
# license: CC0
# function: Re-Baseline
# x-poshcode-id: 3496
# x-archived: 2015-05-05T00:48:14
# x-published: 2015-07-02T10:59:00
#
# -Steve
#
#Get group membership for a list of security
#groups and export to an XML for comparison
#against baseline.
#
$script:WorkingDirectory = split-path $myinvocation.Mycommand.Definition -parent
Function Re-Baseline
{
#First, declare array and hashtable.
$securitygroups = @()
$table = @{}
#Import Security Group list from XML and add to "securitygroups" array.
$securitygroupsxml = [XML] (gc "$script:WorkingDirectory\sg.xml")
$securitygroups += $securitygroupsxml.objs.S
#Get membership for each group
foreach($securitygroup in $securitygroups){
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = [ADSI] "LDAP://$($dom.Name)"
$searcher = New-Object System.DirectoryServices.DirectorySearcher $root
$searcher.filter = "(&(objectCategory=group)(objectClass=group)(sAMAccountName=$securitygroup))"
$group = $searcher.findone()
$table += @{"$securitygroup"= $group.properties.member}
}
#Export hashtable to XML. So nice.
$table | export-clixml $script:WorkingDirectory\baseline.xml
}
#
#First, declare hashtable.
$comparetable = @{}
#Import Security Group list from XML and add to "securitygroups" array.
$securitygroupsxml = [XML] (gc "$script:WorkingDirectory\sg.xml")
$securitygroups = $securitygroupsxml.objs.S
#Get membership for each group and create a compare table.
foreach($securitygroup in $securitygroups){
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = [ADSI] "LDAP://$($dom.Name)"
$searcher = New-Object System.DirectoryServices.DirectorySearcher $root
$searcher.filter = "(&(objectCategory=group)(objectClass=group)(sAMAccountName=$securitygroup))"
$group = $searcher.findone()
$comparetable += @{"$securitygroup"= $group.properties.member}
}
#Export hashtable to XML. So nice.
$comparetable | export-clixml "$script:WorkingDirectory\compare.xml"
#Import baseline XML to hashtable.
$baselinetable = @{}
$baselinetable += import-clixml "$script:WorkingDirectory\baseline.xml"
#Import baseline XML to hashtable.
$comparetable = @{}
$comparetable += import-clixml "$script:WorkingDirectory\compare.xml"
#Compare respective Keys and Values for $comparetable against
#$baselinetable and get differences.
$passtoemailsubuser = @()
$passtoemailbody = @()
foreach($securitygroup in $securitygroups) {
If($comparetable."$securitygroup" -eq $NULL)
{
If($baselinetable."$securitygroup" -eq $NULL)
{
(get-date).tostring() + " - Security Group $securitygroup is empty in the compare and the baseline" >> $script:WorkingDirectory\log.txt
}
Else
{
foreach($entry in $baselinetable."$securitygroup")
{$passtoemailbody += "`r" + $entry + " " + "`r`r" + "***WAS REMOVED FROM***: " + "`r`r" + $securitygroup + "`r`r"}
$passtoemailbody += "`r" + $securitygroup + " " + "`r`r" + "in AD contains no more objects" + "`r`r"
(get-date).tostring() + " - $securitygroup in AD contains no more objects" >> $script:WorkingDirectory\log.txt
}
}
Else
{
$baseline = @($baselinetable."$securitygroup")
$compare = @($comparetable."$securitygroup")
$results = Compare-Object $baseline $compare
foreach($result in $results){
if (($result.equals.isinstance -eq $true) -and ($result.sideindicator -eq "=>")) {$passtoemailbody += "`r" + $result.inputobject + " " + "`r`r" + "***WAS ADDED TO***: " + "`r`r" + $securitygroup + "`r`r"
$user = $result.inputobject
$searcher.filter = "(&(objectCategory=person)(objectClass=user)(distinguishedname=$user))"
$user = $searcher.FindOne()
$passtoemailsubuser += $user.properties.samaccountname
$mod = $true
}
if (($result.equals.isinstance -eq $true) -and ($result.sideindicator -eq "<=")) {$passtoemailbody += "`r" + $result.inputobject + " " + "`r`r" + "***WAS REMOVED FROM***: " + "`r`r" + $securitygroup + "`r`r"
$user = $result.inputobject
$searcher.filter = "(&(objectCategory=person)(objectClass=user)(distinguishedname=$user))"
$user = $searcher.FindOne()
$passtoemailsubuser += $user.properties.samaccountname
$mod = $true
}}
}
}
if ($mod -eq $true) {
$from = New-Object System.Net.Mail.MailAddress "from@address.com"
$to = New-Object System.Net.Mail.MailAddress "to@address.com"
$message = new-object System.Net.Mail.MailMessage $from, $to
$message.Subject = "The following accounts were involved in a security group modification: $passtoemailsubuser"
$message.Body = "Note the following security group modification information: `r`r $passtoemailbody"
$server = "SMTPSERVERNAME"
$client = new-object system.net.mail.smtpclient $server
$client.port = 125
$client.Send($message)
foreach($entry in $passtoemailbody)
{(get-date).tostring() + " - " + $Entry >> $script:WorkingDirectory\Log.txt}
(get-date).tostring() + " - Group Membership compare has been baselined" >> $script:WorkingDirectory\log.txt
re-baseline
}
else {
$from = New-Object System.Net.Mail.MailAddress "from@address.com"
$to = New-Object System.Net.Mail.MailAddress "to@address.com"
$message = new-object System.Net.Mail.MailMessage $from, $to
$message.Subject = "No modifications to the audited security groups have been made."
$message.Body = "No modifications to the audited security groups have been made."
$server = "SMTPSERVERNAME"
$client = new-object system.net.mail.smtpclient $server
$client.port = 125
$client.Send($message)
"No Changes have been made"
}