Update on ASM to ARM Migration Experience

A while ago I posted a little rant about the migration experience from ASM to ARM, when moving to a new subscription in the same flow: https://cloudpuzzles.net/2016/10/asm-to-arm-migration-and-fun-with-key-vault/

After working with support for a weeks, we finally made it through our migration. The solution involved support (and at that point, the Product Group too who had to prepare our VMs before running the script), and a few lines of PowerShell:

$vmName = "vmName"
$rgName = "rgName"
$vm = Get-AzureRmVM -ResourceGroupName $rgName -Name $vmName
$vm.OSProfile.Secrets = New-Object -TypeName "System.Collections.Generic.List[Microsoft.Azure.Management.Compute.Models.VaultSecretGroup]"
Update-AzureRmVM -ResourceGroupName $rgName -VM $vm -Debug

What this does, is basically just remove the OSProfile.Secrets part of our VM configuration. The impact of this, is that WinRM won’t work anymore, since the link between VM and Key Vault (where certificates for WinRM are stored), is broken. If you look at your VM templates, you can see this clearly. Anyways, if you use WinRM on the public DNS name (*.cloudapp.net), you will need to fix this afterwards. Personally I think you should reconsider if using WinRM that way is a good idea in general.

Since then the experience has been improved a bit – Thanks to Samuel P. for pointing out in comments – and we no longer need to involve support. I have succesfully used the script below to migrate from ASM to ARM, and then to a new subscription.

Is everything just awesome and sunshine now? Not exactly, I’m afraid. After migrating a bunch of environments for a customer with the above solution, we have issues with billing. Some of the resources are billed on the new subscription – most are still on the old though. Ugh! I’m currently working with support and product groups to figure out what’s wrong – will update when I have news on that. Not sure how widespread that issue is though, but make sure you check this after migrating!

The script I used (make sure to replace variables with your own values):

$oldSub = "oldSubscriptionName"
$cred = Get-Credential #Should have access to both subscriptions

Login-AzureRmAccount -Credential $cred
Select-AzureRmSubscription -SubscriptionName $oldSub

Add-AzureAccount -Credential $cred
Select-AzureSubscription -SubscriptionName $oldSub

#Migrate to ARM
Register-AzureRmResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate
Get-AzureRmResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate

$vnetName = "vnetName"
Move-AzureVirtualNetwork -Prepare -VirtualNetworkName $vnetName -Verbose

#Move-AzureVirtualNetwork -Abort -VirtualNetworkName $vnetName

Move-AzureVirtualNetwork -Commit -VirtualNetworkName $vnetName

$storageAccountName = "storageAccountName"
Move-AzureStorageAccount -Prepare -StorageAccountName $storageAccountName

#Move-AzureStorageAccount -Abort -StorageAccountName $storageAccountName

Move-AzureStorageAccount -Commit -StorageAccountName $storageAccountName

#Move all resources to same RG
$sourceRG = "rgName-Migrated"
$destRG = "destinationRGName"
$resources = Find-AzureRmResource -ResourceGroupNameContains $sourceRg | ? {$_.ResourceType -ne "Microsoft.Compute/virtualMachines/extensions"} #VM Extensions are not top level resources, so can’t be moved this way, but follows the VM
Move-AzureRmResource -DestinationResourceGroupName $destRG -ResourceId $resources.ResourceID
Remove-AzureRmResourceGroup $sourceRG

#Remove Key Vault link
$vmName = "vmName"
$vm = Get-AzureRmVM -ResourceGroupName $destRG -Name $vmName
$vm.OSProfile.Secrets = New-Object -TypeName "System.Collections.Generic.List[Microsoft.Azure.Management.Compute.Models.VaultSecretGroup]"
Update-AzureRmVM -ResourceGroupName $destRG -VM $vm -Debug

#Move subscription
$newSub = "newSubscriptionName"
$newRG = "newRGName"
$location = "North Europe"
$subscriptionID = Get-AzureRmSubscription -SubscriptionName $newSub
$resources = Find-AzureRmResource -ResourceGroupNameContains $destRg| ? {$_.ResourceType -ne "Microsoft.Compute/virtualMachines/extensions"}
Select-AzureRmSubscription -SubscriptionName $newSub
if (!(Get-AzureRmResourceGroup -Name $newRG -ErrorAction SilentlyContinue)) {
New-AzureRmResourceGroup -Name $newRG -Location $location
Select-AzureRmSubscription -SubscriptionName $oldSub
Move-AzureRmResource -DestinationResourceGroupName $newRG -ResourceId $resources.ResourceID -DestinationSubscriptionId $subscriptionID.SubscriptionId

Edit: Thanks to Tiberiu Radu for pointing out that this can be done using Azure CLI 2.0 too:

az vm update -g rgname -n vmname --set osProfile.Secrets=[]


  1. Excellent. This has been bugging me for ages, really appreciate the writeup. In my case – the keyvault for the migrated VMs had gone into a failed state and the certificates had disappeared! You just need to separate $rgName from -Name in your first code example 🙂


  2. silly question I assume – but storage account RG’s also need to be combined into the one RG? Otherwise a migration will fail because of dependencies to the storage account?


  3. I see you are removing the location of Key Vault Secret from the Virtual Machine’s OS profile. Don’t we have to add this back after migration is complete?

    Also, will it work if I move the key vault also to the new subscription?


    1. It depends – if you’re using it to remotely access PowerShell or something like that, then you’d break it by removing it. I personally never used it for anything though, as I have other connectivity to my environments.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s