Use a Linux VM Managed Service Identity to access Azure Storage via access key

Managed Service Identity (MSI) is a preview feature of Azure Active Directory. Make sure you review the known issues before you begin. For more information about previews, see Supplemental Terms of Use for Microsoft Azure Previews.

This tutorial shows you how to enable Managed Service Identity (MSI) for a Linux Virtual Machine and then use that identity to retrieve storage account access keys. You can use a storage access key as usual when doing storage operations, for example when using the Storage SDK. For this tutorial, we upload and download blobs using Azure CLI. You will learn how to:

  • Enable MSI on a Linux Virtual Machine
  • Grant your VM access to storage account access keys in Resource Manager
  • Get an access token using your VM's identity, and use it to retrieve the storage access keys from Resource Manager

If you don't have an Azure subscription, create a free account before you begin.

Sign in to Azure

Sign in to the Azure portal at https://portal.azure.com.

Create a Linux virtual machine in a new resource group

For this tutorial, we create a new Linux VM. You can also enable MSI on an existing VM.

  1. Click the +/Create new service button found on the upper left-hand corner of the Azure portal.
  2. Select Compute, and then select Ubuntu Server 16.04 LTS.
  3. Enter the virtual machine information. For Authentication type, select SSH public key or Password. The created credentials allow you to log in to the VM.

    Alt image text

  4. Choose a Subscription for the virtual machine in the dropdown.

  5. To select a new Resource Group you would like the virtual machine to be created in, choose Create New. When complete, click OK.
  6. Select the size for the VM. To see more sizes, select View all or change the Supported disk type filter. On the settings blade, keep the defaults and click OK.

Enable MSI on your VM

A Virtual Machine MSI enables you to get access tokens from Azure AD without you needing to put credentials into your code. Under the covers, enabling MSI does two things: it installs the MSI VM extension on your VM and it enables Managed Service Identity for the VM.

  1. Navigate to the resource group of your new virtual machine, and select the virtual machine you created in the previous step.
  2. Under the VM "Settings" on the left, click Configuration.
  3. To register and enable the MSI, select Yes, if you wish to disable it, choose No.
  4. Ensure you click Save to save the configuration.

    Alt image text

  5. If you wish to check which extensions are on the VM, click Extensions. If MSI is enabled, the ManagedIdentityExtensionforLinux appears in the list.

    Alt image text

Create a storage account

If you don't already have one, you will now create a storage account. You can also skip this step and grant your VM MSI access to the keys of an existing storage account.

  1. Click the +/Create new service button found on the upper left-hand corner of the Azure portal.
  2. Click Storage, then Storage Account, and a new "Create storage account" panel will display.
  3. Enter a Name for the storage account, which you will use later.
  4. Deployment model and Account kind should be set to "Resource manager" and "General purpose", respectively.
  5. Ensure the Subscription and Resource Group match the ones you specified when you created your VM in the previous step.
  6. Click Create.

    Create new storage account

Create a blob container in the storage account

Later we will upload and download a file to the new storage account. Because files require blob storage, we need to create a blob container in which to store the file.

  1. Navigate back to your newly created storage account.
  2. Click the Containers link in the left, under "Blob service."
  3. Click + Container on the top of the page, and a "New container" panel slides out.
  4. Give the container a name, select an access level, then click OK. The name you specified will be used later in the tutorial.

    Create storage container

Grant your VM's MSI access to use storage account access keys

Azure Storage does not natively support Azure AD authentication. However, you can use an MSI to retrieve storage account access keys from the Resource Manager, then use a key to access storage. In this step, you grant your VM MSI access to the keys to your storage account.

  1. Navigate back to your newly created storage account.
  2. Click the Access control (IAM) link in the left panel.
  3. Click + Add on top of the page to add a new role assignment for your VM
  4. Set Role to "Storage Account Key Operator Service Role", on the right side of the page.
  5. In the next dropdown, set Assign access to the resource "Virtual Machine".
  6. Next, ensure the proper subscription is listed in Subscription dropdown, then set Resource Group to "All resource groups".
  7. Finally, under Select choose your Linux Virtual Machine in the dropdown, then click Save.

    Alt image text

Get an access token using the VM's identity and use it to call Azure Resource Manager

For the remainder of the tutorial, we will work from the VM we created earlier.

