Private/Deploy-Accelerator-Helpers/Request-AcceleratorConfigurationInput.ps1
|
function Request-AcceleratorConfigurationInput { <# .SYNOPSIS Prompts the user for accelerator configuration input and creates the folder structure. .DESCRIPTION This function interactively prompts the user for the inputs needed to set up the accelerator folder structure, calls New-AcceleratorFolderStructure to create the folders and configuration files, and returns the paths needed for Deploy-Accelerator to continue. .PARAMETER Destroy When set, only prompts for the target folder path and validates the existing folder structure exists. .OUTPUTS Returns a hashtable with the following keys: - Continue: Boolean indicating whether to continue with deployment - InputConfigFilePaths: Array of input configuration file paths - StarterAdditionalFiles: Array of additional files/folders for the starter module - OutputFolderPath: Path to the output folder #> [CmdletBinding(SupportsShouldProcess = $true)] param( [Parameter(Mandatory = $false)] [switch] $Destroy, [Parameter(Mandatory = $false)] [switch] $ClearCache, [Parameter(Mandatory = $false)] [string] $OutputFolderName = "output" ) if ($PSCmdlet.ShouldProcess("Accelerator folder structure setup", "prompt and create")) { # Display appropriate header message if ($Destroy.IsPresent) { Write-ToConsoleLog "Running in destroy mode. Please provide the path to your existing accelerator folder." -IsWarning } else { Write-ToConsoleLog "No input configuration files provided. Let's set up the accelerator folder structure first..." -IsSuccess Write-ToConsoleLog "For more information, see: https://aka.ms/alz/acc/phase2" } # Prompt for target folder path (first prompt for both modes) $targetFolderPathInput = Read-MenuSelection ` -Title "Enter the target folder path for the accelerator files:" ` -DefaultValue "~/accelerator" ` -AllowManualEntry ` -ManualEntryPrompt "Target folder path" # Normalize the path $normalizedTargetPath = Get-NormalizedPath -Path $targetFolderPathInput # Analyze existing folder configuration $folderConfig = Get-AcceleratorFolderConfiguration -FolderPath $normalizedTargetPath $useExistingFolder = $false $forceFlag = $false # If folder exists, ask about overwriting before other prompts if ($folderConfig.FolderExists) { # Ask about overwriting the folder Write-ToConsoleLog "Target folder '$normalizedTargetPath' already exists." -IsWarning $forceResponse = Read-MenuSelection ` -Title "Do you want to overwrite the existing folder structure? This will replace existing configuration files." ` -DefaultValue "no" ` -Type "boolean" ` -AllowManualEntry ` -ManualEntryPrompt "Enter '[y]es' to overwrite or '[n]o' to keep existing" Write-Verbose "User overwrite response: $forceResponse" Write-Verbose $forceResponse.GetType().FullName if ($forceResponse) { $forceFlag = $true } else { # User wants to keep existing folder $useExistingFolder = $true # Validate config files exist if (-not $folderConfig.IsValid) { if (-not (Test-Path -Path $folderConfig.ConfigFolderPath)) { Write-ToConsoleLog "ERROR: Config folder not found at '$($folderConfig.ConfigFolderPath)'" -IsError } elseif (-not (Test-Path -Path $folderConfig.InputsYamlPath)) { Write-ToConsoleLog "ERROR: Required configuration file not found: inputs.yaml" -IsError } Write-ToConsoleLog "Please overwrite the folder structure by choosing 'y', or run New-AcceleratorFolderStructure manually." -IsWarning return ConvertTo-AcceleratorResult -Continue $false } } } # Handle destroy mode - validate existing folder and return early if ($Destroy.IsPresent) { if (-not $folderConfig.FolderExists) { Write-ToConsoleLog "ERROR: Target folder '$normalizedTargetPath' does not exist." -IsError Write-ToConsoleLog "Cannot destroy a deployment that doesn't exist. Please check the path and try again." -IsWarning return ConvertTo-AcceleratorResult -Continue $false } if (-not (Test-Path -Path $folderConfig.ConfigFolderPath)) { Write-ToConsoleLog "ERROR: Config folder not found at '$($folderConfig.ConfigFolderPath)'" -IsError Write-ToConsoleLog "Cannot destroy a deployment without configuration files." -IsWarning return ConvertTo-AcceleratorResult -Continue $false } if (-not (Test-Path -Path $folderConfig.InputsYamlPath)) { Write-ToConsoleLog "ERROR: Required configuration file not found: inputs.yaml" -IsError Write-ToConsoleLog "Cannot destroy a deployment without inputs.yaml." -IsWarning return ConvertTo-AcceleratorResult -Continue $false } # Build input config file paths based on detected IaC type $configPaths = Get-AcceleratorConfigPath -IacType $folderConfig.IacType -ConfigFolderPath $folderConfig.ConfigFolderPath $resolvedTargetPath = (Resolve-Path -Path $normalizedTargetPath).Path Write-ToConsoleLog "Using existing folder: $resolvedTargetPath" -IsSuccess # Prompt for sensitive inputs that are not already set (e.g., PATs) Write-ToConsoleLog "Checking for sensitive inputs that need to be provided..." -IsWarning Request-ALZConfigurationValue ` -ConfigFolderPath $folderConfig.ConfigFolderPath ` -IacType $folderConfig.IacType ` -VersionControl $folderConfig.VersionControl ` -AzureContextOutputDirectory $folderConfig.OutputFolderPath ` -AzureContextClearCache:$ClearCache.IsPresent ` -SensitiveOnly Write-ToConsoleLog "Proceeding with destroy..." -IsWarning return ConvertTo-AcceleratorResult -Continue $true ` -InputConfigFilePaths $configPaths.InputConfigFilePaths ` -StarterAdditionalFiles $configPaths.StarterAdditionalFiles ` -OutputFolderPath $folderConfig.OutputFolderPath } # Set selected values from detected values (for use existing folder case) $selectedIacType = $folderConfig.IacType $selectedVersionControl = $folderConfig.VersionControl $selectedScenarioNumber = 1 # Only prompt for IaC type, version control, and scenario if creating new folder or overwriting if (-not $useExistingFolder) { # Prompt for IaC type with detected value as default $iacTypeOptions = @("terraform", "bicep") $defaultIacTypeIndex = if ($null -ne $folderConfig.IacType) { [Math]::Max(0, $iacTypeOptions.IndexOf($folderConfig.IacType)) } else { 0 } $selectedIacType = Read-MenuSelection ` -Title "Select the Infrastructure as Code (IaC) type:" ` -Options $iacTypeOptions ` -DefaultIndex $defaultIacTypeIndex # Prompt for version control with detected value as default $versionControlOptions = @("github", "azure-devops", "local") $defaultVcsIndex = if ($null -ne $folderConfig.VersionControl) { [Math]::Max(0, $versionControlOptions.IndexOf($folderConfig.VersionControl)) } else { 0 } $selectedVersionControl = Read-MenuSelection ` -Title "Select the Version Control System:" ` -Options $versionControlOptions ` -DefaultIndex $defaultVcsIndex # Prompt for scenario number (Terraform only) if ($selectedIacType -eq "terraform") { $scenarioOptions = @( @{ label = "1 - Full Multi-Region - Hub and Spoke VNet"; value = 1 }, @{ label = "2 - Full Multi-Region - Virtual WAN"; value = 2 }, @{ label = "3 - Full Multi-Region NVA - Hub and Spoke VNet"; value = 3 }, @{ label = "4 - Full Multi-Region NVA - Virtual WAN"; value = 4 }, @{ label = "5 - Management Only"; value = 5 }, @{ label = "6 - Full Single-Region - Hub and Spoke VNet"; value = 6 }, @{ label = "7 - Full Single-Region - Virtual WAN"; value = 7 }, @{ label = "8 - Full Single-Region NVA - Hub and Spoke VNet"; value = 8 }, @{ label = "9 - Full Single-Region NVA - Virtual WAN"; value = 9 } ) $selectedScenarioNumber = Read-MenuSelection ` -Title "Select the Terraform scenario (see https://aka.ms/alz/acc/scenarios):" ` -Options $scenarioOptions ` -DefaultIndex 0 } } # Create folder structure if needed if (-not $folderConfig.FolderExists -or $forceFlag) { New-AcceleratorFolderStructure ` -iacType $selectedIacType ` -versionControl $selectedVersionControl ` -scenarioNumber $selectedScenarioNumber ` -targetFolderPath $targetFolderPathInput ` -outputFolderName $OutputFolderName ` -force:$forceFlag Write-ToConsoleLog "Folder structure created at: $normalizedTargetPath" -IsSuccess } # Resolve the path after folder creation or validation $resolvedTargetPath = (Resolve-Path -Path $normalizedTargetPath).Path $outputFolderPath = Join-Path $resolvedTargetPath $OutputFolderName $configFolderPath = if ($useExistingFolder) { $folderConfig.ConfigFolderPath } else { Join-Path $resolvedTargetPath "config" } if ($useExistingFolder) { Write-ToConsoleLog "Using existing folder structure at: $resolvedTargetPath" -IsSuccess } Write-ToConsoleLog "Config folder: $configFolderPath" # Offer to configure inputs interactively (default is Yes) $configureNowResponse = Read-MenuSelection ` -Title "Would you like to configure the input values interactively now?" ` -DefaultValue "yes" ` -Type "boolean" ` -AllowManualEntry ` -ManualEntryPrompt "Enter '[y]es' for interactive mode or '[n]o' to update the file manually later" if ($configureNowResponse) { Request-ALZConfigurationValue ` -ConfigFolderPath $configFolderPath ` -IacType $selectedIacType ` -VersionControl $selectedVersionControl ` -AzureContextOutputDirectory $outputFolderPath ` -AzureContextClearCache:$ClearCache.IsPresent } else { Write-ToConsoleLog "Checking for sensitive inputs that need to be provided..." -IsWarning Request-ALZConfigurationValue ` -ConfigFolderPath $configFolderPath ` -IacType $selectedIacType ` -VersionControl $selectedVersionControl ` -AzureContextOutputDirectory $outputFolderPath ` -AzureContextClearCache:$ClearCache.IsPresent ` -SensitiveOnly } # Check for VS Code or VS Code Insiders and offer to open the config folder $vsCodeCommand = $null $vsCodeName = $null if (Get-Command "code-insiders" -ErrorAction SilentlyContinue) { $vsCodeCommand = "code-insiders" $vsCodeName = "VS Code Insiders" } elseif (Get-Command "code" -ErrorAction SilentlyContinue) { $vsCodeCommand = "code" $vsCodeName = "VS Code" } if ($null -ne $vsCodeCommand) { $openInVsCodeResponse = Read-MenuSelection ` -Title "Would you like to open the config folder in $($vsCodeName)?" ` -DefaultValue "yes" ` -Type "boolean" ` -AllowManualEntry ` -ManualEntryPrompt "Enter '[y]es' to open or '[n]o' to continue without opening" if ($openInVsCodeResponse) { Write-ToConsoleLog "Opening config folder in $vsCodeName..." -IsSuccess & $vsCodeCommand $configFolderPath } } Write-ToConsoleLog "Please check and update the configuration files in the config folder before continuing:" -IsWarning Write-ToConsoleLog " - inputs.yaml: Bootstrap configuration (required)" -IsSelection if ($selectedIacType -eq "terraform") { Write-ToConsoleLog " - platform-landing-zone.tfvars: Platform configuration (required)" -IsSelection Write-ToConsoleLog " - starter_locations: Enter the regions for you platform landing zone (required)" -IsSelection Write-ToConsoleLog " - defender_email_security_contact: Enter the email security contact for Microsoft Defender for Cloud (required)" -IsSelection Write-ToConsoleLog " - lib/: Library customizations (optional)" -IsSelection } elseif ($selectedIacType -eq "bicep") { Write-ToConsoleLog " - platform-landing-zone.yaml: Platform configuration (required)" -IsSelection Write-ToConsoleLog " - starter_locations: Enter the regions for you platform landing zone (required)" -IsSelection } Write-ToConsoleLog "For more details, see: https://azure.github.io/Azure-Landing-Zones/accelerator/configuration-files/" # Prompt to continue or exit $continueResponse = Read-MenuSelection ` -Title "Have you checked and updated the configuration files? Ready to continue with deployment?" ` -DefaultValue "yes" ` -Type "boolean" ` -AllowManualEntry ` -ManualEntryPrompt "Enter '[y]es' to continue or '[n]o' to exit" if (!$continueResponse) { Write-ToConsoleLog "To continue later, run Deploy-Accelerator with the following parameters:" -IsSuccess if ($selectedIacType -eq "terraform") { Write-ToConsoleLog @" Deploy-Accelerator `` -inputs "$configFolderPath/inputs.yaml", "$configFolderPath/platform-landing-zone.tfvars" `` -starterAdditionalFiles "$configFolderPath/lib" `` -output "$outputFolderPath" "@ -Color Cyan } elseif ($selectedIacType -eq "bicep") { Write-ToConsoleLog @" Deploy-Accelerator `` -inputs "$configFolderPath/inputs.yaml", "$configFolderPath/platform-landing-zone.yaml" `` -output "$outputFolderPath" "@ -Color Cyan } else { Write-ToConsoleLog @" Deploy-Accelerator `` -inputs "$configFolderPath/inputs.yaml" `` -output "$outputFolderPath" "@ -Color Cyan } return ConvertTo-AcceleratorResult -Continue $false } # Build the result for continuing with deployment $configPaths = Get-AcceleratorConfigPath -IacType $selectedIacType -ConfigFolderPath $configFolderPath Write-ToConsoleLog "Continuing with deployment..." -IsSuccess return ConvertTo-AcceleratorResult -Continue $true ` -InputConfigFilePaths $configPaths.InputConfigFilePaths ` -StarterAdditionalFiles $configPaths.StarterAdditionalFiles ` -OutputFolderPath $outputFolderPath } } # SIG # Begin signature block # MIIoLwYJKoZIhvcNAQcCoIIoIDCCKBwCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDixdG7bkWO3fZC # at8o+MMj2ez904nB2KLBeJJUsaL206CCDXYwggX0MIID3KADAgECAhMzAAAEhV6Z # 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 # /Xmfwb1tbWrJUnMTDXpQzTGCGg8wghoLAgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAASFXpnsDlkvzdcAAAAABIUwDQYJYIZIAWUDBAIB # BQCggbAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEO # MAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIEQRPdaF/eWYooRZAYFdHhM5 # TD7zx51P1vR6+KmG3N8XMEQGCisGAQQBgjcCAQwxNjA0oBSAEgBNAGkAYwByAG8A # cwBvAGYAdKEcgBpodHRwczovL3d3dy5taWNyb3NvZnQuY29tIDANBgkqhkiG9w0B # AQEFAASCAQAuKv3e+5KIv6Ylm9+h7timzRcGw/T/IT0QEg2JeZG0kL1iCL4fjC70 # q43KXxFjrTSIo4eW3frUJBm+G0U9ElDH6c2fZAGqwPREX1fv0G5q7HXrZb6O+lwz # OS61YXzw9stWAHjdybRXwfOfEVXA5t5VybON1hvgIhyFRTxfG3+NdGI2eQmt+6nJ # UCtdYngUOiB9jpiB++viXixcy/GDId5lq2MwGD65q/AhN4eqSD/qlDoZ3ZlD/eGi # HaakxtLkkwsoLY8+tr+ylb2v7ZeXaaOlaMNar6S2D2+ox/85KQ140yk8OV7FVvE+ # vuKYpbwL/u/RNG/Id8eXKiMxP/z7qebroYIXlzCCF5MGCisGAQQBgjcDAwExgheD # MIIXfwYJKoZIhvcNAQcCoIIXcDCCF2wCAQMxDzANBglghkgBZQMEAgEFADCCAVIG # CyqGSIb3DQEJEAEEoIIBQQSCAT0wggE5AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZI # AWUDBAIBBQAEIC/6NoCqNFzZU8KVM19WcQ8YnnVe11LSeSBjnpPdihuMAgZpaRT4 # WyYYEzIwMjYwMTMwMjAwNjA5LjczMVowBIACAfSggdGkgc4wgcsxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBB # bWVyaWNhIE9wZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBMDAw # LTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj # ZaCCEe0wggcgMIIFCKADAgECAhMzAAACCHidWF2Sx9lSAAEAAAIIMA0GCSqGSIb3 # DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk # BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTI1MDEzMDE5 # NDI1M1oXDTI2MDQyMjE5NDI1M1owgcsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9wZXJhdGlv # bnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVTTjpBMDAwLTA1RTAtRDk0NzElMCMG # A1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCAiIwDQYJKoZIhvcN # AQEBBQADggIPADCCAgoCggIBALXLcAjmUjPcinWcrkExRRsZGyNKcLP9UazffO9j # Q16yGw+B+V3f9nf/d1LxYoEuUOWiyZck5mUVKI1dR3oNMnED2KT9lsJ1YnvwsqNs # 3e0WRfZzpFGlEykDyyr+gFtGvI/dzxD+DGkkAocfPxy5Kft7B8IvOc2bGqWJOTdD # kserPY+N5goP91sowFPZMABYC+6bjP8dcgnq0V0ag1XhZRFmzAJK3pE7BqpDWgBg # a8Sd0f4NdmrX5seyC9w80J1NIilahtCIlL9QouJHTYo0KoHgj3JqMVNKWcwgQzP8 # 2LnfygYjrimFy82lR7b6popYdnx3hPUqCG9GZJIXhgXkM0QlvFoJTCzLudQuawWd # No6NU6hMVZZ9Ze8G44qQFxApYYq+uSL3vqPjH7l7MA/fp+re7p0dElMtkC7h0S46 # ihTf6Qxmv5EFhaNMdAIpX7JnVJPR4aRsdegDaXLJEOU2MFByh5kjFYJm2z93f6d/ # WOJIs3p/rB0dpTPQAPA5ND9oSjUgLzl4V4+/IgprEUmQZTYyprpfOreoKrm2iQge # 2OGiCysSB8MpN4VdO12GXUg+0twJ8xxY4YYBeixVRTsb3jwXpb3rjbh/ZUcPwvcW # jIAj36vjPIhBSaqIRLO5BZ5alNOMVjAKaBdoY65INXxw05VAHog/M+d5mFVOPDFs # BmVpAgMBAAGjggFJMIIBRTAdBgNVHQ4EFgQUozHi986pxROBg5UH1/Xz+aF6AU0w # HwYDVR0jBBgwFoAUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXwYDVR0fBFgwVjBUoFKg # UIZOaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0 # JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3JsMGwGCCsGAQUFBwEBBGAw # XjBcBggrBgEFBQcwAoZQaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # ZXJ0cy9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcnQw # DAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAOBgNVHQ8BAf8E # BAMCB4AwDQYJKoZIhvcNAQELBQADggIBAFGzMokrAB+zCp1pA8WJpgH9k0BhYNrT # jRdNxCwJoK5rmewbUiyVhpKkfuaJMuvp5ASpdzNmip45r/G8OcwaJ8Y11rQIdtDC # 2mciGy62so7aOGMRobCUmA4yqXbWvsiTpecHNrR7eEE67hQGQyX8sRf4BRG3uLv5 # FM2wY3Rxc/A9JtMUT73PtZqAZtj2nBSj83GQYmx6oYJD/0rZUxTvhvDl7v7wgZSE # zbGykk+qdJ4c+FiZwHRZyU7FxUh+P9m5C/Cis9tMQRgNULNI3ftzTIKE8xjsUn4c # YUE0nHB3mUoivsZh+rxrSA6ILaWMZiVziu3hwJ53VcqDzd/SX1pRWKZYFhe1815u # Gl+votzeMPw2CysOHO3RaCch2dNkKLuPGOwgGKUf32ljn+HptBwsor8TooI/0TVg # 3vx8to5eRczI7rEuu9Bn64JKLWF1O58ULuhIH8JTlFt8hUdcbSPWjafW2d7h4Js1 # 8qpQ9MTfW01tYFHbdiLLSveRCYd5gTUYtsvinCSepqKnUFGfpYhQwm2CdxrAQ3fd # /wBgZnhrc2ceinMZVXqd598ZVqDhN27L6jLVgX6yEKGhd0yp+E9YWkd7e4kZPgYk # SI2zj7bxr/AdS4X5pFpHRw3k/teU7BTXfrSJQIm1B28pBo0DAYjb0o7BLdAauJH0 # XaM4Y9QCWl4TMIIHcTCCBVmgAwIBAgITMwAAABXF52ueAptJmQAAAAAAFTANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTAwHhcNMjEwOTMwMTgyMjI1WhcNMzAwOTMwMTgzMjI1WjB8MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQg # VGltZS1TdGFtcCBQQ0EgMjAxMDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC # ggIBAOThpkzntHIhC3miy9ckeb0O1YLT/e6cBwfSqWxOdcjKNVf2AX9sSuDivbk+ # F2Az/1xPx2b3lVNxWuJ+Slr+uDZnhUYjDLWNE893MsAQGOhgfWpSg0S3po5GawcU # 88V29YZQ3MFEyHFcUTE3oAo4bo3t1w/YJlN8OWECesSq/XJprx2rrPY2vjUmZNqY # O7oaezOtgFt+jBAcnVL+tuhiJdxqD89d9P6OU8/W7IVWTe/dvI2k45GPsjksUZzp # cGkNyjYtcI4xyDUoveO0hyTD4MmPfrVUj9z6BVWYbWg7mka97aSueik3rMvrg0Xn # Rm7KMtXAhjBcTyziYrLNueKNiOSWrAFKu75xqRdbZ2De+JKRHh09/SDPc31BmkZ1 # zcRfNN0Sidb9pSB9fvzZnkXftnIv231fgLrbqn427DZM9ituqBJR6L8FA6PRc6ZN # N3SUHDSCD/AQ8rdHGO2n6Jl8P0zbr17C89XYcz1DTsEzOUyOArxCaC4Q6oRRRuLR # vWoYWmEBc8pnol7XKHYC4jMYctenIPDC+hIK12NvDMk2ZItboKaDIV1fMHSRlJTY # uVD5C4lh8zYGNRiER9vcG9H9stQcxWv2XFJRXRLbJbqvUAV6bMURHXLvjflSxIUX # k8A8FdsaN8cIFRg/eKtFtvUeh17aj54WcmnGrnu3tz5q4i6tAgMBAAGjggHdMIIB # 2TASBgkrBgEEAYI3FQEEBQIDAQABMCMGCSsGAQQBgjcVAgQWBBQqp1L+ZMSavoKR # PEY1Kc8Q/y8E7jAdBgNVHQ4EFgQUn6cVXQBeYl2D9OXSZacbUzUZ6XIwXAYDVR0g # BFUwUzBRBgwrBgEEAYI3TIN9AQEwQTA/BggrBgEFBQcCARYzaHR0cDovL3d3dy5t # aWNyb3NvZnQuY29tL3BraW9wcy9Eb2NzL1JlcG9zaXRvcnkuaHRtMBMGA1UdJQQM # MAoGCCsGAQUFBwMIMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQE # AwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNX2VsuP6KJcYmjRPZSQ # W9fOmhjEMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwubWljcm9zb2Z0LmNv # bS9wa2kvY3JsL3Byb2R1Y3RzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNybDBa # BggrBgEFBQcBAQROMEwwSgYIKwYBBQUHMAKGPmh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3J0MA0GCSqG # SIb3DQEBCwUAA4ICAQCdVX38Kq3hLB9nATEkW+Geckv8qW/qXBS2Pk5HZHixBpOX # PTEztTnXwnE2P9pkbHzQdTltuw8x5MKP+2zRoZQYIu7pZmc6U03dmLq2HnjYNi6c # qYJWAAOwBb6J6Gngugnue99qb74py27YP0h1AdkY3m2CDPVtI1TkeFN1JFe53Z/z # jj3G82jfZfakVqr3lbYoVSfQJL1AoL8ZthISEV09J+BAljis9/kpicO8F7BUhUKz # /AyeixmJ5/ALaoHCgRlCGVJ1ijbCHcNhcy4sa3tuPywJeBTpkbKpW99Jo3QMvOyR # gNI95ko+ZjtPu4b6MhrZlvSP9pEB9s7GdP32THJvEKt1MMU0sHrYUP4KWN1APMdU # bZ1jdEgssU5HLcEUBHG/ZPkkvnNtyo4JvbMBV0lUZNlz138eW0QBjloZkWsNn6Qo # 3GcZKCS6OEuabvshVGtqRRFHqfG3rsjoiV5PndLQTHa1V1QJsWkBRH58oWFsc/4K # u+xBZj1p/cvBQUl+fpO+y/g75LcVv7TOPqUxUYS8vwLBgqJ7Fx0ViY1w/ue10Cga # iQuPNtq6TPmb/wrpNPgkNWcr4A245oyZ1uEi6vAnQj0llOZ0dFtq0Z4+7X6gMTN9 # vMvpe784cETRkPHIqzqKOghif9lwY1NNje6CbaUFEMFxBmoQtB1VM1izoXBm8qGC # A1AwggI4AgEBMIH5oYHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25z # MScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046QTAwMC0wNUUwLUQ5NDcxJTAjBgNV # BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMV # AI2S+7Q0pxKN1grKuEllyzJc5RM0oIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgUENBIDIwMTAwDQYJKoZIhvcNAQELBQACBQDtJ1gPMCIYDzIwMjYwMTMwMTYx # NzE5WhgPMjAyNjAxMzExNjE3MTlaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAO0n # WA8CAQAwCgIBAAICE18CAf8wBwIBAAICEz4wCgIFAO0oqY8CAQAwNgYKKwYBBAGE # WQoEAjEoMCYwDAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDAN # BgkqhkiG9w0BAQsFAAOCAQEAuprll6Fu9W1p31D624laoGkJAD3RCygnSJXTv6TZ # DIg9TNq1s2/P7gUBJFGVsiwKghOCHdavRAByAjbve1YGkOaV76idY89VtWYWlEmS # t6bYoI0Ww+Oh1/YRe2M2LNR2nhevxhyyP2XvFrNO4yWVCgara6l3ItF2o2LpYQNf # 8CBWBQf68WyGJi/vOAxycf8RDXtMFxaxtUD+RDPgHaVq3BfVIknm71kGF/CZF9CK # w55P0c9QySq0ifJPwJ3h2RCeXD3GuzyYGErIYNx4uNhNiG2V3VbKbtyPwkTzgW0K # nYE26Qy+XkOhk/jJewnZB7MonsUj259cpooZzdzwOkdoyjGCBA0wggQJAgEBMIGT # MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS # ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMT # HU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACCHidWF2Sx9lSAAEA # AAIIMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQ # AQQwLwYJKoZIhvcNAQkEMSIEIBFNc7Ya/WZz+henqd1pe1uwaHGkdVRdt9Qh3lfp # HkYxMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgj/+ObwkdrZbU73vvy334 # W3Znk2Yqq20+TpD71FGmZ6kwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0EgMjAxMAITMwAAAgh4nVhdksfZUgABAAACCDAiBCBatbdbk/9Pzw/y63IMo6Gx # 2p0kR8/hWMZVNgSCbyWD9zANBgkqhkiG9w0BAQsFAASCAgAttijHwSd9PE8DzSCx # mu0DgerK/za2DrUHLlNBs+rWPBLcyZRj2mygFozJwxzcl5Pr3/7sEYZRkADiPNUK # 1SpVq0/dSLJ5DdHvgFkQPiawYQqsUj+yn+mICWxwfnnJ60fJnD6ZrzR4Itvzbnwf # +hKprpQsdN7FsjBQ9OWX8tZymvFHd+qwDo8YMqAsRFdHzvyvp7LoQbnAWJAyqw8P # 1g2k9Iyjj7/RTduwLhF07sVgBfnbtRpUbb7cAa7PAEnj1CQ8YAAD6Dm9z95L0JTl # OkOYM/KPI+LenPPGwQ+GfN5djmFqe+ke6/PQsDiLoUhc7gWIBzckB/Dozz1GAYve # 8IOHbF3T/ODFmIGnm8AcSA5QyGNt2bPXPTjks9BYlfDcCKWQuKlFWMx+ICmXkPHH # sGTucQlFaFzIOXOfFw7Cpfa+/3abGvRNPQHMCeEcndlvbJ5wz1usb+mhTf47nXBi # SDcoP3EE1hZ/EuZ4F41mf9639eazrZC3yXtvdAZKseSVUHBVWH4jSJEzB9AQrzqJ # pB6KqkKBpiVKQO0nLgnId9dXlRMVPGPIEx4Z8tIb2kaU3MjEqcTaMs0/Wr6yqiGy # Kq1FgL8Z27JkbUEQmHNZ26J4s/B/PH2kvvQJOLLdj2suC/Q9/YAJoSoQutKds5gt # gxwWKYFvBpKgMfu574+rB9CY1A== # SIG # End signature block |