Private/Tools/Test-Tooling.ps1
function Test-Tooling { [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $false)] [switch]$skipAlzModuleVersionCheck ) $checkResults = @() $hasFailure = $false # Check if PowerShell is the correct version Write-Verbose "Checking PowerShell version" $powerShellVersionTable = $PSVersionTable $powerShellVersion = $powerShellVersionTable.PSVersion.ToString() if ($powerShellVersionTable.PSVersion.Major -lt 7) { $checkResults += @{ message = "PowerShell version $powerShellVersion is not supported. Please upgrade to PowerShell 7.4 or higher. Either switch to the `pwsh` prompt or follow the instructions here: https://aka.ms/install-powershell" result = "Failure" } $hasFailure = $true } elseif ($powerShellVersionTable.PSVersion.Major -eq 7 -and $powerShellVersionTable.PSVersion.Minor -lt 4) { $checkResults += @{ message = "PowerShell version $powerShellVersion is not supported. Please upgrade to PowerShell 7.4 or higher. Either switch to the `pwsh` prompt or follow the instructions here: https://aka.ms/install-powershell" result = "Failure" } $hasFailure = $true } else { $checkResults += @{ message = "PowerShell version $powerShellVersion is supported." result = "Success" } } # Check if Git is installed Write-Verbose "Checking Git installation" $gitPath = Get-Command git -ErrorAction SilentlyContinue if ($gitPath) { $checkResults += @{ message = "Git is installed." result = "Success" } } else { $checkResults += @{ message = "Git is not installed. Follow the instructions here: https://git-scm.com/downloads" result = "Failure" } $hasFailure = $true } # Check if using Service Principal Auth Write-Verbose "Checking Azure environment variables" $nonAzCliEnvVars = @( "ARM_CLIENT_ID", "ARM_SUBSCRIPTION_ID", "ARM_TENANT_ID" ) $envVarsSet = $true $envVarValid = $true $envVarUnique = $true $envVarAtLeastOneSet = $false $envVarsWithValue = @() $checkedEnvVars = @() foreach($envVar in $nonAzCliEnvVars) { $envVarValue = [System.Environment]::GetEnvironmentVariable($envVar) if($envVarValue -eq $null -or $envVarValue -eq "" ) { $envVarsSet = $false continue } $envVarAtLeastOneSet = $true $envVarsWithValue += $envVar if($envVarValue -notmatch("^(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}$")) { $envVarValid = $false continue } if($checkedEnvVars -contains $envVarValue) { $envVarUnique = $false continue } $checkedEnvVars += $envVarValue } if($envVarsSet) { Write-Verbose "Using Service Principal Authentication, skipping Azure CLI checks" if($envVarValid -and $envVarUnique) { $checkResults += @{ message = "Azure environment variables are set and are valid unique GUIDs." result = "Success" } } if(-not $envVarValid) { $checkResults += @{ message = "Azure environment variables are set, but are not all valid GUIDs." result = "Failure" } $hasFailure = $true } if (-not $envVarUnique) { $envVarValidationOutput = "" foreach($envVar in $nonAzCliEnvVars) { $envVarValue = [System.Environment]::GetEnvironmentVariable($envVar) $envVarValidationOutput += " $envVar ($envVarValue)" } $checkResults += @{ message = "Azure environment variables are set, but are not unique GUIDs. There is at least one duplicate:$envVarValidationOutput." result = "Failure" } $hasFailure = $true } } else { if($envVarAtLeastOneSet) { $envVarValidationOutput = "" foreach($envVar in $envVarsWithValue) { $envVarValue = [System.Environment]::GetEnvironmentVariable($envVar) $envVarValidationOutput += " $envVar ($envVarValue)" } $checkResults += @{ message = "At least one environment variable is set, but the other expected environment variables are not set. This could cause Terraform to fail in unexpected ways. Set environment variables:$envVarValidationOutput." result = "Warning" } } # Check if Azure CLI is installed Write-Verbose "Checking Azure CLI installation" $azCliPath = Get-Command az -ErrorAction SilentlyContinue if ($azCliPath) { $checkResults += @{ message = "Azure CLI is installed." result = "Success" } } else { $checkResults += @{ message = "Azure CLI is not installed. Follow the instructions here: https://learn.microsoft.com/en-us/cli/azure/install-azure-cli" result = "Failure" } $hasFailure = $true } # Check if Azure CLI is logged in Write-Verbose "Checking Azure CLI login status" $azCliAccount = $(az account show -o json) | ConvertFrom-Json if ($azCliAccount) { $checkResults += @{ message = "Azure CLI is logged in. Tenant ID: $($azCliAccount.tenantId), Subscription: $($azCliAccount.name) ($($azCliAccount.id))" result = "Success" } } else { $checkResults += @{ message = "Azure CLI is not logged in. Please login to Azure CLI using 'az login -t `"00000000-0000-0000-0000-000000000000}`"', replacing the empty GUID with your tenant ID." result = "Failure" } $hasFailure = $true } } if($skipAlzModuleVersionCheck.IsPresent) { Write-Verbose "Skipping ALZ module version check" } else { # Check if latest ALZ module is installed Write-Verbose "Checking ALZ module version" $alzModuleCurrentVersion = Get-InstalledModule -Name ALZ -ErrorAction SilentlyContinue if($null -eq $alzModuleCurrentVersion) { $checkResults += @{ message = "ALZ module is not correctly installed. Please install the latest version using 'Install-Module ALZ'." result = "Failure" } $hasFailure = $true } $alzModuleLatestVersion = Find-Module -Name ALZ if ($null -ne $alzModuleCurrentVersion) { if ($alzModuleCurrentVersion.Version -lt $alzModuleLatestVersion.Version) { $checkResults += @{ message = "ALZ module is not the latest version. Your version: $($alzModuleCurrentVersion.Version), Latest version: $($alzModuleLatestVersion.Version). Please update to the latest version using 'Update-Module ALZ'." result = "Failure" } $hasFailure = $true } else { $checkResults += @{ message = "ALZ module is the latest version ($($alzModuleCurrentVersion.Version))." result = "Success" } } } } Write-Verbose "Showing check results" Write-Verbose $(ConvertTo-Json $checkResults -Depth 100) $checkResults | ForEach-Object {[PSCustomObject]$_} | Format-Table -Property @{ Label = "Check Result"; Expression = { switch ($_.result) { 'Success' { $color = "92"; break } 'Failure' { $color = "91"; break } 'Warning' { $color = "93"; break } default { $color = "0" } } $e = [char]27 "$e[${color}m$($_.result)${e}[0m" } }, @{ Label = "Check Details"; Expression = {$_.message} } -AutoSize -Wrap if($hasFailure) { Write-InformationColored "Accelerator software requirements have no been met, please review and install the missing software." -ForegroundColor Red -InformationAction Continue Write-InformationColored "Cannot continue with Deployment..." -ForegroundColor Red -InformationAction Continue throw "Accelerator software requirements have no been met, please review and install the missing software." } } # SIG # Begin signature block # MIIoRwYJKoZIhvcNAQcCoIIoODCCKDQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCB/8UjrsOzfs837 # 6BXerMr1ab/OuLmN9baEMzkvHLTiqaCCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z # 7A5ZL83XAAAAAASFMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM3WhcNMjYwNjE3MTgyMTM3WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDASkh1cpvuUqfbqxele7LCSHEamVNBfFE4uY1FkGsAdUF/vnjpE1dnAD9vMOqy # 5ZO49ILhP4jiP/P2Pn9ao+5TDtKmcQ+pZdzbG7t43yRXJC3nXvTGQroodPi9USQi # 9rI+0gwuXRKBII7L+k3kMkKLmFrsWUjzgXVCLYa6ZH7BCALAcJWZTwWPoiT4HpqQ # hJcYLB7pfetAVCeBEVZD8itKQ6QA5/LQR+9X6dlSj4Vxta4JnpxvgSrkjXCz+tlJ # 67ABZ551lw23RWU1uyfgCfEFhBfiyPR2WSjskPl9ap6qrf8fNQ1sGYun2p4JdXxe # UAKf1hVa/3TQXjvPTiRXCnJPAgMBAAGjggFzMIIBbzAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUuCZyGiCuLYE0aU7j5TFqY05kko0w # RQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEW # MBQGA1UEBRMNMjMwMDEyKzUwNTM1OTAfBgNVHSMEGDAWgBRIbmTlUAXTgqoXNzci # tW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3JsMGEG # CCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDovL3d3dy5taWNyb3NvZnQu # Y29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDExXzIwMTEtMDctMDguY3J0 # MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBACjmqAp2Ci4sTHZci+qk # tEAKsFk5HNVGKyWR2rFGXsd7cggZ04H5U4SV0fAL6fOE9dLvt4I7HBHLhpGdE5Uj # Ly4NxLTG2bDAkeAVmxmd2uKWVGKym1aarDxXfv3GCN4mRX+Pn4c+py3S/6Kkt5eS # DAIIsrzKw3Kh2SW1hCwXX/k1v4b+NH1Fjl+i/xPJspXCFuZB4aC5FLT5fgbRKqns # WeAdn8DsrYQhT3QXLt6Nv3/dMzv7G/Cdpbdcoul8FYl+t3dmXM+SIClC3l2ae0wO # lNrQ42yQEycuPU5OoqLT85jsZ7+4CaScfFINlO7l7Y7r/xauqHbSPQ1r3oIC+e71 # 5s2G3ClZa3y99aYx2lnXYe1srcrIx8NAXTViiypXVn9ZGmEkfNcfDiqGQwkml5z9 # nm3pWiBZ69adaBBbAFEjyJG4y0a76bel/4sDCVvaZzLM3TFbxVO9BQrjZRtbJZbk # C3XArpLqZSfx53SuYdddxPX8pvcqFuEu8wcUeD05t9xNbJ4TtdAECJlEi0vvBxlm # M5tzFXy2qZeqPMXHSQYqPgZ9jvScZ6NwznFD0+33kbzyhOSz/WuGbAu4cHZG8gKn # lQVT4uA2Diex9DMs2WHiokNknYlLoUeWXW1QrJLpqO82TLyKTbBM/oZHAdIc0kzo # STro9b3+vjn2809D0+SOOCVZMIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGicwghojAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB # BQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHPPYyiU2nuKqDNnOOPBrJUG # eCCmYIc/p/R6gUGpvvClMEQGCisGAQQBgjcCAQwxNjA0oBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQuY29tIDANBgkqhkiG9w0B # AQEFAASCAQCNJX+0os+F6kUO70hbMYtXT5Ra2R6oV1sTOpm5SiA/wcO/XwJ2T4rD # X1tPtzXQvpOLL9molgFKARjI4RFaFUmU/d8eDAiZ+77rVBVjeBsXvPEstLA0866F # HFVtukBRImelbDTYeQ6HQ1uSOlvWWIqdFGGqknEKqM76SuWFmLmPnaDKFnKdMR4A # 9vApJ5aEEB6KRUTXSkhkqq6gDbpMsO6uvyPvMA9O/C3jM9tESvIMrJSjL2IawN0U # 0MAnM2JwCEVcxRo5RG95Z4wb9eJzL/x6g6tTUHEuigrKoghsREifuRF7+dh10S+s # fyGop68/xIbl4GkBHfbb8CnqEJsr4rEhoYIXrzCCF6sGCisGAQQBgjcDAwExgheb # MIIXlwYJKoZIhvcNAQcCoIIXiDCCF4QCAQMxDzANBglghkgBZQMEAgEFADCCAVkG # CyqGSIb3DQEJEAEEoIIBSASCAUQwggFAAgEBBgorBgEEAYRZCgMBMDEwDQYJYIZI # AWUDBAIBBQAEICa1mGMpmg6tK/cIhquUdaqSxTVKrS4wuvuBhA3qiSYtAgZorgES # JzcYEjIwMjUwOTE2MTMzMTU3LjU2WjAEgAIB9KCB2aSB1jCB0zELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IEly # ZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBF # U046MzYwNS0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w # IFNlcnZpY2WgghH+MIIHKDCCBRCgAwIBAgITMwAAAfdYIHUEyvvC9AABAAAB9zAN # BgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0y # NDA3MjUxODMxMDZaFw0yNTEwMjIxODMxMDZaMIHTMQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMS0wKwYDVQQLEyRNaWNyb3NvZnQgSXJlbGFuZCBP # cGVyYXRpb25zIExpbWl0ZWQxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjozNjA1 # LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj # ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANDnR0wTaJuv7lymhCj/ # azyE5E+kMRddbY8wdDZNW8g6T6xUx4Wt4ccEnU3K/GNGt5OhEJcKsukTs+NntEeX # g1vnQqEGqYqQyBVDmKd6DbqsF/8XqQExJGNezMlxceq0FtjXFlCVt0KNgLidBzrW # 5UqSLUGTxph5xqpLfwweORcMZOlaEr8TXECoShE5Ls67fFOg0XHEJtRXYZjyoA84 # HHwzzOaPhp824jLustOvQOBB5izJpHnEpFbwZnGfFZ8xR0w5Bi3aZw1eRV41TmwI # G0jNHJ6mEhn0ae1RhwUasqLHL0eG3EPglfaQ42yekua2Z9bgPIUYY9PR7N9x0Xr7 # eKFgFWBiLYBLBvgawmG6YFjAxCFZwID2RIjwGiPMARnphOH3hJLs+0wMIJEQXFMy # 4EOLrz6kQ9QPiZLduvqQ6lmEp9DAPI9M2nEJPavwL3Ij1w/SLdns/pqhM4BUUbCR # i7XH/R5LLyvCbHeiOcxUoZaouW6c39WODTojToeUMFtaSLwOYq5Wpe6hYZAHnnma # pqKfPrjcWV8RQkBt0d7OaV1vPRYgofa5l61ajgsIHFxSCUAEJJZSrCPlCahqva5k # QASc+ZRykxWJhcHDOdillozcd8+qHcM9ofrMWsXsE6HvRqrQ8d/2lPsqjUXAfMNL # Ul1H/spTeLpOcRxKS6cfmTTbAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQU30akMz95 # vT2Vri39afP5nhX5JpgwHwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIw # XwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9w # cy9jcmwvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3Js # MGwGCCsGAQUFBwEBBGAwXjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3Nv # ZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENB # JTIwMjAxMCgxKS5jcnQwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEF # BQcDCDAOBgNVHQ8BAf8EBAMCB4AwDQYJKoZIhvcNAQELBQADggIBADdGo2nyC3i+ # kkCDCDAFzNUHesWqHItpjq6UfLylssk7C92/NwO1xi4gG0MU66p171VlnjbLeWEA # /LGjvlE4DiyXU3X1AA4S16CvkZcI353YpiCU/TB/bVGFy8yVyoWTNPaLj8DbK5/G # DiyKXQIuUz8jfApddThmUpT/a/CZ76JltNAKCeD5fa5YNBuZXEJJwF6h2vZ0HVqd # WcV6jXftCbCppUfLXADV99wpTPTZ2gpSRMS0B4inh1FFrasizJeuU1usETO15Re2 # Pj05wvHbjVp+Li54Pjjf2d/RjuqgY+yBGcaKuKN2rxIfW2uN1FOk4M1WWgZvFWgN # MEsFHv6aqUzmBVjetly94JfyQtqc3yD8T+ul30SyMWn4wVV5vClQ59nDC/SL0StN # rPeNWOfkUeIEgDoS4kEOgNN1TUbqfrKTGtJPl0zwIvtmjB+cWtWY2/yvLvX/TNOV # NP21DCVyQz/vsrFqSW1UQ4hxu7M2nGvq9x4lD40CckJdjYjnGExlfw3C6ywgStsx # udNxRm9ODeSn9dF4AMBWl5aHeQfXiofeT51ysdizQYC8BvOWp5YYRscQUOZhbCRp # AZ9D2T7QM2cn6/eqsc6adqR/QySXIygg6zJmc4l2s6WuVVTd+gjtZA1OAAZEmE1z # jPEZiV7kJu5lBd21po/oYwCW+Kc+oU+VMIIHcTCCBVmgAwIBAgITMwAAABXF52ue # AptJmQAAAAAAFTANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgz # MjI1WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYD # VQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxO # dcjKNVf2AX9sSuDivbk+F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQ # GOhgfWpSg0S3po5GawcU88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq # /XJprx2rrPY2vjUmZNqYO7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVW # Te/dvI2k45GPsjksUZzpcGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7 # mka97aSueik3rMvrg0XnRm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De # +JKRHh09/SDPc31BmkZ1zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM # 9ituqBJR6L8FA6PRc6ZNN3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEz # OUyOArxCaC4Q6oRRRuLRvWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2 # ZItboKaDIV1fMHSRlJTYuVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqv # UAV6bMURHXLvjflSxIUXk8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q # 4i6tAgMBAAGjggHdMIIB2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcV # AgQWBBQqp1L+ZMSavoKRPEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXS # ZacbUzUZ6XIwXAYDVR0gBFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcC # ARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRv # cnkuaHRtMBMGA1UdJQQMMAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1 # AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaA # FNX2VsuP6KJcYmjRPZSQW9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9j # cmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8y # MDEwLTA2LTIzLmNybDBaBggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAt # MDYtMjMuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8 # qW/qXBS2Pk5HZHixBpOXPTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7p # Zmc6U03dmLq2HnjYNi6cqYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2C # DPVtI1TkeFN1JFe53Z/zjj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BA # ljis9/kpicO8F7BUhUKz/AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJ # eBTpkbKpW99Jo3QMvOyRgNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1 # MMU0sHrYUP4KWN1APMdUbZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz # 138eW0QBjloZkWsNn6Qo3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1 # V1QJsWkBRH58oWFsc/4Ku+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLB # gqJ7Fx0ViY1w/ue10CgaiQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0l # lOZ0dFtq0Z4+7X6gMTN9vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFx # BmoQtB1VM1izoXBm8qGCA1kwggJBAgEBMIIBAaGB2aSB1jCB0zELMAkGA1UEBhMC # VVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV # BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEtMCsGA1UECxMkTWljcm9zb2Z0IEly # ZWxhbmQgT3BlcmF0aW9ucyBMaW1pdGVkMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBF # U046MzYwNS0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1w # IFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVAG9vCgxv8V2zQY5jO/56sN24KxDmoIGD # MIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQG # A1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwDQYJKoZIhvcNAQEL # BQACBQDsc4RXMCIYDzIwMjUwOTE2MDYzODE1WhgPMjAyNTA5MTcwNjM4MTVaMHcw # PQYKKwYBBAGEWQoEATEvMC0wCgIFAOxzhFcCAQAwCgIBAAICHHwCAf8wBwIBAAIC # EoAwCgIFAOx01dcCAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAK # MAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQsFAAOCAQEAQvtM+1rU # WTjEK4KZh+20bEAZ2UlYIM8Bb4GeNqEDnC/A2LkjzLyN1Hp6ra97Xv6COmnSjQnK # cUJlKk79UVas+RlPvHjkN0gBD0zvUtEMUyLXwNPHHT91+apJpU0RMMLqvx0I7GbL # xOdukfy+qzuM4CPJT3obt+anUabybRSe6xU3F5Y8dIi29R4N38foLvZG1uexTftD # 5I5C00y6cz0NqIO7DaC9DmlG4jApC45BN+k9r8hPG+ecePqHG8IduOmrj++GohRI # 2H7pH5T8pYmBwDjNMyf9iV1MUjdgKEL0qbnajHCeaXSUCaCNPIOEeq0Q2CE8uyTl # eo1JfVAFKu3t2DGCBA0wggQJAgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBD # QSAyMDEwAhMzAAAB91ggdQTK+8L0AAEAAAH3MA0GCWCGSAFlAwQCAQUAoIIBSjAa # BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIB5ZCVWg # yhA0lQ9pbV3iqkU0d3pZnfX7rkVren7vRwvcMIH6BgsqhkiG9w0BCRACLzGB6jCB # 5zCB5DCBvQQgIdqY2mt3GtHnGLobutLmBz/yCpz23nW1UCeUqCB+WeIwgZgwgYCk # fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAAAfdYIHUEyvvC9AAB # AAAB9zAiBCDZW3ktKVfl3ZIzwl6IfuixgeC9u7Ab7jtifuVLuLbO4jANBgkqhkiG # 9w0BAQsFAASCAgCsWSiTB7sUi3Ez69fGaebKKkBB1rv7hwvnahzlXhQNgDK/lgC1 # o7q5CbLeuULAKs0M8a3Jvjc/Grq8M+5aeT1vSnk+UwHI+7jmq3hEMD7Ceo67kCPg # HBa87zx0hgHPhZ0h4pb0y8yU8Gn+I0hvsg1penk+92ElAMV4ik8jvfJstY9sZhJh # PSMbiBxsvp+4MEMSlhEHs0IqBYPCgRI5rL2cy1HGv+I0INqNh91txmsEeH1lcnlb # hiT3lVqkWgToIzXiZJtSMRUIdIILbrEtWX6oF7y6dCUz6u6tLcipUGdHprcsbM2C # QBtakWDM67QMQyRIry6kkw81fW1/0RFGaWUogV+pSO9GMMPlTZKJcJGak/fuwBnH # opfDrBWMR1GrTxyOlhy2MIL3M7q4sBFa7UHUzRiADnCZi8LXuRQs67SbvB6WLmqL # +36IC21pdwkkcDFAhecaybkL7D+/OIplChZ2F3dMOml0uNSixYO5+ehQO7hbEUE5 # No0JHSDRkYZ4FuVZF5e7Zq8l9IZmke++O4NPfZviSjTNhS+TnB8U3+LqXA8n/j6R # /schmJjpvue80JNy0gf2KgH7BHf40Bukbsn3Ch4H+yMNnursVLgqaDEQBLP0jm2z # z8UrysAjnca+YNmCzVuMZLHEUiFUxkEJhbi+u89MEX/VuXgK04WN+rD6wA== # SIG # End signature block |