Obs/bin/TestObservability/TestModules/TestTenantJSON/TestTenantJSON.psm1
<##############################################################
# # # Copyright (C) Microsoft Corporation. All rights reserved. # # # ##############################################################> using Module ..\..\HelperFiles\Result.psm1 Import-Module $PSScriptRoot\..\..\HelperFiles\TestObsHelper.psm1 -Force Import-Module $PSScriptRoot\TenantJSONTestRow.psm1 -Force function Test-TenantJSON { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestReport, [Parameter(Mandatory=$true)] [string] $DeviceType ) try { $functionName = $($MyInvocation.MyCommand.Name) $tenantJSONData = Get-Content -Path "$PSScriptRoot\TenantJSONData.json" | ConvertFrom-Json $tenantJSONNames = $tenantJSONData.TenantJSONNames $tenantJSONFields = $tenantJSONData.Fields $tenantJSONs = Get-ChildItem "$env:SystemDrive\GMACache\JsonDropLocation" foreach ($name in $tenantJSONNames) { Trace-Progress "$functionName : Beginning sub tests for TestTenantJSON for area path : $name" $testReport = Test-AreaPathTenantJSON -TestReport $TestReport -TenantJSONs $TenantJSONs -TenantJSONFields $tenantJSONFields ` -AreaPath $name -DeviceType $DeviceType } return $testReport } catch { Trace-Progress "$functionName : Failed with $_" -Error return $TestReport } } function Test-AreaPathTenantJSON { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestReport, [Parameter(Mandatory=$false)] [Object[]] $TenantJSONs, [Parameter(Mandatory=$true)] [PSCustomObject] $TenantJSONFields, [Parameter(Mandatory=$true)] [string] $AreaPath, [Parameter(Mandatory=$true)] [string] $DeviceType ) $functionName = $($MyInvocation.MyCommand.Name) try { Trace-Progress "$functionName : Testing whether tenant JSON exists for area path $AreaPath" $tenantJSonExistsRow = Test-TenantJSONExists -TenantJSONs $TenantJSONs -AreaPath $AreaPath Trace-Progress "$functionName : Finished testing whether Tenant JSON Exists for area path $AreaPath. Adding results to TenantJSON test report." $testReport.Rows.Add($tenantJSonExistsRow) if (($testReport.Rows | Measure-Object).Count -eq 1) { $testTenantJSONExists = $TestReport.Rows } else { $testTenantJSONExists = $TestReport.Rows | Where-Object {$_.AreaPath -eq $AreaPath -and $_.TestName -like "*Tenant JSON Exists*"} } if ($testTenantJSONExists.Result -eq [Result]::PASS) { $tenantJSONExists = $true } else { $tenantJSONExists = $false } Trace-Progress "$functionName : Testing if all expected fields exist for area path $AreaPath" $testFieldsRow = Test-ExpectedFieldsExist -TenantJSONs $TenantJSONs -TenantJSONFields $TenantJSONFields ` -AreaPath $AreaPath -TenantJSONExists $tenantJSONExists -DeviceType $deviceType Trace-Progress "$functionName : Finished testing whether expected fields exist for area path $AreaPath. Adding results to TenantJSON test report." $testReport.Rows.Add($testFieldsRow) Trace-Progress "$functionName : Testing if various fields has a valid value for area path $AreaPath" $testRows = Test-ValidFieldValues -TenantJSONs $TenantJSONs -TenantJSONFields $TenantJSONFields ` -AreaPath $AreaPath -TenantJSONExists $tenantJSONExists foreach ($testRow in $testRows) { $testReport.Rows.Add($testRow) } return $testReport } catch { Trace-Progress "$functionName : failed with $_" -Error return $testReport } } <# # Sub tests for Test-TenantJSON #> function Test-TenantJSONExists { Param( [Parameter(Mandatory=$false)] [Object[]] $TenantJSONs, [Parameter(Mandatory=$true)] [string] $AreaPath ) $functionName = $($MyInvocation.MyCommand.Name) $testName = "Tenant JSON Exists" try { $tenantJSONFileName = $AreaPath + ".json" $tenantJSON = $tenantJSONS | where-object {$_.Name -eq $tenantJSONFileName} Trace-Progress "$functionName : Creating new test row for testing whether Tenant JSON exists" $testRow = New-TenantJSONTestRow -TestName $testName -AreaPath $AreaPath -TestDescription "Confirm if tenant JSON exists for area path $AreaPath" if ($null -ne $tenantJSON) { $result = [Result]::PASS } else { $result = [Result]::FAIL } $testRow.Result = $result if ($result -eq [Result]::FAIL) { $testRow.ReasonForFailure = "$tenantJSONFileName cannot be found" } return $testRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testName -AreaPath $AreaPath } } function Test-ExpectedFieldsExist { Param( [Parameter(Mandatory=$false)] [Object[]] $TenantJSONs, [Parameter(Mandatory=$true)] [PSCustomObject] $TenantJSONFields, [Parameter(Mandatory=$true)] [string] $AreaPath, [Parameter(Mandatory=$true)] [bool] $TenantJSONExists, [Parameter(Mandatory=$true)] [string] $DeviceType ) $functionName = $($MyInvocation.MyCommand.Name) $testName = "All expected fields exist and have non-empty string value." try { Trace-Progress "$functionName : Creating Test Description for testing whether expected fields exist for area path $AreaPath" $testDescription = "Expected Fields: " $fieldProperties = $TenantJSONFields.PSObject.Properties | Where-Object {$_.MemberType -like 'NoteProperty' } foreach ($fieldType in $fieldProperties) { $fields = $fieldType.Value.PSObject.Properties | Where-Object {$_.MemberType -like 'NoteProperty' } foreach ($field in $fields) { if ($field.Value -icontains $DeviceType) { $testDescription += " $($field.Name)," } } } $testDescription = $testDescription.Trim(",") Trace-Progress "$functionName : Creating test row for testing whether expected fields exist for area path $AreaPath." $testFieldsRow = New-TenantJSONTestRow -TestName $testName -TestDescription $TestDescription -AreaPath $AreaPath if (!$TenantJSONExists) { return Fail-TestNoTenantJSON -TestRow $testFieldsRow -AreaPath $AreaPath } if ($DeviceType -ieq "Unknown") { $testFieldsRow.ReasonForFailure = "Can't get expected fields because device type is unknown. Mark test as failure." $testFieldsRow.Result = [Result]::FAIL $testFieldsRow.TestDescription = "" return $testFieldsRow } $tenantJSON = Get-TenantJSONContents -TenantJSONs $TenantJSONs -AreaPath $AreaPath $reasonForFailure = "The following fields are null or empty:" Trace-Progress "$functionName : Iterating through expected fields to check if they exist in the tenant JSON for area path : $AreaPath." $allFieldsValid = $true foreach ($fieldType in $fieldProperties) { $fields = $fieldType.Value.PSObject.Properties | Where-Object {$_.MemberType -like 'NoteProperty' } foreach ($field in $fields) { if ($field.Value -icontains $DeviceType) { $fieldName = $field.Name $fieldTypeName = $fieldType.Name $tenantJSONFieldValue = $tenantJSON.$fieldTypeName.$fieldName if ([string]::IsNullOrEmpty($tenantJSONFieldValue)) { $testFieldsRow.Result = [Result]::FAIL $allFieldsValid = $false $reasonForFailure += " $($field.Name)," } } } } if ($allFieldsValid) { $testFieldsRow.Result = [Result]::PASS } $reasonForFailure = $reasonForFailure.Trim(",") if ($testFieldsRow.Result -eq [result]::FAIL) { $testFieldsRow.ReasonForFailure = $reasonForFailure } return $testFieldsRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testFieldsRow -FailureMessage $failureMessage ` -TestName $testName -AreaPath $AreaPath } } function Test-ValidFieldValues { Param( [Parameter(Mandatory=$false)] [Object[]] $TenantJSONs, [Parameter(Mandatory=$true)] [PSCustomObject] $TenantJSONFields, [Parameter(Mandatory=$true)] [string] $AreaPath, [Parameter(Mandatory=$true)] [bool] $TenantJSONExists ) $functionName = $($MyInvocation.MyCommand.Name) $testName_GCSEnv = "GCSEnvironment field has a valid value" $testName_GCSGenevaAccount = "GCSGenevaAccount is a valid value" $testName_GCSNamespace = "GCSNamespace field is a valid value" $testName_GCSRegion = "GCSRegion field is a valid value" $testName_AzureResourceUri = "MONITORING_AEO_DEVICE_ARM_RESOURCE_URI field has a valid value." $testDescription_GCSEnv = "Valid values are based on values listed in EnvironmentInfo.JSON. Use GCSGenevaAccount value to get Environment Type." $testDescription_GCSGenevaAccount = "GCSGenevaAccount is one of the account values listed in EnvironmentInfo.JSON. (Make list of all accounts from all environment types)." $testDescription_GCSNamespace = "Valid values are based on values listed in EnvironmentInfo.JSON. Use GCSGenevaAccount value to get Environment Type." $TestDescription_GCSRegion = "GCSRegion field has a valid value based on values listed in EnvironmentInfo.JSON. Use GCSGenevaAccount value to get Environment Type." $testDescription_AzureResourceUri = "The Azure Resource Uri should match the pattern : " + "/(S|s)ubscriptions/[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/resourceGroups/[\w\-]+/providers/[\w\.\-]+/(clusters|machines)/[\w\-]+" $testNamesAndDescriptions = [ordered]@{} $testNamesAndDescriptions[$testName_GCSEnv] = $testDescription_GCSEnv $testNamesAndDescriptions[$testName_GCSGenevaAccount] = $testDescription_GCSGenevaAccount $testNamesAndDescriptions[$testName_GCSNamespace] = $testDescription_GCSNamespace $testNamesAndDescriptions[$testName_GCSRegion] = $TestDescription_GCSRegion $testNamesAndDescriptions[$testName_AzureResourceUri] = $testDescription_AzureResourceUri $testRows = New-Object System.Collections.Generic.List[System.Object] try { foreach ($testPair in $testNamesAndDescriptions.GetEnumerator()) { $testName = $testPair.Name $TestDescription = $testPair.Value Trace-Progress "$functionName : Creating test row for test Name: [$testName]. Testing for area path $AreaPath." $testRow = New-TenantJSONTestRow -TestName $testName -TestDescription $TestDescription -AreaPath $AreaPath $testRows.Add($testRow) } if (!$TenantJSONExists) { foreach ($testRow in $testRows) { $testRow = Fail-TestNoTenantJSON -TestRow $testRow -AreaPath $AreaPath } return $testRows } $tenantJSON = Get-TenantJSONContents -TenantJSONs $TenantJSONs -AreaPath $AreaPath Trace-Progress "$functionName : Checking whether GCSEnvironment is a valid value." $testGCSEnvRow = $testRows | Where-Object { $_.TestName -like "*GCSEnvironment*" } $testGCSEnvRow = Test-GCSEnvironment -TestRow $testGCSEnvRow -TenantJSON $tenantJSON Trace-Progress "$functionName : Checking whether GCSGenevaAccount is a valid value." $testGCSGenevaRow = $testRows | Where-Object { $_.TestName -like "*GCSGenevaAccount*" } $testGCSGenevaRow = Test-GCSGenevaAccount -TestRow $testGCSGenevaRow -TenantJSON $tenantJSON Trace-Progress "$functionName : Checking whether GCSNamespace is a valid value." $testGCSNamespaceRow = $testRows | Where-Object { $_.TestName -like "*GCSNamespace*" } $testGCSGenevaRow = Test-GCSNameSpace -TestRow $testGCSNamespaceRow -TenantJSON $tenantJSON Trace-Progress "$functionName : Checking whether GCSRegion is a valid value." $testGCSRegionRow = $testRows | Where-Object { $_.TestName -like "*GCSRegion*" } $testGCSGenevaRow = Test-GCSRegion -TestRow $testGCSRegionRow -TenantJSON $tenantJSON Trace-Progress "$functionName : Checking whether MONITORING_AEO_DEVICE_ARM_RESOURCE_URI is a valid value." $testAzureResourceUriRow = $testRows | Where-Object { $_.TestName -like "*MONITORING_AEO_DEVICE_ARM_RESOURCE_URI*" } $testAzureResourceUriRow = Test-AzureResourceUri -TestRow $testAzureResourceUriRow -TenantJSON $tenantJSON return $testRows } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error if ($testRows.Count -eq 0) { foreach ($testName in $testNames) { $testRow = New-TenantJSONTestRow -TestName $testName -AreaPath $AreaPath $testRows.Add($testRow) } } foreach ($testRow in $testRows) { $testRow = Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $AreaPath } return $testRows } } <# Testing whether various fields in TenantJSONs have valid values. #> function Test-GCSEnvironment { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$false)] [PSCustomObject] $TenantJSON ) $functionName = $($MyInvocation.MyCommand.Name) try { $gCSEnvValue = $tenantJSON.UserArguments.GCSEnvironment $gcsAccount = $tenantJSON.UserArguments.GcsGenevaAccount Trace-Progress "$functionName : Getting valid endpoint from EnvironmentInfo.JSON based on environment type" $environmentInfo = Get-EnvironmentInfo Trace-Progress "$functionName : Get Environment Type based on GcsGenevaAccount value of $gcsAccount" $environmentType = $environmentInfo.PSObject.Properties | Where-Object {$_.Value.Account -ieq $gcsAccount} Trace-Progress "$functionName : Environment Type is $($environmentType.Name)" $endpoint = $environmentType.Value.Endpoint Trace-Progress "The valid endpoint from EnvironmentInfo.JSON is $endpoint" if ($null -ne $gcsEnvValue -and $gcsEnvValue -ieq $endpoint) { $TestRow.Result = [RESULT]::PASS } else { $TestRow.Result = [RESULT]::FAIL $TestRow.ReasonForFailure = "The GCSEnvironment field had an invalid value of [$gCSEnvValue]" } $TestRow.AdditionalInformation = "GCS Environment Value is $gCSEnvValue" Trace-Progress "$functionName : GCS Environment Value is $gCSEnvValue" return $TestRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $TestRow.AreaPath } } function Test-GCSGenevaAccount { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$false)] [PSCustomObject] $TenantJSON ) $functionName = $($MyInvocation.MyCommand.Name) try { Trace-Progress "$functionName : Checking that Geneva Account Value is in list of valid accounts, per EnvironmentInfo.JSON" $genevaAccountValue = $tenantJSON.UserArguments.GCSGenevaAccount $accounts = New-Object System.Collections.ArrayList $environmentInfo = Get-EnvironmentInfo $environmentInfo.PSObject.Properties | ForEach-Object { $accounts.Add($_.Value.Account) } Trace-Progress "$functionName : Valid account values are $($accounts | Out-String)" if ($null -ne $genevaAccountValue -and $accounts -icontains $genevaAccountValue) { $TestRow.Result = [RESULT]::PASS } else { $TestRow.Result = [RESULT]::FAIL $TestRow.ReasonForFailure = "The GCSGenevaAccount field had an invalid value of [$genevaAccountValue]" } $TestRow.AdditionalInformation = "The GCSGenevaAccount value is $genevaAccountValue" Trace-Progress "$functionName : The GCSGenevaAccount value is $genevaAccountValue" return $testRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $TestRow.AreaPath } } function Test-GCSNamespace { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$false)] [PSCustomObject] $TenantJSON ) $functionName = $($MyInvocation.MyCommand.Name) try { $gcsNamespaceValue = $tenantJSON.UserArguments.GCSNamespace $areaPath = $TestRow.AreaPath $gcsAccount = $tenantJSON.UserArguments.GcsGenevaAccount Trace-Progress "$functionName : Getting valid namespace from EnvironmentInfo.JSON based on Environment Type" $environmentInfo = Get-EnvironmentInfo $environmentInfo.PSObject.Properties | ForEach-Object { $account = $_.Value.Account if ($account -ieq $gcsAccount) { $validNamespaces = $_.Value.Namespaces } } Trace-Progress "$functionName : Getting valid namespace for specific area path" $validNamespace = $validNamespaces.PSObject.Properties | Where-Object {$AreaPath -like "*$($_.Name)*" } if ($AreaPath -like "*Metrics*") { $validNamespaceValue = $validNamespace.Value.Prefix } else { $validNamespaceValue = $validNamespace.Value } Trace-Progress "$functionName : The valid namespace value from EnvironmentInfo.JSON is $validNamespaceValue" if ($null -ne $gcsNamespaceValue) { if (-not ($AreaPath -like "*Metrics*")) { $validValue = $gcsNamespaceValue -ieq $validNamespaceValue } else { $validValue = $gcsNamespaceValue -like "*$validNamespaceValue*" } if ($validValue) { $TestRow.Result = [RESULT]::PASS } else { $TestRow.Result = [RESULT]::FAIL } $testRow.AdditionalInformation = "The GCSNameSpace value is $gcsNamespaceValue" Trace-Progress "$functionName : The GCSNameSpace value is $gcsNamespaceValue" } else { $TestRow.Result = [RESULT]::FAIL } if ($TestRow.Result -eq [RESULT]::FAIL) { $TestRow.ReasonForFailure = "The GCSNamespace field had an invalid value of [$gcsNamespaceValue]" } return $testRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $TestRow.AreaPath } } function Test-GCSRegion { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$false)] [PSCustomObject] $TenantJSON ) $functionName = $($MyInvocation.MyCommand.Name) try { $gcsRegionValue = $tenantJSON.UserArguments.GcsRegion $gcsAccount = $tenantJSON.UserArguments.GcsGenevaAccount Trace-Progress "$functionName : Getting valid regions from EnvironmentInfo.JSON based on Environment Type" $environmentInfo = Get-EnvironmentInfo Trace-Progress "$functionName : Get Environment Type based on GcsGenevaAccount value of $gcsAccount" $environmentType = $environmentInfo.PSObject.Properties | Where-Object {$_.Value.Account -ieq $gcsAccount} Trace-Progress "$functionName : Environment Type is $($environmentType.Name)" $validRegions = $environmentType.Value.Namespaces.Metrics.Region Trace-Progress "$functionName : Valid Regions are $($validRegions | Out-String)" if ($null -ne $gcsRegionValue -and $validRegions -icontains $gcsRegionValue) { $TestRow.Result = [RESULT]::PASS } else { $TestRow.Result = [RESULT]::FAIL $TestRow.ReasonForFailure = "The GCSRegion field had an invalid value of [$gcsRegionValue]" } $TestRow.AdditionalInformation = "The GCSRegion value is $gcsRegionValue" Trace-Progress "$functionName : The GCSRegion value is $gcsRegionValue" return $testRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $TestRow.AreaPath } } function Test-AzureResourceUri { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$false)] [PSCustomObject] $TenantJSON ) $functionName = $($MyInvocation.MyCommand.Name) try { $azureresourceUri = $tenantJSON.ConstantVariables.MONITORING_AEO_DEVICE_ARM_RESOURCE_URI $regex = "\/(S|s)ubscriptions\/[a-zA-Z0-9]{8}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{12}\/resourceGroups\/[\w\-]+\/providers\/[\w\.\-]+\/(clusters|machines)\/[\w\-]+" if ($azureresourceUri -match $regex) { $TestRow.Result = [RESULT]::PASS } else { $TestRow.Result = [RESULT]::FAIL $TestRow.ReasonForFailure = "The Azure Resource Uri field had an invalid value of [$azureresourceUri]" } $TestRow.AdditionalInformation = "Azure Resource Uri is $azureresourceUri" Trace-Progress "$functionName : Azure Resource Uri is $azureresourceUri" return $testRow } catch { $failureMessage = "$functionName : failed with $_" Trace-Progress $failureMessage -Error return Update-TenantJSONTestRowForError -TestRow $testRow -FailureMessage $failureMessage ` -TestName $testRow.TestName -AreaPath $TestRow.AreaPath } } <# # Helper Functions for Sub-Tests in TestTenantJSON #> # Get contents from the tenant JSON function Get-TenantJSONContents { Param( [Parameter(Mandatory=$true)] [object[]] $TenantJSONs, [Parameter(Mandatory=$true)] [string] $AreaPath ) $functionName = $($MyInvocation.MyCommand.Name) $tenantJSONFileName = $AreaPath + ".json" Trace-Progress "$functionName : Get contents from $tenantJSONFileName" $tenantJSON = $tenantJSONS | where-object {$_.Name -eq $tenantJSONFileName} return Get-Content $tenantJSON.FullName | ConvertFrom-JSON } function Fail-TestNoTenantJSON { Param( [Parameter(Mandatory=$true)] [PSCustomObject] $TestRow, [Parameter(Mandatory=$true)] [string] $AreaPath ) $functionName = $($MyInvocation.MyCommand.Name) Trace-Progress "$functionName : Tenant JSON does not exist for area path $AreaPath, so fail test automatically." $TestRow.Result = [Result]::FAIL $TestRow.ReasonForFailure = "$AreaPath.json does not exist" return $TestRow } function Get-EnvironmentInfo { $functionName = $($MyInvocation.MyCommand.Name) $tenantJSONData = Get-Content -Path "$PSScriptRoot\TenantJSONData.json" | ConvertFrom-Json $pathToEnvironmentJSON = $tenantJSONData.PathToEnvironmentInfoJSON if ($pathToEnvironmentJSON.Contains('$')) { # The path might contain environment variables, hence expanding it to actual path. # Example for valid environment variables: $env:WinDir, $env:SystemDrive, $env:ProgramData. $pathToEnvironmentJSON = $ExecutionContext.InvokeCommand.ExpandString($pathToEnvironmentJSON) } $files = Get-ChildItem -Path $pathToEnvironmentJSON -recurse -filter "*EnvironmentInfo.JSON" $environmentInfoFullName = $files[0].FullName Trace-Progress "$functionName : Found EnvironmentInfo.JSON at $environmentInfoFullName" $environmentInfo = Get-Content -Path $environmentInfoFullName | ConvertFrom-Json return $environmentInfo } Export-ModuleMember -Function Test-TenantJSON -Verbose:$false # SIG # Begin signature block # MIInzgYJKoZIhvcNAQcCoIInvzCCJ7sCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBYRk0c4TDDXJG1 # p4SIk2rB5OYASA0EnOAwGWZvW5OrE6CCDYUwggYDMIID66ADAgECAhMzAAADri01 # UchTj1UdAAAAAAOuMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjMxMTE2MTkwODU5WhcNMjQxMTE0MTkwODU5WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQD0IPymNjfDEKg+YyE6SjDvJwKW1+pieqTjAY0CnOHZ1Nj5irGjNZPMlQ4HfxXG # yAVCZcEWE4x2sZgam872R1s0+TAelOtbqFmoW4suJHAYoTHhkznNVKpscm5fZ899 # QnReZv5WtWwbD8HAFXbPPStW2JKCqPcZ54Y6wbuWV9bKtKPImqbkMcTejTgEAj82 # 6GQc6/Th66Koka8cUIvz59e/IP04DGrh9wkq2jIFvQ8EDegw1B4KyJTIs76+hmpV # M5SwBZjRs3liOQrierkNVo11WuujB3kBf2CbPoP9MlOyyezqkMIbTRj4OHeKlamd # WaSFhwHLJRIQpfc8sLwOSIBBAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUhx/vdKmXhwc4WiWXbsf0I53h8T8w # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwMTgzNjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGrJYDUS7s8o0yNprGXRXuAnRcHKxSjFmW4wclcUTYsQZkhnbMwthWM6cAYb/h2W # 5GNKtlmj/y/CThe3y/o0EH2h+jwfU/9eJ0fK1ZO/2WD0xi777qU+a7l8KjMPdwjY # 0tk9bYEGEZfYPRHy1AGPQVuZlG4i5ymJDsMrcIcqV8pxzsw/yk/O4y/nlOjHz4oV # APU0br5t9tgD8E08GSDi3I6H57Ftod9w26h0MlQiOr10Xqhr5iPLS7SlQwj8HW37 # ybqsmjQpKhmWul6xiXSNGGm36GarHy4Q1egYlxhlUnk3ZKSr3QtWIo1GGL03hT57 # xzjL25fKiZQX/q+II8nuG5M0Qmjvl6Egltr4hZ3e3FQRzRHfLoNPq3ELpxbWdH8t # Nuj0j/x9Crnfwbki8n57mJKI5JVWRWTSLmbTcDDLkTZlJLg9V1BIJwXGY3i2kR9i # 5HsADL8YlW0gMWVSlKB1eiSlK6LmFi0rVH16dde+j5T/EaQtFz6qngN7d1lvO7uk # 6rtX+MLKG4LDRsQgBTi6sIYiKntMjoYFHMPvI/OMUip5ljtLitVbkFGfagSqmbxK # 7rJMhC8wiTzHanBg1Rrbff1niBbnFbbV4UDmYumjs1FIpFCazk6AADXxoKCo5TsO # zSHqr9gHgGYQC2hMyX9MGLIpowYCURx3L7kUiGbOiMwaMIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGZ8wghmbAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAAOuLTVRyFOPVR0AAAAA # A64wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFnr # 7SYUldo7sMHJ8WRJm96Wd8by0VqqI15mPHrDAgd1MEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAHh/+EJ472T0jwQwGUdAu++l8mdINv42v5pzf # XOUeG5yvQpkHpfQogVTu+esG+fhDo7KnLtN7sHjW2qamNKdx06X7I895NeMXUh/S # TyJXOc5I7TCaCCLUACG2IqkAHP3qRHa/knEAZWHDcfDBwm+UHiBQqz87RtPb65Yv # /AQtNAlrUrIJDYKRnfE/yTd4nHWsHKaEGoOKJPYEj2HmrNSJNjGe9gLFrTWzykYL # y7MhZxeeUHPsyD1wx4esWrUzfs+ZejF+GbFPOAT7s/m25Dz1/QdIMy3zG+HiN9g1 # vVzrtGBobdIx+QfQ6qtiFl57QEFsLN1ongJu00B9uBIlX7Pca6GCFykwghclBgor # BgEEAYI3AwMBMYIXFTCCFxEGCSqGSIb3DQEHAqCCFwIwghb+AgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFZBgsqhkiG9w0BCRABBKCCAUgEggFEMIIBQAIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCC5jdWXCmc/4JdmTN2GHfDxC5Cswi6SGEk5 # Iz2lYQfu8QIGZdZD5kg1GBMyMDI0MDMxMTE4MTg0Ny42NTJaMASAAgH0oIHYpIHV # MIHSMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQL # EyRNaWNyb3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQxJjAkBgNVBAsT # HVRoYWxlcyBUU1MgRVNOOkQwODItNEJGRC1FRUJBMSUwIwYDVQQDExxNaWNyb3Nv # ZnQgVGltZS1TdGFtcCBTZXJ2aWNloIIReDCCBycwggUPoAMCAQICEzMAAAHcweCM # wl9YXo4AAQAAAdwwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAg # UENBIDIwMTAwHhcNMjMxMDEyMTkwNzA2WhcNMjUwMTEwMTkwNzA2WjCB0jELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9z # b2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1UaGFsZXMg # VFNTIEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt # U3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvI # syA1sjg9kSKJzelrUWF5ShqYWL83amn3SE5JyIVPUC7F6qTcLphhHZ9idf21f0Ra # GrU8EHydF8NxPMR2KVNiAtCGPJa8kV1CGvn3beGB2m2ltmqJanG71mAywrkKATYn # iwKLPQLJ00EkXw5TSwfmJXbdgQLFlHyfA5Kg+pUsJXzqumkIvEr0DXPvptAGqkdF # LKwo4BTlEgnvzeTfXukzX8vQtTALfVJuTUgRU7zoP/RFWt3WagahZ6UloI0FC8Xl # BQDVDX5JeMEsx7jgJDdEnK44Y8gHuEWRDq+SG9Xo0GIOjiuTWD5uv3vlEmIAyR/7 # rSFvcLnwAqMdqcy/iqQPMlDOcd0AbniP8ia1BQEUnfZT3UxyK9rLB/SRiKPyHDlg # 8oWwXyiv3+bGB6dmdM61ur6nUtfDf51lPcKhK4Vo83pOE1/niWlVnEHQV9NJ5/Db # USqW2RqTUa2O2KuvsyRGMEgjGJA12/SqrRqlvE2fiN5ZmZVtqSPWaIasx7a0GB+f # dTw+geRn6Mo2S6+/bZEwS/0IJ5gcKGinNbfyQ1xrvWXPtXzKOfjkh75iRuXourGV # PRqkmz5UYz+R5ybMJWj+mfcGqz2hXV8iZnCZDBrrnZivnErCMh5Flfg8496pT0ph # jUTH2GChHIvE4SDSk2hwWP/uHB9gEs8p/9Pe/mt9AgMBAAGjggFJMIIBRTAdBgNV # HQ4EFgQU6HPSBd0OfEX3uNWsdkSraUGe3dswHwYDVR0jBBgwFoAUn6cVXQBeYl2D # 9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3Nv # ZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy # MDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1l # LVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUB # Af8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQAD # ggIBANnrb8Ewr8eX/H1sKt3rnwTDx4AqgHbkMNQo+kUGwCINXS3y1GUcdqsK/R1g # 6Tf7tNx1q0NpKk1JTupUJfHdExKtkuhHA+82lT7yISp/Y74dqJ03RCT4Q+8ooQXT # MzxiewfErVLt8WefebncST0i6ypKv87pCYkxM24bbqbM/V+M5VBppCUs7R+cETiz # /zEA1AbZL/viXtHmryA0CGd+Pt9c+adsYfm7qe5UMnS0f/YJmEEMkEqGXCzyLK+d # h+UsFi0d4lkdcE+Zq5JNjIHesX1wztGVAtvX0DYDZdN2WZ1kk+hOMblUV/L8n1YW # zhP/5XQnYl03AfXErn+1Eatylifzd3ChJ1xuGG76YbWgiRXnDvCiwDqvUJevVRY1 # qy4y4vlVKaShtbdfgPyGeeJ/YcSBONOc0DNTWbjMbL50qeIEC0lHSpL2rRYNVu3h # sHzG8n5u5CQajPwx9PzpsZIeFTNHyVF6kujI4Vo9NvO/zF8Ot44IMj4M7UX9Za4Q # wGf5B71x57OjaX53gxT4vzoHvEBXF9qCmHRgXBLbRomJfDn60alzv7dpCVQIuQ06 # 2nyIZKnsXxzuKFb0TjXWw6OFpG1bsjXpOo5DMHkysribxHor4Yz5dZjVyHANyKo0 # bSrAlVeihcaG5F74SZT8FtyHAW6IgLc5w/3D+R1obDhKZ21WMIIHcTCCBVmgAwIB # AgITMwAAABXF52ueAptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0 # IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1 # WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O # 1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZn # hUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t # 1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxq # D89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmP # frVUj9z6BVWYbWg7mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSW # rAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv # 231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zb # r17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYcten # IPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQc # xWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17a # j54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQAB # MCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQU # n6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEw # QTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9E # b2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQB # gjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/ # MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJ # oEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01p # Y1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYB # BQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9v # Q2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3h # LB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x # 5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74p # y27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1A # oL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbC # HcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB # 9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNt # yo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3 # rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcV # v7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A24 # 5oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lw # Y1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGCAtQwggI9AgEBMIIBAKGB2KSB1TCB # 0jELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMk # TWljcm9zb2Z0IElyZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMSYwJAYDVQQLEx1U # aGFsZXMgVFNTIEVTTjpEMDgyLTRCRkQtRUVCQTElMCMGA1UEAxMcTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsOAwIaAxUAHDn/cz+3yRkIUCJf # SbL3djnQEqaggYMwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu # Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv # cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAN # BgkqhkiG9w0BAQUFAAIFAOmZJPIwIhgPMjAyNDAzMTExNDM2MzRaGA8yMDI0MDMx # MjE0MzYzNFowdDA6BgorBgEEAYRZCgQBMSwwKjAKAgUA6Zkk8gIBADAHAgEAAgIP # 5jAHAgEAAgISBTAKAgUA6Zp2cgIBADA2BgorBgEEAYRZCgQCMSgwJjAMBgorBgEE # AYRZCgMCoAowCAIBAAIDB6EgoQowCAIBAAIDAYagMA0GCSqGSIb3DQEBBQUAA4GB # AEnp5IEb3Yf3GB5/uVjS4xo4JZEx2KfJ6LX11vwW4T9ViD7bWIN8NsqHuJX96IBA # D/2YNah18Midhe38BMtmYPtQNoEd+FdYxfcZN97swDTFR14W1qGOCWdftv3MsK8+ # QkthEeNbLfNnrXPsXmvCqpb2f9UCsXRvK3M1y+cAiH4GMYIEDTCCBAkCAQEwgZMw # fDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1Jl # ZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd # TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAHcweCMwl9YXo4AAQAA # AdwwDQYJYIZIAWUDBAIBBQCgggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB # BDAvBgkqhkiG9w0BCQQxIgQgomMgjyNQU2i1JBsF72mNTairtwlPW/zeefKteX9Y # JS4wgfoGCyqGSIb3DQEJEAIvMYHqMIHnMIHkMIG9BCBTpxeKatlEP4y8qZzjuWL0 # Ou0IqxELDhX2TLylxIINNzCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD # QSAyMDEwAhMzAAAB3MHgjMJfWF6OAAEAAAHcMCIEIIryvC4+0V7RzAR/kEzt6v8L # CncFnPLA8Eyd0hpkqbWjMA0GCSqGSIb3DQEBCwUABIICAAG/3vO2oQbPXa3VKeQv # 7rgRqJsXhd9E130dP5XIVEo6eUJNFLu+PL1ZUd5WLokQcHGbcMnbXGreCRUVHXm3 # DftJcvb45WOZ2GZR4pivkEVQLDufoIOZSJmDvNeRlOdLsbGUFo5p67gGIV9K4OZ6 # eJYGXtmbJiyc9abeGPtu4gp/XeZbXNSBvop4ySiFoXi6NVejEtggu70ZVrL5/iWt # R3Ckx3GtL1/zpB0EnUSqy+F6N0pCkQn81T4enH+hFNlox7hAe/G3wwNF3MkpYEl7 # VDiU/PE2DxqVnfph2tuRkfE3WpjhGoNmQhH5utxRwCi5XPMq+PXssPma/9zJyK9v # iLt5cU3jXmWHrcIXFD5D/FhYRtn977IwU02iG61P7unIs4vhM8iRLN+jwoHxGCwP # 2llMpiJ1Uiy/ff1PyxXJjTsV0VqGcwbNifeJKQZmnXKeT2TYudNMVBNNaoDoSZWj # Br6kddnGYRvDioM0Fl0L2s4rv+Lou55AW2g+ZQ9eNl7/wmOdML9EiIFh32A/ttAw # s0CQNxv3UIUAqis2MzivVroYgQj4m/zYWCYEHBh31cLhxXjwAFxxZBBZQ32JQFJ6 # mBvaAYRMWWiAv8NIwWUbxFO9sru8Eyth4pFVmDtt9sv0MLUO/9bzVnHT95jZItGu # D5AgQL0WUJL90fhV/1TQhTvj # SIG # End signature block |