I wrote this script to watch the time on all our domain controllers, compare it, and alert me if it's off.
Be aware that this version doesn't have a window of larger than 1 minute. I plan to fix that later.
Same as always, create the xml config file in the same folder. See the end of the script for parameters for the file. Use at your own risk. Feel free to do what you want with the script (It would be great if you leave my name associated with this and any other scripts I write, but thats up to you.)
NOTE: Please use this as reference ONLY for now. Until I can add a trigger window all this will do is spam you all week!
Param(
[bool]$Console = $false
)
<#==============================================================================
File Name : DCTimeTest.ps1
Original Author : Kenneth C. Mazie
:
Description : Identifies all domain
controllers and polls them for current time, then compares.
:
Notes : Normal operation is with
no command line options.
:
Optional argument: -Console $true (displays
runtime info on console)
:
Warnings : None
:
Legal : Public Domain. Modify and
redistribute freely. No rights reserved.
: SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR
GUARANTEES OF
: ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
:
Credits
: Code snippets and/or ideas came from many sources including but
:
not limited to the following:
:
Last Update by : Kenneth C. Mazie
Version History : v1.0 - 11-30-17 -
Original
Change History : v1.1 - 00-00-00 - Coming
soon. Expected to allow finer comparison of minute differences.
:
#===============================================================================#>
#requires
-version 5.0
Clear-host
$ErrorActionPreference = "silentlycontinue"
$Computer = $Env:ComputerName
$ScriptName = ($MyInvocation.MyCommand.Name).split(".")[0]
$Script:ConfigFile = "$PSScriptRoot\$ScriptName.xml"
Import-Module ActiveDirectory
$Script:Message = @()
$Script:MError = 0
$Script:HError = 0
$Script:LoopCount = 1
#--[ Add header
to email report ]--
$Script:ReportBody = @()
$Script:ReportBody += '
<style type="text/css">
table.myTable { border:5px solid black;border-collapse:collapse; }
table.myTable td { border:2px solid black;padding:5px}
table.myTable th { border:2px solid black;padding:5px;background: #949494 }
table.bottomBorder { border-collapse:collapse; }
table.bottomBorder td, table.bottomBorder th { border-bottom:1px dotted black;padding:5px; }
tr.noBorder td {border: 0; }
</style>'
$Script:ReportBody +=
'<table class="myTable">
<tr class="noBorder"><td colspan=2><center><h1>- Domain Controller Time Sync Error -</h1></td></tr>
<tr class="noBorder"><td colspan=2><center>A time synchronization error has been detected on a domain controller.</td></tr>
<tr><th>Domain Controller</th><th>Detected Time</th></tr>
'
#--[ Read and
load configuration file ]-------------------------------------
If (!(Test-Path $Script:ConfigFile)){ #--[ Error out if configuration file
doesn't exist ]--
Write-Host "---------------------------------------------" -ForegroundColor Red
Write-Host "--[
MISSING CONFIG FILE. Script aborted.
]--" -ForegroundColor Red
Write-Host "---------------------------------------------" -ForegroundColor Red
break
}Else{
[xml]$Script:Configuration = Get-Content "$PSScriptRoot\$ScriptName.xml" #--[ Load configuration ]--
$Script:DebugEmail = $Script:Configuration.Settings.Email.Debug
$Script:EmailTo = $Script:Configuration.Settings.Email.To
$Script:EmailFrom = $Script:Configuration.Settings.Email.From
$Script:Subject = $Script:Configuration.Settings.Email.Subject
$Script:EmailHTML = $Script:Configuration.Settings.Email.HTML
$Script:UserName = $Script:Configuration.Settings.Credentials.Username
$Script:EncryptedPW = $Script:Configuration.Settings.Credentials.Password
$Script:Base64String = $Script:Configuration.Settings.Credentials.Key
$Script:SmtpServer = $Script:Configuration.Settings.Email.SmtpServer
$Script:UserName = $Script:Configuration.Settings.Credentials.Username
$Script:EncryptedPW = $Script:Configuration.Settings.Credentials.Password
$Script:Base64String = $Script:Configuration.Settings.Credentials.Key
$ByteArray = [System.Convert]::FromBase64String($Script:Base64String);
$Script:Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Script:UserName, ($Script:EncryptedPW | ConvertTo-SecureString -Key $ByteArray)
}
#-------------------------------------------------------------------------------
Function eMail {
If ($Console){Write-Host "--
Sending Email" -ForegroundColor Yellow}
$SMTP = new-object System.Net.Mail.SmtpClient($Script:SmtpServer)
$Email = New-Object System.Net.Mail.MailMessage
$Email.Body = $Script:ReportBody
$Email.IsBodyHtml = $Script:EmailHTML
$Email.To.Add($Script:EmailTo)
$Email.From = $Script:EmailFrom
$Email.Subject = $Script:Subject
$SMTP.Send($Email)
$Email.Dispose()
$SMTP.Dispose()
}
Function GetTimes {
If ($Console){Write-Host "`nGetting
Data..." -ForegroundColor Yellow}
$Script:HourResults = @()
$Script:MinuteResults = @()
$FGColor = "#000000"
$BGColor = "#bbbbbb"
$BGColorRed = "#bbbbbb"
$BGColorOra = "#bbbbbb"
$BGColorYel = "#bbbbbb"
$Script:RunSummary = @()
foreach($DC in $Script:DcList){
if ($DC.Name -ne $Env:computername){
try{
If ($Console){Write-Host "--
Polling:"$DC.Name.PadRight(13," ") -ForegroundColor cyan -NoNewline }
$Data = @(Get-WmiObject -Class win32_localtime -ComputerName $DC.name -Credential $Script:Credential -ErrorAction "stop") #--[ Array with all returned time data
for selected DC ]--
$HMS = (($Data.Hour).ToString().PadLeft(2,"0"))+':'+(($Data.Minute).ToString().PadLeft(2,"0"))+':'+(($Data.Second).ToString().PadLeft(2,"0"))
If ($Console){Write-Host $HMS}
}catch{
$_.Exception.Message
}
}Else{
#--[ local time if run from a DC
]--
}
$Script:HourResults += ($Data.Hour).ToString()
$Script:MinuteResults += ($Data.Minute).ToString()
$RowData += '<tr>'
$RowData += '<td bgcolor='+$BGColor+'><font
color='+$FGColor+'>'+$Data.PSComputerName+'</td>'
$RowData += '<td bgcolor='+$BGColor+'><font
color='+$FGColor+'>'+$HMS+'</td>'
$RowData += '</tr>'
}
$Script:RunSummary += $RowData
}
Function CheckHour {
If (($Script:HourResults | Sort-Object | Get-Unique).count -gt 1){
#If (($Script:Results[0]).Hour -eq
($Script:Results[1]).Hour -eq ($Script:Results[2]).Hour -eq
($Script:Results[3]).Hour){
If ($Console){Write-Host "-- Hour
mis-match" -ForegroundColor red}
#If ($Console){Write-Host ($Script:Results[0])[1]" "($Script:Results[1])[1]" "($Script:Results[1])[1]" "($Script:Results[1])[1]}
$Script:HError
}Else{
If ($Console){Write-Host "-- Hour
match" -ForegroundColor green}
$Script:HError = $False
}
}
Function CheckMinute {
If (($Script:MinuteResults | Sort-Object | Get-Unique).count -gt 1){
If ($Console){Write-Host "-- Minute
mis-match" -ForegroundColor red}
$Script:MError = $True
}Else{
If ($Console){Write-Host "-- Minute
match" -ForegroundColor green}
$Script:MError = $False
}
}
#--[ Main Loop
]-----------------------------------------------------
#$Script:DcList
= Get-ADGroupMember 'Domain Controllers' -Credential $Script:Credential
$Script:DcList = Get-ADDomainController -Credential $Script:Credential -Filter *
While(($Script:HError) -or ($Script:MError) -or ($Script:LoopCount -eq 1)){
If ($Console -and ($Script:LoopCount -gt 1)){Write-Host "`nLooping..." -ForegroundColor yellow}
Write-Host "`n--[
Loop Iteration: $Script:LoopCount ]--------------------------------"
GetTimes
If ($Console){Write-Host "`nComparing..." -ForegroundColor Yellow}
CheckHour
CheckMinute
If(($Script:HError) -or ($Script:MError)){
$SleepSec = 6
If ($Console){Write-Host "`nLooping..." -ForegroundColor yellow}
If ($Console){Write-Host "--
Sleeping $SleepSec sec..." -ForegroundColor cyan}
Sleep -Seconds $SleepSec
}
$Script:LoopCount++
If (($Script:LoopCount % 11) -eq 0){ #--[ Send email every 10 loops (counter
starts at 1) ]--
$Script:ReportBody +=$Script:RunSummary
$Script:ReportBody += '<tr
class="noBorder"><td colspan=2><font size=2
color=#909090>Script "'+$MyInvocation.MyCommand.Name+'"
executed from server "'+$env:computername+'".</td></tr>'
$Script:ReportBody += '</table><br><br>'
eMail
}
}
If ((!$Script:HError) -and (!$Script:MError)){
If ($Console){Write-Host "`n-- Good
Result. No further action required." -ForegroundColor green}
If ($Console){Write-Host "`n---
COMPLETED ---`n" -ForegroundColor red}
}
<#--[ Sample
Config file
]--------------------------------------------------------------------
<!-- Settings
& Configuration File -->
<Settings>
<General>
<DebugTarget>testpc</DebugTarget>
</General>
<Email>
<From>PowerShell@domain.com</From>
<To>you@domain.com</To>
<Debug>you@domain.com</Debug>
<Subject>Domain Controller
Time Sync Error</Subject>
<HTML>$true</HTML>
<SmtpServer>10.10.10.50</SmtpServer>
</Email>
<Credentials>
<UserName>domain\serviceaccount</UserName>
<Password>764A0AGEAMAAwf0423413b16050a5345MgBA0AGEAMAAw0a5AWQB6AHoFEAPQA9AHA0AGEAMAAwAZgA3ADIAYQAwADYAZAADQAZgBiAGMAYQBA0AGEAMAAwQAzAAeQA0AEcAaAB1AGYANAAyADUAYQA2AGQAZAA2ADQAYwBkAA0ADEANgBiADAANwBkADEANAA4AGQA3AGUAZgBkAGYAZAA=</Password>
<Key>kdh/AWnHbuC+Eyj2CvLO6/AWnHbuTh7HCvLOIObie8mE=</Key>
</Credentials>
</Settings>
#>
No comments:
Post a Comment