<# .Synopsis Script som sjekker nødvendig miljøoppsett for bruk av kjernejournal. .DESCRIPTION Scriptet sjekker om nødvendige endepunkter er tilgjengelig, om klokken går riktig og evt. om Buypass Javafri er installert. Som standard sjekker den kun tilgang mot kjernejournals endepunkter, pluss klokken, men de andre testene kan kjøres ved å legge på parametre. Scriptet kan kjøres med følgende parametre: -Alle <- kjør alle tester. -Server <- kun sjekk tilkobling mot kjernejournals API og HelseID. -Buypass <- Sjekk åpninger mot Buypass på Helsenettet, og om Buypass Javafri er installert. -Commfides <- Sjekk åpninger mot Commfides på Helsenettet. -BankID <- Sjekk åpninger mot HelseID, ID-porten og BankID. -Cert <- Sjekker om Buypass sine rotsertifikater ligger korrekt inne. -Logg <- Fil som det skal logges til, for debugging. -Verbose <- Aktiver mer detaljert output. .NOTES Author : Norsk helsenett Version : 2022.3.15 #> param ( [switch]$Alle, [switch]$Bankid, [switch]$Buypass, [switch]$Cert, [switch]$Commfides, [string]$Logg, [switch]$Server, [switch]$Verbose ) $version = "2022.3.15" $ErrorActionPreference = "Stop" $ProgressPreference = "SilentlyContinue" $PSDefaultParameterValues = @{ "Invoke-WebRequest:Method" = "HEAD" "Invoke-WebRequest:TimeoutSec" = 5 "Invoke-WebRequest:UseBasicParsing" = $true "Invoke-WebRequest:UserAgent" = "Kjernejournal miljosjekk $($version)" } $minimumBuypassJavafriVersion = [System.Version]"1.4.1.0" $buypassJavafriUrl = [Uri]"https://127.0.0.1:31505/scard/version" $kjernejournalApiUrl = [Uri]"https://api.kjernejournal.no:8000/healthcheck" $kjernejournalPortalUrl = [Uri]"https://kjernejournal.no/hpp-webapp/ping" $urlSets = @{ "buypass" = @{ "Buypass på Helsenettet" = [Uri]"https://secure.nhn.buypass.no/wips/service?op=DIAG" } "commfides" = @{ "Commfides Javafri på Helsenettet" = [Uri]"https://app06.commfides.com" } "helseid" = @{ "HelseID" = [Uri]"https://helseid-sts.nhn.no/.well-known/openid-configuration" } "bankid" = @{ "ID-porten" = [Uri]"https://idporten.difi.no" "ID-porten OIDC provider" = [Uri]"https://oidc.difi.no/.well-known/openid-configuration" "BankID" = [Uri]"https://csfe.bankid.no" } } function Out-ErrorMessage($errormessage, $exception) { Write-Verbose "$($errormessage): $($exception)" if (![string]::IsNullOrWhiteSpace($Logg)) { "$((Get-date).ToString()): $($errormessage):" | Out-File -FilePath $Logg -Append $exception | Out-File -FilePath $Logg -Append } } function Out-TraceMessage($message) { Write-Verbose $message if (![string]::IsNullOrWhiteSpace($Logg)) { "$((Get-date).ToString()): $($message)" | Out-File -FilePath $Logg -Append } } function Debug-WebException ($err, $service) { $exception = $err.Exception $response = $exception.Response if ($null -ne $response -and $response.Method -ne "CONNECT") { # The response was not from a proxy. Not all services return 200 OK, so this is OK. Out-ErrorMessage "Got expected exception when checking $($service)" $err Write-Host "Tilkoblingstest til $($service) vellykket" -ForegroundColor Green return $true } elseif ($null -ne $response -and $response.Method -eq "CONNECT") { # The response was from a proxy. $proxy = $response.ResponseUri.Host if ($response.StatusCode -eq [System.Net.HttpStatusCode]::Forbidden) { Out-ErrorMessage "Proxy '$($proxy)' returned Forbidden for $($service)" $err Write-Host "Tilkobling til $($service) ble nektet av proxyen '$($proxy)'" -ForegroundColor Red } elseif ($response.StatusCode -eq [System.Net.HttpStatusCode]::ServiceUnavailable) { Out-ErrorMessage "Proxy '$($proxy)' returned ServiceUnavailable for $($service)" $err Write-Host "Proxyen '$($proxy)' klarte ikke å koble til $($service)" -ForegroundColor Red } else { Out-ErrorMessage "Proxy '$($proxy)' returned $($response.StatusCode) for $($service)" $err Write-Host "Fikk '$($response.StatusCode)' fra " -NoNewline -ForegroundColor Red Write-Host "proxyen '$($proxy)' på tilkobling mot $($service)" -ForegroundColor Red } } elseif ($exception.Status -eq [System.Net.WebExceptionStatus]::TrustFailure) { Out-ErrorMessage "Got trust failure when checking $($service)" $err Write-Host "Sertifikatfeil under tilkobling til $($service), " -NoNewline -ForegroundColor Red Write-Host "dette tyder på at noen rotsertifikater mangler" -ForegroundColor Red } elseif ($exception.Status -eq [System.Net.WebExceptionStatus]::ConnectFailure) { Out-ErrorMessage "Got connect failure when checking $($service)" $err Write-Host "Klarte ikke å koble til $($service), " -NoNewline -ForegroundColor Red Write-Host "dette tyder på at koblingen blir blokkert " -NoNewline -ForegroundColor Red Write-Host "av en brannmur" -ForegroundColor Red } elseif ($exception.Status -eq [System.Net.WebExceptionStatus]::Timeout) { Out-ErrorMessage "Got timeout when checking $($service)" $err Write-Host "Tilkoblngen til $($service) timet ut, " -NoNewline -ForegroundColor Red Write-Host "dette tyder på at koblingen blir droppet " -NoNewline -ForegroundColor Red Write-Host "av en brannmur" -ForegroundColor Red } else { # ¯\_(ツ)_/¯ Out-ErrorMessage "Got $($exception.Status) while checking $($service)" $err Write-Host "Tilkoblingstest til $($service) feilet: $($exception.Status)" -ForegroundColor Red } return $false } function Test-URL($serviceName, $url) { # Resolve it and log the result, so that we know which way (Helsenett vs. Internett) # we are resolving here, in case this log ends up in a support case. try { $dnsResponse = Resolve-DnsName -Name $url.Host Out-TraceMessage "$($url.Host) resolves to $($dnsResponse.IPAddress)" $dnsResponseNoHostFile = Resolve-DnsName -Name $url.Host -NoHostsFile Out-TraceMessage "$($url.Host) resolves to $($dnsResponseNoHostFile.IPAddress) (no hosts file)" } catch { Out-ErrorMessage "Failed to lookup $($url.Host)" $_ } $service = "$($serviceName) ($($url.Host):$($url.Port))" try { [void]$(Invoke-WebRequest -Uri $url) Out-TraceMessage "Test for $($service) was successful" Write-Host "Tilkoblingstest til $($service) vellykket" -ForegroundColor Green return $true } catch [System.Net.WebException] { return Debug-WebException $_ $service } catch { Out-ErrorMessage "An error occured while checking $($service)" $_ Write-Host "Tilkoblingstest til $($service) feilet" -ForegroundColor Red return $false } } function Test-KjernejournalPortal { try { $service = "kjernejournals portal ($($kjernejournalPortalUrl.Host):$($kjernejournalPortalUrl.Port))" $response = Invoke-WebRequest -Uri $kjernejournalPortalUrl $eventId = $response.Headers."X-EVENT-ID" Out-TraceMessage "$($service) test OK, EVENT=$($eventId)" Write-Host "Tilkoblingstest til $($service) vellykket" -ForegroundColor Green return Get-Date($response.Headers.Date) } catch [System.Net.WebException] { return Debug-WebException $_ $service } catch { Out-ErrorMessage "An error occured while testing $($service)" $_ Write-Host "Fikk ikke kontakt med $($service)" -ForegroundColor Red return $false } } function Test-KjernejournalAPI { try { $service = "kjernejournals API ($($kjernejournalApiUrl.Host):$($kjernejournalApiUrl.Port))" $response = Invoke-WebRequest -Uri $kjernejournalApiUrl $eventId = $response.Headers."X-CorrelationID" Out-TraceMessage "$($service) test OK, EVENT=$($eventId)" Write-Host "Tilkoblingstest til $($service) vellykket" -ForegroundColor Green return Get-Date($response.Headers.Date) } catch [System.Net.WebException] { return Debug-WebException $_ $service } catch { Out-ErrorMessage "An error occured while testing $($service)" $_ Write-Host "Fikk ikke kontakt med $($service)" -ForegroundColor Red return $false } } function Test-BuypassJavafri { $listenPort = Get-NetTCPConnection -State Listen -LocalPort $buypassJavafriUrl.Port -ErrorAction SilentlyContinue if ($null -eq $listenPort) { Out-TraceMessage "Localhost not listening to Buypass Javafri port" Write-Host "Buypass Javafri ser ikke ut til å være installert/kjørende" -ForegroundColor Red return $false } else { Out-TraceMessage "Localhost listening on Buypass Javafri port: $($listenPort)" } try { $response = Invoke-RestMethod $buypassJavafriUrl -Method POST -Headers @{ "origin" = "https://secure.nhn.buypass.no" } -TimeoutSec 5 $buypassJavafriVersion = [System.Version]$response.version } catch { Out-ErrorMessage "An error occured while checking for Buypass Javafri" $_ Write-Host "Det skjedde en ukjent feil under sjekk av Buypass Javafri" -ForegroundColor Red return $false } Out-TraceMessage "Buypass Javafri installed, version: $($buypassJavafriVersion.ToString())" if ($buypassJavafriVersion -lt $minimumBuypassJavafriVersion) { Write-Host "Buypass Javafri er installert, men versjonen er for gammel. " -NoNewline -ForegroundColor Red Write-Host "$($buypassJavafriVersion.ToString()) er installert, men " -NoNewline -ForegroundColor Red Write-Host "kjernejournal krever minimum $($minimumBuypassJavafriVersion.ToString())" -ForegroundColor Red return $false } Write-Host "Buypass Javafri er installert, og versjonen er OK" -ForegroundColor Green } function Test-TrustedRoots { $hasBuypassClass2 = Test-Path Cert:\LocalMachine\Root\490A7574DE870A47FE58EEF6C76BEBC60B124099 $hasBuypassClass3 = Test-Path Cert:\LocalMachine\Root\DAFAF7FA6684EC068F1450BDC7C281A5BCA96457 if ($hasBuypassClass2) { Out-TraceMessage "Buypass Class 2 Root CA is installed" Write-Host "Buypass Class 2 Root CA er installert riktig" -ForegroundColor Green } else { Out-TraceMessage "Buypass Class 2 Root CA is NOT installed" Write-Host "Buypass Class 2 Root CA mangler" -ForegroundColor Red } if ($hasBuypassClass3) { Out-TraceMessage "Buypass Class 3 Root CA is installed" Write-Host "Buypass Class 3 Root CA er installert riktig" -ForegroundColor Green } else { Out-TraceMessage "Buypass Class 3 Root CA is NOT installed" Write-Host "Buypass Class 3 Root CA mangler" -ForegroundColor Red } return ($hasBuypassClass2 -and $hasBuypassClass3) } function Test-URLSet ($urlSet) { $testResults = [System.Collections.ArrayList]@() $urlSets.$urlSet.GetEnumerator() | ForEach-Object { Out-TraceMessage "Test-URL $($_.Name) $($_.Value)" [void]$testResults.Add($(Test-URL $_.Name $_.Value)) } return !($testResults -contains $false) } function Test-TimeSync ($kjernejournalTime) { $systemTime = Get-Date $allowedClockSkew = New-TimeSpan -Minutes 5 # kerberos style $actualClockSkew = ($systemTime - $kjernejournalTime).Duration() Out-TraceMessage "System time: $($systemTime.ToString())" Out-TraceMessage "Kjernejournal time: $($kjernejournalTime.ToString())" Out-TraceMessage "Clock skew: $($actualClockSkew)" if ($actualClockSkew -ge $allowedClockSkew) { Out-TraceMessage "Clock skew not acceptable" Write-Host "Det virker som om klokken ikke er i sync, " -NoNewline -ForegroundColor Red Write-Host "målte at den var $($actualClockSkew.TotalMinutes) minutter feil" -ForegroundColor Red return $false } Out-TraceMessage "Clock skew acceptable" Write-Host "Klokken er korrekt" -ForegroundColor Green } function Test-SpecifiedServices ($testsToRun) { $testResults = [System.Collections.ArrayList]@() $kjernejournalTime = $null if ($testsToRun.kjportal) { Write-Host ":: Tester kobling mot kjernejournals portal" $kjportalResult = Test-KjernejournalPortal if ($null -ne $kjportalResult -and $kjportalResult.GetType() -eq [System.DateTime]) { $kjernejournalTime = $kjportalResult } [void]$testResults.Add($kjportalResult) } if ($testsToRun.kjapi) { Write-Host ":: Tester kobling mot kjernejournals API" $kjapiResult = Test-KjernejournalAPI if ($null -ne $kjapiResult -and $kjapiResult.GetType() -eq [System.DateTime]) { $kjernejournalTime = $kjapiResult } [void]$testResults.Add($kjapiResult) } if ($testsToRun.kjportal -or $testsToRun.kjapi) { Write-Host ":: Sjekker om klokken på lokal maskin er korrekt" if ($null -ne $kjernejournalTime) { [void]$testResults.Add($(Test-TimeSync $kjernejournalTime)) } else { Out-TraceMessage "Not able to perform time sync test" Write-Host "Kan ikke sjekke klokken på lokal maskin, " -NoNewline -ForegroundColor Yellow Write-Host "pga. manglende kontakt med kjernejournal" -ForegroundColor Yellow } } if ($testsToRun.cert) { Write-Host ":: Tester om Buypass sine rot-sertifikater ligger inne" [void]$testResults.Add($(Test-TrustedRoots)) } if ($testsToRun.helseid) { Write-Host ":: Tester nødvendige åpninger for HelseID-autentisering" [void]$testResults.Add($(Test-URLSet "helseid")) } if ($testsToRun.buypass) { Write-Host ":: Tester nødvendige åpninger for Buypass-pålogging" [void]$testResults.Add($(Test-URLSet "buypass")) Write-Host ":: Sjekker etter Buypass Javafri-installasjon lokalt" [void]$testResults.Add($(Test-BuypassJavafri)) } if ($testsToRun.commfides) { Write-Host ":: Tester nødvendige åpninger for Commfides-pålogging" [void]$testResults.Add($(Test-URLSet "commfides")) } if ($testsToRun.bankid) { Write-Host ":: Tester nødvendige åpninger for BankID-pålogging" [void]$testResults.Add($(Test-URLSet "helseid")) [void]$testResults.Add($(Test-URLSet "bankid")) } if ($testResults -contains $false) { Write-Host Write-Host "Se dokumentasjon.kjernejournal.no for feilsøkingstips." } } function main { Write-Host " _ ___ _ _ " Write-Host " | |/ (_) (_) | |" Write-Host " | ' / _ ___ _ __ _ __ ___ _ ___ _ _ _ __ _ __ __ _| |" Write-Host " | < | |/ _ \ '__| '_ \ / _ \ |/ _ \| | | | '__| '_ \ / _` | |" Write-Host " | . \| | __/ | | | | | __/ | (_) | |_| | | | | | | (_| | |" Write-Host " |_|\_\ |\___|_| |_| |_|\___| |\___/ \__,_|_| |_| |_|\__,_|_|" Write-Host " _/ | _/ | " Write-Host " |__/ |__/ " Write-Host Write-Host "Velkommen til kjernejournals miljøsjekk, version $($version)." Write-Host $powershellVersion = (Get-Host).Version if ($powershellVersion.Major -lt 4 -or $powershellVersion.Major -gt 5) { # Invoke-Webrequest has been thoroughly changed in the Powershell Core versions, # so a lot of the error checking must be implemented twice if both are to be supported. # This should be done in the future, but for now this is no big deal, as Windows Powershell # does the job here just fine, and should be installed pretty much everywhere anyways. Write-Host "Dette scriptet er kun støttet på versjon 4 " -NoNewline -ForegroundColor Red Write-Host "eller nyere av Windows Powershell (altså ikke core)." -ForegroundColor Red exit 1 } if (![string]::IsNullOrWhiteSpace($Logg) -and !(Test-Path -Path $Logg -IsValid)) { Write-Host "Ugyldig Logg-parameter oppgitt. Vennligst oppgi en gyldig filsti." -ForegroundColor Red exit 1 } if ($Verbose) { $VerbosePreference = "Continue" } Out-TraceMessage "Starting kjernejournal environment check $($version)" Out-TraceMessage "Powershell version: $($powershellVersion.ToString())" Out-TraceMessage "Windows version: $([System.Environment]::OSVersion.VersionString)" Out-TraceMessage "Flags: Alle: $($Alle) Server: $($Server) Cert: $($Cert)" Out-TraceMessage "Flags: Buypass: $($Buypass) Commfides: $($Commfides) BankID: $($BankID)" $testsToRun = @{ "kjapi" = ($Alle -or $Server -or !($Buypass -or $Commfides -or $BankID -or $Cert)) "kjportal" = ($Alle -or $Buypass -or $Commfides -or $BankID -or !($Server -or $Cert)) "buypass" = ($Alle -or $Buypass) "commfides" = ($Alle -or $Commfides) "bankid" = ($Alle -or $BankID) "helseid" = ($Alle -or $Server) "cert" = ($Alle -or $Cert) } Write-Host # Some of the services that we connect to require TLSv1.2, and this is not # supported by default on some older Powershell/Windows versions, so we # have to enable it ourselves. Clean up after we're done, as this setting # is not scoped to the script. $originalSecurityProtocols = [Net.ServicePointManager]::SecurityProtocol [Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12 try { Test-SpecifiedServices $testsToRun } finally { [Net.ServicePointManager]::SecurityProtocol = $originalSecurityProtocols } Out-TraceMessage "Finished run" } main # SIG # Begin signature block # MIIZkwYJKoZIhvcNAQcCoIIZhDCCGYACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUkd6jouexmEpWNagP0ywFJw1+ # YUGgghShMIIE/jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgVGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMxMDEw # NjAwMDAwMFowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2UtAxQ # tSYQ/h3Ib5FrDJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4CGPN4 # bbx9+cdtCT2+anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xObTOK # fF1FLUuxUOZBOjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wODMSlK # XAwxikqMiMX3MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwfoYer # vnpbCiAvSwnJlaeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgwggG0 # MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG # AQUFBwMIMEEGA1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEWG2h0 # dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4prtLk # YaWyoiWyyBc1bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYDVR0f # BGowaDAyoDCgLoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl # ZC10cy5jcmwwMqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGluZ0NB # LmNydDANBgkqhkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0CiNH # o6uS0iXEcFm+FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1UUp4 # eTZ6J7fz51Kfk6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2QzI2h # F3MN9PNlOXBL85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnYIpp1 # FUL1LTI4gdr0YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oNcX6X # t/Q/hOvB46NJofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBTAwggQY # oAMCAQICEAQJGBtf1btmdVNDtW+VUAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UE # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj # ZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4X # DTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEx # MC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBD # QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsx # SRnP0PtFmbE620T1f+Wondsy13Hqdp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawO # eSg6funRZ9PG+yknx9N7I5TkkSOWkHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJ # RdQtoaPpiCwgla4cSocI3wz14k1gGL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEc # z+ryCuRXu0q16XTmK/5sy350OTYNkO/ktU6kqepqCquE86xnTrXE94zRICUj6whk # PlKWwfIPEvTFjg/BougsUfdzvL2FsWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8l # k9ECAwEAAaOCAc0wggHJMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQD # AgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEF # BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRw # Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0Eu # Y3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20v # RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARI # MEYwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdp # Y2VydC5jb20vQ1BTMAoGCGCGSAGG/WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg # +S32ZXUOWDAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG # 9w0BAQsFAAOCAQEAPuwNWiSz8yLRFcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/E # r4v97yrfIFU3sOH20ZJ1D1G0bqWOWuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3 # nEZOXP+QsRsHDpEV+7qvtVHCjSSuJMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpo # aK+bp1wgXNlxsQyPu6j4xRJon89Ay0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW # 6Fkd6fp0ZGuy62ZD2rOwjNXpDd32ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ # 92JuoVP6EpQYhS6SkepobEQysmah5xikmmRR7zCCBTEwggQZoAMCAQICEAqhJdbW # Mht+QeQF2jaXwhUwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTATBgNV # BAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIG # A1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTE2MDEwNzEyMDAw # MFoXDTMxMDEwNzEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGln # aUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTCCASIwDQYJKoZI # hvcNAQEBBQADggEPADCCAQoCggEBAL3QMu5LzY9/3am6gpnFOVQoV7YjSsQOB0Uz # URB90Pl9TWh+57ag9I2ziOSXv2MhkJi/E7xX08PhfgjWahQAOPcuHjvuzKb2Mln+ # X2U/4Jvr40ZHBhpVfgsnfsCi9aDg3iI/Dv9+lfvzo7oiPhisEeTwmQNtO4V8CdPu # XciaC1TjqAlxa+DPIhAPdc9xck4Krd9AOly3UeGheRTGTSQjMF287DxgaqwvB8z9 # 8OpH2YhQXv1mblZhJymJhFHmgudGUP2UKiyn5HU+upgPhH+fMRTWrdXyZMt7HgXQ # hBlyF/EXBu89zdZN7wZC/aJTKk+FHcQdPK/P2qwQ9d2srOlW/5MCAwEAAaOCAc4w # ggHKMB0GA1UdDgQWBBT0tuEgHf4prtLkYaWyoiWyyBc1bjAfBgNVHSMEGDAWgBRF # 66Kv9JLLgjEtUYunpyGd823IDzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB # /wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB5BggrBgEFBQcBAQRtMGswJAYI # KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3 # aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v # dENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2Ny # bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBQBgNV # HSAESTBHMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cu # ZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggEB # AHGVEulRh1Zpze/d2nyqY3qzeM8GN0CE70uEv8rPAwL9xafDDiBCLK938ysfDCFa # KrcFNB1qrpn4J6JmvwmqYN92pDqTD/iy0dh8GWLoXoIlHsS6HHssIeLWWywUNUME # aLLbdQLgcseY1jxk5R9IEBhfiThhTWJGJIdjjJFSLK8pieV4H9YLFKWA1xJHcLN1 # 1ZOFk362kmf7U2GJqPVrlsD0WGkNfMgBsbkodbeZY4UijGHKeZR+WfyMD+NvtQEm # tmyl7odRIeRYYJu6DC0rbaLEfrvEJStHAgh8Sa4TtuF8QkIoxhhWz0E0tmZdtnR7 # 9VYzIi8iNrJLokqV2PWmjlIwggUyMIIEGqADAgECAhABEZOV2L1tgp11Koj6LhwP # MA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lD # ZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwHhcNMjEwNTA1MDAw # MDAwWhcNMjIwNTEwMjM1OTU5WjBwMQswCQYDVQQGEwJOTzETMBEGA1UECAwKVHLD # uG5kZWxhZzESMBAGA1UEBxMJVHJvbmRoZWltMRswGQYDVQQKExJOb3JzayBIZWxz # ZW5ldHQgU0YxGzAZBgNVBAMTEk5vcnNrIEhlbHNlbmV0dCBTRjCCASIwDQYJKoZI # hvcNAQEBBQADggEPADCCAQoCggEBAOezDP2Wo0sTBzJePvLgHNJxus/+mjRs8ha3 # IRDic6Gc9YQDgjuP2QJm8Q/OP93+16X5lHNNu6Zows+lfqzT74+s05FsLPSGzabQ # SrVCZ0cEcaVfmc7saE3/jJtbNo5VFZ0xTOZ24D2NkAGbpFKH/sYpS1A1oIYHvGAw # FZnp7kGFRT6MYv+RUZq6C4c2pzSZLTev1qY5e+KdPFGxB8ltr0iZlTeKxSiqVb5w # +6Q8ENqUBrzO5xZRsKR8Tu5ze7VJqn3ThuJCH9JuFNsyxTq2a8n9W/bJygaXdFl5 # 3lydQUdHoWtKJUzJDMVdRi1o87XsSK3QRDpOS2J3HtaKjpXXnwECAwEAAaOCAcQw # ggHAMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB0GA1UdDgQWBBQl # FOP0OTwH9BdpyOoDBAmCtmm+LTAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYI # KwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDovL2NybDMuZGlnaWNlcnQu # Y29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGGL2h0dHA6Ly9jcmw0LmRp # Z2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMEsGA1UdIAREMEIwNgYJ # YIZIAYb9bAMBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29t # L0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0 # cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0 # cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNzdXJlZElEQ29kZVNpZ25pbmdD # QS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAAquNzzItVBKc # r13VO7+CvPYxozqfVIcvtMq33zzHm6MWQTjuCf3vi6jG5zKf++ckpUxGastLCl26 # uIrD+sbqRny8TvDOMWAWk88QrzUJV9OHd2/VGGUcUKWPAQe8f9oTvgJst+k+ra9S # abFWOxaRCcVcpmQUddUsu1Io7YqMNHnEC8FpSzKJb7OaODaXEnksivmXl/ve2XHF # oPQu9p6EHANiRpsWE7PRH8vwqlgn0JtF3f/xQTyUYvswFiYNQBUOcQvXLbitBIm8 # ks9ZUQbWtwJqBrgtuFpPcL/kgZaG36OfSEv2joEu+iQWfmJNuonuA2nTGtl715H2 # 2O5fVdIVQjGCBFwwggRYAgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE # aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMT # KERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0ECEAERk5XY # vW2CnXUqiPouHA8wCQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKEC # gAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwG # CisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFJlQVxOeQabWAL/MSpwxoCyFje3Q # MA0GCSqGSIb3DQEBAQUABIIBAE6ABP0UnBuTBV6ZEGhr3jHd6tETBn1CqG3ze6wH # 8iMXpmRlPOGSnx24oyrhspXjVQGj1JPETz6GMle7sdUcgZsiu/gpjeucdkL2rORK # Ijy3XvGuhk+p8tNw0TloawbHJj/6x5QWnNmaFDM5ZMid+qFvaVGr1JC1/C3DbPm4 # VmlPmdOGecmXlqbXm5Ea9RJzTNgmbWC96t7A8U+XnDCVxZmy362SgGamAXIZpFbN # 6LlgZ4On00bPQsGN7uIfQRv75BTUuWQrPHda1EYkK7GRN4a50rrMHFnuOqVrcrfM # VVDq5aU/3zFismcEghgWvdexeTJ69D+2qs0irHgxpG2as++hggIwMIICLAYJKoZI # hvcNAQkGMYICHTCCAhkCAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMo # RGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46 # iP9gQCHOFADw3TANBglghkgBZQMEAgEFAKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG # 9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIyMDMxNTE0MDUxN1owLwYJKoZIhvcNAQkE # MSIEIATDcOMhpysdAG6a9Pnq9JIVI1KC0XT/o6H9gAQh1YxJMA0GCSqGSIb3DQEB # AQUABIIBAKbnA6vqxJoWJJcIxIKbugA8+3fl08d/O2nuuzJF61EwlIj/tS7+T2mr # hRYHU5pG/nBZMW7FSGoofRY+SIdv/WUtv4m3Z267LVpW+WT0zwb+6hbiaHyDdEii # cKncWDd1oWtYdYLZsrz4kU6ZHlEye4CqBFLDk2eKXR83VljOUuilispQoto9e/Sw # yO7c9LEh/w1eZZJyejeaBD1L0dCJWvSLyBaYSBa4RLVTzhVBhoHeZy6b4AxeS58r # vhqvU0zG08KTpQ5MNGEH+14W2xs5sfXvTgs+wen5+T0Lj/zCd1Mt+pcuzX2b+fjc # DpsxDGVz5mGpyJGQRSwmwK7sWTcW6Xc= # SIG # End signature block