Let’s say we have a generalized Azure Managed Image in our Azure subscription and we need to generate Azure blob Shared Access Signature (SAS) URL to the VHD representing that image.
One of the scenarios where this is useful is during publishing a VM offer in Azure Marketplace. Currently, as of August 2020, Partner Center UI requires the publisher to provide SAS URL for the OS and Data disks
Although it is possible to generate SAS URLs from Azure Managed Disks by using “az disk grant-access”, it is not currently possible to generate SAS URL from a managed image (i.e. there is no “az image grant-access” type of command).
In addition, even with “az disk grant-access” we would not get SAS URL that is required for publishing a VM offer in Azure Marketplace (refer to this doc).
The high-level steps to accomplish what we need are as follows:
- Create Azure Shared Image Gallery image version from the managed image
- Create Azure Managed Disk from the Shared Image Gallery (SIG) image version we created
- Generate temporary SAS URL to the Azure Managed Disk
- Use AzCopy to copy the SAS URL of the managed disk to our own Azure storage account container as a VHD
- Generate SAS from the VHD in our storage account
Create Azure Shared Image Gallery from Managed Image
We first create an Azure Shared Image Gallery and image definition.
# Create resource group
az group create --name avsig1000 --location eastus# Create shared image gallery resource
az sig create --resource-group avsig1000 --gallery-name gallery1000# Create shared image gallery image definition
az sig image-definition create --resource-group avsig1000 --gallery-name gallery1000 --gallery-image-definition image1000 --os-type Linux --publisher mypublisher1000 --offer myoffer1000 --sku mysku1000
Next, we create an image version in our gallery from our managed image. This command may take a few minutes to execute. Also, we need to make sure to use the proper target regions for the image version including the ones where our storage account will be located. In the example below, the image version is replicated to the eastus region.
# Create shared image gallery image version from existing managed image
az sig image-version create --resource-group avsig1000 --gallery-name gallery1000 --gallery-image-definition image1000 --gallery-image-version 1.0.0 --target-regions eastus=1=standard_lrs --managed-image /subscriptions/MY_SUBSCRIPTION_ID/resourceGroups/MY_RESOURCE_GROUP_WITH_MANAGED_IMAGE/providers/Microsoft.Compute/images/MY_MANAGED_IMAGE_NAME
We should now have the following Azure Shared Image Gallery resources in our resource group:
The resource ID of the image version is something like this:
Create Azure Managed Disk from Shared Image Gallery
We now can use “az disk create” with gallery-image-reference parameter to create a managed disk directly from our image.
az disk create --resource-group avsig1000 --location eastus --name my-disk-from-image --gallery-image-reference /subscriptions/MY_SUBSCRIPTION_ID/resourceGroups/avsig1000/providers/Microsoft.Compute/galleries/gallery1000/images/image1000/versions/1.0.0
NOTE: If our image consists of multiple disks (e.g. OS plus data disks), we need to create multiple managed disks by using the gallery-image-reference-lun to create individual disks for the OS and each of the data disks.
Generate SAS URL for the Managed Disk
We use “az disk grant-access” to export the newly created managed disk via a temporary (e.g. 10 hours) SAS URL.
az disk grant-access --resource-group avsig1000 --name my-disk-from-image --duration-in-seconds 36000 --access-level Read
We get back a SAS URL that looks like this:
AzCopy Managed Disk to Our Azure Blob Storage Container
If we don’t yet have a specific storage account we will use for storing the VHD, we create a simple Azure Blob storage account and container.
# Create storage account
az storage account create --resource-group avsig1000 --name avvhdstorage1000 --location eastus --sku Standard_LRS --kind StorageV2 --access-tier Hot# Create storage container
az storage container create --resource-group avsig1000 --account-name avvhdstorage1000 --name myvhds
Create writable SAS URL for our destination container.
az storage container generate-sas --account-name avvhdstorage1000 --name myvhds --permissions acw --expiry "2020-08-08T00:00:00Z"
We now can use AzCopy command to copy the managed disk using its SAS URL to the container we created. For the destination, we make sure to name the blob with .vhd extension.
azcopy copy "https://md-3r0d4kzc5jhz.blob.core.windows.net/s3vffgdlczdj/abcd?sv=2017-04-17&sr=b&si=e931bb4b-8a79-4119-b4bb-8b2c1b763369&sig=SIGNATURE_WILL_BE_HERE" "https://avvhdstorage1000.blob.core.windows.net/myvhds/myimage1.vhd?se=2020-08-08T00%3A00%3A00Z&sp=acw&sv=2018-11-09&sr=c&sig=SIGNATURE_WILL_BE_HERE"
We now have the blob in our storage container.
Generate SAS for VHD in our Storage Account
Following the documentation for Azure Marketplace VM Offer, we generate read+list SAS URL for the VHD in our storage account making sure to specify start date of at least one day before current date and expiry date at least three weeks after current date.
az storage container generate-sas --account-name avvhdstorage1000 --name myvhds --permissions rl --start "2020-08-04T00:00:00Z" --expiry "2020-09-08T00:00:00Z"
Finally, we append the resultant SAS token it to the URL of our VHD blob name as follows and use it in the VM Offer page in the Partner Center.
My other posts and videos about Azure VM offers
- Simple Azure Marketplace Virtual Machine Offer: creating VM images and publishing in Partner Center
- Using Self-Test API to validate VM images for publishing in Azure Marketplace
- Azure Marketplace API to programmatically review and accept publisher agreement/EULA
- Using Cloud Partner Portal CPP API for managing Virtual Machine offers in Azure Marketplace
Please leave feedback and questions below or on Twitter https://twitter.com/ArsenVlad