Functions/Invoke-AnalyzeAzureConnectivity.ps1
function Invoke-AnalyzeAzureConnectivity { <# .Synopsis Analyzes the connectifity to O365 and Azure Endpoints. .Description Analyzes the connectifity to O365 and Azure Endpoints according to https://docs.microsoft.com/en-us/office365/enterprise/urls-and-ip-address-ranges. Returns array of Messages with four properties: - Testname: Name of the Tets - Type: Information, Warning or Error - Issue: Description of the issue - Possible Cause: Tips on how to solve the issue. .Example # Displays a deep analyisis of the currently found issues in the system. Invoke-AnalyzeAzureConnectivity #> [alias("Invoke-AnalyzeO365Connectivity")] [CmdletBinding()] param( [ValidateSet("Common","Exchange","Skype","SharePoint","All")] [String] $UrlSet = "Common", [Switch] $OnlyRequired ) Write-Verbose "Conenctivity Tests to Azure Endpoints in $UrlSet category, which are Required=$OnlyRequired." $data = New-Object System.Collections.Generic.List[PSCustomObject] $possibleErrors = @() $results = New-Object System.Collections.Generic.List[pscustomobject] Write-Progress -Activity "Connectivity Tests" -status "Load TestUrls" -percentComplete 0 $EndpointsObjs = Get-AzureO365UrlEndpoint -Path ((Get-Item $PSScriptRoot).Parent.FullName) $EndpointsObjs = $EndpointsObjs | Where-Object { ($_.serviceArea -eq $UrlSet -or $UrlSet -eq "All") -and ($OnlyRequired -eq $false -or $_.required -eq $true)} Write-Progress -Activity "Connectivity Tests" -status "Load TestUrls finisehed" -percentComplete 100 Write-Verbose "Found $($EndpointsObjs.length) endpoints to check" $j = 0 foreach($EndpointsObj in $EndpointsObjs){ Write-Progress -Activity "Connectivity Tests" -status "Building urls for $($EndpointsObj.serviceArea) with id $($EndpointsObj.id)" -percentComplete ($j / $EndpointsObjs.length*100) if($null -eq $EndpointsObj.tcpPorts){ Add-Member -InputObject $EndpointsObj -MemberType NoteProperty -Name tcpPorts -Value "443" } foreach($Port in $EndpointsObj.tcpPorts.Split(',')){ switch ($Port) { 80 {$Protocol = "http://"; $UsePort = "";$TestType="HTTP"; break} 443 {$Protocol = "https://"; $UsePort = "";$TestType="HTTP"; break} default {$Protocol = ""; $UsePort = $Port;$TestType="TCP"; break} } if($EndpointsObj.PSObject.Properties.Name -match "notes"){ $Notes = " - " + $EndpointsObj.notes } else { $Notes = "" } foreach($url in $EndpointsObj.urls){ if($TestType -eq "HTTP"){ $ExpectedResult = Get-AzureEndpointExpectedResult -TestType $TestType -Url ($Protocol + $url) -Path ((Get-Item $PSScriptRoot).Parent.FullName) } else { $ExpectedResult = Get-AzureEndpointExpectedResult -TestType $TestType -Url ($url + ":" + $UsePort) -Path ((Get-Item $PSScriptRoot).Parent.FullName) } if($url -notmatch "\*"){ $data.Add([PSCustomObject]@{ TestType = $TestType; TestUrl = $url; UsePort = $UsePort; Protocol = $Protocol; UrlPattern = $url; ExpectedStatusCode = $ExpectedResult.ActualStatusCode; Description = "$($EndpointsObj.serviceAreaDisplayName)$Notes"; PerformBluecoatLookup=$false; IgnoreCertificateValidationErrors=$ExpectedResult.HasError; Blocked=$ExpectedResult.Blocked; Verbose=$false }) } else { $staticUrls = Get-UrlWildCardLookup -Url $url -Path ((Get-Item $PSScriptRoot).Parent.FullName) if($staticUrls){ foreach($staticUrl in $staticUrls){ $data.Add([PSCustomObject]@{ TestType = $TestType; TestUrl = $staticUrl; UsePort = $UsePort; Protocol = $Protocol; UrlPattern = $url; ExpectedStatusCode = $ExpectedResult.ActualStatusCode; Description = "$($EndpointsObj.serviceAreaDisplayName)$Notes"; PerformBluecoatLookup=$false; IgnoreCertificateValidationErrors=$ExpectedResult.HasError; Blocked=$ExpectedResult.Blocked; Verbose=$false }) } } else { $possibleErrors += New-AnalyzeResult -TestName "Connectivity" -Type "Warning" -Issue "Could not check connectivity to $url and Port $Port because no static url for this wildcard url was found." -PossibleCause $Cause } } } <#if($EndpointsObj.PSObject.Properties.Name -match "ips"){ foreach($ip in $EndpointsObj.ips){ $firstip = $ip.Split("/")[0] $data.Add(@{ TestUrl = ($Protocol + $firstip + $UsePort); UrlPattern = ($Protocol + $firstip + $UsePort); ExpectedStatusCode = 403; Description = "$($EndpointsObj.serviceAreaDisplayName) - $Notes - Need communication $Protocol to $ip"; PerformBluecoatLookup=$false; Verbose=$false }) } }#> } } $possibleErrors = $possibleErrors | Group-Object -Property @("Type", "Issue") | ForEach-Object{ $_.Group | Select-Object * -First 1} $i = 1 $dataObjs = $data | Group-Object -Property @("TestUrl","TestType","UsePort") | ForEach-Object{ $_.Group | Select-Object * -First 1} ForEach($dataObj in $dataObjs) { Write-Progress -Activity "Connectivity Tests" -status "Processing $($d.TestUrl)" -percentComplete ($i / $dataObjs.count*100) if($dataObj.TestType -eq "HTTP"){ $connectivity = Get-HttpConnectivity -TestUrl ($dataObj.Protocol + $dataObj.TestUrl) -Method "GET" -UrlPattern ($dataObj.Protocol + $dataObj.UrlPattern) -ExpectedStatusCode $dataObj.ExpectedStatusCode -Description $dataObj.Description -PerformBluecoatLookup $dataObj.PerformBluecoatLookup -IgnoreCertificateValidationErrors:$dataObj.IgnoreCertificateValidationErrors } else { $connectivity = Get-TcpConnectivity -TestHostname $dataObj.TestUrl -TestPort $dataObj.UsePort -HostnamePattern ($dataObj.UrlPattern + ":" + $dataObj.UsePort) -ExpectedStatusCode $dataObj.ExpectedStatusCode -Description $dataObj.Description } $results.Add($connectivity) if ($connectivity.Blocked -eq $true -and $dataObj.Blocked -eq $false) { $possibleErrors += New-AnalyzeResult -TestName "Connectivity" -Type "Error" -Issue "Connection blocked `n $($connectivity)" -PossibleCause "Firewall is blocking connection to '$($connectivity.UnblockUrl)'." } elseif ($connectivity.ExpectedStatusCode -notcontains $connectivity.ActualStatusCode) { if($connectivity.ActualStatusCode -eq 407){ $Cause = "Keep in mind that the proxy has to be set in WinHTTP.`nWindows 1709 and newer: Set the proxy by using netsh or WPAD. --> https://docs.microsoft.com/en-us/windows/desktop/WinHttp/winhttp-autoproxy-support `nWindows 1709 and older: Set the proxy by using 'netsh winhttp set proxy ?' --> https://blogs.technet.microsoft.com/netgeeks/2018/06/19/winhttp-proxy-settings-deployed-by-gpo/ " } else { $Cause = "Interfering Proxy server can change HTTP status codes." } $possibleErrors += New-AnalyzeResult -TestName "Connectivity" -Type "Error" -Issue "Returned Status code '$($connectivity.ActualStatusCode)' is not expected '$($connectivity.ExpectedStatusCode)'`n $($connectivity)" -PossibleCause $Cause } if ($connectivity.Resolved -eq $false) { $possibleErrors += New-AnalyzeResult -TestName "Connectivity" -Type "Error" -Issue "DNS name not resolved `n $($connectivity)" -PossibleCause "DNS server not correctly configured." } if ($null -ne $connectivity.ServerCertificate -and $connectivity.ServerCertificate.HasError -and -not $dataObj.IgnoreCertificateValidationErrors) { $possibleErrors += New-AnalyzeResult -TestName "Connectivity" -Type "Error" -Issue "Certificate Error when connecting to $($connectivity.TestUrl)`n $(($connectivity.ServerCertificate))" -PossibleCause "Interfering Proxy server can change Certificate or not the Root Certificate is not trusted." } $i += 1 } Write-Progress -Completed -Activity "Connectivity Tests" # No errors detected, return success message if ($possibleErrors.Count -eq 0) { $possibleErrors += New-AnalyzeResult -TestName "All" -Type Information -Issue "All tests went through successfully." -PossibleCause "" } return $possibleErrors } # SIG # Begin signature block # MIIZwgYJKoZIhvcNAQcCoIIZszCCGa8CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU0bdZ1BKbooQD8uRI/f6qA7Ky # j9WgghUDMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B # AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG # A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh # d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg # Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV # UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu # dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q # WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC # i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4 # ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3 # +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI # fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd # BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG # CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB # Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro # YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV # HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y # MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf # plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y # 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq # IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3 # DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh # dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD # QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE # BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT # eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN # BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow # mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0 # jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu # ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh # d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz # C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB # o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO # BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw # Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90 # cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx # oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy # bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV # HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa # 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH # bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73 # BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR # EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW # yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu # e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw # ggWtMIIElaADAgECAhAEP0tn9l4Sf9gdog2gb/SWMA0GCSqGSIb3DQEBBQUAMGUx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEVWIENvZGUgU2lnbmlu # ZyBDQTAeFw0yMDAzMDYwMDAwMDBaFw0yMzAzMTUxMjAwMDBaMIHOMRMwEQYLKwYB # BAGCNzwCAQMTAkNIMRowGAYLKwYBBAGCNzwCAQITCVNvbG90aHVybjEdMBsGA1UE # DwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xGDAWBgNVBAUTD0NIRS0zMTQuNjM5LjUy # MzELMAkGA1UEBhMCQ0gxEjAQBgNVBAgTCVNvbG90aHVybjERMA8GA1UEBwwIRMOk # bmlrZW4xFjAUBgNVBAoTDWJhc2VWSVNJT04gQUcxFjAUBgNVBAMTDWJhc2VWSVNJ # T04gQUcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCn0xZCT8yT681H # ZVY8gtUlURKywy8Nfq8uiv/jJJU+/Tf4HHXXJzHo96ZFo/WOWMD3WMWRYRnpj95P # ZbfLaF+ki/PURRhp9/oT/p5O3zTv4Jqnig7AOeIL5dt9W5Uij9rDOEZhmFpVT08K # CKhMNMMu7MhBs+uHBlyQ70j5H2IjBjePtEDYcakbv1RNDK5hU+k2UqKZEQSaqt2+ # riewxS2R4RUvZJ5nRraf4pNYqDdem2H0vJ17zHsG+ZB0YFLk/P3i6r4tJEAksYAU # kuJsFDt0Yz9xM2qmG2Rr4iw7AUTfE5Gx0NNWD/fMWFP/2sD3VkHA8Mz8PAokDfFz # 21OqYrXPAgMBAAGjggHtMIIB6TAfBgNVHSMEGDAWgBStaQZw/IAbFrOpGJRrlAKG # XvcnjDAdBgNVHQ4EFgQURdlk/2RkqKDvZs8sol0UhzmJTCowNwYDVR0RBDAwLqAs # BggrBgEFBQcIA6AgMB4MHENILVNPTE9USFVSTi1DSEUtMzE0LjYzOS41MjMwDgYD # VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHMGA1UdHwRsMGowM6Ax # oC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9FVkNvZGVTaWduaW5nLWcxLmNy # bDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0VWQ29kZVNpZ25pbmct # ZzEuY3JsMEsGA1UdIAREMEIwNwYJYIZIAYb9bAMCMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwBwYFZ4EMAQMweQYIKwYBBQUHAQEE # bTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYB # BQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEVWQ29k # ZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEA # GYerL9YA8gW4cx7nWEaDFpN2XnaY4+90Nl8gaj6aeQj6kwIfjWLWAzByDdVNvxSk # rwXdfo3dkG5DNNI3wPR2SE2iyImDF6zXTThccBqkwE1x1Tb5qfhaA48jf18f8Jbv # VgvtbZWXph1b+ALyD2911b34Qt6cYmolg19vkmWXZUADRjA11S3VHhhH4GLKeHoE # 23jSSs69tQPNC1jdS+Rx6yO/Ya14UrDwOrJo1qSn2xTilf9s77mSxRJCpL8Cd1PU # HPvugUFHLw9nqOQAMUb7cHdDUREs7Brvfcyo0qRx7lyKjIM1d0wGtiBz+8kQJcSC # dK9S8HGSD3y4R1N++Y8gYTCCBrUwggWdoAMCAQICEA3Q4zdKyVvb+mtDSypI7AYw # DQYJKoZIhvcNAQEFBQAwbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0 # IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNl # cnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTAeFw0xMjA0MTgxMjAwMDBaFw0y # NzA0MTgxMjAwMDBaMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0 # IEVWIENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC # ggEBALkGdBxdtCCqqSGoKkJGqyUgFyXLIo+QoqAxa4MFda+yDnwSSXtqhmSED4Pc # ZLmxbhYFPhyVuefniG24YoGQedTd9eKW+cO1iCNXShrPcSnpCACPtZjjpzL9rC64 # 9JNT9Ao5Q5Gv1Wvo1J9GvY49q+L5K9TqAEBmJLfof7REdY14mq4xwTfPTh9b+EVK # 1z/CyZIGZL7eBoqv0OiKsfAsiABvC9yFp0zLBr/WLioybilxr44i8w/Q2JhILagI # y7aLI8Jj4LZz6299Jk+L9zQ9N4YMt3gn9MKG20NrWvg9PfTosGJWxufteKH7/Xpy # TzJlxHzDxHegBDIy7Y8/r4bdftECAwEAAaOCA1gwggNUMBIGA1UdEwEB/wQIMAYB # Af8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMH8GCCsG # AQUFBwEBBHMwcTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t # MEkGCCsGAQUFBzAChj1odHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl # cnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3J0MIGPBgNVHR8EgYcwgYQwQKA+oDyG # Omh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VF # VlJvb3RDQS5jcmwwQKA+oDyGOmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RDQS5jcmwwggHEBgNVHSAEggG7MIIBtzCC # AbMGCWCGSAGG/WwDAjCCAaQwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cuZGlnaWNl # cnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFkBggrBgEFBQcCAjCCAVYe # ggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBzACAAQwBlAHIAdABpAGYA # aQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBzACAAYQBjAGMAZQBwAHQA # YQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBDAGUAcgB0ACAAQwBQAC8A # QwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBpAG4AZwAgAFAAYQByAHQA # eQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBoACAAbABpAG0AaQB0ACAA # bABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBlACAAaQBuAGMAbwByAHAA # bwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAgAHIAZQBmAGUAcgBlAG4A # YwBlAC4wHQYDVR0OBBYEFK1pBnD8gBsWs6kYlGuUAoZe9yeMMB8GA1UdIwQYMBaA # FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQCeW5Y6LhKI # rKsBbaSfdeQBh6OlMte8uql+o9YUF/fCE2t8c48rauUPJllosI4lm2zv+myTkgjB # Tc9FnpxG1h50oZsUo/oBL0qxAeFyQEgRE2i5Np2RS9fCORIQwcTcu2IUFCphXU84 # fGYfxhv/rb5Pf5Rbc0MAD01zt1HPDvZ3wFvNNIzZYxOqDmER1vKOJ/y0e7i5ESCR # hnjqDtQo/yrVJDjoN7LslrufvEoWUOFev1F9I6Ayx8GUnnrJwCaizCWHoBJ+dJ8t # jbHI54S+udHp3rtqTohzceEiOMskh+lzflGy/5jrTn4v4MoO+rNe0boFQqhIn4P2 # P8TKqN9ooFBhMYIEKTCCBCUCAQEweTBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD # ExtEaWdpQ2VydCBFViBDb2RlIFNpZ25pbmcgQ0ECEAQ/S2f2XhJ/2B2iDaBv9JYw # CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN # AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw # IwYJKoZIhvcNAQkEMRYEFBQxn1s9bV3PiDAQ/J2G7+c0FdtaMA0GCSqGSIb3DQEB # AQUABIIBAAFt9/Cqiy+KMgqqp1eWHrRgq1RqW3WgQSoFlWGeN/d0xkPXE4TBifzA # cn75CzSeEYGy7lHMDbJlblVR1O3V2B6FjBIZSGVcsqG6RyAY0cAyVoQhpuHrP1XT # QSh11pvBhC7Im0RNf+bcX2nXW0FKd/bLWOGilP9fqXqa9eWOG88UCM6+grXjjWq/ # sZhM/BYGEs6PYi5ep33klcWWayoMx7zejudZzAb+MvsyU+ceE5ceADNlJW+tNUH6 # bBScN+Gr9uN2Cj2wR4R6rS6BPjJVO/pHzMu6+I2gZV+5YNyHaEXCx6jVcbKTuytz # uk4tfmGmbPTh65PQUxrmTZXTI5sNhf+hggILMIICBwYJKoZIhvcNAQkGMYIB+DCC # AfQCAQEwcjBeMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9y # YXRpb24xMDAuBgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMg # Q0EgLSBHMgIQDs/0OMj+vzVuBNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZIhvcN # AQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwNjAyMjE0NTMyWjAj # BgkqhkiG9w0BCQQxFgQUR57qrFBJoCxc/xBQ7dNoEtL8Hg8wDQYJKoZIhvcNAQEB # BQAEggEATS155ZbNf6Wsrf5V8L4GnVY9EviRdoqSS0ckRZwUN7ZuI6prbqIFoHqq # cpIQ9+lBXu43RCEeZGfzn5CfZRYL+g2QskJT5huXGFRXUDVRSjJbw9aHupzNot7r # xTgYXWKpsxyIiCasH0VV1ZqMA5RCD2XW8hKkaDr4q/aehQxa1I4j8TQhXAkdmosY # BTeg8HE1Ng6qlZ9dU5JNIyAc4hw6U+mZsl0ejCKD+SK27N9HsVz5EUTfnDt2Hun+ # lCh4XLKwO9i9To7P43raYZaTUnB8ihIJOG1BC1ZPZW/mVBzh8OWOO5pCsf+PnBVG # I/kyncaaJ9WeXQNbJmElfB4fnWKhIA== # SIG # End signature block |