Share gallery VM images across Azure tenants using PowerShell

Shared Image Galleries let you share images using Azure RBAC. You can use Azure RBAC to share images within your tenant, and even to individuals outside of your tenant. For more information about this simple sharing option, see the Share the gallery.

But, if you want to share images outside of your Azure tenant, at scale, you should create an app registration to facilitate sharing. Using an app registration can enable more complex sharing scenarios, like:

  • Managing shared images when one company acquires another, and the Azure infrastructure is spread across separate tenants.
  • Azure Partners manage Azure infrastructure on behalf of their customers. Customization of images is done within the partners tenant, but the infrastructure deployments will happen in the customer's tenant.

Create the app registration

Create an application registration that will be used by both tenants to share the image gallery resources.

  1. Open the App registrations (preview) in the Azure portal.
  2. Select New registration from the menu at the top of the page.
  3. In Name, type myGalleryApp.
  4. In Supported account types, select Accounts in any organizational directory and personal Microsoft accounts.
  5. In Redirect URI, type https://www.microsoft.com and then select Register. After the app registration has been created, the overview page will open.
  6. On the overview page, copy the Application (client) ID and save for use later.
  7. Select Certificates & secrets, and then select New client secret.
  8. In Description, type Shared image gallery cross-tenant app secret.
  9. In Expires, leave the default of In 1 year and then select Add.
  10. Copy the value of the secret and save it to a safe place. You cannot retrieve it after you leave the page.

Give the app registration permission to use the shared image gallery.

  1. In the Azure portal, select the Shared Image Gallery that you want to share with another tenant.
  2. Select select Access control (IAM), and under Add role assignment select Add.
  3. Under Role, select Reader.
  4. Under Assign access to:, leave this as Azure AD user, group, or service principal.
  5. Under Select, type myGalleryApp and select it when it shows up in the list. When you are done, select Save.

Give Tenant 2 access

Give Tenant 2 access to the application by requesting a sign-in using a browser. Replace <Tenant2 ID> with the tenant ID for the tenant that you would like to share your image gallery with. Replace <Application (client) ID> with the application ID of the app registration you created. When done making the replacements, paste the URL into a browser and follow the sign-in prompts to sign into Tenant 2.

https://login.microsoftonline.com/<Tenant 2 ID>/oauth2/authorize?client_id=<Application (client) ID>&response_type=code&redirect_uri=https%3A%2F%2Fwww.microsoft.com%2F 

In the Azure portal sign in as Tenant 2 and give the app registration access to the resource group where you want to create the VM.

  1. Select the resource group and then select Access control (IAM). Under Add role assignment select Add.
  2. Under Role, type Contributor.
  3. Under Assign access to:, leave this as Azure AD user, group, or service principal.
  4. Under Select type myGalleryApp then select it when it shows up in the list. When you are done, select Save.

Note

You need to wait for the image version to completely finish being built and replicated before you can use the same managed image to create another image version.

Important

You cannot use the portal to deploy a VM from an image in another azure tenant. To create a VM from an image shared between tenants, you must use the Azure CLI or Powershell.

Create a VM using PowerShell

Log into both tenants using the application ID, secret and tenant ID.

$applicationId = '<App ID>'
$secret = <Secret> | ConvertTo-SecureString -AsPlainText -Force
$tenant1 = "<Tenant 1 ID>"
$tenant2 = "<Tenant 2 ID>"
$cred = New-Object -TypeName PSCredential -ArgumentList $applicationId, $secret
Clear-AzContext
Connect-AzAccount -ServicePrincipal -Credential $cred  -Tenant "<Tenant 1 ID>"
Connect-AzAccount -ServicePrincipal -Credential $cred -Tenant "<Tenant 2 ID>"

Create the VM in the resource group that has permission on the app registration. Replace the information in this example with your own.

$resourceGroup = "myResourceGroup"
$location = "South Central US"
$vmName = "myVMfromImage"

# Set a variable for the image version in Tenant 1 using the full image ID of the shared image version
$image = "/subscriptions/<Tenant 1 subscription>/resourceGroups/<Resource group>/providers/Microsoft.Compute/galleries/<Gallery>/images/<Image definition>/versions/<version>"

# Create user object
$cred = Get-Credential -Message "Enter a username and password for the virtual machine."

# Create a resource group
New-AzResourceGroup -Name $resourceGroup -Location $location

# Networking pieces
$subnetConfig = New-AzVirtualNetworkSubnetConfig -Name mySubnet -AddressPrefix 192.168.1.0/24
$vnet = New-AzVirtualNetwork -ResourceGroupName $resourceGroup -Location $location `
  -Name MYvNET -AddressPrefix 192.168.0.0/16 -Subnet $subnetConfig
$pip = New-AzPublicIpAddress -ResourceGroupName $resourceGroup -Location $location `
  -Name "mypublicdns$(Get-Random)" -AllocationMethod Static -IdleTimeoutInMinutes 4
$nsgRuleRDP = New-AzNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP  -Protocol Tcp `
  -Direction Inbound -Priority 1000 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * `
  -DestinationPortRange 3389 -Access Allow
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroup -Location $location `
  -Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP
$nic = New-AzNetworkInterface -Name myNic -ResourceGroupName $resourceGroup -Location $location `
  -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id

# Create a virtual machine configuration using the $image variable to specify the shared image
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize Standard_D1_v2 | `
Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $cred | `
Set-AzVMSourceImage -Id $image | `
Add-AzVMNetworkInterface -Id $nic.Id

# Create a virtual machine
New-AzVM -ResourceGroupName $resourceGroup -Location $location -VM $vmConfig

Next steps

You can also create shared image gallery resources using the Azure portal.