Using SCOM to detect missing Active Directory site IP subnet allocations

We say hello to Ruben Zimmerman today for his first guest post on our blog. Ruben is an infrastructure specialist, who specializes in Active Directory, public key infrastructure and System Center Operations Manager (SCOM). Ruben has written an article on how to use SCOM to detect missing Active Directory site IP subnet allocations - let's get started.

 

PowerShell script to parse netlogon.log

Crucial for our script is the log file netlogon.log located in C:\Windows\debug\ that contains information about clients with missing subnet allocations. A typical record could look like this:

 

04/08 16:11:14 Contoso: NO_CLIENT_SITE: Wks-01127 10.20.12.34
Month/Day   Hour:Minute:Second   AuthenticationTarget   NO_CLIENT_SITE   ClientName   ClientIP 

 

The following script parses the log file and stores all entries of the current day in a list. If there is an entry in the list, it will send the overthreshold state to SCOM and underthreshold if not.

 

$scomAPI       = New-Object -comObject "MOM.ScriptAPI"
$propertyBag   = $scomAPI.CreatePropertyBag()
 
$computerName  = $env:COMPUTERNAME
 
$cleanedList   = New-Object -TypeName 'System.Collections.Generic.List[psobject]'
$uniqueList    = New-Object -TypeName 'System.Collections.Generic.List[psobject]'
 
try {
 
    $logContent    = Get-Content -Path C:\Windows\debug\netlogon.log
    $noClientSite  = $logContent -match 'NO_CLIENT_SITE'
 
    $today         = Get-Date -Format 'MM/dd'
    $todaysRecords = $noClientSite -match "$($today).*"
 
    foreach ($record in $todaysRecords) {
 
            $recordItems   = $record -split '\s{1}'
            $itmDate       = $recordItems[0]
            $itmAuthTarget = $recordItems[2]
            $itmClientName = $recordItems[4]
            $itmClientIP   = $recordItems[5]
 
            $recordHash = @{'DomainController' = $computerName}
            $recordHash.Add('Date', $itmDate)
            $recordHash.Add('AuthenticationTarget', $itmAuthTarget)
            $recordHash.Add('ClientName', $itmClientName)
            $recordHash.Add('ClientIP', $itmClientIP)
            $recordObj = New-Object -TypeName psobject -Property $recordHash
            $null      = $cleanedList.Add($recordObj)
 
    }
 
    $cleanedList | Sort-Object -Property ClientIP -Unique | ForEach-Object {
            $null = $uniqueList.Add($_)
    }
 
    $messageText  = "The following computers could not find a DC that matches their IP range and where authenticated against $($computerName) `n`n"
    $messageText += "Please map the IP ranges to Sites in the Active Directory Sites & Services MMC. `n`n"
 
    foreach ($client in $uniqueList) {
            $messageText += "Client Name: $($client.ClientName) `t, Client IP: $($client.ClientIP) `t Authentication Target $($client.AuthenticationTarget) `tDate: $($client.Date) `n"
    }
 
} catch {
    
    $messageText = "Failed to parse logfile with error message $($error)"
 
}
 
$propertyBag.AddValue("MessageText",$messageText)
$propertyBag.AddValue("ComputerName",$computerName)
 
if($uniqueList.count -gt 0) {
  $propertyBag.AddValue("Result","OverThreshold")
} else {
  $propertyBag.AddValue("Result","UnderThreshold")
}
 
$propertyBag
System.Exception: A Text or Comment node cannot have attributes.
   at HtmlAgilityPack.HtmlAttributeCollection.Append(HtmlAttribute newAttribute)
   at HtmlAgilityPack.HtmlNode.AddClass(String name, Boolean throwError)
   at UmbracoSquaredUp.Core.Helpers.TemplateHelper.ParseImages(String text, HtmlHelper helper)
   at ASP._Page_Views_Partials_grid_editors_rte_cshtml.Execute() in C:\home\site\wwwroot\Views\Partials\grid\editors\rte.cshtml:line 10
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
   at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
   at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
   at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
   at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
   at Umbraco.Core.Profiling.ProfilingView.Render(ViewContext viewContext, TextWriter writer)
   at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
   at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model)
   at ASP._Page_Views_Partials_grid_editors_base_cshtml.Execute() in C:\home\site\wwwroot\Views\Partials\grid\editors\base.cshtml:line 20