#########################################################################
############         Ghetto GPO Change Audit               ##############
############         DRAFT / WIP in-progress               ##############
############ Lists/Emails modified GPO's only, not linking ##############
#########################################################################
############   script by NJD 2021-03-08, edited Oct 2024   ##############
#########################################################################

############# Programmatically set variables ################
$MyDomain = (Get-ADDomain).DNSRoot                # AD Domain root in plain-text format
$MyDomainDN = (Get-ADDomain).DistinguishedName    # AD Domain root distinguishedName
$today = Get-Date '0:00'                          # today at minute 0
$yesterday = $Today.AddDays(-1)                   # yesterday
$hostname=$Env:COMPUTERNAME
########### End Programmatically set variables ##############

########## REQUIRED USER VARIABLES ###################
$adminEmailAddr = "email1$MyDomain"#,"email2@$MyDomain","email3@$MyDomain"
$hostname=$Env:COMPUTERNAME
$smtpServer="mgate.$MyDomain"
$from = "$hostname <noreply@$MyDomain>"
$subject = "Automated script: GPO Change Audit"
########### END REQUIRED USER VARIABLES ##############

########### TESTING VARIABLES ############
$testing = $true
if ($testing) {
    $today = Get-Date                #change this for testing some other day/time
    $yesterday = $Today.AddDays(-8)  #change this for testing some other time period
    $subject+=" (TESTING)"
}
########## END TESTING VARIABLES #########


############ sendEmail ###############
function sendEmail {
    param($body)
    if ($body) {
        Write-host -NoNewline "Emailing $adminEmailAddr : "
        $textEncoding = [System.Text.Encoding]::UTF8
        try {
            Send-Mailmessage -smtpServer $smtpServer -from $from -to $adminEmailAddr -subject $subject -body $body -bodyashtml -priority High -Encoding $textEncoding -ErrorAction Stop
            if (!($SendErr)) {
                write-host "Successfully emailed $adminEmailAddr"
            }
        } catch {
            write-host "FAILED to email $adminEmailAddr via $smtpServer"
            throw $_
        }
    } else {
        Write-Host "Nothing to email."
    }
}
########## end sendEmail ###############

############# MAIN ##############
$body = ''      # init
$count = 0      # init
$summary = ''   # init

Try {
    Write-Host "Gathering GPO Policy Changes ...`r`n"
    ### Get all the required Security Events ###
    $List = Get-ADObject -SearchBase "CN=Policies,CN=System,$MyDomainDN" -Filter 'WhenChanged -ge $yesterday' -Properties * -ErrorAction stop -ErrorVariable Err
} catch {
    write-host -fore Red "GPO Policy Changes not found for $yesterday"
    throw $_
} finally { ### email the GPO/results
    ForEach ($object in $List) {
        if ($object.Displayname) {
            $count++
            $changedTime = ($object.whenChanged).ToString()
            $changedGPO = ($object.Displayname).ToString()

            # I wish to print [$object.] AddedProperties, RemovedProperties and ModifiedProperties , but continuously fail at such.

            foreach ($h in ($object.AddedProperties)) {
                Write-Host "${h}: $($object.AddedProperties.$h)"
            }

            $summary += "GPO Changed: $changedTime $changedGPO`r`n"
            $body += "GPO Changed: $changedTime $changedGPO<br><br>"
            $body += '<b>Details</b>'
            $body += ($object | convertto-html -as list)
            $body += '<br><b>Report</b>'
            $body += (Get-GPOReport -Name $object.DisplayName -ReportType Html)
        }
        $body += "<br><br>"
    }
    $summary = "$count GPO's changed.`r`n" + $summary 
}

write-host $summary

if ($body) { sendEmail($body) }
############ END MAIN #############