AzStackHCIDNS/AzStackHci.DNS.Helpers.psm1
Import-LocalizedData -BindingVariable ldTxt -FileName AzStackHci.DNS.Strings.psd1 # This file contains a list of discreet tests that can be run against the environment # Each test named Test-* is exported and discovered to be run by the user-facing function. # The user uses Include and Exclude parameters to run specific tests. (this provides a consistent experience across validators) # If tests have dependencies on other tests, or they should be run in a specific order, the pattern describe above should be removed. function Test-ExternalDnsResolution { <# .SYNOPSIS Test DNS Resolution #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $ExternalName ) $SkipDnsWithProxy = $ldTxt.SkipDnsWithProxy # Test if proxy is enabled and return because proxy maybe doing dns resolution function IsProxyEnabled { $line1, $line2, $line3, $JsonLines = netsh winhttp show advproxy $proxy = $JsonLines | ConvertFrom-Json -ErrorAction SilentlyContinue [bool]$proxy.Proxy } if (IsProxyEnabled) { $testDnsServer = @{ Resource = $SkipDnsWithProxy Status = 'SUCCESS' TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $SkipDnsWithProxy -f $ENV:COMPUTERNAME } } else { if ([string]::IsNullOrEmpty($PSBoundParameters['ExternalName'])) { Log-Info "No DNS target found, using microsoft.com as fall back" -ConsoleOut -Type Warning $ExternalName = @('microsoft.com') } if ($ExternalName.count -ne 1) { throw "Expected 1 System_Check_DNS_External_Hostname_Resolution, found $($ExternalName.count)" } $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } if ($PSBoundParameters['ExternalName']) { $TestDNSResolutionParams.Add('TargetName', $ExternalName) } $testDnsServer = TestDNSResolution @TestDNSResolutionParams } # build result $now = [datetime]::UtcNow # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ "WARNING" } else { "INFO" } ) } $extDnsResult = @() $extDnsResult += $testDnsServer | Foreach-Object { $params = @{ Name = 'AzStackHci_DNS_Test_External_Hostname_Resolution' Title = 'Test External Hostname Resolution' DisplayName = 'Test External Hostname Resolution' Severity = 'Critical' Description = 'Test External Hostname Resolution' Tags = @{ Service = 'System' } Remediation = $ldTxt.ExternalDnsRemediation TargetResourceID = "$($PsItem.Source)/$($PsItem.Resource)" TargetResourceName = $PsItem.Resource TargetResourceType = 'DNS' Timestamp = $now Status = $PsItem.Status AdditionalData = $PsItem HealthCheckSource = $ENV:EnvChkrId } New-AzStackHciResultObject @params } return $extDnsResult } function Test-ActiveDirectoryDomainName { <# .SYNOPSIS Test DNS Resolution #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $DomainFQDN ) $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } if ($PSBoundParameters['DomainFQDN']) { $TestDNSResolutionParams.Add('TargetName', $DomainFQDN) } $testDnsServer = TestDNSResolution @TestDNSResolutionParams # build result $now = [datetime]::UtcNow # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ "WARNING" } else { "INFO" } ) } $adDnsResult = @() $adDnsResult += $testDnsServer | Foreach-Object { $params = @{ Name = 'AzStackHci_DNS_Test_ActiveDirectory_DomainName_Resolution' Title = 'Test Active Directory Domain Name Resolution' DisplayName = 'Test Active Directory Domain Name Resolution' Severity = 'Critical' Description = 'Test Active Directory Domain Name Resolution' Tags = @{ Service = 'System' } Remediation = $ldTxt.DomainNameDnsRemediation TargetResourceID = "$($PsItem.Source)/$($PsItem.Resource)" TargetResourceName = $PsItem.Resource TargetResourceType = 'DNS' Timestamp = $now Status = $PsItem.Status AdditionalData = $PsItem HealthCheckSource = $ENV:EnvChkrId } New-AzStackHciResultObject @params } return $adDnsResult } function Test-LocalClusterDNSResolution { <# .SYNOPSIS Cluster Name and Node names must be resolvable in DNS. #> [CmdletBinding()] param ( [System.Management.Automation.Runspaces.PSSession[]] $PsSession, [string[]] $PhysicalMachineNames, [string] $ClusterName, # AD integration parameters [Parameter()] [System.String] $DomainFqdn, [Parameter()] [System.Management.Automation.PSCredential] $DomainCredential, [Parameter()] [switch] $IsLocalIdentityEnvironment ) $TestDNSResolutionParams = @{} if ($PSBoundParameters['PsSession']) { $TestDNSResolutionParams.Add('PsSession', $PsSession) } # Add fully qualified cluster and node names to resolve. # Cluster name is already fully qualified, so just add it to the list. $targetNames = @() $targetNames += $PhysicalMachineNames | ForEach-Object { "$_.$DomainFqdn" } $targetNames += "$ClusterName.$DomainFqdn" $TestDNSResolutionParams.Add('TargetName', $targetNames) $testDnsServer = TestDNSResolution @TestDNSResolutionParams # build result $now = [datetime]::UtcNow # Write result to verbose log $testDnsServer | Foreach-Object { Log-Info $_.Detail -Type $(if ( $_.Status -eq 'FAILURE' ){ "WARNING" } else { "INFO" } ) } $LocalClusterDNSResult = @() $LocalClusterDNSResult += $testDnsServer | Foreach-Object { $params = @{ Name = 'AzStackHci_DNS_Test_Local_Cluster_DNS_Resolution' Title = 'Test Local Cluster DNS Resolution' DisplayName = 'Test Local Cluster DNS Resolution' Severity = 'Critical' Description = 'Ensure each DNS server can resolve each node name and cluster name' Tags = @{ Service = 'System' } Remediation = 'Ensure an A record exists on the DNS server for each node name and the cluster name' TargetResourceID = "$($PsItem.Source)/$($PsItem.Resource)" TargetResourceName = $PsItem.Resource TargetResourceType = 'DNS' Timestamp = $now Status = $PsItem.Status AdditionalData = $PsItem HealthCheckSource = $ENV:EnvChkrId } New-AzStackHciResultObject @params } # Check if the test failed and if so, check if AD integration test parameters are set # If AD integration test parameters are set, run the AD integrated DNS test # If the AD integrated DNS test fails, return the result of the AD integrated DNS test (warning) and the local cluster DNS test (critical) # If the AD integrated DNS test passes, return the result of the non AD integrated DNS test if ('FAILURE' -in $LocalClusterDNSResult.Status) { Log-Info -Message "Local Cluster member DNS resolution test failed. Checking if AD integration test parameters are set." -Type Warning # AD deployment's have DomainCredential and DomainFqdn set, AD-less deployments do not have these parameters set. if (-not $PSBoundParameters['IsLocalIdentityEnvironment']) { Log-Info -Message "AD integration test parameters are set. Running AD integrated DNS test." -Type Warning $adIntDnsResult = TestAdIntegratedDns -DomainFqdn $DomainFqdn -DomainCredential $DomainCredential # both tests have failed return both results if ($adIntDnsResult.Status -eq 'FAILURE') { Log-Info -Message "AD integrated DNS test failed. Downgrade the local cluster resolution test to warning." -Type Warning $LocalClusterDNSResult | Foreach-Object {$PsItem.Severity = 'WARNING'} Log-Info -Message "AD integrated DNS test failed. Returning both local resolution and AD integrated together" -Type WARNING return ($LocalClusterDNSResult + $adIntDnsResult) } else { # This is happy path AD deployment has AD integrated DNS. Log-Info -Message "AD integrated DNS test passed. We don't need to block the life cycle operation. Returning AD Integrated DNS test result." return $adIntDnsResult } } else { Log-Info -Message "AD integration test parameters are not set. Local Cluster member DNS resolution test failed. This will block lifecycle operation." -Type CRITICAL return $LocalClusterDNSResult } } else { Log-info -Message "Local Cluster member DNS resolution test passed. Returning." return $LocalClusterDNSResult } } function TestDNSResolution { <# .SYNOPSIS Test DNS Resolution of a target name by testing each dns server configured on any remote machine. .DESCRIPTION This function will test the DNS resolution of a target name by testing each DNS server configured on the machine. It will return the status of each DNS server and the result of the DNS query. It will also enable the DNS client operational log to get the logs for last attempt during failures. It will then disable the log if it was not enabled in the first place. It's intended to be a reusable function to facilitate the testing of DNS resolution in a consistent manner across types of names internal/external/node/cluster etc. #> [CmdletBinding()] param ( [string[]] $TargetName, [System.Management.Automation.Runspaces.PSSession[]] $PsSession ) try { # scriptblock to test dns resolution for each dns server $testDnsSb = { $TargetName = $args[0] -split ' ' # Pass in localized strings $NoDnsConfigured = $args[1] $QueryDnsFail = $args[2] $QueryDnsPass = $args[3] $AdditionalData = @() # Get local DNS servers $dnsServers = @() $netAdapter = Get-NetAdapter | Where-Object Status -EQ Up $dnsServer = Get-DnsClientServerAddress -InterfaceIndex $netAdapter.ifIndex -AddressFamily IPv4 $dnsServers += $dnsServer | ForEach-Object { $PSITEM.Address } | Sort-Object | Get-Unique if (-not $dnsServers) { return @{ Resource = $NoDnsConfigured Status = 'FAILURE' TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $NoDnsConfigured } } else { foreach ($target in $TargetName) { foreach ($dnsServer in $dnsServers) { $status = 'FAILURE' $attempt = 0 $maxRetry = 3 $sleepInSeconds = 5 while ($attempt -lt $maxRetry -and $status -eq 'FAILURE') { try { $attempt++ # if this is the last attempt, check if the DNS client operational log is enabled, enabled it and reads the log for debug information if ($attempt -eq ($maxRetry - 1)) { $dnsLogState = & wevtutil gl Microsoft-Windows-DNS-Client/Operational | select-string -pattern "enabled: (.*)" if ($dnsLogState -like '*false') { # enable the dns log for 5 minutes to get the logs and set the size to 10MB & wevtutil sl Microsoft-Windows-DNS-Client/Operational /e:true /ms:10485760 $dnsLogNeedsToBeDisabled = $true } else { $dnsLogAlreadyEnabled = $true } $preDnsTimeStamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fffZ" -AsUTC } $dnsResult = Resolve-DnsName -Name $target -Server $dnsServer -DnsOnly -ErrorAction SilentlyContinue -QuickTimeout -Type A } catch {} if ([int]($dnsResult.count) -eq 0) { $detail = $QueryDnsFail -f $dnsServer, $target, $ENV:COMPUTERNAME, [int]($dnsResult.count) } else { $detail = $QueryDnsPass -f $dnsServer, $target, $ENV:COMPUTERNAME, [int]($dnsResult.count), ($dnsResult.IpAddress -join ',') } if ($dnsResult) { if ($dnsResult[0] -is [Microsoft.DnsClient.Commands.DnsRecord]) { $status = 'SUCCESS' break } else { $status = 'FAILURE' } } else { $status = 'FAILURE' } Start-Sleep -Second $sleepInSeconds } # If the dns log is enabled get the dns logs for this domain if ($dnsLogNeedsToBeDisabled -eq $true -or $dnsLogAlreadyEnabled) { $xPathFilter = "*[System[Provider[@Name='Microsoft-Windows-DNS-Client']]] and *[EventData[Data[@Name='QueryName']='$target']] and *[System[TimeCreated[@SystemTime > '$preDnsTimeStamp']]]" $dnsEvents = Get-WinEvent -LogName "Microsoft-Windows-DNS-Client/Operational" -FilterXPath $xPathFilter -ErrorAction SilentlyContinue | sort-object TimeCreated | Foreach-Object { "[{0}] [{1}] - {2}" -f $_.TimeCreated, $_.LevelDisplayName, $_.Message} if ($dnsEvents) { $detail += "`n`nDNS Client Operational Log:`n$($dnsEvents -join "`r`n" | Out-String)" } # Disable the DNS client operational log if it was enabled in the first place if ($dnsLogNeedsToBeDisabled -eq $true) { & wevtutil sl Microsoft-Windows-DNS-Client/Operational /e:false } } $AdditionalData += @{ Resource = $dnsServer Status = $status TimeStamp = [datetime]::UtcNow Source = $ENV:COMPUTERNAME Detail = $detail } } } } $AdditionalData } # run scriptblock $dnsargs = @{ ArgumentList = $TargetName, $ldTxt.NoDnsConfigured, $ldTxt.QueryDnsFail, $ldTxt.QueryDnsPass } $testDnsServer = if ($PsSession) { Invoke-Command -Session $PsSession -ScriptBlock $testDnsSb @dnsArgs } else { Invoke-Command -ScriptBlock $testDnsSb @dnsArgs } return $testDnsServer } catch { throw "Failed to run TestDNSResolution: $($_.Exception.Message)" } } function Get-LdapDomain { [CmdletBinding()] [OutputType([System.String])] Param ( [Parameter(Mandatory = $true)] [System.String] $Domain ) $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop $ldapDomain = ($Domain.Split('.') | ForEach-Object {"DC=$_"}) -join ',' return $ldapDomain } function TestAdIntegratedDns { [CmdletBinding()] [OutputType([System.Boolean])] Param ( [Parameter(Mandatory = $true)] [System.String] $DomainFqdn, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] $DomainCredential ) try { $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop Log-Info -Message 'Importing module ActiveDirectory.' Import-Module ActiveDirectory -Verbose:$false # Convert domain name to fully qualified LDAP name $ldapDomain = Get-LdapDomain -Domain $DomainFqdn Log-Info -Message "LdapDomain to search is '$ldapDomain'." # Get forest root domain so we can search for forest zones as well as domain zones $rootDomain = Get-LdapDomain -Domain (Get-ADForest -Credential $DomainCredential -Server $DomainFqdn).RootDomain Log-Info -Message "RootDomain to search is '$rootDomain'." # Build list of locations to search - including legacy Windows 2000 locations $searchBases = @( "DC=$DomainFqdn,CN=MicrosoftDNS,DC=DomainDnsZones,$ldapDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,CN=System,$ldapDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,DC=ForestDnsZones,$rootDomain" "DC=$DomainFqdn,CN=MicrosoftDNS,CN=System,$rootDomain" ) $result = $false # Search each location until one is found foreach ($searchBase in $searchBases) { if (-not $result) { Log-Info -Message "Searching for DNS zone container '$searchBase'." try { $dnsZone = Get-ADObject -SearchBase $searchBase -LDAPFilter '(objectClass=dnsZone)' -Properties @('dnsProperty') -Credential $DomainCredential -Server $DomainFqdn Log-Info -Message "Found DNS zone container '$searchBase'." $result = $true } catch { Log-Info -Message "DNS zone container '$searchBase' does not exist." } } } # Write to log file and set status if ($result) { $dtl = $ldTxt.AdIntDnsPass -f $rootDomain, $dnsZone.DistinguishedName Log-Info -Message $dtl $Status = 'SUCCESS' } else { $dtl = $ldTxt.AdIntDnsFail -f $rootDomain Log-Info -Message $dtl -Type WARNING $Status = 'FAILURE' } # Write result $now = [datetime]::UtcNow $params = @{ Name = 'AzStackHci_DNS_Test_ActiveDirectory_Integrated_DNS' Title = 'Test Active Directory Integrated DNS' DisplayName = 'Test Active Directory Integrated DNS' Severity = 'Warning' Description = 'Test Active Directory Integrated DNS' Tags = @{ Service = 'System' } Remediation = $ldTxt.AdIntDnsRemediation TargetResourceID = "$ENV:COMPUTERNAME/$rootDomain" TargetResourceName = $rootDomain TargetResourceType = 'DNS' Timestamp = $now Status = $Status AdditionalData = @{ Resource = $rootDomain Source = $ENV:COMPUTERNAME Status = $Status Detail = $dtl } HealthCheckSource = $ENV:EnvChkrId } return (New-AzStackHciResultObject @params) } catch { throw "Error checking Active Directory Integrated DNS: $_" } } Export-ModuleMember -Function Test-* # SIG # Begin signature block # MIIoRgYJKoZIhvcNAQcCoIIoNzCCKDMCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBRPiynKv/JZhWD # Gj8Wq4sur2Hs98JXtnDS3hdZeV2wuaCCDXYwggX0MIID3KADAgECAhMzAAAEBGx0 # Bv9XKydyAAAAAAQEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjQwOTEyMjAxMTE0WhcNMjUwOTExMjAxMTE0WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQC0KDfaY50MDqsEGdlIzDHBd6CqIMRQWW9Af1LHDDTuFjfDsvna0nEuDSYJmNyz # NB10jpbg0lhvkT1AzfX2TLITSXwS8D+mBzGCWMM/wTpciWBV/pbjSazbzoKvRrNo # DV/u9omOM2Eawyo5JJJdNkM2d8qzkQ0bRuRd4HarmGunSouyb9NY7egWN5E5lUc3 # a2AROzAdHdYpObpCOdeAY2P5XqtJkk79aROpzw16wCjdSn8qMzCBzR7rvH2WVkvF # HLIxZQET1yhPb6lRmpgBQNnzidHV2Ocxjc8wNiIDzgbDkmlx54QPfw7RwQi8p1fy # 4byhBrTjv568x8NGv3gwb0RbAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU8huhNbETDU+ZWllL4DNMPCijEU4w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwMjkyMzAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAIjmD9IpQVvfB1QehvpC # Ge7QeTQkKQ7j3bmDMjwSqFL4ri6ae9IFTdpywn5smmtSIyKYDn3/nHtaEn0X1NBj # L5oP0BjAy1sqxD+uy35B+V8wv5GrxhMDJP8l2QjLtH/UglSTIhLqyt8bUAqVfyfp # h4COMRvwwjTvChtCnUXXACuCXYHWalOoc0OU2oGN+mPJIJJxaNQc1sjBsMbGIWv3 # cmgSHkCEmrMv7yaidpePt6V+yPMik+eXw3IfZ5eNOiNgL1rZzgSJfTnvUqiaEQ0X # dG1HbkDv9fv6CTq6m4Ty3IzLiwGSXYxRIXTxT4TYs5VxHy2uFjFXWVSL0J2ARTYL # E4Oyl1wXDF1PX4bxg1yDMfKPHcE1Ijic5lx1KdK1SkaEJdto4hd++05J9Bf9TAmi # u6EK6C9Oe5vRadroJCK26uCUI4zIjL/qG7mswW+qT0CW0gnR9JHkXCWNbo8ccMk1 # sJatmRoSAifbgzaYbUz8+lv+IXy5GFuAmLnNbGjacB3IMGpa+lbFgih57/fIhamq # 5VhxgaEmn/UjWyr+cPiAFWuTVIpfsOjbEAww75wURNM1Imp9NJKye1O24EspEHmb # DmqCUcq7NqkOKIG4PVm3hDDED/WQpzJDkvu4FrIbvyTGVU01vKsg4UfcdiZ0fQ+/ # V0hf8yrtq9CkB8iIuk5bBxuPMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCGiYwghoiAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAQEbHQG/1crJ3IAAAAABAQwDQYJYIZIAWUDBAIB # BQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIJkzQQf9LWAeQO4V1wPGAvP2 # +WHJYfMiYA9/bDwF2FhOMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEB # BQAEggEAp5pH1GQ7ElgEYXp1Jb4xBFynlKK8xdX2btqkyaPEJ/nHoG7OfXrpyHe/ # Uqe6V/p1LWDKBi97pW6HUt1ksoil0NbNthw7Ko4pQKjIcOqlSHoEgXJL7HSsUaMW # I8p+BCirdZuCpukrZR6MD6WWZGGDRlGgDZ4L0XZsWcd17IrnJNJTzBCL84z2VBYO # 3YvbXHbqDlysIUYIU53wpbpwF8K8fNImxwAA/9KhV6x42QVQfRAFML83G2XClC8v # xfofpmK64fm010OoK6q9HZ0Rx9ZTY56ScibXQDe951NyAVvx3sP77L0h+myGphyK # fwr1axfw564gxgqIP5jmEbw3zGjBLqGCF7AwghesBgorBgEEAYI3AwMBMYIXnDCC # F5gGCSqGSIb3DQEHAqCCF4kwgheFAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFaBgsq # hkiG9w0BCRABBKCCAUkEggFFMIIBQQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFl # AwQCAQUABCB8I6ZowSb06qQoFakIS2xGkNbCyWeafmP1oC4G10euHQIGaC5MEqt7 # GBMyMDI1MDYxMDE1NDg1OS42NDdaMASAAgH0oIHZpIHWMIHTMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT # Tjo1NTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg # U2VydmljZaCCEf4wggcoMIIFEKADAgECAhMzAAACAdFFWZgQzEJPAAEAAAIBMA0G # CSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9u # MRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp # b24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI0 # MDcyNTE4MzEyMloXDTI1MTAyMjE4MzEyMlowgdMxCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9w # ZXJhdGlvbnMgTGltaXRlZDEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjU1MUEt # MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNl # MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtWrf+HzDu7sk50y5YHhe # CIJG0uxRSFFcHNek+Td9ZmyJj20EEjaU8JDJu5pWc4pPAsBI38NEAJ1b+KBnlStq # U8uvXF4qnEShDdi8nPsZZQsTZDKWAgUM2iZTOiWIuZcFs5ZC8/+GlrVLM5h1Y9nf # Mh5B4DnUQOXMremAT9MkvUhg3uaYgmqLlmYyODmba4lXZBu104SLAFsXOfl/TLhp # ToT46y7lI9sbI9uq3/Aerh3aPi2knHvEEazilXeooXNLCwdu+Is6o8kQLouUn3Kw # UQm0b7aUtsv1X/OgPmsOJi6yN3LYWyHISvrNuIrJ4iYNgHdBBumQYK8LjZmQaTKF # acxhmXJ0q2gzaIfxF2yIwM+V9sQqkHkg/Q+iSDNpMr6mr/OwknOEIjI0g6ZMOymi # vpChzDNoPz9hkK3gVHZKW7NV8+UBXN4G0aBX69fKUbxBBLyk2cC+PhOoUjkl6UC8 # /c0huqj5xX8m+YVIk81e7t6I+V/E4yXReeZgr0FhYqNpvTjGcaO2WrkP5XmsYS7I # vMPIf4DCyIJUZaqoBMToAJJHGRe+DPqCHg6bmGPm97MrOWv16/Co6S9cQDkXp9vM # SSRQWXy4KtJhZfmuDz2vr1jw4NeixwuIDGw1mtV/TdSI+vpLJfUiLl/b9w/tJB92 # BALQT8e1YH8NphdOo1xCwkcCAwEAAaOCAUkwggFFMB0GA1UdDgQWBBSwcq9blqLo # PPiVrym9mFmFWbyyUjAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBf # BgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3Bz # L2NybC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmww # bAYIKwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29m # dC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0El # MjAyMDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUF # BwMIMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAgEAOjQAyz0cVztT # FGqXX5JLRxFK/O/oMe55uDqEC8Vd1gbcM28KBUPgvUIPXm/vdDN2IVBkWHmwCp4A # Icy4dZtkuUmd0fnu6aT9Mvo1ndsLp2YJcMoFLEt3TtriLaO+i4Grv0ZULtWXUPAW # /Mn5Scjgn0xZduGPBD/Xs3J7+get9+8ZvBipsg/N7poimYOVsHxLcem7V5XdMNsy # tTm/uComhM/wgR5KlDYTVNAXBxcSKMeJaiD3V1+HhNkVliMl5VOP+nw5xWF55u9h # 6eF2G7eBPqT+qSFQ+rQCQdIrN0yG1QN9PJroguK+FJQJdQzdfD3RWVsciBygbYaZ # lT1cGJI1IyQ74DQ0UBdTpfeGsyrEQ9PI8QyqVLqb2q7LtI6DJMNphYu+jr//0spr # 1UVvyDPtuRnbGQRNi1COwJcj9OYmlkFgKNeCfbDT7U3uEOvWomekX60Y/m5utRcU # PVeAPdhkB+DxDaev3J1ywDNdyu911nAVPgRkyKgMK3USLG37EdlatDk8FyuCrx4t # iHyqHO3wE6xPw32Q8e/vmuQPoBZuX3qUeoFIsyZEenHq2ScMunhcqW32SUVAi5oZ # 4Z3nf7dAgNau21NEPwgW+2wkrNqDg7Hp8yHyoOKbgEBu6REQbvSfZ5Kh4PV+S2gx # f2uq6GoYDnlqABOMYwz309ISi0bPMh8wggdxMIIFWaADAgECAhMzAAAAFcXna54C # m0mZAAAAAAAVMA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0aWZp # Y2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAxODIyMjVaFw0zMDA5MzAxODMy # MjVaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNV # BAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0B # AQEFAAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7VgtP97pwHB9KpbE51 # yMo1V/YBf2xK4OK9uT4XYDP/XE/HZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY # 6GB9alKDRLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gmU3w5YQJ6xKr9 # cmmvHaus9ja+NSZk2pg7uhp7M62AW36MEBydUv626GIl3GoPz130/o5Tz9bshVZN # 7928jaTjkY+yOSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoFVZhtaDua # Rr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJiss254o2I5JasAUq7vnGpF1tnYN74 # kpEeHT39IM9zfUGaRnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+AutuqfjbsNkz2 # K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afomXw/TNuvXsLz1dhzPUNOwTM5 # TI4CvEJoLhDqhFFG4tG9ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZk # i1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y1BzFa/ZcUlFdEtsluq9Q # BXpsxREdcu+N+VLEhReTwDwV2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3Pmri # Lq0CAwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEwIwYJKwYBBAGCNxUC # BBYEFCqnUv5kxJq+gpE8RjUpzxD/LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJl # pxtTNRnpcjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8GCCsGAQUFBwIB # FjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL0RvY3MvUmVwb3NpdG9y # eS5odG0wEwYDVR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAweCgBTAHUA # YgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU # 1fZWy4/oolxiaNE9lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2Ny # bC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0XzIw # MTAtMDYtMjMuY3JsMFoGCCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXRfMjAxMC0w # Ni0yMy5jcnQwDQYJKoZIhvcNAQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/yp # b+pcFLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHkwo/7bNGhlBgi7ulm # ZzpTTd2YurYeeNg2LpypglYAA7AFvonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM # 9W0jVOR4U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2EhIRXT0n4ECW # OKz3+SmJw7wXsFSFQrP8DJ6LGYnn8AtqgcKBGUIZUnWKNsIdw2FzLixre24/LAl4 # FOmRsqlb30mjdAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZMcm8Qq3Uw # xTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQEcb9k+SS+c23Kjgm9swFXSVRk2XPX # fx5bRAGOWhmRaw2fpCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBMdrVX # VAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L+DvktxW/tM4+pTFRhLy/AsGC # onsXHRWJjXD+57XQKBqJC4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU # 5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/2XBjU02N7oJtpQUQwXEG # ahC0HVUzWLOhcGbyoYIDWTCCAkECAQEwggEBoYHZpIHWMIHTMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJl # bGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT # Tjo1NTFBLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAg # U2VydmljZaIjCgEBMAcGBSsOAwIaAxUA1+26cR/yH100DiNFGWhuAv2rYBqggYMw # gYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD # VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkqhkiG9w0BAQsF # AAIFAOvyffYwIhgPMjAyNTA2MTAwOTQ4MzhaGA8yMDI1MDYxMTA5NDgzOFowdzA9 # BgorBgEEAYRZCgQBMS8wLTAKAgUA6/J99gIBADAKAgEAAgIGlQIB/zAHAgEAAgIU # CjAKAgUA6/PPdgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEEAYRZCgMCoAow # CAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQAfi+MGnunW # ybtUkrkwLDZX//z34ylWV1dRMzJyaqBTNnbPDaXxEl3FZpXbHM9+w+jLusEyONCH # Pwrs1MBQ4pH7XAYyXbUhfq2mhK1ehRuSJLE8mq7MWv0Hz6Ry3VhHAIpuxXTFzy0Z # nra2oeVxOzWdLwGrnAUyZJ0cBvz4ws5W28cVozT9zNEOj4LnHHFVZoOSEZYoDhzP # DuGohvJsym+INRclCuWzfMbWyI9U352DlHXIcvkrjaOjN6T6zMB2g2UOYEFnRSGz # y3TRIVLQCUGAl3BFmoeuM1zwRGod1LUEl1R6nROtHQobv/pmGT1NaNp/nTnHZQg2 # BKCIu1C+ohavMYIEDTCCBAkCAQEwgZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENB # IDIwMTACEzMAAAIB0UVZmBDMQk8AAQAAAgEwDQYJYIZIAWUDBAIBBQCgggFKMBoG # CSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgYB9LtZNU # tsQiOBuXVZvLLGei9Wz7Dszpu034o2D5VwQwgfoGCyqGSIb3DQEJEAIvMYHqMIHn # MIHkMIG9BCBYa7I6TJQRcmx0HaSTWZdJgowdrl9+Zrr0pIdqHtc4IzCBmDCBgKR+ # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACAdFFWZgQzEJPAAEA # AAIBMCIEIGXf2ArpJzaxZZF6XoFIb/jMjZpoRUaPtqukZ0JzHWTvMA0GCSqGSIb3 # DQEBCwUABIICADJ7BokE5SaJvFJ57Qw/lIGoVg/SBLon7b3sshfjfQsN9o14B9I7 # cWkCi139Pla2s4ouF/QCNZlH4vUq73Y9S4G8SmBUcT2mwPPMc/82ROxrEtzgsOx6 # Kuz6upBi+USBQyMnYX/mBjQz81jxwYkvze2Dlmk1SSVeU1XXysm+boiky42h7eZ6 # HyAufR3HxrU5rqfM9KlW/v38AVeuvx8xZLfgejgZoRhdkCxds0jE6BBi1vBKEbZP # 4NcBx8uNhP99y7EsYMbNs6rHQroCjlfW883CBYXUZZPTNaQwC0wF1PXPC3QaFceL # X+54fDXUvBty6IYOhtnQU9vPMbzva/kZLNRHKXmt8si/EriGUH/XQyU5NfbulI56 # IN2PKJOFUjs+WJX+7nW+hbJqZEzfL69aXPX+AiaiYJV7XWix4TTfKRMTK6RjcO+f # Dz2QZTFVxNSli/Ihhj8ZvvOce4ogkYukgbfTH/k+D3pHkcdyOfjcCfvsg7Pxsr+c # rq17k7dcIJ3GbNLPLj9neCCrq2Zh9uvJ4WyS39KMQ2n2QpyQ5wIIKOFjhl2TzfwR # sVzf9pbVnsOaKixe6Sfe4HavasfU4gqBBukLSJQpjXj7wwgrZyvgQ1eTiQ4z7t5U # jYl60AKSPHGNH8uO03a/UhR28+3DGw94BvaF+LIGXyPAUhpPobRyERQz # SIG # End signature block |