To complete these steps, you will need an SSH client. If you are using Windows, you can use the SSH client in the Windows Subsystem for Linux.

  1. In the Azure portal, navigate to Virtual Machines, go to your Linux virtual machine, then from the Overview page click Connect at the top. Copy the string to connect to your VM.
  2. Connect to your VM using your SSH client.
  3. Next, you will be prompted to enter in your Password you added when creating the Linux VM. You should then be successfully signed in.
  4. Use CURL to get an access token for Azure Resource Manager.

    The CURL request and response for the access token is below:

    curl http://localhost:50342/oauth2/token --data "resource=https://management.azure.com/" -H Metadata:true    
    
    Note

    In the previous request, the value of the "resource" parameter must be an exact match for what is expected by Azure AD. When using the Azure Resource Manager resource ID, you must include the trailing slash on the URI. In the following response, the access_token element as been shortened for brevity.

    {"access_token":"eyJ0eXAiOiJ...",
    "refresh_token":"",
    "expires_in":"3599",
    "expires_on":"1504130527",
    "not_before":"1504126627",
    "resource":"https://management.azure.com",
    "token_type":"Bearer"} 
    

Get storage account access keys from Azure Resource Manager to make storage calls

Now use CURL to call Resource Manager using the access token we retrieved in the previous section, to retrieve the storage access key. Once we have the storage access key, we can call storage upload/download operations. Be sure to replace the <SUBSCRIPTION ID>, <RESOURCE GROUP>, and <STORAGE ACCOUNT NAME> parameter values with your own values. Replace the <ACCESS TOKEN> value with the access token you retrieved earlier:

curl https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.Storage/storageAccounts/<STORAGE ACCOUNT NAME>/listKeys?api-version=2016-12-01 –-request POST -d "" -H "Authorization: Bearer <ACCESS TOKEN>" 
Note

The text in the prior URL is case sensitive, so ensure if you are using upper-lowercase for your Resource Groups to reflect it accordingly. Additionally, it’s important to know that this is a POST request not a GET request and ensure you pass a value to capture a length limit with -d that can be NULL.

The CURL response gives you the list of Keys:

{"keys":[{"keyName":"key1","permissions":"Full","value":"iqDPNt..."},{"keyName":"key2","permissions":"Full","value":"U+uI0B..."}]} 

Create a sample blob file to upload to your blob storage container. On a Linux VM you can do this with the following command.

echo "This is a test file." > test.txt

Next, authenticate with the CLI az storage command using the storage access key, and upload the file to the blob container. For this step, you will need to install the latest Azure CLI on your VM, if you haven't already.

az storage blob upload -c <CONTAINER NAME> -n test.txt -f test.txt --account-name <STORAGE ACCOUNT NAME> --account-key <STORAGE ACCOUNT KEY>

Response:

Finished[#############################################################]  100.0000%
{
  "etag": "\"0x8D4F9929765C139\"",
  "lastModified": "2017-09-12T03:58:56+00:00"
}

Additionally, you can download the file using the Azure CLI and authenticating with the storage access key.

Request:

az storage blob download -c <CONTAINER NAME> -n test.txt -f test-download.txt --account-name <STORAGE ACCOUNT NAME> --account-key <STORAGE ACCOUNT KEY>

Response:

{
  "content": null,
  "metadata": {},
  "name": "test.txt",
  "properties": {
    "appendBlobCommittedBlockCount": null,
    "blobType": "BlockBlob",
    "contentLength": 21,
    "contentRange": "bytes 0-20/21",
    "contentSettings": {
      "cacheControl": null,
      "contentDisposition": null,
      "contentEncoding": null,
      "contentLanguage": null,
      "contentMd5": "LSghAvpnElYyfUdn7CO8aw==",
      "contentType": "text/plain"
    },
    "copy": {
      "completionTime": null,
      "id": null,
      "progress": null,
      "source": null,
      "status": null,
      "statusDescription": null
    },
    "etag": "\"0x8D5067F30D0C283\"",
    "lastModified": "2017-09-28T14:42:49+00:00",
    "lease": {
      "duration": null,
      "state": "available",
      "status": "unlocked"
    },
    "pageBlobSequenceNumber": null,
    "serverEncrypted": false
  },
  "snapshot": null
}

Next steps

Use the following comments section to provide feedback and help us refine and shape our content.