Framework/Listeners/LogAnalytics/LogAnalyticsOutput.ps1
Set-StrictMode -Version Latest class LogAnalyticsOutput: ListenerBase { hidden static [LogAnalyticsOutput] $Instance = $null; #Default source is kept as SDL / PowerShell. static [string] $DefaultLAWSource = "SDL" #This value must be set in respective environment i.e. CICD,CA hidden static [bool] $IsIssueLogged = $false LogAnalyticsOutput() { } static [LogAnalyticsOutput] GetInstance() { if($null -eq [LogAnalyticsOutput]::Instance) { [LogAnalyticsOutput]::Instance = [LogAnalyticsOutput]::new(); } return [LogAnalyticsOutput]::Instance; } [void] RegisterEvents() { $this.UnregisterEvents(); # Mandatory: Generate Run Identifier Event $this.RegisterEvent([AzSKRootEvent]::GenerateRunIdentifier, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $currentInstance.SetRunIdentifier([AzSKRootEventArgument] ($Event.SourceArgs | Select-Object -First 1)); [LogAnalyticsOutput]::IsIssueLogged = $false } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([SVTEvent]::CommandStarted, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { [LogAnalyticsHelper]::SetLAWSDetails(); $settings = [ConfigurationManager]::GetAzSKSettings() if((-not [string]::IsNullOrEmpty($settings.LAWSId)) -or (-not [string]::IsNullOrEmpty($settings.AltLAWSId))) { $currentInstance.PublishCustomMessage("Scan events will be sent to the following Log Analytics workspace(s):",[MessageType]::Info); if(-not [string]::IsNullOrEmpty($settings.LAWSId)) { $currentInstance.PublishCustomMessage("WSId: $($settings.LAWSId)`n",[MessageType]::Info); } if(-not [string]::IsNullOrEmpty($settings.AltLAWSId)) { $currentInstance.PublishCustomMessage("AltWsId: $($settings.AltLAWSId)`n",[MessageType]::Info); $currentInstance.PublishCustomMessage("`n"); } else { $currentInstance.PublishCustomMessage("`n"); } } else { $currentInstance.PublishCustomMessage("Scan events are currently not being sent to a Log Analytics workspace. To set one up refer: https://aka.ms/devopskit/setuplaws `n",[MessageType]::Warning); } $currentInstance.CommandAction($Event,"Command Started"); } catch{ $currentInstance.PublishException($_); } #TODO: Disabling OMS inventory call. Need to rework on performance part. # if(-not ([LogAnalyticsHelper]::IsLAWSSettingValid -eq -1 -and [LogAnalyticsHelper]::IsAltLAWSSettingValid -eq -1)) # { # try # { # $invocationContext = [System.Management.Automation.InvocationInfo] $currentInstance.InvocationContext # if(!$invocationContext.BoundParameters.ContainsKey("SubscriptionId")) {return;} # [LogAnalyticsHelper]::PostResourceInventory($currentInstance.GetAzSKContextDetails()) # } # catch # { # $currentInstance.PublishException($_); # } # } }); $this.RegisterEvent([AzSKRootEvent]::CommandStarted, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $currentInstance.CommandAction($Event,"Command Started"); } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([AzSKRootEvent]::CommandCompleted, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $currentInstance.CommandAction($Event,"Command Completed"); } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([SVTEvent]::CommandCompleted, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $currentInstance.CommandAction($Event,"Command Completed"); } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([SVTEvent]::EvaluationCompleted, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $invocationContext = [System.Management.Automation.InvocationInfo] $currentInstance.InvocationContext $SVTEventContexts = [SVTEventContext[]] $Event.SourceArgs #foreach($svtEventContext in $SVTEventContexts) #{ # $currentInstance.WriteControlResult($svtEventContext); #} $currentInstance.WriteControlResult($SVTEventContexts); } catch { $currentInstance.PublishException($_); } }); $this.RegisterEvent([SVTEvent]::PostCredHygiene, { $currentInstance = [LogAnalyticsOutput]::GetInstance(); try { $invocationContext = [System.Management.Automation.InvocationInfo] $currentInstance.InvocationContext $credentialInfo = $Event.SourceArgs; [LogAnalyticsHelper]::WriteControlResult( $credentialInfo, "AzSK_CredHygiene"); } catch { $currentInstance.PublishException($_); } }); # $this.RegisterEvent([SVTEvent]::WriteInventory, { # $currentInstance = [LogAnalyticsOutput]::GetInstance(); # try # { # [LogAnalyticsHelper]::SetLAWSDetails(); # if(-not ([LogAnalyticsHelper]::IsLAWSSettingValid -eq -1 -and [LogAnalyticsHelper]::IsAltLAWSSettingValid -eq -1)) # { # $invocationContext = [System.Management.Automation.InvocationInfo] $currentInstance.InvocationContext # $SVTEventContexts = [SVTEventContext[]] $Event.SourceArgs # [LogAnalyticsHelper]::PostApplicableControlSet($SVTEventContexts,$currentInstance.GetAzSKContextDetails()); # } # } # catch # { # $currentInstance.PublishException($_); # } # }); } hidden [void] WriteControlResult([SVTEventContext[]] $eventContextAll) { try { $settings = [ConfigurationManager]::GetAzSKSettings() $tempBodyObjectsAll = [System.Collections.ArrayList]::new() try{ if((-not [string]::IsNullOrWhiteSpace($settings.LAWSId)) -or (-not [string]::IsNullOrWhiteSpace($settings.AltLAWSId))) { $eventContextAll | ForEach-Object{ $eventContext = $_ $tempBodyObjects = [LogAnalyticsHelper]::GetLAWSBodyObjects($eventContext,$this.GetAzSKContextDetails()) $tempBodyObjects | ForEach-Object{ Set-Variable -Name tempBody -Value $_ -Scope Local $tempBodyObjectsAll.Add($tempBody) } } $body = $tempBodyObjectsAll | ConvertTo-Json $lawBodyByteArray = ([System.Text.Encoding]::UTF8.GetBytes($body)) #publish to primary workspace if(-not [string]::IsNullOrWhiteSpace($settings.LAWSId) -and [LogAnalyticsHelper]::IsLAWSSettingValid -ne -1) { [LogAnalyticsHelper]::PostLAWSData($settings.LAWSId, $settings.LAWSSharedKey, $lawBodyByteArray, $settings.LAType, 'LAWS') } #publish to secondary workspace if(-not [string]::IsNullOrWhiteSpace($settings.AltLAWSId) -and [LogAnalyticsHelper]::IsAltLAWSSettingValid -ne -1) { [LogAnalyticsHelper]::PostLAWSData($settings.AltLAWSId, $settings.AltLAWSSharedKey, $lawBodyByteArray, $settings.LAType, 'AltLAWS') } } } catch { if(-not [LogAnalyticsOutput]::IsIssueLogged) { $this.PublishCustomMessage("An error occurred while pushing data to Log Analytics. Please check logs for more details. AzSK control evaluation results will not be sent to the configured Log Analytics workspace from this environment until the error is resolved.", [MessageType]::Warning); $this.PublishException($_); [LogAnalyticsOutput]::IsIssueLogged = $true } } } catch { [Exception] $ex = [Exception]::new("Error sending events to Log Analytics. The following exception occurred: `r`n$($_.Exception.Message) `r`nFor more on AzSK Log Analytics workspace setup, refer: https://aka.ms/devopskit/ca", $_.Exception) throw [SuppressedException] $ex } } hidden [AzSKContextDetails] GetAzSKContextDetails() { $AzSKContext = [AzSKContextDetails]::new(); $AzSKContext.RunIdentifier= $this.RunIdentifier; $commandMetadata = $this.GetCommandMetadata(); if($commandMetadata) { $AzSKContext.RunIdentifier += "_" + $commandMetadata.ShortName; } $AzSKContext.Version = $scannerVersion = $this.GetCurrentModuleVersion() $settings = [ConfigurationManager]::GetAzSKSettings() if(-not [string]::IsNullOrWhiteSpace($settings.LASource)) { $AzSKContext.Source = $settings.LASource } else { $AzSKContext.Source = [LogAnalyticsOutput]::DefaultLAWSource } $AzSKContext.PolicyOrgName = [ConfigurationManager]::GetAzSKConfigData().PolicyOrgName return $AzSKContext } hidden [void] CommandAction($event,$eventName) { $arg = $event.SourceArgs | Select-Object -First 1; $commandModel = [CommandModel]::new() $commandModel.EventName = $eventName $commandModel.RunIdentifier = $this.RunIdentifier $commandModel.ModuleVersion= $this.GetCurrentModuleVersion(); $commandModel.ModuleName = $this.GetModuleName(); $commandModel.MethodName = $this.InvocationContext.InvocationName; $commandModel.Parameters =$(($this.InvocationContext.BoundParameters | Out-String).TrimEnd()) if([Helpers]::CheckMember($arg,"SubscriptionContext")) { $commandModel.SubscriptionId = $arg.SubscriptionContext.SubscriptionId $commandModel.SubscriptionName = $arg.SubscriptionContext.SubscriptionName } if([Helpers]::CheckMember($arg,"PartialScanIdentifier")) { $commandModel.PartialScanIdentifier = $arg.PartialScanIdentifier } [LogAnalyticsHelper]::WriteControlResult($commandModel,"AzSK_CommandEvent") } } |