SendEffectiveConfiguration.psm1
<#
.Synopsis Collects monitor and rule data from SCOM and sends it to OMS HTTP Data Collector API. .Description The collected data will be presented in OMS via custom solution. This module is for collecting and sending the monitor and rule overrides to OMS. .Parameter GroupDisplayName Display name of a SCOM group where objects are contained. .Parameter ManagementServer SCOM management server to connect to. .Parameter CustomerID OMS Workspace GUID .Parameter SharedKey Primary key of the workspace provided in OMS. .Example # Send-EffectiveConfiguration -GroupDisplayName "All Windows Computers" -ManagementServer SCOM -CustomerId '[Workspace GUID]' -SharedKey '[Workspace primary key]' -Verbose #> Function Send-EffectiveConfiguration { [CmdletBinding()] Param( [Parameter(Mandatory = $true,HelpMessage = 'Please specify a SCOM group display name.')] [ValidateNotNullOrEmpty()] [String]$GroupDisplayName, [Parameter(Mandatory = $true,HelpMessage = 'Please specify a SCOM management server display name.')] [ValidateNotNullOrEmpty()] [String]$ManagementServer, [Parameter(Mandatory = $true,HelpMessage = 'Please specify a workspace id (OMS).')] [ValidateNotNullOrEmpty()] [String]$CustomerID, [Parameter(Mandatory = $true,HelpMessage = 'Please specify a primary key (OMS).')] [ValidateNotNullOrEmpty()] [String]$SharedKey ) Try { Write-Verbose -Message 'Importing OperationsManager module [Send-EffectiveConfiguration]' Import-Module -Name OperationsManager Write-Verbose -Message ('Creating connection to {0} [Send-EffectiveConfiguration]' -f $ManagementServer) New-SCOMManagementGroupConnection -ComputerName $ManagementServer } Catch { Throw ('Could not Import OperationsManager module or connection failed. Exception: {0}' -f $_.Exception.InnerException) } Try { Write-Verbose -Message ('Getting SCOM class {0} [Send-EffectiveConfiguration]' -f $GroupDisplayName) $GroupClass = Get-SCOMClass -DisplayName $GroupDisplayName Write-Verbose -Message 'Getting SCOM objects [Send-EffectiveConfiguration]' $GroupObject = Get-SCOMMonitoringObject -Class $GroupClass Write-Verbose -Message 'Getting related monitoring objects [Send-EffectiveConfiguration]' $GroupMembers = $GroupObject.GetRelatedMonitoringObjects() } Catch { Throw ('Could not get SCOM class {0}. Exception: {1}' -f $GroupDisplayName, $_.Exception.InnerException) } If ($GroupMembers) { Try { Write-Verbose -Message ('Group {0} members found [Send-EffectiveConfiguration]' -f $GroupMembers.count) ForEach($Member in $GroupMembers) { Write-Verbose -Message ('Getting workflows for {0} [Send-EffectiveConfiguration]' -f $Member.Name) $Workflows = (Get-SCOMManagementGroup).EffectiveMonitoring.GetAllEffectiveMonitoringWorkflows($Member.id,$true) $Rules = @() $Monitors = @() Foreach ($Workflow in $Workflows) { Write-Verbose -Message ('Determing rule or monitor for {0}' -f $Workflow.WorkflowName) If ($Workflow.Type -eq 'Rule') { $Object = (Get-SCOMRule -id $Workflow.WorkflowId) $Properties = @{} $Properties.Add('Type', 'Rule') $Properties.Add('Overridden', $Workflow.Overridden) $Properties.Add('ManagementPack', $Object.ManagementPackName) $Properties.Add('DisplayName', $Object.DisplayName) $Properties.Add('Enabled', $Object.Enabled) $Properties.Add('TargetObject', $Workflow.EntityName) $Properties.Add('TargetClass', $Workflow.EntityTypeName) $Properties.Add('LastModified', $Object.LastModified) ForEach ($Param in $Workflow.OverrideableParameters) { $Properties.Add("$($Param.ParameterName)_D", $Param.DefaultValue) $Properties.Add("$($Param.ParameterName)_E", $Param.EffectiveValue) } $Rules += New-Object -TypeName PSObject -Property $Properties } ElseIf ($Workflow.Type -eq 'Monitor') { $Object = (Get-SCOMMonitor -id $Workflow.WorkflowId) $Properties = @{} $Properties.Add('Type', 'Monitor') $Properties.Add('Overridden', $Workflow.Overridden) $Properties.Add('ManagementPack', $Object.GetManagementPack().Name) $Properties.Add('DisplayName', $Object.DisplayName) $Properties.Add('Enabled', $Object.Enabled) $Properties.Add('TargetObject', $Workflow.EntityName) $Properties.Add('TargetClass', $Workflow.EntityTypeName) $Properties.Add('LastModified', $Object.LastModified) If ($Workflow.OverrideableParameters) { ForEach ($Param in $Workflow.OverrideableParameters) { $Properties.Add("$($Param.ParameterName)_D", $Param.DefaultValue) $Properties.Add("$($Param.ParameterName)_E", $Param.EffectiveValue) } } $Monitors += New-Object -TypeName PSObject -Property $Properties } } Write-Verbose -Message 'Calling Post-OMSData function for monitors' Post-OMSData -CustomerId $CustomerID -SharedKey $SharedKey -Body ($Monitors | ConvertTo-Json) -LogType 'EffMonitor' Write-Verbose -Message 'Calling Post-OMSData function for rules' Post-OMSData -CustomerId $CustomerID -SharedKey $SharedKey -Body ($Rules | ConvertTo-Json) -LogType 'EffRule' } } catch { Write-Verbose -Message ('{0} generated an error. Error {1}' -f $Workflow.Name, $_.Error.Message) } } Else { Throw ('Provided group {0} does not contain any members' -f $GroupDisplayName) } } Function Build-Signature { Param ( [String]$CustomerID, [string]$SharedKey, [string]$Date, [int]$ContentLength, [string]$Method, [string]$ContentType, [string]$Resource ) Write-Verbose -Message 'Preparing header data [Build-Signature]' $xHeaders = "x-ms-date:" + $Date $StringToHash = $Method + "`n" + $ContentLength + "`n" + $ContentType + "`n" + $xHeaders + "`n" + $Resource Write-Verbose -Message 'Encoding header data [Build-Signature]' $BytesToHash = [Text.Encoding]::UTF8.GetBytes($StringToHash) $KeyBytes = [Convert]::FromBase64String($SharedKey) Write-Verbose -Message 'Encrypting data [Build-Signature]' $SHA256 = New-Object System.Security.Cryptography.HMACSHA256 $SHA256.Key = $KeyBytes $CalculatedHash = $SHA256.ComputeHash($BytesToHash) $EncodedHash = [Convert]::ToBase64String($CalculatedHash) $Authorization = 'SharedKey {0}:{1}' -f $CustomerID,$EncodedHash Write-Verbose -Message 'Returning authorization [Build-Signature]' return $Authorization } #Function to create and post the request Function Post-OMSData { Param( [String]$CustomerID, [string]$SharedKey, [string]$Body, [string]$LogType ) Write-Verbose -Message 'Preparing URI [Post-OMSData]' $TimeStampField="" $Method = "POST" $ContentType = "application/json" $Resource = "/api/logs" $rfc1123date = [DateTime]::UtcNow.ToString("r") $ContentLength = $Body.Length $Signature = Build-Signature ` -customerId $CustomerID ` -sharedKey $SharedKey ` -date $rfc1123date ` -contentLength $ContentLength ` -fileName $fileName ` -method $Method ` -contentType $ContentType ` -resource $Resource $URI = "https://" + $CustomerID + ".ods.opinsights.azure.com" + $Resource + "?api-version=2016-04-01" Write-Verbose -Message 'Preparing Header [Post-OMSData]' $Headers = @{ "Authorization" = $Signature; "Log-Type" = $LogType; "x-ms-date" = $rfc1123date; "time-generated-field" = $TimeStampField; } #$Response = Invoke-WebRequest -Uri $URI -Method $Method -ContentType $ContentType -Headers $Headers -Body $Body -UseBasicParsing Try { Write-Verbose -Message 'Trying to send data [Post-OMSData]' $Response = Invoke-WebRequest -Uri $Uri -Method $Method -ContentType $ContentType -Headers $Headers -Body $Body -UseBasicParsing } Catch { $Error = $_.Exception.Message } if ($Response.StatusCode -eq 202) { Write-Verbose -Message 'Data successfully sent!' } else { Write-Error -Exception $Error } Write-Verbose -Message 'Returning response code URI [Post-OMSData]' Write-Verbose ('Response code: {0}' -f $Response.StatusCode) return $Response.StatusCode } |