AzureAppGWIPMigrate.ps1
|
<#PSScriptInfo .VERSION 1.0.0 .GUID 17258599-db9d-4035-b2dd-ae2a37654d9a .AUTHOR Microsoft Corporation .COMPANYNAME Microsoft Corporation .COPYRIGHT Microsoft Corporation. All rights reserved. .TAGS Azure, Az, ApplicationGateway, AzNetworking .RELEASENOTES 1.0.0 -- Attach the public IP of a V1 Application Gateway to V2 Application Gateway #> <# .SYNOPSIS Application Gateway v1 -> v2 IP Migration .DESCRIPTION This script will help you attach IP of a V1 SKU Application Gateway to a V2 SKU Application Gateway .PARAMETER V1ResourceId Application Gateway ResourceId, like "/subscriptions/<your-subscriptionId>/resourceGroups/<v1-app-gw-rgname>/providers/Microsoft.Network/applicationGateways/<v1-app-gw-name>" .PARAMETER V2ResourceId Application Gateway ResourceId, like "/subscriptions/<your-subscriptionId>/resourceGroups/<v2-app-gw-rgname>/providers/Microsoft.Network/applicationGateways/<v2-app-gw-name>" .EXAMPLE .\ipmigrate.ps1 -V1ResourceId "/subscriptions/<your-sub-id>/resourceGroups/<your-rg>/providers/Microsoft.Network/applicationGateways/<v1AppGatewayName>" -V2ResourceId "/subscriptions/<your-sub-id>/resourceGroups/<your-rg>/providers/Microsoft.Network/applicationGateways/<v2AppGatewayName>" .INPUTS String .OUTPUTS PSApplicationGateway .LINK https://aka.ms/appgwipmigratedoc https://docs.microsoft.com/en-us/azure/application-gateway/ #> #Requires -Module Az.Accounts #Requires -Module Az.Network #Requires -Module Az.Compute #Requires -Module Az.Resources Param( [Parameter(Mandatory = $True)][string] $V1ResourceId, [Parameter(Mandatory = $True)][string] $V2ResourceId ) if (!(Get-Module -ListAvailable -Name Az.Network)) { Write-Error ("You need 'Az' module to proceed. Az is a new cross-platform PowerShell module that will replace AzureRM. You can install this module by running 'Install-Module Az' in an elevated PowerShell prompt.") Write-Warning ("If you see error 'AzureRM.Profile already loaded. Az and AzureRM modules cannot be imported in the same session', You would need to close the current session and start new one.") exit } Function Private:ScriptVersionCheck() { $InstalledScriptVersion = (Get-InstalledScript -Name 'AzureAppGWIPMigrate' -ErrorAction SilentlyContinue).Version $LatestScriptVersion = (Find-Script -Name 'AzureAppGWIPMigrate' -ErrorAction SilentlyContinue).Version if(!$InstalledScriptVersion) { Write-Warning("You have manually downloaded the IP migration script. The stable version of this script is $LatestScriptVersion, which contains critical fixes and bugs that may not be present in the version you have installed. It is recommended to use the stable version. You can find more information about the currently installed version and how to download the stable version at https://aka.ms/ipmigratescriptdownload") $confirmation = Read-Host "Are you sure you want to proceed? Press 'y' to continue, any other key for exiting" if ($confirmation -ne 'y') { exit; } } else { if($InstalledScriptVersion -ne $LatestScriptVersion) { Write-Warning("You have installed the IP migration script version : $InstalledScriptVersion. It is recommended to use the stable version of the script : $LatestScriptVersion. This version contains critical bug fixes that may not be present in the version you are currently using. You can install the stable version by running 'UnInstall-Script -Name 'AzureAppGWIPMigrate -Force; Install-Script -Name 'AzureAppGWIPMigrate' -RequiredVersion $LatestScriptVersion -Force'") $confirmation = Read-Host "Are you sure you want to proceed? Press 'y' to continue, any other key for exiting" if ($confirmation -ne 'y') { exit; } } } } ScriptVersionCheck # Validations for V1 AppGw $matchResponse = $V1ResourceId -match "/subscriptions/(.*?)/resourceGroups/" if(!$matchResponse) { Write-Warning("Invalid V1ResourceId format $V1ResourceId.") exit } # Validating set-context succeess $subscription1 = $matches[1] $context = Set-AzContext -Subscription $subscription1 -ErrorVariable contextFailure if ($contextFailure) { Write-Warning("Unable to set subscription $subscription1 in context. Please retry again") exit } $V1Resource = Get-AzResource -ResourceId $V1ResourceId -ErrorVariable getResourceFailure -ErrorAction SilentlyContinue # Validating Get-Resource if($getResourceFailure -or !$V1Resource) { Write-Warning("Unable to get resource for $V1ResourceId. Please retry again") exit } $V1ResourceGroup = $V1Resource.ResourceGroupName $V1AppGwName = $V1Resource.Name $V1AppGw = Get-AzApplicationGateway -Name $V1AppGwName -ResourceGroupName $V1ResourceGroup -ErrorVariable getAppGwResourceFailure -ErrorAction SilentlyContinue # Validating Get-AppGwResource Failure if($getAppGwResourceFailure -or !$V1AppGw) { Write-Warning("Unable to get application gateway resource for $V1ResourceId. Please retry again") exit } # Validations for V2 AppGw $matchResponse = $V2ResourceId -match "/subscriptions/(.*?)/resourceGroups/" if(!$matchResponse) { Write-Warning("Invalid V2ResourceId format $V2ResourceId.") exit } # Validating set-context succeess $subscription2 = $matches[1] if ($subscription1 -NE $subscription2) { Write-Warning("V1 AppGw subscription $subscription1 and V2 AppGw subscription $subscription2 is different. AppGw must be in same subscription") exit } $V2Resource = Get-AzResource -ResourceId $V2ResourceId -ErrorVariable getResourceFailure -ErrorAction SilentlyContinue # Validating Get-Resource if($getResourceFailure -or !$V2Resource) { Write-Warning("Unable to get resource for $V2ResourceId. Please retry again") exit } $V2ResourceGroup = $V2Resource.ResourceGroupName $V2AppGwName = $V2Resource.Name $V2AppGw = Get-AzApplicationGateway -Name $V2AppGwName -ResourceGroupName $V2ResourceGroup -ErrorVariable getAppGwResourceFailure -ErrorAction SilentlyContinue # Validating Get-AppGwResource Failure if($getAppGwResourceFailure -or !$V2AppGw) { Write-Warning("Unable to get application gateway resource for $V2ResourceId. Please retry again") exit } $V1fp = (Get-AzApplicationGatewayFrontendIPConfig -ApplicationGateway $V1AppGw | Where-Object { $_.PublicIPAddress -NE $null }) if ($V1fp) { if ($V1fp.count -NE 1) { Write-Error ("Multiple Public FrontendIP are not supported for AppGw.") exit } $V1PipResourceId = $V1fp.PublicIPAddress.Id } else { Write-Error ("V1 AppGw does not have a frontend IP") exit } $V2fp = (Get-AzApplicationGatewayFrontendIPConfig -ApplicationGateway $V2AppGw | Where-Object { $_.PublicIPAddress -NE $null }) if ($V2fp) { if ($V2fp.count -NE 1) { Write-Error ("Multiple Public FrontendIP are not supported for AppGw.") exit } $V2PipResourceId = $V2fp.PublicIPAddress.Id } else { Write-Error ("V2 AppGw does not have a frontend IP") exit } Write-Host("Attaching $V1PipResourceId to $V2AppGwName") $migrationCompleted = $false $sw = [Diagnostics.Stopwatch]::StartNew() # Migrate IP REST API call $path = $V1ResourceId + "/v1tov2Migration?api-version=2023-02-01" $payload = @{V2GatewayResourceId=$V2ResourceId} | ConvertTo-Json $response = Invoke-AzRestMethod -Method POST -Path $path -Payload $payload $sc = $response.StatusCode $data = ($response.Content | ConvertFrom-Json) if ($sc -ne 202) { $ErrorCode = $data.error.code $ErrorMessage = $data.error.message Write-Host "Encountered error while triggering migration" -ForegroundColor Red Write-Host "Error Code: $ErrorCode" -ForegroundColor Red Write-Host "Error Message: $ErrorMessage" -ForegroundColor Red exit } $StatusPathAndQuery = $response.Headers.Location.PathAndQuery # polling for the status of the migration for 10 mins $pollIntervalSeconds = 30 $maxAttempts = 20 Write-Host "Starting poll to check status of Application Gateway IP Migration Operation" $attempt = 0 do { $attempt++ Write-Host "Poll attempt $attempt of $maxAttempts..." $pollResponse = Invoke-AzRestMethod -Path $StatusPathAndQuery $sc = $pollResponse.StatusCode if ($sc -eq 200) { Write-Host "Application Gateway IP Migration completed successfully!" $sw.Stop() $migrationCompleted = $true break } elseif ($sc -eq 201 -or $sc -eq 202) { Write-Host "Application Gateway IP Migration Operation is in progress." # Wait for the specified interval before the next poll if ($attempt -lt $maxAttempts) { Write-Host "Waiting for $pollIntervalSeconds seconds before next poll..." Start-Sleep -Seconds $pollIntervalSeconds } } else { Write-Host "Encountered error while polling migration status. Please contact Azure Customer Support." -ForegroundColor Red break } } while ($attempt -lt $maxAttempts) if ($attempt -ge $maxAttempts) { Write-Host "Maximum polling attempts reached. The Application Gateway may still be updating. Please contact Azure Customer Support" -ForegroundColor Red } if ($migrationCompleted -eq $true) { Write-Host "IP Migration Complete. TimeTaken : $($sw.Elapsed.TotalSeconds) seconds" -ForegroundColor Green } # SIG # Begin signature block # MIIr4wYJKoZIhvcNAQcCoIIr1DCCK9ACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD7kQDZu9QDXYkL # voFLTnPGJsn9NaCfY5hpRyI5qDLiaaCCEW4wggh+MIIHZqADAgECAhM2AAACAO38 # jbec3qFIAAIAAAIAMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH # QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe # Fw0yNDExMDgxMjQzMjhaFw0yNTExMDgxMjQzMjhaMCQxIjAgBgNVBAMTGU1pY3Jv # c29mdCBBenVyZSBDb2RlIFNpZ24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK # AoIBAQC5L/UPrOpwYjxcoZC0TqqvMF1WUELvwXN+k27SrA5rohJknn7Cgbxg4hGT # XKqpcdbtsVTN3ZY896SJ20uQ+INL5OVLzpW408nCNTPYg2LtGJbqHUjpNm0hLCJ+ # gO5Jn2T8DDzIJoUijGXj1m+hRLKb2nOIicCED2GuYBmuWXnaY7INmVEaU3peryty # ZjDuxdyGDuiPURz8lW1SUiDzoszNp1oswVr+WjDvLDUx4HlxPsG8zUjIst0NnJ6o # z4tNFKaUBDCetcMjQxpCETn29a1CuRddxZLjPHZHfcotr5sh1S6bNQdzVaMNsxV8 # L3wjHb7XJ6ZVm662mHEiPgpyNcLhAgMBAAGjggWKMIIFhjApBgkrBgEEAYI3FQoE # HDAaMAwGCisGAQQBgjdbAQEwCgYIKwYBBQUHAwMwPQYJKwYBBAGCNxUHBDAwLgYm # KwYBBAGCNxUIhpDjDYTVtHiE8Ys+hZvdFs6dEoFgg93NZoaUjDICAWQCAQ4wggJ2 # BggrBgEFBQcBAQSCAmgwggJkMGIGCCsGAQUFBzAChlZodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpaW5mcmEvQ2VydHMvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F # JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDEu # YW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUy # MDAxKDIpLmNydDBSBggrBgEFBQcwAoZGaHR0cDovL2NybDIuYW1lLmdibC9haWEv # QlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBS # BggrBgEFBQcwAoZGaHR0cDovL2NybDMuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAx # LkFNRS5HQkxfQU1FJTIwQ1MlMjBDQSUyMDAxKDIpLmNydDBSBggrBgEFBQcwAoZG # aHR0cDovL2NybDQuYW1lLmdibC9haWEvQlkyUEtJQ1NDQTAxLkFNRS5HQkxfQU1F # JTIwQ1MlMjBDQSUyMDAxKDIpLmNydDCBrQYIKwYBBQUHMAKGgaBsZGFwOi8vL0NO # PUFNRSUyMENTJTIwQ0ElMjAwMSxDTj1BSUEsQ049UHVibGljJTIwS2V5JTIwU2Vy # dmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJhdGlvbixEQz1BTUUsREM9R0JM # P2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0aW9uQXV0 # aG9yaXR5MB0GA1UdDgQWBBST/HE52ZUlmsYqZcZBdrXZ5u4ZnzAOBgNVHQ8BAf8E # BAMCB4AwRQYDVR0RBD4wPKQ6MDgxHjAcBgNVBAsTFU1pY3Jvc29mdCBDb3Jwb3Jh # dGlvbjEWMBQGA1UEBRMNMjM2MTY3KzUwMzE1NTCCAeYGA1UdHwSCAd0wggHZMIIB # 1aCCAdGgggHNhj9odHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpaW5mcmEvQ1JM # L0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwxLmFtZS5nYmwv # Y3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwyLmFtZS5n # YmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmwzLmFt # ZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGMWh0dHA6Ly9jcmw0 # LmFtZS5nYmwvY3JsL0FNRSUyMENTJTIwQ0ElMjAwMSgyKS5jcmyGgb1sZGFwOi8v # L0NOPUFNRSUyMENTJTIwQ0ElMjAwMSgyKSxDTj1CWTJQS0lDU0NBMDEsQ049Q0RQ # LENOPVB1YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZp # Z3VyYXRpb24sREM9QU1FLERDPUdCTD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0 # P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwHwYDVR0jBBgw # FoAUllGE4Gtve/7YBqvD8oXmKa5q+dQwHwYDVR0lBBgwFgYKKwYBBAGCN1sBAQYI # KwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAEDd8Wf5RkHsB64vgn2slxDtHzSo # It9xN/Dm3RdFjNZ0diTUPMgSPYQlSk8nIAfudnB9FLavGlvZLlyUpfrPSuikepj3 # i3pqNEFn6fNdNFv/wHMxv7hQTIDCmuoR1v1rX+w3oeleBPMnN3QmH4ff1NsynyV4 # dZdYgN9Cw9sC/S3pWZpJrbOs7YOM3vqyU6DciHhC4D9i2zByHCF2pu9nYfiQf5A2 # iUZenRvyo1E5rC+UP2VZXa4k7g66W20+zAajIKKIqEmRtWahekMkCcOIHFBY4RDA # ybgPRSGur4VDAiZPjTXS90wQXrX9CwU20cfiCC6e76F4H95KtQjKYpzuNVAwggjo # MIIG0KADAgECAhMfAAAAUeqP9pxzDKg7AAAAAABRMA0GCSqGSIb3DQEBCwUAMDwx # EzARBgoJkiaJk/IsZAEZFgNHQkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxEDAOBgNV # BAMTB2FtZXJvb3QwHhcNMjEwNTIxMTg0NDE0WhcNMjYwNTIxMTg1NDE0WjBBMRMw # EQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQD # EwxBTUUgQ1MgQ0EgMDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDJ # mlIJfQGejVbXKpcyFPoFSUllalrinfEV6JMc7i+bZDoL9rNHnHDGfJgeuRIYO1LY # /1f4oMTrhXbSaYRCS5vGc8145WcTZG908bGDCWr4GFLc411WxA+Pv2rteAcz0eHM # H36qTQ8L0o3XOb2n+x7KJFLokXV1s6pF/WlSXsUBXGaCIIWBXyEchv+sM9eKDsUO # LdLTITHYJQNWkiryMSEbxqdQUTVZjEz6eLRLkofDAo8pXirIYOgM770CYOiZrcKH # K7lYOVblx22pdNawY8Te6a2dfoCaWV1QUuazg5VHiC4p/6fksgEILptOKhx9c+ia # piNhMrHsAYx9pUtppeaFAgMBAAGjggTcMIIE2DASBgkrBgEEAYI3FQEEBQIDAgAC # MCMGCSsGAQQBgjcVAgQWBBQSaCRCIUfL1Gu+Mc8gpMALI38/RzAdBgNVHQ4EFgQU # llGE4Gtve/7YBqvD8oXmKa5q+dQwggEEBgNVHSUEgfwwgfkGBysGAQUCAwUGCCsG # AQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNxQCAQYJKwYBBAGCNxUGBgorBgEEAYI3 # CgMMBgkrBgEEAYI3FQYGCCsGAQUFBwMJBggrBgEFBQgCAgYKKwYBBAGCN0ABAQYL # KwYBBAGCNwoDBAEGCisGAQQBgjcKAwQGCSsGAQQBgjcVBQYKKwYBBAGCNxQCAgYK # KwYBBAGCNxQCAwYIKwYBBQUHAwMGCisGAQQBgjdbAQEGCisGAQQBgjdbAgEGCisG # AQQBgjdbAwEGCisGAQQBgjdbBQEGCisGAQQBgjdbBAEGCisGAQQBgjdbBAIwGQYJ # KwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMBIGA1UdEwEB/wQI # MAYBAf8CAQAwHwYDVR0jBBgwFoAUKV5RXmSuNLnrrJwNp4x1AdEJCygwggFoBgNV # HR8EggFfMIIBWzCCAVegggFToIIBT4YxaHR0cDovL2NybC5taWNyb3NvZnQuY29t # L3BraWluZnJhL2NybC9hbWVyb290LmNybIYjaHR0cDovL2NybDIuYW1lLmdibC9j # cmwvYW1lcm9vdC5jcmyGI2h0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL2FtZXJvb3Qu # Y3JshiNodHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9hbWVyb290LmNybIaBqmxkYXA6 # Ly8vQ049YW1lcm9vdCxDTj1BTUVSb290LENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl # MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPUFNRSxE # Qz1HQkw/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdD9iYXNlP29iamVjdENsYXNz # PWNSTERpc3RyaWJ1dGlvblBvaW50MIIBqwYIKwYBBQUHAQEEggGdMIIBmTBHBggr # BgEFBQcwAoY7aHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJhL2NlcnRz # L0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6Ly9jcmwyLmFt # ZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUHMAKGK2h0dHA6 # Ly9jcmwzLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQwNwYIKwYBBQUH # MAKGK2h0dHA6Ly9jcmwxLmFtZS5nYmwvYWlhL0FNRVJvb3RfYW1lcm9vdC5jcnQw # gaIGCCsGAQUFBzAChoGVbGRhcDovLy9DTj1hbWVyb290LENOPUFJQSxDTj1QdWJs # aWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9u # LERDPUFNRSxEQz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNl # cnRpZmljYXRpb25BdXRob3JpdHkwDQYJKoZIhvcNAQELBQADggIBAFAQI7dPD+jf # XtGt3vJp2pyzA/HUu8hjKaRpM3opya5G3ocprRd7vdTHb8BDfRN+AD0YEmeDB5HK # QoG6xHPI5TXuIi5sm/LeADbV3C2q0HQOygS/VT+m1W7a/752hMIn+L4ZuyxVeSBp # fwf7oQ4YSZPh6+ngZvBHgfBaVz4O9/wcfw91QDZnTgK9zAh9yRKKls2bziPEnxeO # ZMVNaxyV0v152PY2xjqIafIkUjK6vY9LtVFjJXenVUAmn3WCPWNFC1YTIIHw/mD2 # cTfPy7QA1pT+GPARAKt0bKtq9aCd/Ym0b5tPbpgCiRtzyb7fbNS1dE740re0COE6 # 7YV2wbeo2sXixzvLftH8L7s9xv9wV+G22qyKt6lmKLjFK1yMw4Ni5fMabcgmzRvS # jAcbqgp3tk4a8emaaH0rz8MuuIP+yrxtREPXSqL/C5bzMzsikuDW9xH10graZzSm # PjilzpRfRdu20/9UQmC7eVPZ4j1WNa1oqPHfzET3ChIzJ6Q9G3NPCB+7KwX0OQmK # yv7IDimj8U/GlsHD1z+EF/fYMf8YXG15LamaOAohsw/ywO6SYSreVW+5Y0mzJutn # BC9Cm9ozj1+/4kqksrlhZgR/CSxhFH3BTweH8gP2FEISRtShDZbuYymynY1un+Ry # fiK9+iVTLdD1h/SxyxDpZMtimb4CgJQlMYIZyzCCGccCAQEwWDBBMRMwEQYKCZIm # iZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRUwEwYDVQQDEwxBTUUg # Q1MgQ0EgMDECEzYAAAIA7fyNt5zeoUgAAgAAAgAwDQYJYIZIAWUDBAIBBQCgga4w # GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG # AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIFV1nFla0rOPbOaV3WWqEhNtuyIAGbxA # gRQuMLovBFLkMEIGCisGAQQBgjcCAQwxNDAyoBSAEgBNAGkAYwByAG8AcwBvAGYA # dKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20wDQYJKoZIhvcNAQEBBQAEggEA # XNLAPPFlnYtXCeUFDzmXzDk5nDpafqwRe1xx7MqmBeBfHprwxqm2RGo5tiAEQcE+ # 7vL4USMo6Kv618uGnVIbLLIqinq8RFhkRXBEZo7gLC4mSB8PpC6vifuqdwWvXE0/ # kETfrPujH8DdP1K8yavZQ4a56BpOpqV98/LNLU2+dh+CEHSp7Q3Cpxfd4KDuBY9B # OPJ3IzOpeY6f1CNhTpndTuxWUAYxyf8OQSD0I3jEHqh2XcM1maH9XM/J+WyM/bAO # C4dVuXGliR+WT/NTu/M7BnIeg29vlypDerNnac3VtMjoTY4fy0ObMh7PUx9Z39bQ # bytSMBnbg735CqxWpMetYqGCF5MwghePBgorBgEEAYI3AwMBMYIXfzCCF3sGCSqG # SIb3DQEHAqCCF2wwghdoAgEDMQ8wDQYJYIZIAWUDBAIBBQAwggFSBgsqhkiG9w0B # CRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGEWQoDATAxMA0GCWCGSAFlAwQCAQUA # BCB/iDTZHKnWErGdoqXa7pwNkzaeMKYnWIXFKHOYa7CFEAIGaPAnmLX2GBMyMDI1 # MTAxNjA2MjU1Mi4wMjNaMASAAgH0oIHRpIHOMIHLMQswCQYDVQQGEwJVUzETMBEG # A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj # cm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBP # cGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046REMwMC0wNUUwLUQ5 # NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2WgghHpMIIH # IDCCBQigAwIBAgITMwAAAgO7HlwAOGx0ygABAAACAzANBgkqhkiG9w0BAQsFADB8 # MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk # bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N # aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDAeFw0yNTAxMzAxOTQyNDZaFw0y # NjA0MjIxOTQyNDZaMIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYD # VQQLEx5uU2hpZWxkIFRTUyBFU046REMwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1p # Y3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3DQEBAQUAA4IC # DwAwggIKAoICAQChl0MH5wAnOx8Uh8RtidF0J0yaFDHJYHTpPvRR16X1KxGDYfT8 # PrcGjCLCiaOu3K1DmUIU4Rc5olndjappNuOgzwUoj43VbbJx5PFTY/a1Z80tpqVP # 0OoKJlUkfDPSBLFgXWj6VgayRCINtLsUasy0w5gysD7ILPZuiQjace5KxASjKf2M # VX1qfEzYBbTGNEijSQCKwwyc0eavr4Fo3X/+sCuuAtkTWissU64k8rK60jsGRApi # ESdfuHr0yWAmc7jTOPNeGAx6KCL2ktpnGegLDd1IlE6Bu6BSwAIFHr7zOwIlFqyQ # uCe0SQALCbJhsT9y9iy61RJAXsU0u0TC5YYmTSbEI7g10dYx8Uj+vh9InLoKYC5D # pKb311bYVd0bytbzlfTRslRTJgotnfCAIGMLqEqk9/2VRGu9klJi1j9nVfqyYHYr # MPOBXcrQYW0jmKNjOL47CaEArNzhDBia1wXdJANKqMvJ8pQe2m8/cibyDM+1BVZq # uNAov9N4tJF4ACtjX0jjXNDUMtSZoVFQH+FkWdfPWx1uBIkc97R+xRLuPjUypHZ5 # A3AALSke4TaRBvbvTBYyW2HenOT7nYLKTO4jw5Qq6cw3Z9zTKSPQ6D5lyiYpes5R # R2MdMvJS4fCcPJFeaVOvuWFSQ/EGtVBShhmLB+5ewzFzdpf1UuJmuOQTTwIDAQAB # o4IBSTCCAUUwHQYDVR0OBBYEFLIpWUB+EeeQ29sWe0VdzxWQGJJ9MB8GA1UdIwQY # MBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6 # Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY3JsL01pY3Jvc29mdCUyMFRpbWUt # U3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYIKwYB # BQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj # cm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB # /wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/BAQDAgeAMA0G # CSqGSIb3DQEBCwUAA4ICAQCQEMbesD6TC08R0oYCdSC452AQrGf/O89GQ54CtgEs # bxzwGDVUcmjXFcnaJSTNedBKVXkBgawRonP1LgxH4bzzVj2eWNmzGIwO1FlhldAP # OHAzLBEHRoSZ4pddFtaQxoabU/N1vWyICiN60It85gnF5JD4MMXyd6pS8eADIi6T # tjfgKPoumWa0BFQ/aEzjUrfPN1r7crK+qkmLztw/ENS7zemfyx4kGRgwY1WBfFqm # /nFlJDPQBicqeU3dOp9hj7WqD0Rc+/4VZ6wQjesIyCkv5uhUNy2LhNDi2leYtAiI # FpmjfNk4GngLvC2Tj9IrOMv20Srym5J/Fh7yWAiPeGs3yA3QapjZTtfr7NfzpBIJ # Q4xT/ic4WGWqhGlRlVBI5u6Ojw3ZxSZCLg3vRC4KYypkh8FdIWoKirjidEGlXsNO # o+UP/YG5KhebiudTBxGecfJCuuUspIdRhStHAQsjv/dAqWBLlhorq2OCaP+wFhE3 # WPgnnx5pflvlujocPgsN24++ddHrl3O1FFabW8m0UkDHSKCh8QTwTkYOwu99iExB # VWlbYZRz2qOIBjL/ozEhtCB0auKhfTLLeuNGBUaBz+oZZ+X9UAECoMhkETjb6YfN # aI1T7vVAaiuhBoV/JCOQT+RYZrgykyPpzpmwMNFBD1vdW/29q9nkTWoEhcEOO0L9 # NzCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQEL # BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH # EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNV # BAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDEwMB4X # DTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIyNVowfDELMAkGA1UEBhMCVVMxEzAR # BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p # Y3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3Rh # bXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk4aZM # 57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX9gF/bErg4r25PhdgM/9cT8dm # 95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzB # RMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2Nr41JmTamDu6GnszrYBb # fowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCO # Mcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL64NF50ZuyjLVwIYw # XE8s4mKyzbnijYjklqwBSru+cakXW2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW # /aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOmTTd0lBw0gg/w # EPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlMjgK8QmguEOqEUUbi0b1qGFphAXPK # Z6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ+QuJYfM2 # BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AFemzFER1y7435UsSFF5PAPBXbGjfH # CBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJKwYB # BAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQUKqdS/mTEmr6CkTxGNSnPEP8v # BO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYM # KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEF # BQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBW # BgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUH # AQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtp # L2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsF # AAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U518Jx # Nj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN3Zi6th542DYunKmCVgADsAW+ # iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2 # pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnDvBewVIVCs/wMnosZiefw # C2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7 # T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+CljdQDzHVG2dY3RILLFO # Ry3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhL # mm77IVRrakURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+CrvsQWY9af3L # wUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKiexcdFYmNcP7ntdAoGokLjzbaukz5 # m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL6Xu/OHBE # 0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggNMMIICNAIB # ATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UE # CxMeblNoaWVsZCBUU1MgRVNOOkRDMDAtMDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNy # b3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDNrxRX/iz6 # ss1lBCXG8P1LFxD0e6CBgzCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAy # MDEwMA0GCSqGSIb3DQEBCwUAAgUA7JqmEjAiGA8yMDI1MTAxNTIzMDAzNFoYDzIw # MjUxMDE2MjMwMDM0WjBzMDkGCisGAQQBhFkKBAExKzApMAoCBQDsmqYSAgEAMAYC # AQACAQgwBwIBAAICEjEwCgIFAOyb95ICAQAwNgYKKwYBBAGEWQoEAjEoMCYwDAYK # KwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0BAQsF # AAOCAQEALVGcvMACFbHH0o/2V7PO8OjUThc06KaSB5ahQ0xsHJrpZ1KUUI1nqbnH # TUdNW0DgceTlCTA5hekgGBdLZFpvBJ/ipTQus8F8XztVOMZ5g1Y62OvjVc1kusRU # 5o9aXEe1KwUClmzxRFnlNZx3WEiqt9T2MnfOXovfXkLFXctScMgZrrpAEco2SefR # dtWwWpmU9D5BmXhRU74D93lpf+TJS3l4BQ5DOOeaw/GjpYDLrDI2sC3qSuYPNPiT # R49uGE1CEu82YV1nUy2aI+NFtUKMpqas7gr+RuMImSoi2SbyL+w5OQ0RV/HStbm0 # qd5uvnmL1Rv5oRkwDIRf51nJpEf2ATGCBA0wggQJAgEBMIGTMHwxCzAJBgNVBAYT # AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYD # VQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBU # aW1lLVN0YW1wIFBDQSAyMDEwAhMzAAACA7seXAA4bHTKAAEAAAIDMA0GCWCGSAFl # AwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwLwYJKoZIhvcN # AQkEMSIEIBnipHfGhIofsjQwqS9mkuKNtDfJNV/77eAjJXT+XCROMIH6BgsqhkiG # 9w0BCRACLzGB6jCB5zCB5DCBvQQgSwPdG3GW9pPEU5lmelDDQOSw+ZV26jlLIr2H # 3D76Ey0wgZgwgYCkfjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAA # AgO7HlwAOGx0ygABAAACAzAiBCBU2yqyZJj3q29SEvTQl2zR9yn54iUn+v73y5e7 # PaJEhzANBgkqhkiG9w0BAQsFAASCAgAgYOkimTsceX00KHRyMpo06TAMBY3sR6Oo # YQIHWdSAb1RnZ2xZ4KBDr+Yrk07RoSOGTUbbT5iklKOUbwr3zJhrbKSLMcjSrNDo # qRtKSEQEWVEjJCvrqy8E4FUwG337SkUpkf+IaVYELbbvhB2gz0AIIP2qT9Qnhptu # sKzs2Hmu2oaDx69n0//SqhH9/4fWWh0UnR1N4IP7VmSvvLDnQI422GyGgQBWUP22 # MS/7Hs16o4Cq4pXbrqozQM8Fe4L2WHrl8/PSD/2V4Y3pIRNR54ZmMbatxAlX8TG3 # MJnI4QRqc5FCqXyjIzTEzsmlWcQlKZY9rDUlrqjGLFiR7VMDOIrjlxWz1V75XMH7 # lYRRrm9bxvminffLVW1ciSXkJANZ9sFbttfXpSh4nw83VyR1RHZN+MGsIOuMjCXF # 6KCgP0K3vvvtJGOKRGlxYKSaURLCRPP94Ev83T+zu2vnRP4/VlCqUnrB0o0s3udM # nTg/mXPjVB4RBLqFApbm4NhfciB51SWq3vH+IljUekyaebsg4kF0wVEsblqi3djF # DZX0Wb0uYEiSydM+sxFnjYoiaSIze/1TtMu1/AE/LLGP8HuScmKKQ4OrQV4tVgaQ # KNnzuy5zen37sWWrqqRxbdXbaoumC8WvuVpuJNG0mEDmn4jaOHmWf/QGcm2cxnCu # usTIcfk8CQ== # SIG # End signature block |