custom/Initialize-AzMigrateReplicationInfrastructure.ps1
# ---------------------------------------------------------------------------------- # # Copyright Microsoft Corporation # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ---------------------------------------------------------------------------------- <# .Synopsis Initialises the infrastructure for the migrate project. .Description The Initialize-AzMigrateReplicationInfrastructure cmdlet initialises the infrastructure for the migrate project. .Link https://docs.microsoft.com/powershell/module/az.migrate/initialize-azmigratereplicationinfrastructure #> function Initialize-AzMigrateReplicationInfrastructure { [OutputType([System.Boolean])] [CmdletBinding(DefaultParameterSetName = 'agentlessVMware', PositionalBinding = $false, SupportsShouldProcess, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Path')] [System.String] # Specifies the Resource Group of the Azure Migrate Project in the current subscription. ${ResourceGroupName}, [Parameter(Mandatory)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Path')] [System.String] # Specifies the name of the Azure Migrate project to be used for server migration. ${ProjectName}, [Parameter(Mandatory)] [ValidateSet("agentlessVMware")] [ArgumentCompleter( { "agentlessVMware" })] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Path')] [System.String] # Specifies the server migration scenario for which the replication infrastructure needs to be initialized. ${Scenario}, [Parameter(Mandatory)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Path')] [System.String] # Specifies the target Azure region for server migrations. ${TargetRegion}, [Parameter()] [System.String] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Runtime.DefaultInfo(Script = '(Get-AzContext).Subscription.Id')] # Azure Subscription ID. ${SubscriptionId}, [Parameter()] [Alias('AzureRMContext', 'AzureCredential')] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Azure')] [System.Management.Automation.PSObject] # The credentials, account, tenant, and subscription used for communication with Azure. ${DefaultProfile}, [Parameter(DontShow)] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [System.Management.Automation.SwitchParameter] # Wait for .NET debugger to attach ${Break}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Runtime.SendAsyncStep[]] # SendAsync Pipeline Steps to be appended to the front of the pipeline ${HttpPipelineAppend}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Runtime.SendAsyncStep[]] # SendAsync Pipeline Steps to be prepended to the front of the pipeline ${HttpPipelinePrepend}, [Parameter(DontShow)] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [System.Uri] # The URI for the proxy server to use ${Proxy}, [Parameter(DontShow)] [ValidateNotNull()] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [System.Management.Automation.PSCredential] # Credentials for a proxy server to use for the remote call ${ProxyCredential}, [Parameter(DontShow)] [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Category('Runtime')] [System.Management.Automation.SwitchParameter] # Use the default credentials for the proxy ${ProxyUseDefaultCredentials} ) process { Import-Module Az.Resources Import-Module Az.KeyVault Import-Module Az.Storage Import-Module Az.ServiceBus # Validate user specified target region $TargetRegion = $TargetRegion.ToLower() $allAvailableAzureLocations = Get-AzLocation $matchingLocationByLocationName = $allAvailableAzureLocations | Where-Object { $_.Location -eq $TargetRegion } $matchingLocationByDisplayName = $allAvailableAzureLocations | Where-Object { $_.DisplayName -eq $TargetRegion } if ($matchingLocationByLocationName) { $TargetRegion = $matchingLocationByLocationName.Location } elseif ($matchingLocationByDisplayName) { $TargetRegion = $matchingLocationByDisplayName.Location } elseif ($TargetRegion -match "euap") { } else { throw "Creation of resources required for replication failed due to invalid location. Run Get-AzLocation to verify the validity of the location and retry this step." } # Get/Set SubscriptionId if (($null -eq $SubscriptionId) -or ($SubscriptionId -eq "")) { $context = Get-AzContext $SubscriptionId = $context.Subscription.Id if (($null -eq $SubscriptionId) -or ($SubscriptionId -eq "")) { throw "Please login to Azure to select a subscription." } } else { Select-AzSubscription -SubscriptionId $SubscriptionId } $context = Get-AzContext Write-Host "Using Subscription Id: ", $SubscriptionId Write-Host "Selected Target Region: ", $TargetRegion $rg = Get-AzResourceGroup -Name $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$rg) { Write-Host "Creating Resource Group ", $ResourceGroupName $output = New-AzResourceGroup -Name $ResourceGroupName -Location $TargetRegion Write-Host $ResourceGroupName, " created." } Write-Host "Selected resource group : ", $ResourceGroupName $LogStringCreated = "Created : " $LogStringSkipping = " already exists." $userObject = Get-AzADUser -UserPrincipalName $context.Subscription.ExtendedProperties.Account if (-not $userObject) { $userObject = Get-AzADUser -Mail $context.Subscription.ExtendedProperties.Account } if (-not $userObject) { $mailNickname = "{0}#EXT#" -f $($context.Account.Id -replace '@', '_') $userObject = Get-AzADUser | Where-Object { $_.MailNickname -eq $mailNickname } } if (-not $userObject) { $userObject = Get-AzADServicePrincipal -ApplicationID $context.Account.Id } if (-not $userObject) { throw 'User Object Id Not Found!' } # Hash code source code $Source = @" using System; public class HashFunctions { public static int hashForArtifact(String artifact) { int hash = 0; int al = artifact.Length; int tl = 0; char[] ac = artifact.ToCharArray(); while (tl < al) { hash = ((hash << 5) - hash) + ac[tl++] | 0; } return Math.Abs(hash); } } "@ #Get vault name from SMS solution. $smsSolution = Get-AzMigrateSolution -MigrateProjectName $ProjectName -ResourceGroupName $ResourceGroupName -Name "Servers-Migration-ServerMigration" if (-not $smsSolution.DetailExtendedDetail.AdditionalProperties.vaultId) { throw 'Azure Migrate appliance not configured. Setup Azure Migrate appliance before proceeding.' } $VaultName = $smsSolution.DetailExtendedDetail.AdditionalProperties.vaultId.Split("/")[8] # Get all appliances and sites in the project from SDS solution. $sdsSolution = Get-AzMigrateSolution -MigrateProjectName $ProjectName -ResourceGroupName $ResourceGroupName -Name "Servers-Discovery-ServerDiscovery" $appMap = @{} if ($null -ne $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV2"]) { $appMapV2 = $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV2"] | ConvertFrom-Json # Fetch all appliance from V2 map first. Then these can be updated if found again in V3 map. foreach ($item in $appMapV2) { $appMap[$item.ApplianceName] = $item.SiteId } } if ($null -ne $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV3"]) { $appMapV3 = $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV3"] | ConvertFrom-Json foreach ($item in $appMapV3) { $t = $item.psobject.properties $appMap[$t.Name] = $t.Value.SiteId } } if ($null -eq $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV2"] -And $null -eq $sdsSolution.DetailExtendedDetail["applianceNameToSiteIdMapV3"] ) { throw "Server Discovery Solution missing Appliance Details. Invalid Solution." } foreach ($eachApp in $appMap.GetEnumerator()) { $SiteName = $eachApp.Value.Split("/")[8] $applianceName = $eachApp.Key $HashCodeInput = $SiteName + $TargetRegion # User cannot change location if it's already set in mapping. $mappingName = "containermapping" $allFabrics = Get-AzMigrateReplicationFabric -ResourceGroupName $ResourceGroupName -ResourceName $VaultName foreach ($fabric in $allFabrics) { if (($fabric.Property.CustomDetail.InstanceType -ceq "VMwareV2") -and ($fabric.Property.CustomDetail.VmwareSiteId.Split("/")[8] -ceq $SiteName)) { $peContainers = Get-AzMigrateReplicationProtectionContainer -FabricName $fabric.Name -ResourceGroupName $ResourceGroupName -ResourceName $VaultName $peContainer = $peContainers[0] $existingMapping = Get-AzMigrateReplicationProtectionContainerMapping -ResourceGroupName $ResourceGroupName -ResourceName $VaultName -FabricName $fabric.Name -ProtectionContainerName $peContainer.Name -MappingName $mappingName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (($existingMapping) -and ($existingMapping.ProviderSpecificDetail.TargetLocation -ne $TargetRegion)) { $targetRegionMismatchExceptionMsg = $ProjectName + " is already configured for migrating servers to " + $TargetRegion + ". Target Region cannot be modified once configured." throw $targetRegionMismatchExceptionMsg } } } $job = Start-Job -ScriptBlock { Add-Type -TypeDefinition $args[0] -Language CSharp $hash = [HashFunctions]::hashForArtifact($args[1]) $hash } -ArgumentList $Source, $HashCodeInput Wait-Job $job $hash = Receive-Job $job Write-Host "Initiating Artifact Creation for Appliance: ", $applianceName # Phase 1 # Storage account $MigratePrefix = "migrate" $LogStorageAcName = $MigratePrefix + "lsa" + $hash $GateWayStorageAcName = $MigratePrefix + "gwsa" + $hash $StorageType = "Microsoft.Storage/storageAccounts" $StorageApiVersion = "2017-10-01" $LogStorageProperties = @{ encryption = @{ services = @{ blob = @{enabled = $true }; file = @{enabled = $true }; table = @{enabled = $true }; queue = @{enabled = $true } }; keySource = "Microsoft.Storage" }; supportsHttpsTrafficOnly = $true } $ResourceTag = @{"Migrate Project" = $ProjectName } $StorageSku = @{name = "Standard_LRS" } $ResourceKind = "Storage" $lsaStorageAccount = Get-AzResource -ResourceGroupName $ResourceGroupName -Name $LogStorageAcName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$lsaStorageAccount) { $output = New-AzResource -ResourceGroupName $ResourceGroupName -Location $TargetRegion -Properties $LogStorageProperties -ResourceName $LogStorageAcName -ResourceType $StorageType -ApiVersion $StorageApiVersion -Kind $ResourceKind -Sku $StorageSku -Tag $ResourceTag -Force Write-Host $LogStringCreated, $LogStorageAcName } else { Write-Host $LogStorageAcName, $LogStringSkipping } $gwyStorageAccount = Get-AzResource -ResourceGroupName $ResourceGroupName -Name $GateWayStorageAcName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$gwyStorageAccount) { $output = New-AzResource -ResourceGroupName $ResourceGroupName -Location $TargetRegion -Properties $LogStorageProperties -ResourceName $GateWayStorageAcName -ResourceType $StorageType -ApiVersion $StorageApiVersion -Kind $ResourceKind -Sku $StorageSku -Tag $ResourceTag -Force Write-Host $LogStringCreated, $GateWayStorageAcName } else { Write-Host $GateWayStorageAcName, $LogStringSkipping } # Service bus namespace $ServiceBusNamespace = $MigratePrefix + "sbns" + $hash $ServiceBusType = "Microsoft.ServiceBus/namespaces" $ServiceBusApiVersion = "2017-04-01" $ServiceBusSku = @{ name = "Standard"; tier = "Standard" } $ServiceBusProperties = @{} $ServieBusKind = "ServiceBusNameSpace" $serviceBusAccount = Get-AzResource -ResourceGroupName $ResourceGroupName -Name $ServiceBusNamespace -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$serviceBusAccount) { $output = New-AzResource -ResourceGroupName $ResourceGroupName -Location $TargetRegion -Properties $ServiceBusProperties -ResourceName $ServiceBusNamespace -ResourceType $ServiceBusType -ApiVersion $ServiceBusApiVersion -Kind $ServieBusKind -Sku $ServiceBusSku -Tag $ResourceTag -Force Write-Host $LogStringCreated, $ServiceBusNamespace } else { Write-Host $ServiceBusNamespace, $LogStringSkipping } # Key vault $KeyVaultName = $MigratePrefix + "kv" + $hash $KeyVaultType = "Microsoft.KeyVault/vaults" $KeyVaultApiVersion = "2016-10-01" $KeyVaultKind = "KeyVault" $existingKeyVaultAccount = Get-AzResource -ResourceGroupName $ResourceGroupName -Name $KeyVaultName -ErrorVariable notPresent -ErrorAction SilentlyContinue if ($existingKeyVaultAccount) { Write-Host $KeyVaultName, $LogStringSkipping } else { $tenantID = $context.Tenant.TenantId $KeyVaultPermissions = @{ keys = @("Get", "List", "Create", "Update", "Delete"); secrets = @("Get", "Set", "List", "Delete"); certificates = @("Get", "List"); storage = @("get", "list", "delete", "set", "update", "regeneratekey", "getsas", "listsas", "deletesas", "setsas", "recover", "backup", "restore", "purge") } $CloudEnvironMent = $context.Environment.Name $HyperVManagerAppId = "b8340c3b-9267-498f-b21a-15d5547fd85e" if ($CloudEnvironMent -eq "AzureUSGovernment") { $HyperVManagerAppId = "AFAE2AF7-62E0-4AA4-8F66-B11F74F56326" } $hyperVManagerObject = Get-AzADServicePrincipal -ApplicationID $HyperVManagerAppId $accessPolicies = @() $userAccessPolicy = @{ "tenantId" = $tenantID; "objectId" = $userObject.Id; "permissions" = $KeyVaultPermissions } $hyperVAccessPolicy = @{ "tenantId" = $tenantID; "objectId" = $hyperVManagerObject.Id; "permissions" = $KeyVaultPermissions } $accessPolicies += $userAccessPolicy $accessPolicies += $hyperVAccessPolicy $allFabrics = Get-AzMigrateReplicationFabric -ResourceGroupName $ResourceGroupName -ResourceName $VaultName $selectedFabricName = "" foreach ($fabric in $allFabrics) { if (($fabric.Property.CustomDetail.InstanceType -ceq "VMwareV2") -and ($fabric.Property.CustomDetail.VmwareSiteId.Split("/")[8] -ceq $SiteName)) { $projectRSPObject = Get-AzMigrateReplicationRecoveryServicesProvider -ResourceGroupName $ResourceGroupName -ResourceName $VaultName foreach ($projectRSP in $projectRSPObject) { $projectRSPFabricName = $projectRSP.Id.Split("/")[10] if (($projectRSP.FabricType -eq "VMwareV2") -and ($fabric.Name -eq $projectRSPFabricName)) { $projectAccessPolicy = @{ "tenantId" = $tenantID; "objectId" = $projectRSP.ResourceAccessIdentityDetailObjectId; "permissions" = $KeyVaultPermissions } $accessPolicies += $projectAccessPolicy } } } } $keyVaultProperties = @{ sku = @{ family = "A"; name = "standard" }; tenantId = $tenantID; enabledForDeployment = $true; enabledForDiskEncryption = $false; enabledForTemplateDeployment = $true; enableSoftDelete = $true; accessPolicies = $accessPolicies } $output = New-AzResource -ResourceGroupName $ResourceGroupName -Location $TargetRegion -Properties $keyVaultProperties -ResourceName $KeyVaultName -ResourceType $KeyVaultType -ApiVersion $KeyVaultApiVersion -Kind $KeyVaultKind -Tag $ResourceTag -Force Write-Host $LogStringCreated, $KeyVaultName } # Locks $CommonLockName = $ProjectName + "lock" $lockNotes = "This is in use by Azure Migrate project" $lsaLock = Get-AzResourceLock -LockName $CommonLockName -ResourceName $LogStorageAcName -ResourceType $StorageType -ResourceGroupName $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$lsaLock) { $output = New-AzResourceLock -LockLevel CanNotDelete -LockName $CommonLockName -ResourceName $LogStorageAcName -ResourceType $StorageType -ResourceGroupName $ResourceGroupName -LockNotes $lockNotes -Force Write-Host $LogStringCreated, $CommonLockName, " for ", $LogStorageAcName } else { Write-Host $CommonLockName, " for ", $LogStorageAcName, $LogStringSkipping } $gwyLock = Get-AzResourceLock -LockName $CommonLockName -ResourceName $GateWayStorageAcName -ResourceType $StorageType -ResourceGroupName $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$gwyLock) { $output = New-AzResourceLock -LockLevel CanNotDelete -LockName $CommonLockName -ResourceName $GateWayStorageAcName -ResourceType $StorageType -ResourceGroupName $ResourceGroupName -LockNotes $lockNotes -Force Write-Host $LogStringCreated, $CommonLockName, " for ", $GateWayStorageAcName } else { Write-Host $CommonLockName, " for ", $LogStorageAcName, $LogStringSkipping } $sbsnsLock = Get-AzResourceLock -LockName $CommonLockName -ResourceName $ServiceBusNamespace -ResourceType $ServiceBusType -ResourceGroupName $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$sbsnsLock) { $output = New-AzResourceLock -LockLevel CanNotDelete -LockName $CommonLockName -ResourceName $ServiceBusNamespace -ResourceType $ServiceBusType -ResourceGroupName $ResourceGroupName -LockNotes $lockNotes -Force Write-Host $LogStringCreated, $CommonLockName, " for ", $ServiceBusNamespace } else { Write-Host $CommonLockName, " for ", $ServiceBusNamespace, $LogStringSkipping } $kvLock = Get-AzResourceLock -LockName $CommonLockName -ResourceName $KeyVaultName -ResourceType $KeyVaultType -ResourceGroupName $ResourceGroupName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$kvLock) { $output = New-AzResourceLock -LockLevel CanNotDelete -LockName $CommonLockName -ResourceName $KeyVaultName -ResourceType $KeyVaultType -ResourceGroupName $ResourceGroupName -LockNotes $lockNotes -Force Write-Host $LogStringCreated, $CommonLockName, " for ", $KeyVaultName } else { Write-Host $CommonLockName, " for ", $KeyVaultName, $LogStringSkipping } # Intermediate phase # RoleAssignments $roleDefinitionId = "81a9662b-bebf-436f-a333-f67b29880f12" $kvspnid = (Get-AzADServicePrincipal -DisplayName "Azure Key Vault" )[0].Id $gwyStorageAccount = Get-AzResource -ResourceName $GateWayStorageAcName -ResourceGroupName $ResourceGroupName $lsaStorageAccount = Get-AzResource -ResourceName $LogStorageAcName -ResourceGroupName $ResourceGroupName $gwyRoleAssignments = Get-AzRoleAssignment -ObjectId $kvspnid -Scope $gwyStorageAccount.Id -ErrorVariable notPresent -ErrorAction SilentlyContinue $lsaRoleAssignments = Get-AzRoleAssignment -ObjectId $kvspnid -Scope $lsaStorageAccount.Id -ErrorVariable notPresent -ErrorAction SilentlyContinue if (-not $lsaRoleAssignments) { $output = New-AzRoleAssignment -ObjectId $kvspnid -Scope $lsaStorageAccount.Id -RoleDefinitionId $roleDefinitionId } if (-not $gwyRoleAssignments) { $output = New-AzRoleAssignment -ObjectId $kvspnid -Scope $gwyStorageAccount.Id -RoleDefinitionId $roleDefinitionId } if (-not $lsaRoleAssignments -or -not $gwyRoleAssignments) { for ($i = 1; $i -le 18; $i++) { Write-Information "Waiting for Role Assignments to be available... $( $i * 10 ) seconds" -InformationAction Continue Start-Sleep -Seconds 10 $gwyRoleAssignments = Get-AzRoleAssignment -ObjectId $kvspnid -Scope $gwyStorageAccount.Id -ErrorVariable notPresent -ErrorAction SilentlyContinue $lsaRoleAssignments = Get-AzRoleAssignment -ObjectId $kvspnid -Scope $lsaStorageAccount.Id -ErrorVariable notPresent -ErrorAction SilentlyContinue if ($gwyRoleAssignments -and $lsaRoleAssignments) { break } } } # SA. SAS definition $gatewayStorageAccountSasSecretName = "gwySas" $cacheStorageAccountSasSecretName = "cacheSas" $regenerationPeriod = [System.Timespan]::FromDays(30) $keyName = 'Key2' Add-AzKeyVaultManagedStorageAccount -VaultName $KeyVaultName -AccountName $LogStorageAcName -AccountResourceId $lsaStorageAccount.Id -ActiveKeyName $keyName -RegenerationPeriod $regenerationPeriod Add-AzKeyVaultManagedStorageAccount -VaultName $KeyVaultName -AccountName $GateWayStorageAcName -AccountResourceId $gwyStorageAccount.Id -ActiveKeyName $keyName -RegenerationPeriod $regenerationPeriod $lsasctx = New-AzStorageContext -StorageAccountName $LogStorageAcName -Protocol Https -StorageAccountKey $keyName $gwysctx = New-AzStorageContext -StorageAccountName $GateWayStorageAcName -Protocol Https -StorageAccountKey $keyName $lsaat = New-AzStorageAccountSasToken -Service blob, file, Table, Queue -ResourceType Service, Container, Object -Permission "racwdlup" -Protocol HttpsOnly -Context $lsasctx $gwyat = New-AzStorageAccountSasToken -Service blob, file, Table, Queue -ResourceType Service, Container, Object -Permission "racwdlup" -Protocol HttpsOnly -Context $gwysctx Set-AzKeyVaultManagedStorageSasDefinition -AccountName $LogStorageAcName -VaultName $KeyVaultName -Name $cacheStorageAccountSasSecretName -TemplateUri $lsaat -SasType 'account' -ValidityPeriod ([System.Timespan]::FromDays(30)) Set-AzKeyVaultManagedStorageSasDefinition -AccountName $GateWayStorageAcName -VaultName $KeyVaultName -Name $gatewayStorageAccountSasSecretName -TemplateUri $gwyat -SasType 'account' -ValidityPeriod ([System.Timespan]::FromDays(30)) # Phase 2 # ServiceBusConnectionString $serviceBusConnString = "ServiceBusConnectionString" $serviceBusSecretObject = Get-AzKeyVaultSecret -VaultName $KeyVaultName -Name $serviceBusConnString -ErrorVariable notPresent -ErrorAction SilentlyContinue if ($serviceBusSecretObject) { Write-Host $serviceBusConnString, " for ", $applianceName, $LogStringSkipping } else { $serviceBusRootKey = Get-AzServiceBusKey -ResourceGroupName $ResourceGroupName -Namespace $ServiceBusNamespace -Name "RootManageSharedAccessKey" $secret = ConvertTo-SecureString -String $serviceBusRootKey.PrimaryConnectionString -AsPlainText -Force $output = Set-AzKeyVaultSecret -VaultName $KeyVaultName -Name $serviceBusConnString -SecretValue $secret Write-Host $LogStringCreated, $serviceBusConnString, " for ", $applianceName } # Policy $policyName = $MigratePrefix + $SiteName + "policy" $existingPolicyObject = Get-AzMigrateReplicationPolicy -PolicyName $policyName -ResourceGroupName $ResourceGroupName -ResourceName $VaultName -ErrorVariable notPresent -ErrorAction SilentlyContinue if (!$existingPolicyObject) { $providerSpecificPolicy = [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Models.Api20210210.VMwareCbtPolicyCreationInput]::new() $providerSpecificPolicy.AppConsistentFrequencyInMinute = 240 $providerSpecificPolicy.InstanceType = "VMwareCbt" $providerSpecificPolicy.RecoveryPointHistoryInMinute = 360 $providerSpecificPolicy.CrashConsistentFrequencyInMinute = 60 $existingPolicyObject = New-AzMigrateReplicationPolicy -PolicyName $policyName -ResourceGroupName $ResourceGroupName -ResourceName $VaultName -ProviderSpecificInput $providerSpecificPolicy Write-Host $LogStringCreated, $policyName } else { Write-Host $policyName, $LogStringSkipping } # Policy-container mapping $mappingName = "containermapping" $allFabrics = Get-AzMigrateReplicationFabric -ResourceGroupName $ResourceGroupName -ResourceName $VaultName foreach ($fabric in $allFabrics) { if (($fabric.Property.CustomDetail.InstanceType -ceq "VMwareV2") -and ($fabric.Property.CustomDetail.VmwareSiteId.Split("/")[8] -ceq $SiteName)) { $peContainers = Get-AzMigrateReplicationProtectionContainer -FabricName $fabric.Name -ResourceGroupName $ResourceGroupName -ResourceName $VaultName $peContainer = $peContainers[0] $existingMapping = Get-AzMigrateReplicationProtectionContainerMapping -ResourceGroupName $ResourceGroupName -ResourceName $VaultName -FabricName $fabric.Name -ProtectionContainerName $peContainer.Name -MappingName $mappingName -ErrorVariable notPresent -ErrorAction SilentlyContinue if ($existingMapping) { Write-Host $mappingName, " for ", $applianceName, $LogStringSkipping } else { $keyVaultAccountDetails = Get-AzKeyVault -ResourceGroupName $ResourceGroupName -Name $KeyVaultName $gwyStorageAccount = Get-AzResource -ResourceGroupName $ResourceGroupName -ResourceName $GateWayStorageAcName $providerSpecificInput = [Microsoft.Azure.PowerShell.Cmdlets.Migrate.Models.Api20210210.VMwareCbtContainerMappingInput]::new() $providerSpecificInput.InstanceType = "VMwareCbt" $providerSpecificInput.KeyVaultId = $keyVaultAccountDetails.ResourceId $providerSpecificInput.KeyVaultUri = $keyVaultAccountDetails.VaultUri $providerSpecificInput.ServiceBusConnectionStringSecretName = $serviceBusConnString $providerSpecificInput.StorageAccountId = $gwyStorageAccount.Id $providerSpecificInput.StorageAccountSasSecretName = $GateWayStorageAcName + "-gwySas" $providerSpecificInput.TargetLocation = $TargetRegion $output = New-AzMigrateReplicationProtectionContainerMapping -FabricName $fabric.Name -MappingName $mappingName -ProtectionContainerName $peContainer.Name -ResourceGroupName $ResourceGroupName -ResourceName $VaultName -PolicyId $existingPolicyObject.Id -ProviderSpecificInput $providerSpecificInput -TargetProtectionContainerId "Microsoft Azure" Write-Host $LogStringCreated, $mappingName, " for ", $applianceName } } } } Write-Host "Finished successfully." return $true } } # SIG # Begin signature block # MIInpQYJKoZIhvcNAQcCoIInljCCJ5ICAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCACU2EpZFRIEJbl # CDNHtsYKVL7f5uGFirpKU10zZQH9CqCCDYUwggYDMIID66ADAgECAhMzAAACzfNk # v/jUTF1RAAAAAALNMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjIwNTEyMjA0NjAyWhcNMjMwNTExMjA0NjAyWjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDrIzsY62MmKrzergm7Ucnu+DuSHdgzRZVCIGi9CalFrhwtiK+3FIDzlOYbs/zz # HwuLC3hir55wVgHoaC4liQwQ60wVyR17EZPa4BQ28C5ARlxqftdp3H8RrXWbVyvQ # aUnBQVZM73XDyGV1oUPZGHGWtgdqtBUd60VjnFPICSf8pnFiit6hvSxH5IVWI0iO # nfqdXYoPWUtVUMmVqW1yBX0NtbQlSHIU6hlPvo9/uqKvkjFUFA2LbC9AWQbJmH+1 # uM0l4nDSKfCqccvdI5l3zjEk9yUSUmh1IQhDFn+5SL2JmnCF0jZEZ4f5HE7ykDP+ # oiA3Q+fhKCseg+0aEHi+DRPZAgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQU0WymH4CP7s1+yQktEwbcLQuR9Zww # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzQ3MDUzMDAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AE7LSuuNObCBWYuttxJAgilXJ92GpyV/fTiyXHZ/9LbzXs/MfKnPwRydlmA2ak0r # GWLDFh89zAWHFI8t9JLwpd/VRoVE3+WyzTIskdbBnHbf1yjo/+0tpHlnroFJdcDS # MIsH+T7z3ClY+6WnjSTetpg1Y/pLOLXZpZjYeXQiFwo9G5lzUcSd8YVQNPQAGICl # 2JRSaCNlzAdIFCF5PNKoXbJtEqDcPZ8oDrM9KdO7TqUE5VqeBe6DggY1sZYnQD+/ # LWlz5D0wCriNgGQ/TWWexMwwnEqlIwfkIcNFxo0QND/6Ya9DTAUykk2SKGSPt0kL # tHxNEn2GJvcNtfohVY/b0tuyF05eXE3cdtYZbeGoU1xQixPZAlTdtLmeFNly82uB # VbybAZ4Ut18F//UrugVQ9UUdK1uYmc+2SdRQQCccKwXGOuYgZ1ULW2u5PyfWxzo4 # BR++53OB/tZXQpz4OkgBZeqs9YaYLFfKRlQHVtmQghFHzB5v/WFonxDVlvPxy2go # a0u9Z+ZlIpvooZRvm6OtXxdAjMBcWBAsnBRr/Oj5s356EDdf2l/sLwLFYE61t+ME # iNYdy0pXL6gN3DxTVf2qjJxXFkFfjjTisndudHsguEMk8mEtnvwo9fOSKT6oRHhM # 9sZ4HTg/TTMjUljmN3mBYWAWI5ExdC1inuog0xrKmOWVMIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGXYwghlyAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAALN82S/+NRMXVEAAAAA # As0wDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIMHj # ZC35kshzn8HDX2mGTzE+wP1OT21SXUPbBI8P64aJMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEAi3tQoux1KnXwnohVymaCW4/JFXLfDyh0Gn3m # VMBfr4ZdCHL4OqgqPEgQE965trnRu8lwjXTSNVWk1k6C9PxfQ0dCfBHn0fRwFPeK # T1B3BVd509Fib4drLAqjgSNRisuHhfg8x6S/SOGL6Wr/YHv+w1D0QiK/QMEOEe8h # McwG1d+jquKz7ozjIXrrA6ymTJ55b9ETnXYbWJrJD+tJ9w1QmcMnomyqB+ZVwzaA # NZTPa7+vXcqUnYDyPXmyVhnN+YIBv5Qf69GXEndnsrMS8KsOWDNO6ANAyDfcy2o0 # bDzAjBqdZrA8O1goPFykJ/7NILnH1ZxuOoXzkMpcaLY5tTF/n6GCFwAwghb8Bgor # BgEEAYI3AwMBMYIW7DCCFugGCSqGSIb3DQEHAqCCFtkwghbVAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFRBgsqhkiG9w0BCRABBKCCAUAEggE8MIIBOAIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCAaiP+dqxTSGjvQVK0ry+GM50UfUlpgfAQ9 # LK/htwFV4gIGYtbQraqvGBMyMDIyMDcyNzEwMTcxOS40MDJaMASAAgH0oIHQpIHN # MIHKMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL # ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMSYwJAYDVQQLEx1UaGFsZXMg # VFNTIEVTTjpFNUE2LUUyN0MtNTkyRTElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUt # U3RhbXAgU2VydmljZaCCEVcwggcMMIIE9KADAgECAhMzAAABlbf8DdbjNzElAAEA # AAGVMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo # aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y # cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEw # MB4XDTIxMTIwMjE5MDUxMloXDTIzMDIyODE5MDUxMlowgcoxCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVy # aWNhIE9wZXJhdGlvbnMxJjAkBgNVBAsTHVRoYWxlcyBUU1MgRVNOOkU1QTYtRTI3 # Qy01OTJFMSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNlMIIC # IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAn21BDGe2Szs/WqEQniS+IYU/ # UPCWQdsWlZTDQrd28IXEyORiz67dnvdwwLJpajs8NXBYjz4OkubCwl8+y221EKS4 # WvEuL9qnHDLU6JBGg0EvkCRK5wLJelUpkbwMtJ5Y/gvz2mbi29zs2NAEcO1HgmS6 # cljzx/pOTHWI+jVA0zaF6m80Bwrj7Pn4CKK6Octwx6DtO+4OiK9kxyMdcn1RRLec # w3BTzmDIOMgYuAOl3N4ZvbWesPOPZwb1SsJuWAC3x98v395+C5zetW9cMwMd2QmY # 39d1Cm6RO6eg2Cax0Qf/qcBYxvfU8Bx+rl8w3mU+v6+qh+wAAcJ/H6WHNU5pXhWP # GEblc846fVZDx1fFc78yy+0CtpLXnlyy/2OJb4y+oc8jphPtS1Q95RG2IaNcwrfh # e21PhaY8gX0wuIv8B7KbW9tfGJW5ELdYtQepZZicFRcAi1+4MUOPECBlGnDMvJKd # fs3M2PksZaWhIDZkJH3Na2j4fcubDGul+PPsdCuwfDqg6F3E4hAiIyXrccLbgZUL # HidOR0X4rH4BZtPZBu73RxKNzW1LjDARYpHOG6DfVH5tIlIavybaldCsK7/Qr92s # g4HTcBFoi9muuSJxFkqUU2H7AkNN3qhIeQN68Ffyn1BXIrfg6z/vVXA6Y1kbAqJG # b+LYJ+agFzTLR2vDYqkCAwEAAaOCATYwggEyMB0GA1UdDgQWBBSrl9NiAhRXV4K3 # AgZgyXx+b/ypFzAfBgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBfBgNV # HR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2Ny # bC9NaWNyb3NvZnQlMjBUaW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYI # KwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAy # MDEwKDEpLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0G # CSqGSIb3DQEBCwUAA4ICAQDgszbeHyfozr0LqtCLZ9+yGa2DQRrMAIviABTN2Biv # 8BkJRJ3II5jQbmnPeVtnwC+sbRVXzH5HqkizC6qInVbFPQZuAxAY2ljTk/bl/7XG # IiUnxUDNKw265fFeJzPPEWReehv6iVvYOXSKjkqIpsylLf0O1h+lQcltLGq+cBr4 # KLyt6hWncCkoc0WHBKk5Bx9s4qeXu943szx8dvrWmKiRucSc3QxK2dZzIsUY2h7N # yqXLJmWLsbCEXwWDibwBRspkxkb+T7sLDabPRHIdQGrKvOB/2P/MTdxkI+D9zIg5 # /Is1AQwrlyHx2JN/W6p2gJhW1Igm8vllqbs3ZOKAys/7FsK57KEO9rhBlRDe/pMs # Pfh0qOYvJfGYNWJo/bVIA6VVBowHbqC8h0O16pJypkvZCUgSpOKJBA4NCHei3ii0 # MB9XuGlXk8lGMHAV98IO6SyUFr0e52tkhq7Zf9t2BkE7nZljq8ocfZZ1OygRlf2j # b89LU6XLLnLCvnGRSgxJFgf6FBVa7crp+jQ+aWGTY9AoEbqeYK1QAqvwIG/hDhiw # g/sxLRjaKeLXyr7GG+uNuezSfV6zB4KQom++lk9+ET5ggQcsS1JB8R6ucwsmDbtC # BVwLdQFYnMNeDPnMy2CFTOzTslaRXXAdQfTIiYpO6XkootF00XZef1fyrHE2ggRc # 9zCCB3EwggVZoAMCAQICEzMAAAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQEL # 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/ZcGNTTY3ugm2lBRDBcQZqELQdVTNYs6FwZvKhggLOMIICNwIB # ATCB+KGB0KSBzTCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEmMCQGA1UE # CxMdVGhhbGVzIFRTUyBFU046RTVBNi1FMjdDLTU5MkUxJTAjBgNVBAMTHE1pY3Jv # c29mdCBUaW1lLVN0YW1wIFNlcnZpY2WiIwoBATAHBgUrDgMCGgMVANGPgsi3sxoF # R1hTZiiNS7hP4WOroIGDMIGApH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh # c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBD # b3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIw # MTAwDQYJKoZIhvcNAQEFBQACBQDmizI9MCIYDzIwMjIwNzI3MTE0MDQ1WhgPMjAy # MjA3MjgxMTQwNDVaMHcwPQYKKwYBBAGEWQoEATEvMC0wCgIFAOaLMj0CAQAwCgIB # AAICKQQCAf8wBwIBAAICEacwCgIFAOaMg70CAQAwNgYKKwYBBAGEWQoEAjEoMCYw # DAYKKwYBBAGEWQoDAqAKMAgCAQACAwehIKEKMAgCAQACAwGGoDANBgkqhkiG9w0B # AQUFAAOBgQAg2e4MjnpGi/BxP73mAPiypPz1hIG9/AtryPQ43crG+qyDH8XJCMbd # YCvZfqRKEFELioLpLsMIM9xyli/ClM00YXfGpviRBf3B0ZGmJkAA9R8Ail7g6DQ1 # GtgNHoiDds/1TEFB7/yiMy5AEE6CppLQGEFju94cjPe+9lDpDLTCLTGCBA0wggQJ # AgEBMIGTMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk # BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMzAAABlbf8Ddbj # NzElAAEAAAGVMA0GCWCGSAFlAwQCAQUAoIIBSjAaBgkqhkiG9w0BCQMxDQYLKoZI # hvcNAQkQAQQwLwYJKoZIhvcNAQkEMSIEIMPUxSgRO8/9wlGSXOC+/JEvxUUtg0r4 # FY7vwZTmLyVyMIH6BgsqhkiG9w0BCRACLzGB6jCB5zCB5DCBvQQgXOZL4Y2QC3tp # oSM/0He5HlTpgP3AtXcymU+MmyxJAscwgZgwgYCkfjB8MQswCQYDVQQGEwJVUzET # MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV # TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T # dGFtcCBQQ0EgMjAxMAITMwAAAZW3/A3W4zcxJQABAAABlTAiBCCP7vbk7c+B9gM4 # o4mr14kLmDVeZsnKv6vglEZ5Fs3Y7DANBgkqhkiG9w0BAQsFAASCAgAZZ2h5yaDc # OcrZheM3QvgLttTaU4YJyJ9by2fhV+r2PiRnLy1wx5Nw9XbH62TSezZo6ruc8bg3 # tyKnYpj3pXS0EdwByQMzgcZCKUUJ05yr1pjufjH6LMhHBT03dmHxbJSYFNpxIqTJ # 94vsmVPejrVFQ6yDd3Svs8Webd/Yh0xGc0pPV2jiZrCfPlS6CvdPmqdozAnQLSMc # 2CnLsPGLLrvXg2VH5odhQflRbQ4VkDJ1uKsjDOLsneKyV6kPpuYdyRUgzydph/+s # fMJsPXXDYdzOVH4Z36tPGdTt4X7dfnrzA9cmrFYfzW8T7iDmfAg2e7BJsGrf6sMT # R86IPb3g99VdQtY8KLwtRDdyZwWw1hnFt6FZjnYffexxj3MR/R3CaaDfhV7P6BJv # LpARxFbZN9VYFyboNo2GQkRYlJQZeqSVtOTq4xh0D56eppIrRBeyUU1Y+zatQkgq # oijlPJkh4scGC9//R4UYEbmAd5OjtwyXX6PhqAqjTGvkU9QcXCfgy0y011idrADl # k134S39JOonY6mkv9vrZUuqzaqpLVE2qdNCd1pREPQ1+kZvM3JQY8Fvqj/WCgGok # Oalp/mhIyS78ENLf7Los7jr9Tqo0T3JzahO/UTBv97stc2Wb7Shfmz4vfduw5KJs # fk9c+EPN9W6IVPsIHQ8UfiCdHGj/eRMVuw== # SIG # End signature block |