Framework/Core/AzureMonitoring/OMSMonitoring.ps1
Set-StrictMode -Version Latest class OMSMonitoring: CommandBase { [string] $OMSSampleViewTemplateFilepath; [string] $OMSSearchesTemplateFilepath; [string] $OMSAlertsTemplateFilepath; [string] $OMSGenericTemplateFilepath; [string] $OMSLocation; [string] $OMSResourceGroup; [string] $OMSWorkspaceName; [string] $OMSWorkspaceId; [string] $ApplicationSubscriptionName OMSMonitoring([string] $_omsSubscriptionId,[string] $_omsResourceGroup,[string] $_omsWorkspaceId, [InvocationInfo] $invocationContext): Base([string] $_omsSubscriptionId, $invocationContext) { $this.OMSResourceGroup = $_omsResourceGroup $this.OMSWorkspaceId = $_omsWorkspaceId $omsWorkSpaceInstance = Get-AzureRmOperationalInsightsWorkspace | Where-Object {$_.CustomerId -eq "$_omsWorkspaceId" -and $_.ResourceGroupName -eq "$($this.OMSResourceGroup)"} if($null -eq $omsWorkSpaceInstance) { throw "Invalid OMS Workspace." } $this.OMSWorkspaceName = $omsWorkSpaceInstance.Name; $locationInstance = Get-AzureRmLocation | Where-Object { $_.DisplayName -eq $omsWorkSpaceInstance.Location -or $_.Location -eq $omsWorkSpaceInstance.Location } $this.OMSLocation = $locationInstance.Location } [void] ConfigureOMS([string] $_applicationSubscriptionId,[string] $_applicationResourceGroups,[string] $_uniqueName,[string] $_securityContactEmails,[OMSInstallationOption] $_omsInstallationOption, [bool] $_validateOnly, [bool] $_useOMSModel) { $this.PublishCustomMessage([Constants]::DoubleDashLine + "`r`nStarted setting up AzSDK OMS solution pack`r`n"+[Constants]::DoubleDashLine); $OptionalParameters = New-Object -TypeName Hashtable #the default installation option is All if($null -eq $_omsInstallationOption) { $OMSInstallationOption = [OMSInstallationOption]::All } $OMSLogPath = [Constants]::AzSdkTempFolderPath + "\OMS"; if(-not (Test-Path -Path $OMSLogPath)) { mkdir -Path $OMSLogPath -Force | Out-Null } if($_useOMSModel) { [MessageData] $data = [MessageData]@{ Message = "`nSetting up OMS view using old query language."; MessageType = [MessageType]::Warning; }; $this.PublishCustomMessage($data) $appSub = Get-AzureRmSubscription -SubscriptionId $_applicationSubscriptionId $this.ApplicationSubscriptionName = $appSub.Name if([OMSInstallationOption]::All -eq $_omsInstallationOption -or [OMSInstallationOption]::Queries -eq $_omsInstallationOption) { $searchesTemplateFilepath = [ConfigurationManager]::LoadServerConfigFile("AzSDK.AM.OMS.Searches.omsview"); $this.OMSSearchesTemplateFilepath = $OMSLogPath+"\AzSDK.AM.OMS.Searches.omsview"; $searchesTemplateFilepath | ConvertTo-Json -Depth 100 | Out-File $this.OMSSearchesTemplateFilepath $this.PublishCustomMessage("`r`nSetting up OMS search queries."); $this.ConfigureSearches($_validateOnly); } if([OMSInstallationOption]::All -eq $_omsInstallationOption -or [OMSInstallationOption]::Alerts -eq $_omsInstallationOption) { $alertsTemplateFilepath = [ConfigurationManager]::LoadServerConfigFile("AzSDK.AM.OMS.Alerts.omsview"); $this.OMSAlertsTemplateFilepath = $OMSLogPath+"\AzSDK.AM.OMS.Alerts.omsview"; $alertsTemplateFilepath | ConvertTo-Json -Depth 100 | Out-File $this.OMSAlertsTemplateFilepath $this.PublishCustomMessage("`r`nSetting up OMS alerts."); $this.ConfigureAlerts($_uniqueName, $_securityContactEmails, $_validateOnly); } if([OMSInstallationOption]::All -eq $_omsInstallationOption -or [OMSInstallationOption]::SampleView -eq $_omsInstallationOption) { $sampleViewTemplateFilepath = [ConfigurationManager]::LoadServerConfigFile("AzSDK.AM.OMS.SampleView.omsview"); $this.OMSSampleViewTemplateFilepath = $OMSLogPath+"\AzSDK.AM.OMS.SampleView.omsview"; $sampleViewTemplateFilepath | ConvertTo-Json -Depth 100 | Out-File $this.OMSSampleViewTemplateFilepath $this.PublishCustomMessage("`r`nSetting up OMS sample view."); $this.ConfigureSampleView($_uniqueName, $_applicationResourceGroups, $_validateOnly); } if([OMSInstallationOption]::All -eq $_omsInstallationOption -or [OMSInstallationOption]::GenericView -eq $_omsInstallationOption) { $sampleViewTemplateFilepath = [ConfigurationManager]::LoadServerConfigFile("AZSDK.AM.OMS.GenericView.V1.omsview"); $this.OMSGenericTemplateFilepath = $OMSLogPath+"\AZSDK.AM.OMS.GenericView.V1.omsview"; $sampleViewTemplateFilepath | ConvertTo-Json -Depth 100 | Out-File $this.OMSGenericTemplateFilepath $this.PublishCustomMessage("`r`nSetting up OMS AzSDK Generic view."); $this.ConfigureGenericView($_uniqueName, $_validateOnly); } } else { $genericViewTemplateFilepath = [ConfigurationManager]::LoadServerConfigFile("AZSDK.AM.OMS.GenericView.V2.omsview"); $this.OMSGenericTemplateFilepath = $OMSLogPath+"\AZSDK.AM.OMS.GenericView.V2.omsview"; $genericViewTemplateFilepath | ConvertTo-Json -Depth 100 | Out-File $this.OMSGenericTemplateFilepath $this.PublishCustomMessage("`r`nSetting up OMS AzSDK generic view."); $this.ConfigureGenericView($_uniqueName, $_validateOnly); } $this.PublishCustomMessage([Constants]::SingleDashLine + "`r`nCompleted setting up AzSDK OMS solution pack.`r`n"+[Constants]::DoubleDashLine); } [void] ConfigureGenericView([string] $_uniqueName, [bool] $_validateOnly) { $OptionalParameters = New-Object -TypeName Hashtable $OptionalParameters = $this.GetOMSGenericViewParameters($_uniqueName); $ErrorMessages = @() if ($_validateOnly) { $ErrorMessages =@() Test-AzureRmResourceGroupDeployment -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSGenericTemplateFilepath ` -TemplateParameterObject $OptionalParameters -Verbose } else { $ErrorMessages =@() $SubErrorMessages = @() New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $this.OMSGenericTemplateFilepath).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSGenericTemplateFilepath ` -TemplateParameterObject $OptionalParameters ` -Verbose -Force -ErrorVariable SubErrorMessages $SubErrorMessages = $SubErrorMessages | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") } $ErrorMessages += $SubErrorMessages } if ($ErrorMessages) { "", ("{0} returned the following errors:" -f ("Template deployment", "Validation")[[bool]$_validateOnly]), @($ErrorMessages) | ForEach-Object { $this.PublishCustomMessage([MessageData]::new($_));} } } [void] ConfigureSampleView([string] $_applicationName, [string] $_applicationResourceGroups, [bool] $_validateOnly) { $OptionalParameters = New-Object -TypeName Hashtable $_query = $this.GetOMSAppQuery($_applicationResourceGroups); $OptionalParameters = $this.GetOMSSampleViewParameters($_applicationName, $_query); $ErrorMessages = @() if ($_validateOnly) { $ErrorMessages =@() Test-AzureRmResourceGroupDeployment -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSSampleViewTemplateFilepath ` -TemplateParameterObject $OptionalParameters -Verbose } else { $ErrorMessages =@() $SubErrorMessages = @() New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $this.OMSSampleViewTemplateFilepath).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSSampleViewTemplateFilepath ` -TemplateParameterObject $OptionalParameters ` -Verbose -Force -ErrorVariable SubErrorMessages $SubErrorMessages = $SubErrorMessages | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") } $ErrorMessages += $SubErrorMessages } if ($ErrorMessages) { "", ("{0} returned the following errors:" -f ("Template deployment", "Validation")[[bool]$_validateOnly]), @($ErrorMessages) | ForEach-Object { $this.PublishCustomMessage([MessageData]::new($_));} } } [void] ConfigureSearches([bool] $_validateOnly) { $OptionalParameters = New-Object -TypeName Hashtable $savedSearches = Get-AzureRmOperationalInsightsSavedSearch -ResourceGroupName $this.OMSResourceGroup -WorkspaceName $this.OMSWorkspaceName $azSdkSearches = @() if($savedSearches -ne $null -and $savedSearches.Value -ne $null) { $savedSearches.Value | %{ Set-Variable -Name savedSearch -Value $_ if($savedSearch.Properties -ne $null -and $savedSearch.Properties.Category -like "AzSDK_Searches*") { $azSdkSearches += $savedSearch } } } if($azSdkSearches.Length -gt 0) { return; } $OptionalParameters = $this.GetOMSBaseParameters(); $ErrorMessages = @() if ($_validateOnly) { $ErrorMessages =@() Test-AzureRmResourceGroupDeployment -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSSearchesTemplateFilepath ` -TemplateParameterObject $OptionalParameters -Verbose } else { $ErrorMessages =@() $SubErrorMessages = @() New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $this.OMSSearchesTemplateFilepath).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSSearchesTemplateFilepath ` -TemplateParameterObject $OptionalParameters ` -Verbose -Force -ErrorVariable SubErrorMessages $SubErrorMessages = $SubErrorMessages | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") } $ErrorMessages += $SubErrorMessages } if ($ErrorMessages) { "", ("{0} returned the following errors:" -f ("Template deployment", "Validation")[[bool] $_validateOnly]), @($ErrorMessages) | ForEach-Object { $this.PublishCustomMessage([MessageData]::new($_));} } } [void] ConfigureAlerts([string] $_applicationName, [string] $_alertemails, [bool] $_validateOnly) { $OptionalParameters = New-Object -TypeName Hashtable $OptionalParameters = $this.GetOMSAlertParameters($_applicationName, $_alertemails); $ErrorMessages = @() if ($_validateOnly) { $ErrorMessages =@() Test-AzureRmResourceGroupDeployment -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSAlertsTemplateFilepath ` -TemplateParameterObject $OptionalParameters -Verbose } else { $ErrorMessages =@() $SubErrorMessages = @() New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $this.OMSAlertsTemplateFilepath).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` -ResourceGroupName $this.OMSResourceGroup ` -TemplateFile $this.OMSAlertsTemplateFilepath ` -TemplateParameterObject $OptionalParameters ` -Verbose -Force -ErrorVariable SubErrorMessages $SubErrorMessages = $SubErrorMessages | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") } $ErrorMessages += $SubErrorMessages } if ($ErrorMessages) { "", ("{0} returned the following errors:" -f ("Template deployment", "Validation")[[bool]$_validateOnly]), @($ErrorMessages) | ForEach-Object { $this.PublishCustomMessage([MessageData]::new($_));} } } [void] UninstallOMSPack() { $this.PublishCustomMessage("Started Clean up of OMS Security Solution pack"); #Get all the searches with the name of AzSDK $savedSearches = Get-AzureRmOperationalInsightsSavedSearch -ResourceGroupName $this.OMSResourceGroup -WorkspaceName $this.OMSWorkspaceName $azSdkSearches = @() if($savedSearches -ne $null -and $savedSearches.Value -ne $null) { $savedSearches.Value | %{ Set-Variable -Name savedSearch -Value $_ if($savedSearch.Properties -ne $null -and $savedSearch.Properties.Category -like "*AzSDK*") { $azSdkSearches += $savedSearch } } } $RequestURI= [Constants]::OMSRequestURI $accessToken = [Helpers]::GetAccessToken([Constants]::ARMManagementUri); $header = "Bearer " + $accessToken $headers = @{"Authorization"=$header;"Content-Type"="application/json"} $schedules = $null $azSdkSearches | %{ Set-Variable -Name azSdkSearch -Value $_ $azSdkSearchId = $azSdkSearch.Id.Replace($azSdkSearch.Properties.DisplayName.ToLower(),$azSdkSearch.Properties.DisplayName) Set-Variable -Name scheduleURI $scheduleURI = ($RequestURI -f ($azSdkSearchId +"/schedules")) #Get all the Schedules configured using this search $result = "" $err = $null; try { $result = Invoke-WebRequest -Method GET -Uri $scheduleURI -Headers $headers } catch{ $err = $_ } if($result.StatusCode -ge 200 -and $result.StatusCode -le 399){ if($result.Content -ne $null){ $json = (ConvertFrom-Json $result.Content) if($json -ne $null){ $schedules = $json if($json.value -ne $null) { $schedules = $json.value } } } } if($err -ne $null) { if($err.ErrorDetails.Message -ne $null){ $json = (ConvertFrom-Json $err.ErrorDetails.Message) if($json -ne $null){ $return = $json if($json.'odata.error'.code -eq "Request_ResourceNotFound") { $return = $json.'odata.error'.message } } } return $null } $actions = $null; #Get AlertActions if($schedules -ne $null) { $schedules | %{ Set-Variable -Name schedule -Value $_ Set-Variable -Name actionsURI if(Get-Member -InputObject $schedule -Name id) { $actionsURI = ($RequestURI -f ($schedule.Id +"/Actions")) #Get all the actions configured using this search $result = "" $err = $null; try { $result = Invoke-WebRequest -Method GET -Uri $actionsURI -Headers $headers } catch{ $err = $_ } if($result.StatusCode -ge 200 -and $result.StatusCode -le 399){ if($result.Content -ne $null){ $json = (ConvertFrom-Json $result.Content) if($json -ne $null){ $actions = $json if($json.value -ne $null) { $actions = $json.value } } } } if($err -ne $null) { if($err.ErrorDetails.Message -ne $null){ $json = (ConvertFrom-Json $err.ErrorDetails.Message) if($json -ne $null){ $return = $json if($json.'odata.error'.code -eq "Request_ResourceNotFound") { $return = $json.'odata.error'.message } } } return $null } if($actions -ne $null) { $actions | %{ Set-Variable -Name action -Value $_ if(Get-Member -InputObject $actions -Name name) { $subValues = $action.name.Split("|",[StringSplitOptions]::RemoveEmptyEntries) if($subValues.Length -gt 0) { $actionid = $subValues[$subValues.Length-1] Set-Variable -Name actionURI $actionURI = ($RequestURI -f ($schedule.Id+"/Actions/"+$actionid)) #Get all the actions configured using this search $result = "" $err = $null; try { $result = Invoke-WebRequest -Method DELETE -Uri $actionURI -Headers $headers $this.PublishCustomMessage($action.Id + " : Deleted") } catch{ $err = $_ } if($result.StatusCode -ge 200 -and $result.StatusCode -le 399){ if($result.Content -ne $null){ $json = (ConvertFrom-Json $result.Content) if($json -ne $null){ $actions = $json if($json.value -ne $null) { $actions = $json.value } } } } if($err -ne $null) { if($err.ErrorDetails.Message -ne $null){ $json = (ConvertFrom-Json $err.ErrorDetails.Message) if($json -ne $null){ $return = $json if($json.'odata.error'.code -eq "Request_ResourceNotFound") { $return = $json.'odata.error'.message } } } return $null } } } #TODO Message } } #clean up schedule Set-Variable -Name scheduleURI $scheduleURI = ($RequestURI -f $schedule.Id) #Get all the actions configured using this search $result = "" try { $result = Invoke-WebRequest -Method DELETE -Uri $scheduleURI -Headers $headers $this.PublishCustomMessage($schedule.Id + " : Deleted") } catch{ $err = $_ } if($result.StatusCode -ge 200 -and $result.StatusCode -le 399){ if($result.Content -ne $null){ $json = (ConvertFrom-Json $result.Content) if($json -ne $null){ $actions = $json if($json.value -ne $null) { $actions = $json.value } } } } if($err -ne $null) { if($err.ErrorDetails.Message -ne $null){ $json = (ConvertFrom-Json $err.ErrorDetails.Message) if($json -ne $null){ $return = $json if($json.'odata.error'.code -eq "Request_ResourceNotFound") { $return = $json.'odata.error'.message } } } return $null } } } } #Done cleaning up all the schedules and actions } #Finally remove the saved search $azSdkSearches | ForEach-Object { $tempAzSDKSearch = $_; Remove-AzureRmOperationalInsightsSavedSearch -ResourceGroupName $this.OMSResourceGroup -WorkspaceName $this.OMSWorkspaceName -SavedSearchId $tempAzSDKSearch.Properties.DisplayName $this.PublishCustomMessage($tempAzSDKSearch.Id + " : Deleted"); } $this.PublishCustomMessage("Completed clean up of OMS Security Solution pack."); } [Hashtable] GetOMSBaseParameters() { [Hashtable] $omsParams = @{}; $omsParams.Add("omsWorkspaceLocation",$this.OMSLocation); $omsParams.Add("omsResourcegroup",$this.OMSResourceGroup); $omsParams.Add("omsSubscriptionId",$this.SubscriptionContext.SubscriptionId); $omsParams.Add("omsWorkspaceName",$this.OMSWorkspaceName); return $omsParams; } [Hashtable] GetOMSAlertParameters([string] $_applicationName, [string] $_alertemails) { $uniqueID = (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss"); $emailList = $_alertemails.Split(",",[StringSplitOptions]::RemoveEmptyEntries) [Hashtable] $omsParams = $this.GetOMSBaseParameters(); $omsParams.Add("alertEmailsPointOfContact",$emailList); $omsParams.Add("appName",$_applicationName); $omsParams.Add("uniqueId",$uniqueID); $omsParams.Add("applicationSubscriptionName",$this.ApplicationSubscriptionName); return $omsParams; } [Hashtable] GetOMSSampleViewParameters([string] $_applicationName,[string] $_query) { [Hashtable] $omsParams = $this.GetOMSBaseParameters(); $omsParams.Add("appName",$_applicationName); $omsParams.Add("query",$_query); $omsParams.Add("applicationSubscriptionName",$this.ApplicationSubscriptionName); return $omsParams; } [Hashtable] GetOMSGenericViewParameters([string] $_applicationName) { [Hashtable] $omsParams = $this.GetOMSBaseParameters(); $omsParams.Add("uniqueName",$_applicationName); return $omsParams; } [string] GetOMSAppQuery([string] $_resourceGroups) { $rgQueryFormat = "ResourceGroup=""{0 }""" $queryOutput = "" $resourceGroupList = $_resourceGroups.Split(',',[StringSplitOptions]::RemoveEmptyEntries); if($resourceGroupList.Length -gt 0) { $resourceGroupList | ForEach-Object { if([string]::IsNullOrWhiteSpace($queryOutput)) { $queryOutput = $rgQueryFormat -f $_ } else { $queryOutput += " OR " + [string]::Format($rgQueryFormat, $_); } } } return $queryOutput; } } # SIG # Begin signature block # MIIkAQYJKoZIhvcNAQcCoIIj8jCCI+4CAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBn7Neaqjf/5HQG # i1/6hDYBwI1tpc0N6LBQ7NzAvg02OqCCDZMwggYRMIID+aADAgECAhMzAAAAjoeR # pFcaX8o+AAAAAACOMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMTYxMTE3MjIwOTIxWhcNMTgwMjE3MjIwOTIxWjCBgzEL # MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v # bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjENMAsGA1UECxMETU9Q # UjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMIIBIjANBgkqhkiG9w0B # AQEFAAOCAQ8AMIIBCgKCAQEA0IfUQit+ndnGetSiw+MVktJTnZUXyVI2+lS/qxCv # 6cnnzCZTw8Jzv23WAOUA3OlqZzQw9hYXtAGllXyLuaQs5os7efYjDHmP81LfQAEc # wsYDnetZz3Pp2HE5m/DOJVkt0slbCu9+1jIOXXQSBOyeBFOmawJn+E1Zi3fgKyHg # 78CkRRLPA3sDxjnD1CLcVVx3Qv+csuVVZ2i6LXZqf2ZTR9VHCsw43o17lxl9gtAm # +KWO5aHwXmQQ5PnrJ8by4AjQDfJnwNjyL/uJ2hX5rg8+AJcH0Qs+cNR3q3J4QZgH # uBfMorFf7L3zUGej15Tw0otVj1OmlZPmsmbPyTdo5GPHzwIDAQABo4IBgDCCAXww # HwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYBBQUHAwMwHQYDVR0OBBYEFKvI1u2y # FdKqjvHM7Ww490VK0Iq7MFIGA1UdEQRLMEmkRzBFMQ0wCwYDVQQLEwRNT1BSMTQw # MgYDVQQFEysyMzAwMTIrYjA1MGM2ZTctNzY0MS00NDFmLWJjNGEtNDM0ODFlNDE1 # ZDA4MB8GA1UdIwQYMBaAFEhuZOVQBdOCqhc3NyK1bajKdQKVMFQGA1UdHwRNMEsw # SaBHoEWGQ2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY0Nv # ZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcmwwYQYIKwYBBQUHAQEEVTBTMFEGCCsG # AQUFBzAChkVodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p # Y0NvZFNpZ1BDQTIwMTFfMjAxMS0wNy0wOC5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEARIkCrGlT88S2u9SMYFPnymyoSWlmvqWaQZk62J3SVwJR # avq/m5bbpiZ9CVbo3O0ldXqlR1KoHksWU/PuD5rDBJUpwYKEpFYx/KCKkZW1v1rO # qQEfZEah5srx13R7v5IIUV58MwJeUTub5dguXwJMCZwaQ9px7eTZ56LadCwXreUM # tRj1VAnUvhxzzSB7pPrI29jbOq76kMWjvZVlrkYtVylY1pLwbNpj8Y8zon44dl7d # 8zXtrJo7YoHQThl8SHywC484zC281TllqZXBA+KSybmr0lcKqtxSCy5WJ6PimJdX # jrypWW4kko6C4glzgtk1g8yff9EEjoi44pqDWLDUmuYx+pRHjn2m4k5589jTajMW # UHDxQruYCen/zJVVWwi/klKoCMTx6PH/QNf5mjad/bqQhdJVPlCtRh/vJQy4njpI # BGPveJiiXQMNAtjcIKvmVrXe7xZmw9dVgh5PgnjJnlQaEGC3F6tAE5GusBnBmjOd # 7jJyzWXMT0aYLQ9RYB58+/7b6Ad5B/ehMzj+CZrbj3u2Or2FhrjMvH0BMLd7Hald # G73MTRf3bkcz1UDfasouUbi1uc/DBNM75ePpEIzrp7repC4zaikvFErqHsEiODUF # he/CBAANa8HYlhRIFa9+UrC4YMRStUqCt4UqAEkqJoMnWkHevdVmSbwLnHhwCbww # ggd6MIIFYqADAgECAgphDpDSAAAAAAADMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYD # VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe # MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3Nv # ZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgMjAxMTAeFw0xMTA3MDgyMDU5 # MDlaFw0yNjA3MDgyMTA5MDlaMH4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIw # MTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCr8PpyEBwurdhuqoIQ # TTS68rZYIZ9CGypr6VpQqrgGOBoESbp/wwwe3TdrxhLYC/A4wpkGsMg51QEUMULT # iQ15ZId+lGAkbK+eSZzpaF7S35tTsgosw6/ZqSuuegmv15ZZymAaBelmdugyUiYS # L+erCFDPs0S3XdjELgN1q2jzy23zOlyhFvRGuuA4ZKxuZDV4pqBjDy3TQJP4494H # DdVceaVJKecNvqATd76UPe/74ytaEB9NViiienLgEjq3SV7Y7e1DkYPZe7J7hhvZ # PrGMXeiJT4Qa8qEvWeSQOy2uM1jFtz7+MtOzAz2xsq+SOH7SnYAs9U5WkSE1JcM5 # bmR/U7qcD60ZI4TL9LoDho33X/DQUr+MlIe8wCF0JV8YKLbMJyg4JZg5SjbPfLGS # rhwjp6lm7GEfauEoSZ1fiOIlXdMhSz5SxLVXPyQD8NF6Wy/VI+NwXQ9RRnez+ADh # vKwCgl/bwBWzvRvUVUvnOaEP6SNJvBi4RHxF5MHDcnrgcuck379GmcXvwhxX24ON # 7E1JMKerjt/sW5+v/N2wZuLBl4F77dbtS+dJKacTKKanfWeA5opieF+yL4TXV5xc # v3coKPHtbcMojyyPQDdPweGFRInECUzF1KVDL3SV9274eCBYLBNdYJWaPk8zhNqw # iBfenk70lrC8RqBsmNLg1oiMCwIDAQABo4IB7TCCAekwEAYJKwYBBAGCNxUBBAMC # AQAwHQYDVR0OBBYEFEhuZOVQBdOCqhc3NyK1bajKdQKVMBkGCSsGAQQBgjcUAgQM # HgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1Ud # IwQYMBaAFHItOgIxkEO5FAVO4eqnxzHRI4k0MFoGA1UdHwRTMFEwT6BNoEuGSWh0 # dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcmwwXgYIKwYBBQUHAQEEUjBQME4GCCsGAQUF # BzAChkJodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0Nl # ckF1dDIwMTFfMjAxMV8wM18yMi5jcnQwgZ8GA1UdIASBlzCBlDCBkQYJKwYBBAGC # Ny4DMIGDMD8GCCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # b3BzL2RvY3MvcHJpbWFyeWNwcy5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcA # YQBsAF8AcABvAGwAaQBjAHkAXwBzAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZI # hvcNAQELBQADggIBAGfyhqWY4FR5Gi7T2HRnIpsLlhHhY5KZQpZ90nkMkMFlXy4s # PvjDctFtg/6+P+gKyju/R6mj82nbY78iNaWXXWWEkH2LRlBV2AySfNIaSxzzPEKL # UtCw/WvjPgcuKZvmPRul1LUdd5Q54ulkyUQ9eHoj8xN9ppB0g430yyYCRirCihC7 # pKkFDJvtaPpoLpWgKj8qa1hJYx8JaW5amJbkg/TAj/NGK978O9C9Ne9uJa7lryft # 0N3zDq+ZKJeYTQ49C/IIidYfwzIY4vDFLc5bnrRJOQrGCsLGra7lstnbFYhRRVg4 # MnEnGn+x9Cf43iw6IGmYslmJaG5vp7d0w0AFBqYBKig+gj8TTWYLwLNN9eGPfxxv # FX1Fp3blQCplo8NdUmKGwx1jNpeG39rz+PIWoZon4c2ll9DuXWNB41sHnIc+BncG # 0QaxdR8UvmFhtfDcxhsEvt9Bxw4o7t5lL+yX9qFcltgA1qFGvVnzl6UJS0gQmYAf # 0AApxbGbpT9Fdx41xtKiop96eiL6SJUfq/tHI4D1nvi/a7dLl+LrdXga7Oo3mXkY # S//WsyNodeav+vyL6wuA6mk7r/ww7QRMjt/fdW1jkT3RnVZOT7+AVyKheBEyIXrv # QQqxP/uozKRdwaGIm1dxVk5IRcBCyZt2WwqASGv9eZ/BvW1taslScxMNelDNMYIV # xDCCFcACAQEwgZUwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEoMCYGA1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMQITMwAA # AI6HkaRXGl/KPgAAAAAAjjANBglghkgBZQMEAgEFAKCBsDAZBgkqhkiG9w0BCQMx # DAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkq # hkiG9w0BCQQxIgQgQa/bcaBHQv7nYAGJ/2RAITJFJvnrnGW15bfqZIfwdQ4wRAYK # KwYBBAGCNwIBDDE2MDSgEoAQAEEAegBTAEQASwAyADUAMqEegBxodHRwczovL2Fr # YS5tcy9henNka29zc2RvY3MgMA0GCSqGSIb3DQEBAQUABIIBAEooQKdJpYAyfwQG # CxP04XrELt3XJ0RgMVmwp+7rw9Yp++0gQzafnWj0U+cP3w4IgAdVKjeD7ZzHpID/ # //NYMsMWYUbWPPmtEZM8ywF7U0EPUL0NiOIKvsVQe5kpdzCOxZh8OoCmiM3N3Lra # +/EMywN1iXUqsrhGQGJCGjHqwb+PHF5ijz2jx8YhhkT48bpO+ib5d7+xHtNMleM+ # zbcvOM2yuvEZ2lqh3jEhN2VJjBNQFdf7wBFvrU9d6RIvsFJ2O+vlF7i9zoYJrKOa # ojnpPpOaxac2h9i3zvPUa//KVuYE49liI4M5MYk2loEZJFcD09oEjc+gVzB/Z0mJ # +XWSQdWhghNMMIITSAYKKwYBBAGCNwMDATGCEzgwghM0BgkqhkiG9w0BBwKgghMl # MIITIQIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBPAYLKoZIhvcNAQkQAQSgggErBIIB # JzCCASMCAQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQgxF9ECmFJKrZu # XlVw70+9aozyZyg/7Q5EUXe48frX46gCBlmSONxQthgSMjAxNzA5MDUwOTM3MDQu # OTlaMAcCAQGAAgH0oIG5pIG2MIGzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMQ0wCwYDVQQLEwRNT1BSMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBF # U046N0QyRS0zNzgyLUIwRjcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w # IFNlcnZpY2Wggg7QMIIGcTCCBFmgAwIBAgIKYQmBKgAAAAAAAjANBgkqhkiG9w0B # AQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAG # A1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAw # HhcNMTAwNzAxMjEzNjU1WhcNMjUwNzAxMjE0NjU1WjB8MQswCQYDVQQGEwJVUzET # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T # dGFtcCBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkd # Dbx3EYo6IOz8E5f1+n9plGt0VBDVpQoAgoX77XxoSyxfxcPlYcJ2tz5mK1vwFVMn # BDEfQRsalR3OCROOfGEwWbEwRA/xYIiEVEMM1024OAizQt2TrNZzMFcmgqNFDdDq # 9UeBzb8kYDJYYEbyWEeGMoQedGFnkV+BVLHPk0ySwcSmXdFhE24oxhr5hoC732H8 # RsEnHSRnEnIaIYqvS2SJUGKxXf13Hz3wV3WsvYpCTUBR0Q+cBj5nf/VmwAOWRH7v # 0Ev9buWayrGo8noqCjHw2k4GkbaICDXoeByw6ZnNPOcvRLqn9NxkvaQBwSAJk3jN # /LzAyURdXhacAQVPIk0CAwEAAaOCAeYwggHiMBAGCSsGAQQBgjcVAQQDAgEAMB0G # A1UdDgQWBBTVYzpcijGQ80N7fEYbxTNoWoVtVTAZBgkrBgEEAYI3FAIEDB4KAFMA # dQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAW # gBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8v # Y3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRf # MjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRw # Oi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEw # LTA2LTIzLmNydDCBoAYDVR0gAQH/BIGVMIGSMIGPBgkrBgEEAYI3LgMwgYEwPQYI # KwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9QS0kvZG9jcy9DUFMv # ZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0ATABlAGcAYQBsAF8AUABvAGwA # aQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0wDQYJKoZIhvcNAQELBQADggIB # AAfmiFEN4sbgmD+BcQM9naOhIW+z66bM9TG+zwXiqf76V20ZMLPCxWbJat/15/B4 # vceoniXj+bzta1RXCCtRgkQS+7lTjMz0YBKKdsxAQEGb3FwX/1z5Xhc1mCRWS3Tv # QhDIr79/xn/yN31aPxzymXlKkVIArzgPF/UveYFl2am1a+THzvbKegBvSzBEJCI8 # z+0DpZaPWSm8tv0E4XCfMkon/VWvL/625Y4zu2JfmttXQOnxzplmkIz/amJ/3cVK # C5Em4jnsGUpxY517IW3DnKOiPPp/fZZqkHimbdLhnPkd/DjYlPTGpQqWhqS9nhqu # BEKDuLWAmyI4ILUl5WTs9/S/fmNZJQ96LjlXdqJxqgaKD4kWumGnEcua2A5HmoDF # 0M2n0O99g/DhO3EJ3110mCIIYdqwUB5vvfHhAN/nMQekkzr3ZUd46PioSKv33nJ+ # YWtvd6mBy6cJrDm77MbL2IK0cs0d9LiFAR6A+xuJKlQ5slvayA1VmXqHczsI5pgt # 6o3gMy4SKfXAL1QnIffIrE7aKLixqduWsqdCosnPGUFN4Ib5KpqjEWYw07t0Mkvf # Y3v1mYovG8chr1m1rtxEPJdQcdeh0sVV42neV8HR3jDA/czmTfsNv11P6Z0eGTgv # vM9YBS7vDaBQNdrvCScc1bN+NR4Iuto229Nfj950iEkSMIIE2jCCA8KgAwIBAgIT # MwAAAKJMjh3aqSF8hAAAAAAAojANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGlt # ZS1TdGFtcCBQQ0EgMjAxMDAeFw0xNjA5MDcxNzU2NDlaFw0xODA5MDcxNzU2NDla # MIGzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYDVQQL # EwRNT1BSMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046N0QyRS0zNzgyLUIwRjcx # JTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmAXcFe8N9DnZovcaog8aCewFwqLBqhHJP # VI5tvmcgar7sLd0vR3Hhkv10Ymu+dNuFNts0yMdpCuY2EklAR7hBNFliPfETp64J # ASjRFFhjHzmwaDYE2FnaTVvgkXES/EGzDc7BcqEVJvbzmVvo4IquEHWqOdfxDvIJ # wTF1DCkqKd3sjjcq32uq4zK42E17yHEQkMG+OoYZC+jprR+4NCOtYYyWLvs+TC9C # ZcYLHrGwWMJrm+fPiwTHk0Gd5nm45feWV9yAxQUFAKZBIjcW+bTrR6wvOa3QxdMM # RNcJW2nRCfMDK2MnWgeQ9O+MozMljTcsPyWZs/MVPqaS6vlRGOXVAgMBAAGjggEb # MIIBFzAdBgNVHQ4EFgQUbrvZwcLaFrB8rcJTf+fQFxM9vFcwHwYDVR0jBBgwFoAU # 1WM6XIoxkPNDe3xGG8UzaFqFbVUwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljVGltU3RhUENBXzIw # MTAtMDctMDEuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNUaW1TdGFQQ0FfMjAxMC0w # Ny0wMS5jcnQwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDCDANBgkq # hkiG9w0BAQsFAAOCAQEANZlXbTP2SJ2eQdzMqWDuXEdIVBEKhrlXP6dtmI7KfGmm # apaDzjmyvWQOmTC7vtzgdYJrQinhhUSOMXtzaFl5mJ1XtBYH/KIpvKNwgiEmHWVL # GeaJKlXNr7qSat7ImgkCWyUWl8eruVra9POgG4JwqkrGRrV6gMRiQoP3cVpkKyb9 # 844jC04W8hvy0DUKQ9o886kakYrENXjZEKhjBqNkf6y/KO6oHBV4j6D3wnHF2LiS # zqqXcjlMD2hkRE7KhuUty7ICsSg9/Rm/ANZI098NtO0MJJBFFLyVeToD7GOGPDTu # cbI9Lmp5kIK26xsaWbuvi4t58an9SjHyPGobFV06xqGCA3kwggJhAgEBMIHjoYG5 # pIG2MIGzMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMQ0wCwYD # VQQLEwRNT1BSMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046N0QyRS0zNzgyLUIw # RjcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiJQoBATAJ # BgUrDgMCGgUAAxUAXi8X6XGE0jLL7NdeSjv4TreH6fWggcIwgb+kgbwwgbkxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xDTALBgNVBAsTBE1PUFIx # JzAlBgNVBAsTHm5DaXBoZXIgTlRTIEVTTjo1N0Y2LUMxRTAtNTU0QzErMCkGA1UE # AxMiTWljcm9zb2Z0IFRpbWUgU291cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0B # AQUFAAIFAN1YrWwwIhgPMjAxNzA5MDUwNDU4MjBaGA8yMDE3MDkwNjA0NTgyMFow # dzA9BgorBgEEAYRZCgQBMS8wLTAKAgUA3VitbAIBADAKAgEAAgIOeQIB/zAHAgEA # AgIYtDAKAgUA3Vn+7AIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMB # oAowCAIBAAIDFuNgoQowCAIBAAIDB6EgMA0GCSqGSIb3DQEBBQUAA4IBAQByYaME # FOv6bl13h4QN1zZRQWbgCX8IYfNliB04Uq99nX9ieycfowy6hSADAbr4SERbIwOg # VRuzI0Z1TJdc315A8OaNPgaTVOXtxAeAcQpWaoSWBUDIMhITdXcK+piXKkJqxiWK # 4639oT4SIG16tWaQ88QH5cXPUz5YwUSOMD+X/3NNCP1diN7LjjXmjHn+ThNPTYEZ # Sv7Q5xTX/sHMvcKoQdGlqX0RLqLv7yMWybzGCLuJ8xlJNV4WVzDQDM7fz5hRztP6 # i2GNafnQuXQg1hYgTW4cw/oz6EY318PxMrRZ2Foo/n2ltwyl313eSMb6w16CBKFv # BxU8mI3NxUhoZuPEMYIC9TCCAvECAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg # UENBIDIwMTACEzMAAACiTI4d2qkhfIQAAAAAAKIwDQYJYIZIAWUDBAIBBQCgggEy # MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgrJCf # 6A0DgMZHi9MN2MSbzTOtKJHN0W2/TjVAF5cPqBgwgeIGCyqGSIb3DQEJEAIMMYHS # MIHPMIHMMIGxBBReLxfpcYTSMsvs115KO/hOt4fp9TCBmDCBgKR+MHwxCzAJBgNV # BAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4w # HAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29m # dCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAAAokyOHdqpIXyEAAAAAACiMBYEFMwE # SrWjo1vDkQE04SippZzOshpAMA0GCSqGSIb3DQEBCwUABIIBAIXm4wqpr9Xrsluy # OO3jdHXFFq9X4RsxJ5WVX+ssoFjbeeEAB2n7lbQjfcd/wJXUr+K+oa/KDYm9tdfR # M69Gtrm5ObL0H9Yaw7fCvi9oPfxaVT3leaqYp8bdJIVwI5FyUPkeEHNeoYfahT7O # tRugKOb3HMDB9lcFotGEzm5PxALO9f9ma1C18yXDBFL8ZXEljKoGsa4PLF9nmaB6 # Ebqsg2ktI20vldc1vrrzWFmrq2v47EdXbnmg+hskNexQAqNOIDtn0yix/YM42fLq # canvV+RgqrpdzqLzbE7OKVz0g0vVweTDaJq3tU7t2lmnZ/F0ZEh2N4F7Hxz+mwLX # rbFZOU0= # SIG # End signature block |