#!/usr/bin/env pwsh param ( [switch]$help = $false, [switch]$interactive = $false, [switch]$quiet = $false, [switch]$verbose = $false, [switch]$version = $false, [string]$dir = "$Home\.xygeni", [switch]$overwrite = $false, [string]$username = "", [SecureString]$password, [string]$token = "", [string]$server = "https://api.xygeni.io", [string] [Alias('x')] $proxy = "" ) $SCRIPT_VERSION = "1.0.0" $DOWNLOAD_URL="https://get.xygeni.io/latest/scanner/xygeni_scanner.zip" $DOCS_URL = "https://docs.xygeni.io/" function New-TemporaryDirectory { Try { $parent = [System.IO.Path]::GetTempPath() [string] $name = [System.Guid]::NewGuid() New-Item -ItemType Directory -Path (Join-Path $parent $name) } Catch { Write-Warning "Failed to create tempdir $name with error: $_" exit 1 } } $TEMP_DIR = New-TemporaryDirectory $ZIP_FILE_NAME = "xygeni-release.zip" $ZIP_FILEPATH = "$TEMP_DIR\$ZIP_FILE_NAME" $CONFIG_FILE_PATH = "$dir\conf\xygeni.yml" $MIN_JAVA_VERSION = 11 # Helper functions function script:Verbose($str) {} function handle_args { if ($version -eq $true) { Write-Host "Xygeni installation script v$SCRIPT_VERSION" exit 0 } if ($help -eq $true) { show_help exit 0 } if ($verbose -eq $true) { function script:Verbose($str) { Write-Host $str } } if ($quiet -eq $true) { function script:Write-Host() {} } } function show_banner { Verbose "" Verbose " d8b" Verbose " Y8P" Verbose " " Verbose "888 888 888 888 .d88b. .d88b. 88888b. d8b" Verbose "'Y8bd8P' 888 888 d88P'88b d8P Y8b 888 '88b 888" Verbose " X88K 888 888 888 888 88888888 888 888 888" Verbose ".d8''8b. Y88b 888 Y88b 888 Y8b. 888 888 888" Verbose "888 888 'Y88888 'Y88888 'Y8888 888 888 888" Verbose " 888 888 " Verbose " Y8b d88P Y8b d88P " Verbose " 'Y88P' 'Y88P' " Verbose " " Verbose "Stop software supply-chain attacks! xygeni.io" Verbose "" Write-Host "Running xygeni PowerShell installation script v$SCRIPT_VERSION..." Write-Host "" } function show_help { show_banner Write-Host "$($PSStyle.bold)Usage:$($PSStyle.Reset)" Write-Host " .\install.ps1 [-h|-q|-verbose|-Version] [-o] [-u -p | -t ]" Write-Host " [-s ] [-d ]" Write-Host "" Write-Host "$($PSStyle.bold)General Options:$($PSStyle.Reset)" Write-Host " -h, -help Print this Help." Write-Host " -i, -interactive Interactive mode." Write-Host " -q, -quiet Quiet mode." Write-Host " -verbose Verbose mode." Write-Host " -version Print software version." Write-Host "" Write-Host " -x, -proxy Set proxy." Write-Host "" Write-Host "$($PSStyle.bold)Installation Directory Options:$($PSStyle.Reset)" Write-Host " -d, -dir Set installation directory. Default is $dir." Write-Host "" Write-Host " -o, -overwrite Overwrite the existing installation if found." Write-Host "" Write-Host "$($PSStyle.bold)Authentication options:$($PSStyle.Reset)" Write-Host " Authentication is mandatory, but credentials can be provided interactively later." Write-Host "" Write-Host " -t, -token Set authentication token." Write-Host "" Write-Host " -p, -password Set basic authentication password." Write-Host " -u, -username Set basic authentication username." Write-Host "" Write-Host "$($PSStyle.bold)Server options:$($PSStyle.Reset)" Write-Host " -s, -server Set URL of the server that we want to point to." Write-Host "" Write-Host "Please refer to the full at $DOCS_URL for advanced usage information." Write-Host "" } function initial_checks { Verbose ">>> Requirements check step" # Check if the scanner is already installed if(!($overwrite) -and (Test-Path -Path $dir)) { Write-Host "Keeping existing installation found at $dir" exit 0 } $checks_failed=$false $java_ver = (Get-Command java 2>$null | Select-Object -ExpandProperty Version).Major if(!$java_ver) { Write-Host "Java executable not found. Xygeni needs JDK $MIN_JAVA_VERSION or higher to run." Write-Host "You may download Java from https://jdk.java.net/" $checks_failed=$true } elseif($java_ver -lt $MIN_JAVA_VERSION) { Write-Host "Java $java_ver found. Xygeni needs JDK $MIN_JAVA_VERSION or higher to run." Write-Host "You may download Java from https://jdk.java.net/" $checks_failed=$true } if($checks_failed) { Write-Host "Please visit the documentation at $DOCS_URL and check the installation requisites." exit 1 } } function request_user_credentials { Verbose "" Verbose ">>> Credentials step" if($script:token -or ($script:username -and $script:password) -or $interactive -eq $false) { return } $auth_choice = "" while(!($auth_choice) -or ($auth_choice -ne "T" -and $auth_choice -ne "B" )) { Write-Host "Please choose what kind of authentication will you be using:" Write-Host " - (T)oken" Write-Host " - (B)asic Auth (Username and Password)" $auth_choice = Read-Host Write-Host "" } if($auth_choice -eq "T") { while(!$script:token) { $securedToken = Read-Host "Enter your user token" -AsSecureString $creds = New-Object System.Management.Automation.PSCredential("dummy", $securedToken) $cleartextToken = $creds.GetNetworkCredential().Password if (![string]::IsNullOrWhiteSpace($cleartextToken)){ $script:token = $cleartextToken } } } else { while(!$script:username) { $script:username = Read-Host "Enter your username" } while(!$script:password) { $securePassword = Read-Host "Enter your password" -AsSecureString $creds = New-Object System.Management.Automation.PSCredential("dummy", $securePassword) $cleartextPassword = $creds.GetNetworkCredential().Password if (![string]::IsNullOrWhiteSpace($cleartextPassword)){ $script:password = $cleartextPassword } } } } function create_dirs { Verbose "" Verbose ">>> Create dirs step" Try { $null = New-Item -Force -itemType Directory -Path $dir -ErrorAction Stop } Catch { Write-Warning "Failed to create dir $dir with error: $_" exit 1 } } function download_scanner { Verbose "" Verbose ">>> Scanner download step" Try { if($proxy) { # Encode basic auth proxy credentials in the URL [System.Net.Http.HttpClient]::DefaultProxy = New-Object System.Net.WebProxy($proxy) } if($script:token) { $headers = @{ Authorization="Bearer $script:token" } Invoke-WebRequest -URI $DOWNLOAD_URL -OutFile $ZIP_FILEPATH -Headers $headers } else { $pair = "$($username):$($password)" $encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($pair)) $basicAuthValue = "Basic $encodedCreds" $Headers = @{ Authorization = $basicAuthValue } Invoke-WebRequest -URI $DOWNLOAD_URL -OutFile $ZIP_FILEPATH -Headers $headers } } Catch { Write-Warning "Failed to download scanner with error: $_" if($_ -like "*(401)*") { Write-Warning "You're not authorized, please review your credentials." Write-Warning "When Multi-factor authentication is enabled then an API key must be used for authentication." exit 126 } exit 1 } } function unpack_scanner { Verbose "" Verbose ">>> Scanner unpacking step" Try { Expand-Archive -Force $ZIP_FILEPATH -DestinationPath $TEMP_DIR Copy-Item -Force -Recurse (Join-Path $TEMP_DIR/xygeni_scanner "*") $dir } Catch { Write-Warning "Failed to unpack the scanner with error: $_" exit 1 } } function clean_up { Verbose "" Verbose ">>> Clean up step" Try { $null = Remove-Item $TEMP_DIR -Recurse } Catch { Write-Warning "Failed to delete temp dir $TEMP_DIR with error: $_" exit 1 } } function set_config { Verbose "" Verbose ">>> Set config step" Try { if($script:token) { $null = (Get-Content -Path $CONFIG_FILE_PATH -Raw) -replace 'apikey: \${XYGENI_TOKEN}', "apikey: $token" ` | Set-Content $CONFIG_FILE_PATH } if($script:username) { $null = (Get-Content -Path $CONFIG_FILE_PATH -Raw) -replace 'username: \${XYGENI_USERNAME}', "username: $username" ` | Set-Content $CONFIG_FILE_PATH } if($script:password) { $null = (Get-Content -Path $CONFIG_FILE_PATH -Raw) -replace 'password: \${XYGENI_PASSWORD}', "password: $password" ` | Set-Content $CONFIG_FILE_PATH } if($script:server) { $null = (Get-Content -Path $CONFIG_FILE_PATH -Raw) -replace 'url: \${XYGENI_URL:-https://api.xygeni.io}', "url: $server" ` | Set-Content $CONFIG_FILE_PATH } } Catch { Write-Warning "Failed to set config credentials in $CONFIG_FILE_PATH with error: $_" exit 1 } } function encrypt_credentials { Verbose "" Verbose ">>> Encrypt credentials step" $command = -join($dir, "\xygeni.ps1 util encrypt") (invoke-expression $command) > $null } function show_quickstart_help { Verbose "" Write-Host "$($PSStyle.bold)Congratulations, installation was successfully completed. Start scanning right now!$($PSStyle.Reset)" Write-Host "" Write-Host "Run: $($PSStyle.bold)$dir\xygeni scan -n project_name -d project_path$($PSStyle.Reset)" Write-Host "" Write-Host "Please refer to the full documentation at $($PSStyle.bold)$DOCS_URL$($PSStyle.Reset) for advanced usage information." Write-Host "" } function show_deprecation { Verbose "" Write-Host "" Write-Host "$($PSStyle.bold)⚠️ Scanner install script is deprecated and will be removed in future versions.$($PSStyle.Reset)" Write-Host "Please follow $($PSStyle.bold)${DOCS_URL}getting-started/quick-start-with-xygeni-cli$($PSStyle.Reset) for installation." Write-Host "" } # Run show_deprecation handle_args show_banner initial_checks request_user_credentials create_dirs download_scanner unpack_scanner clean_up set_config encrypt_credentials show_quickstart_help exit 0 # SIG # Begin signature block # MIIlpQYJKoZIhvcNAQcCoIIlljCCJZICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBJzixWC1qmf70Q # hlzWypo2OiyizNneFEVsq9dy/NQJ0aCCEu4wggXdMIIDxaADAgECAgh7LJvTFoAy # mTANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx # EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8G # A1UEAwwoU1NMLmNvbSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTAe # Fw0xNjAyMTIxNzM5MzlaFw00MTAyMTIxNzM5MzlaMHwxCzAJBgNVBAYTAlVTMQ4w # DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENv # cnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlvbiBB # dXRob3JpdHkgUlNBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+Q/d # oyt9y9Aq/uxnhabnLhu6d+Hj9a+k7PpKXZHEV0drGHdrdvL9k+Q9D8IWngtmw1aU # nheDhc5W7/IW/QBi9SIJVOhlF05BueBPRpeqG8i4bmJeabFf2yoCfvxsyvNB2O3Q # 6Pw/YUjtsAMUHRAOSxngu07shmX/NvNeZwILnYZVYf16OO3+4hkAt2+hUGJ1dDyg # +sglkrRueiLH+B6h47LdkTGrKx0E/6VKBDfphaQzK/3i1lU0fBmkSmjHsqjTt8qh # k4jrwZe8jPkd2SKEJHTHBD1qqSmTzOu4W+H+XyWqNFjIwSNUnRuYEcM4nH49hmyl # D0CGfAL0XAJPKMuucZ8POsgz/hElNer8usVgPdl8GNWyqdN1eANyIso6wx/vLOUu # qfqeLLZRRv2vA9bqYGjqhRY2a4XpHsCz3cQk3IAqgUFtlD7I4MmBQQCeXr9/xQiY # ohgsQkCz+W84J0tOgPQ9gUfgiHzqHM61dVxRLhwrfxpyKOcAtdF0xtfkn60Hk7ZT # NTX8N+TD9l0WviFz3pIK+KBjaryWkmo++LxlVZve9Q2JJgT8JRqmJWnLwm3KfOJZ # X5es6+8uyLzXG1k8K8zyGciTaydjGc/86Sb4ynGbf5P+NGeETpnr/LN4CTNwumam # du0bc+sapQ3EIhMglFYKTixsTrH9z5wJuqIz7YcCAwEAAaNjMGEwHQYDVR0OBBYE # FN0ECQei9Xp9UlMSkpXuOIAlDaZZMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgw # FoAU3QQJB6L1en1SUxKSle44gCUNplkwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 # DQEBCwUAA4ICAQAgGBGUKfsmnRweHnBh8ZVyk3EkrWiTWI4yrxuzcAP8JSt0hZA9 # eGr0uYullzu1GJG7Hqf5QFuR+VWZrx4R0Fwdp2bjsZQHDDI5puobsHnYHZxwROOK # 3cT5lR+KOEM/AYWlR6c9RrK85SJo93uc2Cw+CiHILTOsv8WBmTF0wXVxxb6x8CNF # 9J1r/BljnaO8BMYYCyW7U4kPs4BQ3kXuRH+rlHhkmNP2KN2H2HBldPsOuRPrpw9h # qTKWzN677WNMGLupQPegVG4giHF1GOp6tDRy4CMnd1y2kOqGJUCr7zMPy5+CvqIg # +/a1LRrmwoWxdA/7yGUCpFIBR91JIsG/2OtrrH7e7GMzFbcjCI/GD41BWt2OxbmP # 5UU/eNu60htAsf5xTT/ggaK6XrTsFeCT3QgffuFVmQsh3pOeCvvmo0m9NjD+53ey # oHWXtS2BiBdlIPfakACfyVLMMso1fPU9D9gr1/UmbMkGNJYW6nBZGjJ5eQu2iH8P # Ukg9v2zYokQu0U63cljTiROV/kSr+NeLG26cvCygW9VqAK9fN+HV+hALmJyG5yaP # zvDsbopXC4DjTrLAoGNhkLpVaDd0araS25+hhiK2ZScO7LafQmDkZ8K12kELxNOL # YRu8+h+RK9dEB166KazZxenvU0ha64DxKFghzbAGVfsnP1OQcKkEHlcnuTCCBnIw # ggRaoAMCAQICCGQzUdPHOJ8IMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVT # MQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NM # IENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2VydGlmaWNhdGlv # biBBdXRob3JpdHkgUlNBMB4XDTE2MDYyNDIwNDQzMFoXDTMxMDYyNDIwNDQzMFow # eDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9u # MREwDwYDVQQKDAhTU0wgQ29ycDE0MDIGA1UEAwwrU1NMLmNvbSBDb2RlIFNpZ25p # bmcgSW50ZXJtZWRpYXRlIENBIFJTQSBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP # ADCCAgoCggIBAJ+DE3OqsMZtIcvbi3qHdNBx3I6Xcprku4g0tN2AA8YvRaR0mr8e # D1Dqnm1485/6USapPZ3RspRXPvs5iRuRK1bvZ8vmC+MOOYzGNfSMPd0l6QGsF0J9 # WBZA3PnVKEQdlWQwYTpk8pfXc0x9eyMCbfN161U9b6otxK++dKxd/mq2/OpceekP # Q5y1UgUP7z6xsY/QSa2m40IZVD/zLw6hy3z+E/kjOdolHLg+AEo6bzIwN2Qex651 # B9hV0hjJDoq8o1zwfAqnhYHCDq+PmVzTYCW8g1ppHCUTzXL165yAm9wsZ8TdyQmY # 1XPrxCGj5TKOPi9SmMZgN2SMsm9KVHIYzCeH+s11omMhTLU9ZP0rpptVryZMYLS5 # XP6rQ72t0BNmUB8L0omm/9eABvHDEQIzM2EX91Yfji87aOcV8XdWSimeA9rCKyZh # MlugVuVJKY02p/XHUqJWAyAvOHiAvfYGrkE0y5RFvZvHiRgfC7r/qa5qQJkT3e9Q # 3wG68gTW0DHfNDheV1vIOB5W1KxIpu3/+bjBO+3CJL5EYKd3zdU9mFm0Q+qqYH3N # wuUv8ev11CDVlzRuXQRrBRHS05KMCSdE7U81MUZ+dBkFYuyJ4+ojcJjk0S/UihMY # RpNl5Vhz00w9J3oiP8P4o1W3+eaHguxFHsVuOnyxTrmraPebY9WRQbypAgMBAAGj # gfswgfgwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTdBAkHovV6fVJTEpKV # 7jiAJQ2mWTAwBggrBgEFBQcBAQQkMCIwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3Nw # cy5zc2wuY29tMBEGA1UdIAQKMAgwBgYEVR0gADATBgNVHSUEDDAKBggrBgEFBQcD # AzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3Jscy5zc2wuY29tL3NzbC5jb20t # cnNhLVJvb3RDQS5jcmwwHQYDVR0OBBYEFFTC/hCVAJPNavXnwNfZsku4jwzjMA4G # A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA9Q8mh3CvmaLK9dbJ8I1m # PTmC04gj2IK/j1SEJ7bTgwfXnieJTYSOVNEg7mBD21dCPMewlfa+zOqjPY5PBsYr # WYZ/63MbyuVAJuA9b8z2vXHGzX0OIEA51gXSr5QIv3/CUbcrtXuDIfBj2uWc4Wku # dR1Oy2Ee9aUz3wKdFdntaZNXukZFLoC8Zb7nEj7eR/+QnBCt9laypNT61vwuvJch # s3aD0pH6BlDRsYAogP7brQ9n7fh93NlwW3q6aLWzSmYXj+fw51fdaf68XuHVjJ8T # u5WaFft5K4XVbT5nR24bB1z7VEUPFhEuEcOwvLVuHDNXlB7+QjRGjjFQTtszV5X6 # OOTmEturWC5Ft9kiyvRaR0ksKOhPjEI8ZGjp5kOsGZGpxxOCX/xxCje3nVB7PF33 # olKCNeS159MKb2v+jfmk19UdS+d9Ygj42desmUnbtYRBFC72LmCXU0ua/vGIenS6 # nnXp4NqnycwsO3tMCnjPlPc2YLaDPIpUy04NaCqUEXUmFOogN8zreRd2VXhxbeJJ # ODM32+RsWccjYua8zi5US/1eAyrI3R5LcUTQdT4xYmWLKabtJOF6HYQ0f6QXfLSs # fT81WMvDvxrdn1RWbUXlU/OIiisxo8o+UNEANOwnCMNnxlzoaL/PLhZluDxm/zuy # lauajZ3MlPDteFB/7GRHo50wggaTMIIEe6ADAgECAhAgBevqUuKpdVIslC+/AUAa # MA0GCSqGSIb3DQEBCwUAMHgxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQ # MA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxNDAyBgNVBAMMK1NT # TC5jb20gQ29kZSBTaWduaW5nIEludGVybWVkaWF0ZSBDQSBSU0EgUjEwHhcNMjUx # MTI2MDUxNjAwWhcNMjYxMTI1MDUxNjAwWjB6MQswCQYDVQQGEwJFUzEcMBoGA1UE # CAwTVmFsbGFkb2xpZCBQcm92aW5jZTETMBEGA1UEBwwKVmFsbGFkb2xpZDEbMBkG # A1UECgwSWHlnZW5pIFNlY3VyaXR5IFNMMRswGQYDVQQDDBJYeWdlbmkgU2VjdXJp # dHkgU0wwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCFYBGsoq+fEAF6 # 9vWZMIzgbCfY+5jCMgwt1yL/RGcds9C/NDe07dNMBlBeUMaZj45xfYSINibhQ4Tg # phmMo6mJlXW8XoCoSPedS4yn/ZvyeRBDh+O9Pr5RMMi+8KYWDxHGT9lzDCVffb/V # Rn1celV7PASx9i4kjdwArAr2C+6xv7SEk/j0k87xTYu5BqL6SjRg13XYzIQmPFeI # 8MIUPrVmEeRXkIsjCbjvtuVcsjuCjatlJH27kZwwDf2gkR8x+XVfkG2ZMUnqCacA # 2vgmpQApcezyqI7Vq+8I3Em1BUICI+bBBpxgNAdVFH2HwWGgU4penPCciNL0J2AT # AXD5UNEb2oIW02NziBTCVMKZ7Gg7CRq/7v64rrBibiSdFFWB62eXORa9c4bj8bXM # Fscoq+6PWKGu5GzW0OX28CIpJfHLTNdwZedqopHbWXePW2031RnUdyLGxNnHOrkX # ZPbwsK179G/chSlGifZiEj09hMoRqmPXZnpg9c4npjoW+vSYo9sCAwEAAaOCAZUw # ggGRMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUVML+EJUAk81q9efA19myS7iP # DOMwegYIKwYBBQUHAQEEbjBsMEgGCCsGAQUFBzAChjxodHRwOi8vY2VydC5zc2wu # Y29tL1NTTGNvbS1TdWJDQS1Db2RlU2lnbmluZy1SU0EtNDA5Ni1SMS5jZXIwIAYI # KwYBBQUHMAGGFGh0dHA6Ly9vY3Nwcy5zc2wuY29tMFEGA1UdIARKMEgwCAYGZ4EM # AQQBMDwGDCsGAQQBgqkwAQMDATAsMCoGCCsGAQUFBwIBFh5odHRwczovL3d3dy5z # c2wuY29tL3JlcG9zaXRvcnkwEwYDVR0lBAwwCgYIKwYBBQUHAwMwTQYDVR0fBEYw # RDBCoECgPoY8aHR0cDovL2NybHMuc3NsLmNvbS9TU0xjb20tU3ViQ0EtQ29kZVNp # Z25pbmctUlNBLTQwOTYtUjEuY3JsMB0GA1UdDgQWBBRYGaPkb+tqCTolawUwdFiB # ixhLfzAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBACOt6Xm/8P+P # c0UBrjYrkZpcZU1IG9rZzS59sQcT5v+2vfcxvLD58gve+ImIGTKpHKSR/HUpg0Tf # ktKqDObECQtKtoKEQyVfmdyHz7tMkehTWvsc8Nn1pLSZsgwJhLysFwAzDP5Ji03f # 6FC/5kyTxB/my6QnKpTZu0g5Gk0zUgUpy3snGoa/SP9psOq1sXxtmn5/GFwKOgtc # WmuNRP4lBDZSvyDljDs1l5cpZf9EMyJM6ZN6frUfeo2e31wt73any/X8YtMe37I6 # RR7ssyCNfktknM1IwqdYE3+QvTbyzNn/PZV/lRl1I9AIQ97NG+PZVPN0/eiZUbGQ # 0ruGoxwX/7GroFUCWDr2iv75vC15l6hBHGdTOO9cLi2LIJhsaZcFzzdmX5lYIp+E # V1b/GuIItOezkFCOx7AbJYCbMCPsQQ8mDoXHjVM9AKH7/WowsT5dnCcr+GCMMGNu # 6bRben2q2gDbwMUlaEm4R531LIeWFivoKXDgriTt9c5ud9m5+ldZ/s1/db4uxaj2 # XEuhaCsPpNQLz8OJDDdKjQJ87/FmILn5DMrA37t35dIrsjxOxP6PK4fyGOBLDH+N # XORj9j+NH8sqmj3t5nSAuQEw58JyjL1AlKid/AEA0RsF+KjQGIRNnaoVI2Xc1T/D # Hmj/EEWfPY5t/ubUZpc6rGDCE4KgdvBjMYISDTCCEgkCAQEwgYwweDELMAkGA1UE # BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMREwDwYDVQQK # DAhTU0wgQ29ycDE0MDIGA1UEAwwrU1NMLmNvbSBDb2RlIFNpZ25pbmcgSW50ZXJt # ZWRpYXRlIENBIFJTQSBSMQIQIAXr6lLiqXVSLJQvvwFAGjANBglghkgBZQMEAgEF # AKCBrzAUBgorBgEEAYI3AgEMMQYwBKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQB # gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLQYJKoZIhvcNAQk0 # MSAwHjANBglghkgBZQMEAgEFAKENBgkqhkiG9w0BAQsFADAvBgkqhkiG9w0BCQQx # IgQgGXM0Q8W5U92X0VP05ZF7VYzvDQPyHzCha8VXoLeiROMwDQYJKoZIhvcNAQEL # BQAEggGAR72sNKAR1mwMQ/JTWpP/4rUfjrnr15Jrfbd0De8AZnTATe2W5PVQyhuf # +O5Do0LDfzgEzyH57z3GpUDiNNLbvPKfrVtwvIjaa0y5aJwYQcUV9l2UdZmGvHwp # L6LKG2EdoI591Nzt5naSp/rftq+Zuwf3NSNwX8Cj+z4ELDStliT4Udh3uCInOaK/ # 2zn+Agg+m99CYtevwglHjUBeXH2HUYAoJO+Zm2mCAobD0gaq842vmvREi0uHzi7y # uEIIW/JFQxvr2C5LkZ4NBNNiblbtnXIKwE/jeLLBaiKdIiCHwi2VqX0vyvIq/2QP # fSOK9GREHZnc6Cm7atu47B5gjWiryObZ7Iwvn3kX170GGzHL6i5uhtTVPV4qJKRj # XU+q22Ghq2Ldmt9Eec1JMEViDWAil10ycHu9Gbe5SjfIEGQ5wtYck8E1J2IOFqje # Qalxf7/i+rBwJbtwqSNiSBAxNUTe/w3/oUvDsv1xJNOm6jE36bLw8jEtvB1LVrzq # WcEZEz1yoYIPHzCCDxsGCisGAQQBgjcDAwExgg8LMIIPBwYJKoZIhvcNAQcCoIIO # +DCCDvQCAQMxDTALBglghkgBZQMEAgEwfwYLKoZIhvcNAQkQAQSgcARuMGwCAQEG # DCsGAQQBgqkwAQMGATAxMA0GCWCGSAFlAwQCAQUABCAaRSUW1eseO/oK/IW02lcu # bFUl3+1xFmTeRIWBdmL9GAIIBSrL88EvxS4YDzIwMjUxMjA0MTkwNzIyWjADAgEB # AgYBmurDDLugggwAMIIE/DCCAuSgAwIBAgIQWlqs6Bo1brRiho1XfeA9xzANBgkq # hkiG9w0BAQsFADBzMQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNV # BAcMB0hvdXN0b24xETAPBgNVBAoMCFNTTCBDb3JwMS8wLQYDVQQDDCZTU0wuY29t # IFRpbWVzdGFtcGluZyBJc3N1aW5nIFJTQSBDQSBSMTAeFw0yNDAyMTkxNjE4MTla # Fw0zNDAyMTYxNjE4MThaMG4xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQ # MA4GA1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxKjAoBgNVBAMMIVNT # TC5jb20gVGltZXN0YW1waW5nIFVuaXQgMjAyNCBFMTBZMBMGByqGSM49AgEGCCqG # SM49AwEHA0IABKdhcvUw6XrEgxSWBULj3Oid25Rt2TJvSmLLaLy3cmVATADvhyMr # yD2ZELwYfVwABUwivwzYd1mlWCRXUtcEsHyjggFaMIIBVjAfBgNVHSMEGDAWgBQM # nRAljpqnG5mHQ88IfuG9gZD0zzBRBggrBgEFBQcBAQRFMEMwQQYIKwYBBQUHMAKG # NWh0dHA6Ly9jZXJ0LnNzbC5jb20vU1NMLmNvbS10aW1lU3RhbXBpbmctSS1SU0Et # UjEuY2VyMFEGA1UdIARKMEgwPAYMKwYBBAGCqTABAwYBMCwwKgYIKwYBBQUHAgEW # Hmh0dHBzOi8vd3d3LnNzbC5jb20vcmVwb3NpdG9yeTAIBgZngQwBBAIwFgYDVR0l # AQH/BAwwCgYIKwYBBQUHAwgwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NybHMu # c3NsLmNvbS9TU0wuY29tLXRpbWVTdGFtcGluZy1JLVJTQS1SMS5jcmwwHQYDVR0O # BBYEFFBPJKzvtT5jEyMJkibsujqW5F0iMA4GA1UdDwEB/wQEAwIHgDANBgkqhkiG # 9w0BAQsFAAOCAgEAmKCPAwCRvKvEZEF/QiHiv6tsIHnuVO7BWILqcfZ9lJyIyiCm # pLOtJ5VnZ4hvm+GP2tPuOpZdmfTYWdyzhhOsDVDLElbfrKMLiOXn9uwUJpa5fMZe # 3Zjoh+n/8DdnSw1MxZNMGhuZx4zeyqei91f1OhEU/7b2vnJCc9yBFMjY++tVKovF # j0TKT3/Ry+Izdbb1gGXTzQQ1uVFy7djxGx/NG1VP/aye4OhxHG9FiZ3RM9oyAiPb # EgjrnVCc+nWGKr3FTQDKi8vNuyLnCVHkiniL+Lz7H4fBgk163Llxi11Ynu5A/php # m1b+M2genvqo1+2r8iVLHrERgFGMUHEdKrZ/OFRDmgFrCTY6xnaPTA5/ursCqMK3 # q3/59uZaOsBZhZkaP9EuOW2p0U8Gkgqp2GNUjFoaDNWFoT/EcoGDiTgN8VmQFgn0 # Fa4/3dOb6lpYEPBcjsWDdqUaxugStY9aW/AwCal4lSN4otljbok8u31lZx5NVa4j # K6N6upvkgyZ6osmbmIWr9DLhg8bI+KiXDnDWT0547gSuZLYUq+TV6O/DhJZH5LVX # JaeS1jjjZZqhK3EEIJVZl0xYV4H4Skvy6hA2rUyFK3+whSNS52TJkshsxVCOPtvq # A9ecPqZLwWBaIICG4zVr+GAD7qjWwlaLMd2ZylgOHI3Oit/0pVETqJHutyYwggb8 # MIIE5KADAgECAhBtUhhwh+gjTYVgANCAj5NWMA0GCSqGSIb3DQEBCwUAMHwxCzAJ # BgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYG # A1UECgwPU1NMIENvcnBvcmF0aW9uMTEwLwYDVQQDDChTU0wuY29tIFJvb3QgQ2Vy # dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBMB4XDTE5MTExMzE4NTAwNVoXDTM0MTEx # MjE4NTAwNVowczELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQH # DAdIb3VzdG9uMREwDwYDVQQKDAhTU0wgQ29ycDEvMC0GA1UEAwwmU1NMLmNvbSBU # aW1lc3RhbXBpbmcgSXNzdWluZyBSU0EgQ0EgUjEwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCuURAT0vk8IKAghd7JUBxkyeH9xek0/wp/MUjoclrFXqhh # /fGH91Fc+7fm0MHCE7A+wmOiqBj9ODrJAYGq3rm33jCnHSsCBNWAQYyoauLq8Ijq # sS1JlXL29qDNMMdwZ8UNzQS7vWZMDJ40JSGNphMGTIA2qn2bohGtgRc4p1395ESy # pUOaGvJ3t0FNL3BuKmb6YctMcQUF2sqooMzd89h0E6ujdvBDo6ZwNnWoxj7YmfWj # SXg33A5GuY9ym4QZM5OEVgo8ebz/B+gyhyCLNNhh4Mb/4xvCTCMVmNYrBviGgdPZ # Yrym8Zb84TQCmSuX0JlLLa6WK1aO6qlwISbb9bVGh866ekKblC/XRP20gAu1Cjvc # YciUgNTrGFg8f8AJgQPOCc1/CCdaJSYwhJpSdheKOnQgESgNmYZPhFOC6IKaMAUX # k5U1tjTcFCgFvvArXtK4azAWUOO1Y3fdldIBL6LjkzLUCYJNkFXqhsBVcPMuB0nU # DWvLJfPimstjJ8lF4S6ECxWnlWi7OElVwTnt1GtRqeY9ydvvGLntU+FecK7DbqHD # Ud366UreMkSBtzevAc9aqoZPnjVMjvFqV1pYOjzmTiVHZtAc80bAfFe5LLfJzPI6 # DntNyqobpwTevQpHqPDN9qqNO83r3kaw8A9j+HZiSw2AX5cGdQP0kG0vhzfgBwID # AQABo4IBgTCCAX0wEgYDVR0TAQH/BAgwBgEB/wIBADAfBgNVHSMEGDAWgBTdBAkH # ovV6fVJTEpKV7jiAJQ2mWTCBgwYIKwYBBQUHAQEEdzB1MFEGCCsGAQUFBzAChkVo # dHRwOi8vd3d3LnNzbC5jb20vcmVwb3NpdG9yeS9TU0xjb21Sb290Q2VydGlmaWNh # dGlvbkF1dGhvcml0eVJTQS5jcnQwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3Nwcy5z # c2wuY29tMD8GA1UdIAQ4MDYwNAYEVR0gADAsMCoGCCsGAQUFBwIBFh5odHRwczov # L3d3dy5zc2wuY29tL3JlcG9zaXRvcnkwEwYDVR0lBAwwCgYIKwYBBQUHAwgwOwYD # VR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybHMuc3NsLmNvbS9zc2wuY29tLXJzYS1S # b290Q0EuY3JsMB0GA1UdDgQWBBQMnRAljpqnG5mHQ88IfuG9gZD0zzAOBgNVHQ8B # Af8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBAJIZdQ2mWkLPGQfZ8vyU+sCb8BXp # RJZaL3Ez3VDlE3uZk3cPxPtybVfLuqaci0W6SB22JTMttCiQMnIVOsXWnIuAbD/a # FTcUkTLBI3xys+wEajzXaXJYWACDS47BRjDtYlDW14gLJxf8W6DQoH3jHDGGy8kG # JFOlDKG7/YrK7UGfHtBAEDVe6lyZ+FtCsrk7dD/IiL/+Q3Q6SFASJLQ2XI89ihFu # gdYL77CiDNXrI2MFspQGswXEAGpHuaQDTHUp/LdR3TyrIsLlnzoLskUGswF/KF8+ # kpWUiKJNC4rPWtNrxlbXYRGgdEdx8SMjUTDClldcrknlFxbqHsVmr9xkT2QtFmG+ # dEq1v5fsIK0vHaHrWjMMmaJ9i+4qGJSD0stYfQ6v0PddT7EpGxGd867Ada6FZyHw # buQSadMb0K0P0OC2r7rwqBUe0BaMqTa6LWzWItgBjGcObXeMxmbQqlEz2YtAcErk # Zvh0WABDDE4U8GyV/32FdaAvJgTfe9MiL2nSBioYe/g5mHUSWAay/Ip1RQmQCvmF # 9sNfqlhJwkjy/1U1ibUkTIUBX3HgymyQvqQTZLLys6pL2tCdWcjI9YuLw30rgZm8 # +K387L7ycUvqrmQ3ZJlujHl3r1hgV76s3WwMPgKk1bAEFMj+rRXimSC+Ev30hXZd # qyMdl/il5Ksd0vhGMYICWTCCAlUCAQEwgYcwczELMAkGA1UEBhMCVVMxDjAMBgNV # BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMREwDwYDVQQKDAhTU0wgQ29ycDEv # MC0GA1UEAwwmU1NMLmNvbSBUaW1lc3RhbXBpbmcgSXNzdWluZyBSU0EgQ0EgUjEC # EFparOgaNW60YoaNV33gPccwCwYJYIZIAWUDBAIBoIIBYTAaBgkqhkiG9w0BCQMx # DQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI1MTIwNDE5MDcyMlowKAYJ # KoZIhvcNAQk0MRswGTALBglghkgBZQMEAgGhCgYIKoZIzj0EAwIwLwYJKoZIhvcN # AQkEMSIEII5nNa/nX2tkb42OAr1Tk9DqAw2NSAU3As6QteapIsnPMIHJBgsqhkiG # 9w0BCRACLzGBuTCBtjCBszCBsAQgnXF/jcI3ZarOXkqw4fV115oX1Bzu2P2v7wP9 # Pb2JR+cwgYswd6R1MHMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G # A1UEBwwHSG91c3RvbjERMA8GA1UECgwIU1NMIENvcnAxLzAtBgNVBAMMJlNTTC5j # b20gVGltZXN0YW1waW5nIElzc3VpbmcgUlNBIENBIFIxAhBaWqzoGjVutGKGjVd9 # 4D3HMAoGCCqGSM49BAMCBEgwRgIhAMO7PlZ/Qc1QvQ9ZbALQRuSA93GtmNUjoj+t # m9uO+KahAiEA2FW56PjK+vtls8+TC99Wq6FFaboTnYfDRQE3hnptrkA= # SIG # End signature block