diff --git a/AlertManagement.PS/AlertManagement.PS.ps1 b/AlertManagement.PS/AlertManagement.PS.ps1 deleted file mode 100644 index c5eb80f..0000000 --- a/AlertManagement.PS/AlertManagement.PS.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -# -# Script.ps1 -# diff --git a/AlertManagement.PS/AlertManagement.PS.pssproj b/AlertManagement.PS/AlertManagement.PS.pssproj index 2f1da76..4014cdf 100644 --- a/AlertManagement.PS/AlertManagement.PS.pssproj +++ b/AlertManagement.PS/AlertManagement.PS.pssproj @@ -25,9 +25,13 @@ prompt 4 - - + + + + + + diff --git a/AlertManagement.PS/Escalate-SCOMAlert.ps1 b/AlertManagement.PS/Escalate-SCOMAlert.ps1 new file mode 100644 index 0000000..2b890f4 --- /dev/null +++ b/AlertManagement.PS/Escalate-SCOMAlert.ps1 @@ -0,0 +1,424 @@ +######################################################################## +# Escalate-SCOMAlert.ps1 +# Hugh Scott +# 2018/07/09 +# +# Description: +# Escalate SCOM alerts based on rules in config file. Note that this +# may require that the administrator add custom ResolutionStates to +# SCOM. +# +# THIS CODE IS PROVIDED AS-IS WITH NO WARRANTIES EITHER EXPRESSED OR +# IMPLIED. +# +# Modifications: +# Date Initials Description +# 2018/07/09 HMS -Original +# 2018/07/10 HMS -Updated; added postPipelineFilter +# +######################################################################## + +# Load the Operations Manager script API +$momApi = New-Object -ComObject MOM.ScriptAPI + +#region Functions +function DateFieldReplace { +param ( + [string]$criteria, + [int]$timeOffset +) + + # INITIALIZE RETURN VALUE + [string]$tmpString = "" + + # COMPUTE TIME OFFSET; CAST AS STRING VALUE + [int]$m_timeOffset = -$timeOffset + [datetime]$compareDate = (Get-Date).AddMinutes($m_timeOffset).ToUniversalTime() + [string]$dateString = $compareDate.ToString("MM/dd/yyyy HH:mm:ss") + + If($criteria -match "__LastModified__") + { + $tmpString = $criteria.Replace("__LastModified__", $dateString) + } + ElseIf($criteria -match "__TimeRaised__") + { + $tmpString = $criteria.Replace("__TimeRaised__", $dateString) + } + Else + { + $tmpString = $criteria + } + + # REPLACE ESCAPED XML CHARACTERS + $tmpString = $tmpString.Replace("<","<") + $tmpString = $tmpString.Replace(">",">") + + Return $tmpString + +} + +function CleanPostPipelineFilter { +param ([string]$postPipelineFilter) + [string]$tmpString = "" + + # REPLACE ESCAPED XML CHARACTERS + $tmpString = $postPipelineFilter.Replace("<","<") + $tmpString = $postPipelineFilter.Replace(">",">") + + Return $tmpString +} +#endregion Functions + +# RETRIEVE CONFIGURATION FILE WITH RULES AND EXCEPTIONS +[xml]$configFile= Get-Content 'D:\Admin\Scripts\EscalateScomAlerts\escalate.alert.config' + +# MANAGEMENT SERVER +[string]$managementServer = '.' + +# LOG FILE +[string]$logFilePath = $configFile.config.settings.outputpath.name +[string]$fileName = "AlertEscalation." + (Get-Date -Format "yyyy.MM.dd") + ".log" +[string]$logFileName = Join-Path $logFilePath $fileName + +if ( -not ( Get-Module -Name OperationsManager ) ) +{ + Import-Module OperationsManager +} + +#region Update Type Data + +# Add a UnitMonitor property to the alert which contains the associated unit monitor object +$updateTypeDataUnitMonitorParameters = @{ + TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert' + MemberType = 'ScriptProperty' + MemberName = 'UnitMonitor' + Value = { + if ( $this.IsMonitorAlert ) + { + function GetScomChildNodes + { + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + #[Microsoft.EnterpriseManagement.Common.MonitoringHierarchyNode`1[[Microsoft.EnterpriseManagement.Configuration.ManagementPackMonitor, Microsoft.EnterpriseManagement.Core, Version=7.0.5000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]] + [System.Object] + $MonitoringHierarchyNode + ) + + # Create an array for the unit monitors + $unitMonitors = @() + + foreach ( $childNode in $MonitoringHierarchyNode.ChildNodes ) + { + if ( $childNode.Item.GetType().FullName -eq 'Microsoft.EnterpriseManagement.Configuration.UnitMonitor' ) + { + Write-Verbose -Message "Unit Monitor: $($childNode.Item.DisplayName)" + $unitMonitors += $childNode.Item + } + else + { + Write-Verbose -Message $childNode.Item.DisplayName + Write-Verbose -Message ($childNode.GetType().FullName) + GetScomChildNodes -MonitoringHierarchyNode $childNode.Item + } + } + + return $unitMonitors + } + + # Get the associated monitor from the alert + if ( $this.IsMonitorAlert ) + { + $monitor = Get-SCOMClassInstance -Id $this.MonitoringObjectId + } + else + { + Write-Verbose -Message ( 'The alert "{0}" is not a monitor alert.' -f $this.Name ) + exit + } + + # Get the child nodes of the monitor + $unitMonitors = @() + foreach ( $childNode in $monitor.GetMonitorHierarchy().ChildNodes ) + { + $unitMonitors += GetScomChildNodes -MonitoringHierarchyNode $childNode + } + + # Get the unit monitor which generated the alert + $unitMonitor = $unitMonitors | Where-Object -FilterScript { $_.Id -eq $this.MonitoringRuleId } + + return $unitMonitor + } + } +} +Update-TypeData @updateTypeDataUnitMonitorParameters + +# Add a Monitor property to the alert which contains the associated unit monitor object +$updateTypeDataMonitorParameters = @{ + TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert' + MemberType = 'ScriptProperty' + MemberName = 'Monitor' + Value = { + Get-SCOMClassInstance -Id $this.MonitoringObjectId + } +} +Update-TypeData @updateTypeDataMonitorParameters + +# Add a HealthStateSuccess property to the alert which contains the associated unit monitor object +$updateTypeDataHealthStateSuccessParameters = @{ + TypeName = 'Microsoft.EnterpriseManagement.Monitoring.MonitoringAlert' + MemberType = 'ScriptProperty' + MemberName = 'HealthStateSuccess' + Value = { + return $this.UnitMonitor.OperationalStateCollection | + Where-Object -FilterScript { $_.HealthState -eq 'Success' } | + Select-Object -ExpandProperty Name + } +} +Update-TypeData @updateTypeDataHealthStateSuccessParameters + +#endregion Update Type Data + +$Connection = New-SCManagementGroupConnection $managementServer -PassThru + +If($Connection.IsActive) +{ + # INITIALIZE AlertCount + [int]$AlertCount = 0 + + # Alert Storm Processing + $alertStormRules = $configFile.SelectNodes("//config/alertStormRules/stormRule[@enabled='true']") | Sort-Object {$_.Sequence} + + foreach ( $alertStormRule in $alertStormRules ) + { + # Get the alerts defined by the criteria and group them by the defined property + $potentialStormAlertGroups = Get-SCOMAlert -Criteria $alertStormRule.Criteria.InnerText | + Group-Object -Property $alertStormRule.Property | + Where-Object -FilterScript { $_.Count -gt 1 } + + # Define a counter which will be used to further subdivide the alerts into groups + $groupCounter = 0 + + # Create a hashtable to store the new groups of alerts + $stormAlertGroups = @{$groupCounter = @()} + + foreach ( $potentialStormAlertGroup in $potentialStormAlertGroups ) + { + # Create a variable to base the time elapsed calcluations off of + $previousDateTime = [System.DateTime]::MinValue + + foreach ( $alert in ( $potentialStormAlertGroup.Group | Sort-Object -Property TimeRaised ) ) + { + # If the alert was raised less than the defined window from the previous alert + if ( ( $alert.TimeRaised - $previousDateTime ).TotalMinutes -lt $alertStormRule.Window ) + { + # Add the alert to the current group + $stormAlertGroups[$groupCounter] += $alert + } + else + { + # Increment the group counter + $groupCounter++ + + # Create a new group + $stormAlertGroups[$groupCounter] = @($alert) + } + + # Update the Previous Date/Time variable + $previousDateTime = $alert.TimeRaised + } + } + + # Get the groups which meet the threshold for number of the same alert + $stormAlerts = $stormAlertGroups.GetEnumerator() | + Where-Object -FilterScript { $_.Value.Count -ge $alertStormRule.Count } + + foreach ( $stormAlert in $stormAlerts.GetEnumerator() ) + { + # Get the alerts which were previously tagged as an alert storm + $oldAlertStormAlerts = $stormAlert.Value | + Where-Object -FilterScript { ( $_.ResolutionState -eq 18 ) -and $_.TicketID } + + if ( $oldAlertStormAlerts.Count -gt 0 ) + { + # Get the existing "ticket id" + $ticketId = $oldAlertStormAlerts | Select-Object -ExpandProperty TicketId -Unique + } + else + { + # Get the alert name + $alertName = $stormAlert.Value | Select-Object -ExpandProperty Name -Unique + + # Define the "ticket id" + $ticketId = ( Get-Date -Format 'MM/dd/yyyy hh:mm:ss {0}' ) -f $alertName + + # Create an array of alerts which should be passed into a storm alert + $createStormAlert = @() + + foreach ( $alert in $stormAlert.Value ) + { + # Get the associated monitoring object + $alertMonitoringObject = Get-ScomMonitoringObject -Id $alert.MonitoringObjectId + + ###################################################################################### + # HMS + # 2020/03/23 + # Comment out Check for Asset Status; most customers won't use this + ###################################################################################### + # if ( $alertMonitoringObject.'[System.ConfigItem].AssetStatus'.Value -eq 'Deployed' ) + # { + $createStormAlert += $alert + # } + } + + # Get a unique list of monitoring objects + $monitoringObjects = $createStormAlert | + Select-Object -ExpandProperty MonitoringObjectFullName -Unique | + Sort-Object + + # Define the string which will be passed in as the "script name" property for LogScriptEvent + $stormDescription = "The alert ""$alertName"" was triggered $($createStormAlert.Count) times for the following objects:" + + # Define the event details + $eventDetails = New-Object -TypeName System.Text.StringBuilder + $eventDetails.AppendLine() > $null + $eventDetails.AppendLine() > $null + $monitoringObjects | ForEach-Object -Process { $eventDetails.AppendLine($_) > $null } + $eventDetails.AppendLine() > $null + $eventDetails.AppendLine("Internal ticket id: $ticketId") > $null + + # Raise an event indicating an alert storm was detected + $momApi.LogScriptEvent($stormDescription, 9908, 2, $eventDetails.ToString()) + } + + # Mark the alert as being part of an alert storm + $stormAlert.Value | + Where-Object -FilterScript { $_.ResolutionState -ne 18 } | + Set-SCOMAlert -ResolutionState 18 -Comment $alertStormRule.Comment.InnerText -TicketId $ticketId + } + } + + # PROCESS EXCEPTIONS FIRST + $alertExceptions = $configFile.SelectNodes("//config/exceptions/exception[@enabled='true']") | Sort-Object {$_.Sequence} + + foreach($exception in $alertExceptions) + { + # ASSIGN VALUES + # Write-Host $exception.name + [string]$criteria = $exception.Criteria.InnerText + [int]$newResolutionState = $exception.NewResolutionState + [string]$postPipelineFilter = $exception.PostPipelineFilter #.InnerText + [string]$comment = $exception.Comment.InnerText + [string]$name = $exception.Name + + # REPLACE TIME BASED CRITERIA + if($criteria -match "__TimeRaised__") + { + [int]$timeRaisedAge = $exception.TimeRaisedAge + $criteria = DateFieldReplace $criteria $timeRaisedAge + } + if($criteria -match "__LastModified__") + { + [int]$lastModifiedAge = $exception.LastModifiedAge + $criteria = DateFieldReplace $criteria $lastModifiedAge + } + + # COLLECT ALERTS BASED ON CRITERIA + If($postPipelineFilter -eq "") + { + $alerts = Get-SCOMAlert -Criteria $criteria + } + Else + { + [string]$cleanString=CleanPostPipelineFilter $postPipelineFilter + [scriptblock]$filter=[System.Management.Automation.ScriptBlock]::Create($cleanString) + + $alerts = Get-SCOMAlert -Criteria $criteria | Where-Object -FilterScript $filter + } + + ### UPDATE MATCHING ALERTS TO NEW RESOLUTION STATE + If($alerts.Count -gt 0) + { + $alerts | Set-SCOMAlert -ResolutionState $newResolutionState -Comment $Comment + # Write-Host $criteria + $AlertCount = $alerts.Count + $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : INFO : Updated $AlertCount alert(s) to resolution state $newResolutionState (Exception: $name)." + # Write-Host " : $msg" + Add-Content $logFileName $msg + } + + + # RESET EXCEPTION VALUES + $criteria = $null + $newResolutionState = $null + $postPipelineFilter = $null + $comment = $null + $name=$null + + } + + # PROCESS RULES SECOND + $alertRules = $configFile.SelectNodes("//config/rules/rule[@enabled='true']") | Sort-Object {$_.sequence} + + foreach($rule in $alertRules) + { + # ASSIGN VALUES + # Write-Host $rule.name + [string]$criteria = $rule.Criteria.InnerText + [int]$newResolutionState = $rule.NewResolutionState + [string]$postPipelineFilter = $rule.PostPipelineFilter #.InnerText + [string]$comment = $rule.Comment.InnerText + [string]$name=$rule.name + + # REPLACE TIME BASED CRITERIA + if($criteria -match "__TimeRaised__") + { + [int]$timeRaisedAge = $rule.TimeRaisedAge + $criteria = DateFieldReplace $criteria $timeRaisedAge + } + if($criteria -match "__LastModified__") + { + [int]$lastModifiedAge = $rule.LastModifiedAge + $criteria = DateFieldReplace $criteria $lastModifiedAge + } + + # COLLECT ALERTS BASED ON CRITERIA + if ( [System.String]::IsNullOrEmpty($postPipelineFilter) ) + { + $alerts = Get-SCOMAlert -Criteria $criteria + } + else + { + [string]$cleanString=CleanPostPipelineFilter $postPipelineFilter + [scriptblock]$filter=[System.Management.Automation.ScriptBlock]::Create($cleanString) + + $alerts = Get-SCOMAlert -Criteria $criteria | Where-Object -FilterScript $filter + } + + ### UPDATE MATCHING ALERTS TO NEW RESOLUTION STATE + If($alerts.Count -gt 0) + { + $alerts | Set-SCOMAlert -ResolutionState $newResolutionState -Comment $Comment + # Write-Host $criteria + $AlertCount = $alerts.Count + $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : INFO : Updated $AlertCount alert(s) to resolution state $newResolutionState (Rule: $name)." + # Write-Host " : $msg" + + Add-Content $logFileName $msg + } + + # RESET RULE VALUES + $criteria = $null + $newResolutionState = $null + $postPipelineFilter = $null + $comment = $null + $name=$null + } + +} +Else +{ + $msg = (Get-Date -Format "yyyy/MM/dd hh:mm:ss") + " : ERROR : Unable to connect to Management Server" + Add-Content $logFileName $msg +} diff --git a/AlertManagement.PS/assign.alert.config b/AlertManagement.PS/assign.alert.config new file mode 100644 index 0000000..9c1d5c6 --- /dev/null +++ b/AlertManagement.PS/assign.alert.config @@ -0,0 +1,382 @@ + + + + + + + + + + 2 + + + + 5 + Assigned + + + Unassigned + 5 + Unassigned + + + + + + Microsoft.SQLServer.Library + DBA Team + + + Microsoft.SQLServer.2008.Discovery + DBA Team + + + Microsoft.SQLServer.2012.Discovery + DBA Team + + + Microsoft.SQLServer.2014.Discovery + DBA Team + + + Microsoft.Windows.Server.AD.Library + Active Directory Team + + + Microsoft.Windows.Server.AD.2000.Discovery + Active Directory Team + + + Microsoft.Windows.Server.AD.2003.Discovery + Active Directory Team + + + Microsoft.Windows.Server.AD.2008.Discovery + Active Directory Team + + + Microsoft.Exchange.2010 + Active Directory Team + + + Microsoft.Windows.Server.2003 + Windows Team + + + Microsoft.Windows.Server.2008 + Windows Team + + + Microsoft.Windows.Server.2012 + Windows Team + + + Microsoft.Windows.Server.2008.Discovery + Windows Team + + + Microsoft.Windows.Server.2012.Discovery + Windows Team + + + Microsoft.Windows.Server.2012.R2.Discovery + Windows Team + + + Microsoft.Windows.Server.Library + Windows Team + + + Microsoft.Windows.Library + Windows Team + + + Microsoft.Windows.Cluster.Library + Windows Team + + + Microsoft.Windows.Cluster.Management.Library + Windows Team + + + Microsoft.Windows.InternetInformationServices.2008 + App Support + + + Microsoft.Windows.InternetInformationServices.2012 + App Support + + + SystemCenterCentral.Utilities.Certificates + App Support + + + Microsoft.SystemCenter.Library + Monitoring Team + + + Microsoft.SystemCenter.Notifications.Library + Monitoring Team + + + Microsoft.SystemCenter.Apm.Infrastructure + Monitoring Team + + + Microsoft.SystemCenter.2012.Orchestrator + Monitoring Team + + + Microsoft.SystemCenter2012.ConfigurationManager.Library + Config Mgmt Team + + + Microsoft.Windows.Server.UpdateServices.2012.R2 + Config Mgmt Team + + + Microsoft.HPUX.11iv2 + Linux Team + + + Microsoft.HPUX.11iv3 + Linux Team + + + Microsoft.Solaris.10 + Linux Team + + + Microsoft.Solaris.11 + Linux Team + + + Microsoft.AIX.6.1 + Linux Team + + + Microsoft.AIX.7 + Linux Team + + + Microsoft.Linux.RHEL.4 + Linux Team + + + Microsoft.Linux.RHEL.5 + Linux Team + + + Microsoft.Linux.RHEL.6 + Linux Team + + + Microsoft.Linux.RHEL.7 + Linux Team + + + Microsoft.Unix.Library + Linux Team + + + SCOM2012.Maintenance.Mode.Scheduler.Monitoring + Monitoring Team + + + Microsoft.SystemCenter.OperationsManager.Infra + Monitoring Team + + + Microsoft.SystemCenter.ACS.Internal + Monitoring Team + + + Microsoft.SystemCenter.DataWarehouse.Internal + Monitoring Team + + + Microsoft.SystemCenter.OperationsManager.DataAccessService + Monitoring Team + + + Microsoft.Windows.Server.ClusterSharedVolumeMonitoring + Windows Team + + + Microsoft.Windows.Server.2016 + Windows Team + + + Microsoft.Windows.Server.2016.Discovery + Windows Team + + + Microsoft.SQLServer.2016.Discovery + DBA Team + + + Microsoft.SQLServer.2008.Replication.Discovery + DBA Team + + + Microsoft.SQLServer.2012.Replication.Discovery + DBA Team + + + Microsoft.SQLServer.2014.Replication.Discovery + DBA Team + + + Microsoft.SQLServer.2016.Replication.Discovery + DBA Team + + + Microsoft.SQLServer.2012.AlwaysOn.Discovery + DBA Team + + + Microsoft.SQLServer.2014.AlwaysOn.Discovery + DBA Team + + + Microsoft.SQLServer.2016.AlwaysOn.Discovery + DBA Team + + + Microsoft.Windows.InternetInformationServices.2016 + App Support + + + Microsoft.SystemCenter.2016.Orchestrator + Monitoring Team + + + Microsoft.SQLServer.Windows.Discovery + DBA Team + + + Microsoft.SQLServer.Windows.Monitoring + DBA Team + + + URLGenie + App Support + + + Microsoft.Windows.Server.AD.2016.Discovery + Active Directory Team + + + Microsoft.Windows.Server.AD.Class.Library + Active Directory Team + + + Microsoft.SQLServer.Core.Library + DBA Team + + + Microsoft.SystemCenter.O365 + O365 Team + + + Microsoft.Windows.ActiveDirectoryCertificateServices.2012.R2.Discovery + Active Directory Team + + + Microsoft.WindowsDefender + Windows Team + + + Microsoft.Windows.ActiveDirectoryCertificateServices.2012.R2.Discovery + Windows Team + + + Microsoft.Windows.HyperV.Library + Virtualization Team + + + Microsoft.Windows.DNSServer.2016 + Active Directory Team + + + Microsoft.Windows.MSDTC.2012.R2 + Windows Team + + + Microsoft.Windows.MSDTC.2016 + Windows Team + + + Microsoft.SharePoint.Foundation.2013.Discovery + App Support + + + Microsoft.SharePoint.2019.Discovery + App Support + + + SharePointCommon + App Support + + + Microsoft.SharePoint.Server.2013.Discovery + App Support + + + + + Health Service Heartbeat Failure + Windows Team + + + + + Failed to Connect to Computer + Windows Team + + + + + Failed to perform Application Pool discovery + App Support + + + + + Failed to retrieve Application Pool state + App Support + + + + + Failed to perform Web Server properties discovery + App Support + + + + + Failed to perform Web Site discovery + App Support + + + + + Certificate lifespan alert + Windows Team + MonitoringObjectDisplayName + rdpcert + + + Microsoft.Windows.Library + EFG Windows Support + MonitoringObjectFullName + efg + + + OpsLogix.IMP.Ping + Network Team + MonitoringObjectFullName + efg + + + \ No newline at end of file diff --git a/AlertManagement.PS/assign.alert.ps1 b/AlertManagement.PS/assign.alert.ps1 new file mode 100644 index 0000000..b6b0413 --- /dev/null +++ b/AlertManagement.PS/assign.alert.ps1 @@ -0,0 +1,265 @@ +######################################################################## +# Assign-SCOMAlert.ps1 +# Hugh Scott +# 2016/05/09 +# +# Description: +# Assign SCOM alerts based on rules in config file. Basic assignment +# is done by management pack association. +# +# NOTE: The configuration file must be updated with entries from the current +# Active Directory environment. +# +# THIS CODE IS PROVIDED AS-IS WITH NO WARRANTIES EITHER EXPRESSED OR +# IMPLIED. +# +# Modifications: +# Date Initials Description +# 2016/05/09 HMS -Original +# 2018/02/20 HMS - Modified to write Queue information to Owner field +# 2019/10/09 HMS - Significant re-write; added variables for Resolution State, Default Owner and Log Level +# +######################################################################## + +function XpathExpression { +param ( + [string]$value +) + + if ($value.Contains("'")) + { + return '\' + $value + '\'; + } + elseif ($value.Contains('\')) + { + return """" + $value + """" + } + else + { + return $value; + } +} + + # Constants section - modify stuff here: + #================================================================================= + # Assign script name variable for use in event logging. + # ScriptName should be the same as the ID of the module that the script is contained in + $ScriptName = "Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1" + $EventID = "9931" + #================================================================================= + + + # Starting Script section - All scripts get this + #================================================================================= + # Gather the start time of the script + $StartTime = Get-Date + #Set variable to be used in logging events + $whoami = whoami + # Load MOMScript API + $momapi = New-Object -comObject MOM.ScriptAPI + #Log script event that we are starting task + $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami).") + #================================================================================= + +#region Initialize +[xml]$configFile= Get-Content '.\assign.alert.config' -ErrorAction SilentlyContinue +If($null -eq $configFile){ + # Write an Error log entry + # quit +} +Else +{ + $managementGroup=$configFile.Config.Settings.ManagementGroup + # [string]$managementServer = '.' + + ## LOGGING + [string]$logPath=$configFile.Config.Settings.Logging.OutputPath + [int]$logLevel=$configFile.Config.Settings.Logging.LogLevel + + [string]$logFileDate = (Get-Date).ToString("yyyy.MM") + + [string]$logFile = "$logPath\AssignAlerts.$logFileDate.log" + + [string]$unroutedLogFile = "$logPath\MissedAlerts.$logFileDate.log" + + ## DEFAULT VALUES + + ## Unassigned Alerts + [string]$defaultUnassignedOwner=$configFile.Config.Settings.Defaults.UnAssigned.DefaultOwner + [int]$defaultUnassignedResolutionState=$configFile.Config.Settings.Defaults.UnAssigned.ResolutionState + [string]$defaultUnassignedResolutionStateName=$configFile.Config.Settings.Defaults.UnAssigned.ResolutionStateName + + ## Assigned alerts + [int]$defaultAssignedResolutionState=$configFile.Config.Settings.Defaults.Assigned.ResolutionState + [string]$defaultAssignedResolutionState=$configFile.Config.Settings.Defaults.Assigned.ResolutionStateName + +#endregion + +#region Connect + Import-Module OperationsManager + foreach($server in $managementGroup.ChildNodes) + { + If($server.Active -eq "true") + { + $connection = New-SCManagementGroupConnection $server.name -PassThru -ErrorAction SilentlyContinue + If($connection.IsActive -eq $true) + { + Break + } + } + } + + If($connection.IsActive -eq $false) + { + # Log an error + # Exit + } + Else + { +#endregion + + ######### GET ALL ALERTS IN RESOLUTION STATE 0 ############ + $NewAlerts=Get-SCOMAlert -ResolutionState 0 + + ForEach($NewAlert in $NewAlerts){ + # $unAssignedAlert = $NewAlert + $mpClassId = $NewAlert.MonitoringClassId + $mpClass = Get-SCOMClass -Id $mpClassId + + + ###### VARIABLE ASSIGNMENT ###### + [string]$mpName = $mpClass.ManagementPackName + [string]$alertName = $NewAlert.Name + [string]$displayName = $NewAlert.MonitoringObjectDisplayName + + $alertName = XPathExpression $AlertName + + #region Exceptions by Alert Name + ###### FIRST PASS; GET QUEUE ASSIGNMENT EXCEPTIONS BY ALERT NAME ###### + Try + { + $searchString = "//Config/Exceptions/Exception[AlertName='$alertName' and @enabled='true' " + + $assignmentRule = $configFile.SelectSingleNode($searchString) + } + Catch [System.Exception] + { + $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss" + $msg = "$timeNow : WARN : " + $_.Exception.Message + # Write-Host $msg + Add-Content $unroutedLogFile $msg + } + #endregion + + #region Exceptions By MP Name + ###### SECOND PASS; GET QUEUE ASSIGNMENT EXCEPTIONS BY MP NAME ###### + if($assignmentRule) + { + [string]$assignedTo=$assignmentRule.Owner + } + Else + { + Try + { + $searchString = @( + "//Config/Exceptions/Exception[ManagementPackName='$mpName' and @enabled='true' " + " and (" + " AlertProperty = 'MonitoringObjectFullName' " + " or AlertProperty = 'MonitoringObjectPath' " + " or AlertProperty = 'MonitoringObjectDisplayName' " + " )]" + ) + + $assignmentRule = $configFile.SelectSingleNode($searchString) + $Prop = $assignmentRule.AlertProperty + $PropValue = $assignmentRule.AlertPropertyContains + + If($newAlert."$Prop" -notlike "*$AlertPropertyContains*") + { + $assignmentRule = $null + } + } + Catch [System.Exception] + { + $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss" + $msg = "$timeNow : WARN : " + $_.Exception.Message + # Write-Host $msg + Add-Content $unroutedLogFile $msg + } + } + #endregion + + #region Rules + if($assignmentRule) + { + [string]$assignedTo=$assignmentRule.Owner + } + else + { + ###### THIRD PASS; GET ALERT ASSIGNMENTS FROM OBJECT CLASS ###### + Try + { + $assignmentRule = $configFile.SelectSingleNode(" + //Config/Rules/Rule[managementPackName='$mpName' and @enabled='true']" + ) + } + Catch [System.Exception] + { + $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss" + $msg = "$timeNow : WARN : " + $_.Exception.Message + # Write-Host $msg + Add-Content $unroutedLogFile $msg + } + + if ($assignmentRule) + { + [string]$assignedTo=$assignmentRule.Owner + } + else + { + [string]$assignedTo=$defaultUnassignedOwner + } + } + #endregion + + #region Set Alert + # Define a comment for Set-SCOMAlert + [string]$comment = 'Alert automation assigned to: {0}' + + If($assignedTo -ne $defaultUnassignedOwner) + { + ######## WRITE UPDATE TO ALERT ######## + $NewAlert | Set-SCOMAlert -ResolutionState $defaultAssignedResolutionState -Owner $assignedTo -Comment ( $comment -f $assignedTo ) + + # Write-LogEntry + If($logLevel -ge 2) + { + $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss" + $msg = "$timeNow : INFO : DisplayName: $displayName; AlertName: $alertName; Management Pack: $mpName; Owner: $assignedTo" + # Write-Host $msg + Add-Content $logFile $msg + } + } + else + { + ####### UNASSIGNED ALERTS ####### + $NewAlert | Set-SCOMAlert -ResolutionState $defaultUnassignedResolutionState -Owner $defaultUnassignedOwner -Comment ( $comment -f $defaultUnassignedOwner ) + # Write-LogEntry + $timeNow = Get-Date -f "yyyy/MM/dd hh:mm:ss" + $msg = "$timeNow : WARN : DisplayName: $displayName; AlertName: $alertName; Management Pack: $mpName; Owner: $defaultUnassignedOwner" + # Write-Host $msg + Add-Content $unroutedLogFile $msg + } + #endregion + } + } +} + + # End of script section + #================================================================================= + #Log an event for script ending and total execution time. + $EndTime = Get-Date + $ScriptTime = ($EndTime - $StartTime).TotalSeconds + $momapi.LogScriptEvent($ScriptName,9931,0,"`n Script Completed. `n Script Runtime: ($ScriptTime) seconds.") + #================================================================================= + # End of script \ No newline at end of file diff --git a/AlertManagement.PS/escalate.alert.config b/AlertManagement.PS/escalate.alert.config new file mode 100644 index 0000000..8c7069d --- /dev/null +++ b/AlertManagement.PS/escalate.alert.config @@ -0,0 +1,371 @@ + + + + + + + + + 100 + Name + 255]]> + 10 + 5 + 18 + + N + + + + 101 + MonitoringObjectId + 255]]> + 10 + 5 + 18 + + N + + + + + + + + 1 + + 255 + 1440 + + + + + + + 2 + + 15 + 10 + ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and ( $_.RepeatCount -gt 0 ) + + + + + + 3 + + 247 + 10 + + ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and + ( $_.RepeatCount -eq 0 ) -and + ( + $_ | ForEach-Object -Process { + $_.Monitor.ScheduleMaintenanceMode( + [System.DateTime]::Now.ToUniversalTime(), + [System.DateTime]::Now.AddMinutes(5).ToUniversalTime(), + [Microsoft.EnterpriseManagement.Monitoring.MaintenanceModeReason]::PlannedOther, + 'Alert automation: Determine if this monitor will increment the repeat count with the associated alert when it exits maintenance mode.' + ) + } + ) + + + + + + + 3 + + 247 + 2190 + + ( $_.HealthStateSuccess -eq 'ManualResetEventRaised' ) -and + ( $_.RepeatCount -eq 0 ) -and + ( $_ | ForEach-Object -Process { $_.Monitor.ResetMonitoringState($_.UnitMonitor) > $null } ) + + + + + + + 4 + + 15 + 10 + + + + + + + 5 + + 15 + 10 + $_.RepeatCount -gt 0 + + + + + + 6 + + 247 + 10 + + + + + + + 7 + + 255 + 2190 + $_.RepeatCount -eq 0 + + + + + + MSSQL Server + + 1 + + 50 + 30 + + + + + MSSQL Server + + 2 + + 50 + 30 + + + + + MSSQL Server + + 3 + + 50 + 30 + + + + + MSSQL Server + + 4 + + 50 + 30 + + + + + MSSQL Server + + 5 + + 50 + 30 + + + + + ="MSSQL Server" + + 5 + + 50 + 30 + + + + + Windows Server + + 6 + + 50 + 30 + + + + + Windows Server + + 6 + + 50 + 30 + + + + + PKI Certificate + + 7 + + 50 + 30 + + + + + MSSQL Server + + 8 + + 50 + 30 + + + + + Active Directory + 9 + + 254 + 30 + + + false + + + Active Directory + 10 + + 254 + 30 + + + false + + + MS Cluster + 11 + + 254 + 30 + + + true + + + MS Cluster + 12 + + 254 + 30 + + + true + + + IIS + 13 + + 255 + 1440 + + + true + + + MS Cluster + 14 + + 255 + 1440 + + + true + + + MS Cluster + 15 + + 255 + 1440 + + + true + + + IIS + 16 + + 255 + 1440 + + + true + + + IIS + 17 + + 15 + 0 + + + true + + + MSSQL Server + 18 + + 255 + 10 + $_.RepeatCount -lt 10 + + true + + + MSSQL Server + 19 + + 255 + 10 + $_.RepeatCount -lt 15 + + true + + + SCOM + 20 + + 255 + 10 + $_.RepeatCount -lt 10 + + true + + + Windows Server + 21 + + 15 + 0 + + + + + MSSQL Server + 22 + + 247 + 0 + + + true + + + diff --git a/AlertManagement/AlertManagement.mpproj b/AlertManagement/AlertManagement.mpproj index 6881505..b155514 100644 --- a/AlertManagement/AlertManagement.mpproj +++ b/AlertManagement/AlertManagement.mpproj @@ -50,5 +50,16 @@ false + + + + + + + + + Code + + \ No newline at end of file diff --git a/AlertManagement/Rules/AlertAssignment.mpx b/AlertManagement/Rules/AlertAssignment.mpx new file mode 100644 index 0000000..b5da626 --- /dev/null +++ b/AlertManagement/Rules/AlertAssignment.mpx @@ -0,0 +1,190 @@ + + + + + + + + System!System.ExpressionEvaluatorSchema + + + + + + + + + + + + + + + $Config/IntervalSeconds$ + $Config/SyncTime$ + + + + + + + + + + + System!System.TriggerData + + + + + + + + + + + + + + + + Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1 + + #================================================================================= + # Describe Script Here + # + # Author: + # v1.0 + #================================================================================= + param($ComputerName,$MGName,$Param1) + + + # Manual Testing section - put stuff here for manually testing script - typically parameters: + #================================================================================= + # $ComputerName = "computername.domain.com" + # $MGName = "foo" + # $Param1 = "bar" + #================================================================================= + + + # Constants section - modify stuff here: + #================================================================================= + # Assign script name variable for use in event logging. + # ScriptName should be the same as the ID of the module that the script is contained in + $ScriptName = "Microsoft.Alert.Management.Alert.Management.Assign.Alert.TimedPowerShell.Rule.WA.ps1" + $EventID = "1234" + #================================================================================= + + + # Starting Script section - All scripts get this + #================================================================================= + # Gather the start time of the script + $StartTime = Get-Date + #Set variable to be used in logging events + $whoami = whoami + # Load MOMScript API + $momapi = New-Object -comObject MOM.ScriptAPI + #Log script event that we are starting task + $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script is starting. `n Running as ($whoami).") + #================================================================================= + + + # Begin MAIN script section + #================================================================================= + # Log an event for the Params + $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n These are the parameters passed from script: `n ComputerName: ($ComputerName). `n ManagementGroup Name: ($MGName) `n Param1: ($Param1).") + #================================================================================= + # End MAIN script section + + + # End of script section + #================================================================================= + #Log an event for script ending and total execution time. + $EndTime = Get-Date + $ScriptTime = ($EndTime - $StartTime).TotalSeconds + $momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script Completed. `n Script Runtime: ($ScriptTime) seconds.") + #================================================================================= + # End of script + + + + ComputerName + $Config/ComputerName$ + + + MGName + $Target/ManagementGroup/Name$ + + + Param1 + $Config/Param1$ + + + $Config/TimeoutSeconds$ + + + + + + + + System!System.BaseData + System!System.BaseData + + + + + + + Custom + + + 86400 + + + + + + $Target/Host/Property[Type="Windows!Microsoft.Windows.Computer"]/PrincipalName$ + YourStringParamData + 120 + + + + + + + + + + Microsoft Alert.Management Alert.Management.Assign.Alert TimedPowerShell Rule + + + + + +