helpers/test/Invoke-WUGLinuxComplianceTest.ps1
|
#requires -Version 5.1 <# .SYNOPSIS Offline test harness for the Linux fleet compliance helpers. .DESCRIPTION Exercises every parser and the check-evaluation logic in helpers/linux/LinuxHelpers.ps1 using canned collector output. No SSH connection, network access, or live Linux host is required. .EXAMPLE .\Invoke-WUGLinuxComplianceTest.ps1 .NOTES Author : jason@wug.ninja Requires: PowerShell 5.1+ #> [CmdletBinding()] param() $script:Passed = 0 $script:Failed = 0 function Record-Test { param([string]$Name, [string]$Status, [string]$Detail = '') if ($Status -eq 'Pass') { $script:Passed++; $color = 'Green' } else { $script:Failed++; $color = 'Red' } Write-Host " [$Status] $Name $Detail" -ForegroundColor $color } function Invoke-Test { param([string]$Name, [scriptblock]$Test) try { $null = & $Test Record-Test -Name $Name -Status 'Pass' } catch { Record-Test -Name $Name -Status 'Fail' -Detail $_.Exception.Message } } function Assert-Equal { param($Expected, $Actual, [string]$Message) if ($Expected -ne $Actual) { throw "$(if ($Message) { $Message + ': ' })Expected '$Expected' but got '$Actual'" } } function Assert-True { param([bool]$Value, [string]$Message = 'Expected true but got false') if (-not $Value) { throw $Message } } $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent $repoRoot = Split-Path (Split-Path $scriptDir -Parent) -Parent $helpersFile = Join-Path $repoRoot 'helpers\linux\LinuxHelpers.ps1' Write-Host '' Write-Host '============================================================' -ForegroundColor Cyan Write-Host ' Linux Fleet Compliance Test Harness' -ForegroundColor Cyan Write-Host '============================================================' -ForegroundColor Cyan try { . $helpersFile Record-Test -Name 'Load LinuxHelpers.ps1' -Status 'Pass' } catch { Record-Test -Name 'Load LinuxHelpers.ps1' -Status 'Fail' -Detail $_.Exception.Message Write-Host 'FATAL: helpers failed to load.' -ForegroundColor Red return } # Epoch 1735689600 = 2025-01-01T00:00:00Z; reference time is 100 days later. $patchEpoch = 1735689600 $referenceTime = [datetimeoffset]::FromUnixTimeSeconds($patchEpoch).LocalDateTime.AddDays(100) $sampleOutput = @" ===WUG:hostname=== web01 ===WUG:osrelease=== NAME="Ubuntu" VERSION_ID="22.04" ID=ubuntu PRETTY_NAME="Ubuntu 22.04.4 LTS" ===WUG:kernel=== 5.15.0-105-generic ===WUG:arch=== x86_64 ===WUG:uptime=== 864000.42 1700000.00 ===WUG:patchepoch=== $patchEpoch ===WUG:failedunits=== nginx.service loaded failed failed A high performance web server fail2ban.service loaded failed failed Fail2Ban Service ===WUG:disk=== Filesystem 1024-blocks Used Available Capacity Mounted on /dev/sda1 41251136 8123456 31000000 21% / /dev/sdb1 103212320 98051704 5160616 96% /data /dev/sdc1 20511312 17434615 3076697 86% /var/log ===WUG:inode=== Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda1 2621440 123456 2497984 5% / /dev/sdb1 6553600 6357000 196600 97% /data ===WUG:ntp=== NTP=yes NTPSynchronized=no ===WUG:ports=== tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=812,fd=3)) tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1044,fd=6)) udp UNCONN 0 0 0.0.0.0:68 0.0.0.0:* tcp LISTEN 0 128 0.0.0.0:23 0.0.0.0:* users:(("telnetd",pid=1500,fd=3)) ===WUG:reboot=== yes ===WUG:sshd=== permitrootlogin yes passwordauthentication yes permitemptypasswords no x11forwarding no ===WUG:end=== "@ $sections = ConvertFrom-LinuxComplianceOutput -Output $sampleOutput Write-Host '' Write-Host '--- Section parsing ---' -ForegroundColor Cyan Invoke-Test -Name 'All sections captured' -Test { Assert-True ($sections.ContainsKey('hostname')) 'hostname section missing' Assert-True ($sections.ContainsKey('disk')) 'disk section missing' Assert-True ($sections.ContainsKey('end')) 'end marker missing' } Invoke-Test -Name 'Hostname section content' -Test { Assert-Equal 'web01' (Get-LinuxSectionText -Sections $sections -Name 'hostname').Trim() } Write-Host '' Write-Host '--- Parsers ---' -ForegroundColor Cyan Invoke-Test -Name 'os-release parsed' -Test { $os = ConvertFrom-LinuxOsRelease -Text (Get-LinuxSectionText -Sections $sections -Name 'osrelease') Assert-Equal 'Ubuntu 22.04.4 LTS' $os.PrettyName Assert-Equal 'ubuntu' $os.Id Assert-Equal '22.04' $os.VersionId } Invoke-Test -Name 'df block output parsed' -Test { $disks = @(ConvertFrom-LinuxDfOutput -Text (Get-LinuxSectionText -Sections $sections -Name 'disk')) Assert-Equal 3 $disks.Count 'disk row count' $data = $disks | Where-Object { $_.MountPoint -eq '/data' } Assert-Equal 96 $data.UsedPercent Assert-Equal '/dev/sdb1' $data.Filesystem } Invoke-Test -Name 'df inode output parsed' -Test { $inodes = @(ConvertFrom-LinuxDfOutput -Text (Get-LinuxSectionText -Sections $sections -Name 'inode')) Assert-Equal 2 $inodes.Count 'inode row count' Assert-Equal 97 ($inodes | Where-Object { $_.MountPoint -eq '/data' }).UsedPercent } Invoke-Test -Name 'Failed systemd units parsed' -Test { $units = @(ConvertFrom-LinuxFailedUnit -Text (Get-LinuxSectionText -Sections $sections -Name 'failedunits')) Assert-Equal 2 $units.Count Assert-Equal 'nginx.service' $units[0].Unit Assert-Equal 'failed' $units[0].Active } Invoke-Test -Name 'NTP status parsed' -Test { $ntp = ConvertFrom-LinuxNtpStatus -Text (Get-LinuxSectionText -Sections $sections -Name 'ntp') Assert-Equal $true $ntp.Enabled Assert-Equal $false $ntp.Synchronized } Invoke-Test -Name 'ss listening ports parsed' -Test { $ports = @(ConvertFrom-LinuxListeningPort -Text (Get-LinuxSectionText -Sections $sections -Name 'ports')) Assert-Equal 4 $ports.Count 'port row count' $ssh = $ports | Where-Object { $_.Port -eq 22 } Assert-Equal 'tcp' $ssh.Protocol Assert-Equal 'sshd' $ssh.Process Assert-True (@($ports | Where-Object { $_.Protocol -eq 'udp' }).Count -eq 1) 'expected one udp socket' } Invoke-Test -Name 'netstat listening ports parsed' -Test { $netstatText = @' Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp6 0 0 :::443 :::* LISTEN udp 0 0 0.0.0.0:123 0.0.0.0:* '@ $ports = @(ConvertFrom-LinuxListeningPort -Text $netstatText) Assert-Equal 3 $ports.Count Assert-True (@($ports | Where-Object { $_.Port -eq 443 }).Count -eq 1) 'expected port 443' } Invoke-Test -Name 'sshd settings parsed' -Test { $sshd = ConvertFrom-LinuxSshdSetting -Text (Get-LinuxSectionText -Sections $sections -Name 'sshd') Assert-Equal 'yes' $sshd['permitrootlogin'] Assert-Equal 'no' $sshd['x11forwarding'] } Write-Host '' Write-Host '--- Facts ---' -ForegroundColor Cyan $facts = Get-LinuxComplianceFact -Sections $sections -Target 'web01' -ReferenceTime $referenceTime Invoke-Test -Name 'Facts assembled' -Test { Assert-Equal 'web01' $facts.Hostname Assert-Equal '5.15.0-105-generic' $facts.Kernel Assert-Equal 'x86_64' $facts.Architecture Assert-Equal $true $facts.RebootRequired } Invoke-Test -Name 'Uptime converted to days' -Test { Assert-Equal 10 $facts.UptimeDays } Invoke-Test -Name 'Patch age computed from epoch' -Test { Assert-Equal 100 $facts.PatchAgeDays } Write-Host '' Write-Host '--- Checks ---' -ForegroundColor Cyan $checks = @(Get-LinuxComplianceCheck -Facts $facts -AllowedPort 22, 80) function Get-Check { param([string]$Name) $match = $checks | Where-Object { $_.Check -eq $Name } | Select-Object -First 1 if (-not $match) { throw "Check not found: $Name" } return $match } Invoke-Test -Name 'Disk 96% flagged Fail' -Test { Assert-Equal 'Fail' (Get-Check 'Disk usage /data').Status } Invoke-Test -Name 'Disk 86% flagged Warn' -Test { Assert-Equal 'Warn' (Get-Check 'Disk usage /var/log').Status } Invoke-Test -Name 'Disk 21% passes' -Test { Assert-Equal 'Pass' (Get-Check 'Disk usage /').Status } Invoke-Test -Name 'Inode 97% flagged Fail' -Test { Assert-Equal 'Fail' (Get-Check 'Inode usage /data').Status } Invoke-Test -Name 'Failed units flagged Fail' -Test { $check = Get-Check 'Failed systemd units' Assert-Equal 'Fail' $check.Status Assert-Equal '2' $check.Value } Invoke-Test -Name 'Unsynchronized NTP flagged Fail' -Test { Assert-Equal 'Fail' (Get-Check 'NTP synchronization').Status } Invoke-Test -Name 'Pending reboot flagged Warn' -Test { Assert-Equal 'Warn' (Get-Check 'Reboot required').Status } Invoke-Test -Name 'Patch age 100 days flagged Fail' -Test { Assert-Equal 'Fail' (Get-Check 'Package patch age').Status } Invoke-Test -Name 'Root login enabled flagged Fail' -Test { Assert-Equal 'Fail' (Get-Check 'SSH root login').Status } Invoke-Test -Name 'Password auth enabled flagged Warn' -Test { Assert-Equal 'Warn' (Get-Check 'SSH password auth').Status } Invoke-Test -Name 'Compliant sshd setting passes' -Test { Assert-Equal 'Pass' (Get-Check 'SSH X11 forwarding').Status } Invoke-Test -Name 'Unexpected port flagged Warn' -Test { $check = Get-Check 'Listening ports' Assert-Equal 'Warn' $check.Status Assert-True ($check.Detail -like '*23*') 'telnet port 23 should be reported' } Invoke-Test -Name 'Port check passes when all allowed' -Test { $allowedChecks = @(Get-LinuxComplianceCheck -Facts $facts -AllowedPort 22, 80, 68, 23) $portCheck = $allowedChecks | Where-Object { $_.Check -eq 'Listening ports' } | Select-Object -First 1 Assert-Equal 'Pass' $portCheck.Status } Write-Host '' Write-Host '--- Healthy host and summary ---' -ForegroundColor Cyan $healthyOutput = @" ===WUG:hostname=== web02 ===WUG:osrelease=== PRETTY_NAME="Debian GNU/Linux 12 (bookworm)" ID=debian VERSION_ID="12" ===WUG:kernel=== 6.1.0-18-amd64 ===WUG:arch=== x86_64 ===WUG:uptime=== 86400.00 100000.00 ===WUG:patchepoch=== $patchEpoch ===WUG:failedunits=== ===WUG:disk=== Filesystem 1024-blocks Used Available Capacity Mounted on /dev/sda1 41251136 4123456 35000000 11% / ===WUG:inode=== Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda1 2621440 93456 2527984 4% / ===WUG:ntp=== NTP=yes NTPSynchronized=yes ===WUG:ports=== tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=800,fd=3)) ===WUG:reboot=== no ===WUG:sshd=== permitrootlogin no passwordauthentication no permitemptypasswords no x11forwarding no ===WUG:end=== "@ $healthySections = ConvertFrom-LinuxComplianceOutput -Output $healthyOutput $healthyFacts = Get-LinuxComplianceFact -Sections $healthySections -Target 'web02' -ReferenceTime ([datetimeoffset]::FromUnixTimeSeconds($patchEpoch).LocalDateTime.AddDays(3)) $healthyChecks = @(Get-LinuxComplianceCheck -Facts $healthyFacts -AllowedPort 22) Invoke-Test -Name 'Healthy host has no failures' -Test { $bad = @($healthyChecks | Where-Object { $_.Status -eq 'Fail' }) Assert-Equal 0 $bad.Count "unexpected failures: $(($bad | ForEach-Object { $_.Check }) -join ', ')" } Invoke-Test -Name 'Healthy host overall status is Pass' -Test { Assert-Equal 'Pass' (Get-LinuxComplianceStatus -Checks $healthyChecks) } Invoke-Test -Name 'Unhealthy host overall status is Fail' -Test { Assert-Equal 'Fail' (Get-LinuxComplianceStatus -Checks $checks) } Invoke-Test -Name 'Summary aggregates per target' -Test { $summary = @(Get-LinuxComplianceSummary -Checks ($checks + $healthyChecks)) Assert-Equal 2 $summary.Count $web01 = $summary | Where-Object { $_.Target -eq 'web01' } $web02 = $summary | Where-Object { $_.Target -eq 'web02' } Assert-Equal 'Fail' $web01.Status Assert-Equal 'Pass' $web02.Status Assert-True ($web01.Fail -ge 5) "expected several failures, got $($web01.Fail)" } Invoke-Test -Name 'Missing data yields Unknown, not an error' -Test { $emptySections = ConvertFrom-LinuxComplianceOutput -Output "===WUG:hostname===`nweb03`n===WUG:end===" $emptyFacts = Get-LinuxComplianceFact -Sections $emptySections -Target 'web03' $emptyChecks = @(Get-LinuxComplianceCheck -Facts $emptyFacts) Assert-True (@($emptyChecks | Where-Object { $_.Status -eq 'Unknown' }).Count -gt 0) 'expected Unknown checks' Assert-Equal 'Package patch age' ($emptyChecks | Where-Object { $_.Check -eq 'Package patch age' }).Check } Invoke-Test -Name 'Collector command includes every section marker' -Test { $command = Get-LinuxComplianceCommand foreach ($name in @('hostname', 'osrelease', 'kernel', 'patchepoch', 'failedunits', 'disk', 'inode', 'ntp', 'ports', 'reboot', 'sshd', 'end')) { Assert-True ($command -like "*===WUG:$name===*") "missing marker: $name" } } Invoke-Test -Name 'Collector command uses LF line endings' -Test { $command = Get-LinuxComplianceCommand Assert-True (-not $command.Contains("`r")) 'CR characters break bash if/fi parsing' } Invoke-Test -Name 'Collector command has balanced if/fi keywords' -Test { $command = Get-LinuxComplianceCommand $ifCount = @([regex]::Matches($command, '(?m)(?:^|[;\s])if\s')).Count $fiCount = @([regex]::Matches($command, '(?m)(?:^|[;\s])fi(?:$|[;\s])')).Count Assert-Equal $ifCount $fiCount 'unbalanced if/fi' } Write-Host '' Write-Host '============================================================' -ForegroundColor Cyan Write-Host " Passed: $script:Passed Failed: $script:Failed" -ForegroundColor $(if ($script:Failed -eq 0) { 'Green' } else { 'Red' }) Write-Host '============================================================' -ForegroundColor Cyan if ($script:Failed -gt 0) { exit 1 } # SIG # Begin signature block # MIIr+wYJKoZIhvcNAQcCoIIr7DCCK+gCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDWi32200Z2JjGz # YWEU9NglTWGOql2fRlEgyqSyrJFioaCCJQ0wggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggWNMIIEdaADAgECAhAOmxiO # +dAt5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYD # VQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAi # BgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAw # MDBaFw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdp # Q2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERp # Z2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC # AgoCggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsb # hA3EMB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iT # cMKyunWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGb # NOsFxl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclP # XuU15zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCr # VYJBMtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFP # ObURWBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTv # kpI6nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWM # cCxBYKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls # 5Q5SUUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBR # a2+xq4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6 # MIIBNjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qY # rhwPTzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8E # BAMCAYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k # aWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0 # LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDig # NoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9v # dENBLmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCg # v0NcVec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQT # SnovLbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh # 65ZyoUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSw # uKFWjuyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAO # QGPFmCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjD # TZ9ztwGpn1eqXijiuZQwggYaMIIEAqADAgECAhBiHW0MUgGeO5B5FSCJIRwKMA0G # CSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExp # bWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBSb290 # IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5NTlaMFQxCzAJBgNVBAYT # AkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNlY3RpZ28g # UHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0GCSqGSIb3DQEBAQUAA4IB # jwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjIztNsfvxYB5UXeWUzCxEe # AEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NVDgFigOMYzB2OKhdqfWGV # oYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/36F09fy1tsB8je/RV0mIk # 8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05ZwmRmTnAO5/arnY83jeNzh # P06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm+qxp4VqpB3MV/h53yl41 # aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUedyz8rNyfQJy/aOs5b4s+ # ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz44MPZ1f9+YEQIQty/NQd/ # 2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBMdlyh2n5HirY4jKnFH/9g # Rvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQYMBaAFDLrkpr/NZZILyhA # QnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritUpimqF6TNDDAOBgNVHQ8B # Af8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcD # AzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsGA1UdHwREMEIwQKA+oDyG # Omh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5n # Um9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsGAQUFBzAChjpodHRwOi8v # Y3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYu # cDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG # 9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURhw1aVcdGRP4Wh60BAscjW # 4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0ZdOaWTsyNyBBsMLHqafvIh # rCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajjcw5+w/KeFvPYfLF/ldYp # mlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNcWbWDRF/3sBp6fWXhz7Dc # ML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalOhOfCipnx8CaLZeVme5yE # Lg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJszkyeiaerlphwoKx1uHRz # NyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z76mKnzAfZxCl/3dq3dUNw # 4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5JKdGvspbOrTfOXyXvmPL6 # E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHHj95Ejza63zdrEcxWLDX6 # xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2Bev6SivBBOHY+uqiirZt # g0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/L9Uo2bC5a4CH2RwwggY+ # MIIEpqADAgECAhAHnODk0RR/hc05c892LTfrMA0GCSqGSIb3DQEBDAUAMFQxCzAJ # BgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzApBgNVBAMTIlNl # Y3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwHhcNMjYwMjA5MDAwMDAw # WhcNMjkwNDIxMjM1OTU5WjBVMQswCQYDVQQGEwJVUzEUMBIGA1UECAwLQ29ubmVj # dGljdXQxFzAVBgNVBAoMDkphc29uIEFsYmVyaW5vMRcwFQYDVQQDDA5KYXNvbiBB # bGJlcmlubzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPN6aN4B1yYW # kI5b5TBj3I0VV/peETrHb6EY4BHGxt8Ap+eT+WpEpJyEtRYPxEmNJL3A38Bkg7mw # zPE3/1NK570ZBCuBjSAn4mSDIgIuXZnvyBO9W1OQs5d67MlJLUAEufl18tOr3ST1 # DeO9gSjQSAE5Nql0QDxPnm93OZBon+Fz3CmE+z3MwAe2h4KdtRAnCqwM+/V7iBdb # w+JOxolpx+7RVjGyProTENIG3pe/hKvPb501lf8uBAADLdjZr5ip8vIWbf857Yw1 # Bu10nVI7HW3eE8Cl5//d1ribHlzTzQLfttW+k+DaFsKZBBL56l4YAlIVRsrOiE1k # dHYYx6IGrEA809R7+TZA9DzGqyFiv9qmJAbL4fDwetDeyIq+Oztz1LvEdy8Rcd0J # BY+J4S0eDEFIA3X0N8VcLeAwabKb9AjulKXwUeqCJLvN79CJ90UTZb2+I+tamj0d # n+IKMEsJ4v4Ggx72sxFr9+6XziodtTg5Luf2xd6+PhhamOxF2px9LObhBLLEMyRs # CHZIzVZOFKu9BpHQH7ufGB+Sa80Tli0/6LEyn9+bMYWi2ttn6lLOPThXMiQaooRU # q6q2u3+F4SaPlxVFLI7OJVMhar6nW6joBvELTJPmANSMjDSRFDfHRCdGbZsL/keE # LJNy+jZctF6VvxQEjFM8/bazu6qYhrA7AgMBAAGjggGJMIIBhTAfBgNVHSMEGDAW # gBQPKssghyi47G9IritUpimqF6TNDDAdBgNVHQ4EFgQU6YF0o0D5AVhKHbVocr8G # aSIBibAwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYI # KwYBBQUHAwMwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEFBQcC # ARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkGA1UdHwRCMEAw # PqA8oDqGOGh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVT # aWduaW5nQ0FSMzYuY3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEFBQcwAoY4aHR0 # cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIz # Ni5jcnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMA0GCSqG # SIb3DQEBDAUAA4IBgQAEIsm4xnOd/tZMVrKwi3doAXvCwOA/RYQnFJD7R/bSQRu3 # wXEK4o9SIefye18B/q4fhBkhNAJuEvTQAGfqbbpxow03J5PrDTp1WPCWbXKX8Oz9 # vGWJFyJxRGftkdzZ57JE00synEMS8XCwLO9P32MyR9Z9URrpiLPJ9rQjfHMb1BUd # vaNayomm7aWLAnD+X7jm6o8sNT5An1cwEAob7obWDM6sX93wphwJNBJAstH9Ozs6 # LwISOX6sKS7CKm9N3Kp8hOUue0ZHAtZdFl6o5u12wy+zzieGEI50fKnN77FfNKFO # WKlS6OJwlArcbFegB5K89LcE5iNSmaM3VMB2ADV1FEcjGSHw4lTg1Wx+WMAMdl/7 # nbvfFxJ9uu5tNiT54B0s+lZO/HztwXYQUczdsFon3pjsNrsk9ZlalBi5SHkIu+F6 # g7tWiEv3rtVApmJRnLkUr2Xq2a4nbslUCt4jKs5UX4V1nSX8OM++AXoyVGO+iTj7 # z+pl6XE9Gw/Td6WKKKswgga0MIIEnKADAgECAhANx6xXBf8hmS5AQyIMOkmGMA0G # CSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 # IFRydXN0ZWQgUm9vdCBHNDAeFw0yNTA1MDcwMDAwMDBaFw0zODAxMTQyMzU5NTla # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEy # NTYgMjAyNSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC0eDHT # CphBcr48RsAcrHXbo0ZodLRRF51NrY0NlLWZloMsVO1DahGPNRcybEKq+RuwOnPh # of6pvF4uGjwjqNjfEvUi6wuim5bap+0lgloM2zX4kftn5B1IpYzTqpyFQ/4Bt0mA # xAHeHYNnQxqXmRinvuNgxVBdJkf77S2uPoCj7GH8BLuxBG5AvftBdsOECS1UkxBv # MgEdgkFiDNYiOTx4OtiFcMSkqTtF2hfQz3zQSku2Ws3IfDReb6e3mmdglTcaarps # 0wjUjsZvkgFkriK9tUKJm/s80FiocSk1VYLZlDwFt+cVFBURJg6zMUjZa/zbCclF # 83bRVFLeGkuAhHiGPMvSGmhgaTzVyhYn4p0+8y9oHRaQT/aofEnS5xLrfxnGpTXi # UOeSLsJygoLPp66bkDX1ZlAeSpQl92QOMeRxykvq6gbylsXQskBBBnGy3tW/AMOM # CZIVNSaz7BX8VtYGqLt9MmeOreGPRdtBx3yGOP+rx3rKWDEJlIqLXvJWnY0v5ydP # pOjL6s36czwzsucuoKs7Yk/ehb//Wx+5kMqIMRvUBDx6z1ev+7psNOdgJMoiwOrU # G2ZdSoQbU2rMkpLiQ6bGRinZbI4OLu9BMIFm1UUl9VnePs6BaaeEWvjJSjNm2qA+ # sdFUeEY0qVjPKOWug/G6X5uAiynM7Bu2ayBjUwIDAQABo4IBXTCCAVkwEgYDVR0T # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU729TSunkBnx6yuKQVvYv1Ensy04wHwYD # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG # A1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU # cnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1s # BwEwDQYJKoZIhvcNAQELBQADggIBABfO+xaAHP4HPRF2cTC9vgvItTSmf83Qh8WI # GjB/T8ObXAZz8OjuhUxjaaFdleMM0lBryPTQM2qEJPe36zwbSI/mS83afsl3YTj+ # IQhQE7jU/kXjjytJgnn0hvrV6hqWGd3rLAUt6vJy9lMDPjTLxLgXf9r5nWMQwr8M # yb9rEVKChHyfpzee5kH0F8HABBgr0UdqirZ7bowe9Vj2AIMD8liyrukZ2iA/wdG2 # th9y1IsA0QF8dTXqvcnTmpfeQh35k5zOCPmSNq1UH410ANVko43+Cdmu4y81hjaj # V/gxdEkMx1NKU4uHQcKfZxAvBAKqMVuqte69M9J6A47OvgRaPs+2ykgcGV00TYr2 # Lr3ty9qIijanrUR3anzEwlvzZiiyfTPjLbnFRsjsYg39OlV8cipDoq7+qNNjqFze # GxcytL5TTLL4ZaoBdqbhOhZ3ZRDUphPvSRmMThi0vw9vODRzW6AxnJll38F0cuJG # 7uEBYTptMSbhdhGQDpOXgpIUsWTjd6xpR6oaQf/DJbg3s6KCLPAlZ66RzIg9sC+N # Jpud/v4+7RWsWCiKi9EOLLHfMR2ZyJ/+xhCx9yHbxtl5TPau1j/1MIDpMPx0LckT # etiSuEtQvLsNz3Qbp7wGWqbIiOWCnb5WqxL3/BAPvIXKUjPSxyZsq8WhbaM2tszW # kPZPubdcMIIG7TCCBNWgAwIBAgIQCE/cM09+RU7bww+P+ZIYNTANBgkqhkiG9w0B # AQsFADBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/ # BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYg # U0hBMjU2IDIwMjUgQ0ExMB4XDTI2MDgwNTAwMDAwMFoXDTM3MTEwNDIzNTk1OVow # YzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQD # EzJEaWdpQ2VydCBTSEEyNTYgUlNBNDA5NiBUaW1lc3RhbXAgUmVzcG9uZGVyIDIw # MjYgMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALZ7pvLJ/s1K+NSb # TGWz/TjGMPh8CQ6RucZCLv5anHzWJjF/NWJrFIhy24fcpKXlgRiky4WAawDfU3YP # 0BMxt9l3Dm5oCG5Z69AqEN1kgHg2epx+l+lZBcmJCcN0ASURML5uFIS80sZsDwO3 # BSkUxDjLJhBI+qiZP3aixAC/qEGLjsBNlLol9VZ7pfGEXiMlneJIC5/YKuizVzNF # KZZEeoy/0B8Zm+nzKBgSWG52lCO1w+nCg6XpCtklTJXeIg283hw7TmmsZXR+SMbj # brEOvZ3fP2VxIgeR28Y90ZStd3F9VuA5RVynb/whITPAo9b75Zr4Ta6Mj3URm26Q # ZYMn/FnbuTegcoRcFEZ9FOqM5T6MTdtr/n74lIT/ug0eeOzmZ6QTFg33otX+bFRs # IolvykE1jive4PuESaT8zzVeFWDAMDtozNgLctkGD1ZjkEyZtJrLl5ya0m5doH/S # cpaZCZVl6pNUOCybMc/kxC6EAmSJY24L0yYKD1Nkddsnb/ItVKi/2nXpQNMu1PT5 # prW83vV8d67WowuUs0HdY4H8AMLGvdL/WHEj3ZnqMqAQQP9u3Ai9t+5eQ02GDwy0 # ODjdzi0xlp70W+ow63/0++YDEX1M0iwgUHwbrJvfpklkZQvw3+kv3vUPItdwrocz # k9icflf55W1zOEKAcJVAIXpcMCU9AgMBAAGjggGVMIIBkTAMBgNVHRMBAf8EAjAA # MB0GA1UdDgQWBBQUyWOKMC7USvtulPPm40B+9ezN4jAfBgNVHSMEGDAWgBTvb1NK # 6eQGfHrK4pBW9i/USezLTjAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYI # KwYBBQUHAwgwgZUGCCsGAQUFBwEBBIGIMIGFMCQGCCsGAQUFBzABhhhodHRwOi8v # b2NzcC5kaWdpY2VydC5jb20wXQYIKwYBBQUHMAKGUWh0dHA6Ly9jYWNlcnRzLmRp # Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFRpbWVTdGFtcGluZ1JTQTQwOTZT # SEEyNTYyMDI1Q0ExLmNydDBfBgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vY3JsMy5k # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2 # U0hBMjU2MjAyNUNBMS5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9 # bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQCNxTphHp1SCt+ZrAmAfn0oQLFr0mLywSLa # DXQIENoyKqxrFbJblzCVP/pkXmwXOdrOpWygLzlT12os5ipDCy35RBCg2UMeApEt # rfGhz45F4Wt4WGdNdIbRWt3YTYJmpR+b7lr4d7Uwn+H600u4D7RnOGf8Wj4UNgAd # ZkfHhHv1mx9EVh71SJelcEN/oORSjXzdjfw1iZH9d8Nh/thn6hH23d+VsPAr6GAY # yzSA02nXD1nYLI7Ijmiv+xLCiYC41DSFYL3GhTiy0PxpawPtGRyaBVGzq+UiTfM8 # pD7KVyF5aQyWP4KhVGUUTnmm/RlYJoW3TiXA/+t0YcT2oRVBm3JETjajHug2AL+v # 5jhtKVnd3D0rbHXEu27o+Q8p4sEWPMqKDB+qbceb6T/6WcwTwXmQ9lOCLLYcsQeS # WmvKqzpAec9etE14jOQAzLKWdE3w/TCaKtLRaRT7LCkRYVnhA2D73FLje1O5b3HR # 5eHs0NzU/+xX7NbEdcofy0W3Wdwd1XOqtlpg/JgwtKfZM5dqO94lbUveOiJBI+xZ # EbGRsMNbXmMREUTgu+Oca7Y73MPWcslIx2VhkSKSXjDbD6rgg39H5Mh7QfieAIjW # agkJNt68Yfim6cjEzVSiLSeZfdkr5dtFPTW6jATlWJdYeeDRGCyatf8R1hSjzSvd # N8yWQPT9gzGCBkQwggZAAgEBMGgwVDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1Nl # Y3RpZ28gTGltaXRlZDErMCkGA1UEAxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWdu # aW5nIENBIFIzNgIQB5zg5NEUf4XNOXPPdi036zANBglghkgBZQMEAgEFAKCBhDAY # BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3 # AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEi # BCC9Nm4T6WGVg8oLawmQm/1B1We73lwJX52e60UEPoNu+DANBgkqhkiG9w0BAQEF # AASCAgCX2iq8dZgio7lCB0SPaz8FTL5ev7tTLxR7i8WKFzvfsbQurOkz9WhcL7MN # 1JCHZc8yXi1i5ie58XE91svmQeVjMLaZJvcxkPb1CQnLEDZs8h2vnhU8EbxK91o3 # 3BTHweJenZfeStgVVt7PkRsmN/2QEJubqJSM7OY1bK005N/Wlj1mU85LsD8bDR2W # H+m9CAt5xC3iCmpKSFZEwj1ai9tJOc8GEAvbeTFDoVmNmQY64sMtguGWqjKxrHS/ # Gkpe7hdAqOQJrv+1QKX465kUM/pMrPzXI47OCP3ZBN5BauR15M/sXd2BEFaa9HgJ # GmKEHaUiJFrTKJOjPvltZElg1Th0TVejGkns1d+DuzPkG6gs6EdpwHMV+YuOJYWI # T1SJKWfxuu+MqajnWrokVLrSzFJWZXftuwz58ASS3qAEWjhMxak8sqi+a6IBRmnL # Gunw6luv6suOI9sgynTzMsSabAO6udSo7aR7sAvlKvIy9F0YsPzOxzL6P9mOFHgO # 3wtbZ8aMw+LYnd22ktviB9xCWhtq/TnGOXBTXXnEUp4ouZcBBBiELk+amUmMwFLq # 5qM7wqtMBKnH6l4kiJNVQ55aT77cURONruabiI7/t9knv+AJXqs0IxYr90KyASzC # eF5iNRO57q/M/k50+Cj6HfSSqs0Kd5DdVryibKZH6cgFXMryyaGCAyYwggMiBgkq # hkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5E # aWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBUaW1l # U3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTECEAhP3DNPfkVO28MPj/mS # GDUwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwG # CSqGSIb3DQEJBTEPFw0yNjA5MjkxODI1MjdaMC8GCSqGSIb3DQEJBDEiBCAT3m7f # VSNm256A868FB3AxrBT0g1oLAPdOvwJDO2GHzjANBgkqhkiG9w0BAQEFAASCAgAO # Gj13LGa/X5yFBmHGH2CPZeeDKxM7KucFiku4bZ8Uz7fdacnGzwlzfbAgEuAHPc4M # HNJ6idPqNgM1U6JvFPmhLVh9f8F2xNPZ6QrhZhB2ThlgWT4PAMgiNrNT8Z5lgLoK # nEBH1x8rjqQvUNPaghOSG97JSchtricKxEwwdn1GPVONnBdE3eeQw9Xb1ZrOwBJu # Js+cTADNqXxOWk0rJEo1N8HFJTFVIlNrFMEx+HcIj0idwquSGYpVEGeeVDdgafen # Zl6S4ZpDy2+D9pA2U1m8aMRL7TPG8C3KBWkYvzdBYsdbaKuNegYxXy9OMzUy4Tzz # tIexMDv0tJE8/vTK6fteSnu/APGGuT5+RvGeXWVrzHlC/r5oej56HUabxhibrbCL # rYKHvF8cdWU+o+F+QBV29ViwRzi7M/ctLGSEGN5WqOdkdKMyvdV4CM/lrMxM3nIP # zKe3lb0bFfESs22vqAiB7IoYrX3pDLA+wLHzSWswwwb0SkDpeFsVOMtjZ3y1amIn # tnaq2oG384H1XpGKeX0Fwf4FDRdJHMqR+dCMTaK/S1wl+5G69NkMGeQC+fd1RTd4 # 2/u/wg+x3db/IxL4Pj7FVv0sUzhj32IHAeeK3hrcYksVLIKv2NT7nredE/P2Cm2j # kkBjYriA8MnsXcWFGxvFiMuBF2LLyRsxRo2UHgpWQw== # SIG # End signature block |