Tutorial: Use a Linux VM system-assigned managed identity to access Azure Cosmos DB

Managed identities for Azure resources is a feature of Azure Active Directory. Each of the Azure services that support managed identities for Azure resources are subject to their own timeline. Make sure you review the availability status of managed identities for your resource and known issues before you begin.

This tutorial shows you how to use a system-assigned managed identity for a Linux virtual machine (VM) to access Azure Cosmos DB. You learn how to:

  • Create a Cosmos DB account
  • Create a collection in the Cosmos DB account
  • Grant the system-assigned managed identity access to an Azure Cosmos DB instance
  • Retrieve the principalID of the of the Linux VM's system-assigned managed identity
  • Get an access token and use it to call Azure Resource Manager
  • Get access keys from Azure Resource Manager to make Cosmos DB calls

Prerequisites

To run the CLI script examples in this tutorial, you have two options:

Create a Cosmos DB account

If you don't already have one, create a Cosmos DB account. You can skip this step and use an existing Cosmos DB account.

  1. Click the +/Create new service button found on the upper left-hand corner of the Azure portal.
  2. Click Databases, then Azure Cosmos DB, and a new "New account" panel displays.
  3. Enter an ID for the Cosmos DB account, which you use later.
  4. API should be set to "SQL." The approach described in this tutorial can be used with the other available API types, but the steps in this tutorial are for the SQL API.
  5. Ensure the Subscription and Resource Group match the ones you specified when you created your VM in the previous step. Select a Location where Cosmos DB is available.
  6. Click Create.

Create a collection in the Cosmos DB account

Next, add a data collection in the Cosmos DB account that you can query in later steps.

  1. Navigate to your newly created Cosmos DB account.
  2. On the Overview tab click the +/Add Collection button, and an "Add Collection" panel slides out.
  3. Give the collection a database ID, collection ID, select a storage capacity, enter a partition key, enter a throughput value, then click OK. For this tutorial, it is sufficient to use "Test" as the database ID and collection ID, select a fixed storage capacity and lowest throughput (400 RU/s).

Retrieve the principalID of the Linux VM's system-assigned managed identity

To gain access to the Cosmos DB account access keys from the Resource Manager in the following section, you need to retrieve the principalID of the Linux VM's system-assigned managed identity. Be sure to replace the <SUBSCRIPTION ID>, <RESOURCE GROUP> (resource group in which you VM resides), and <VM NAME> parameter values with your own values.

az resource show --id /subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.Compute/virtualMachines/<VM NAMe> --api-version 2017-12-01

The response includes the details of the system-assigned managed identity (note the principalID as it is used in the next section):

{
    "id": "/subscriptions/<SUBSCRIPTION ID>/<RESOURCE GROUP>/providers/Microsoft.Compute/virtualMachines/<VM NAMe>",
  "identity": {
    "principalId": "6891c322-314a-4e85-b129-52cf2daf47bd",
    "tenantId": "733a8f0e-ec41-4e69-8ad8-971fc4b533f8",
    "type": "SystemAssigned"
 }

Grant your Linux VM's system-assigned identity access to the Cosmos DB account access keys

Cosmos DB does not natively support Azure AD authentication. However, you can use a managed identity to retrieve a Cosmos DB access key from the Resource Manager, then use the key to access Cosmos DB. In this step, you grant your system-assigned managed identity access to the keys to the Cosmos DB account.

To grant the system-assigned managed identity access to the Cosmos DB account in Azure Resource Manager using the Azure CLI, update the values for <SUBSCRIPTION ID>, <RESOURCE GROUP>, and <COSMOS DB ACCOUNT NAME> for your environment. Replace <MI PRINCIPALID> with the principalId property returned by the az resource show command in Retrieve the principalID of the Linux VM's MI. Cosmos DB supports two levels of granularity when using access keys: read/write access to the account, and read-only access to the account. Assign the DocumentDB Account Contributor role if you want to get read/write keys for the account, or assign the Cosmos DB Account Reader Role role if you want to get read-only keys for the account:

az role assignment create --assignee <MI PRINCIPALID> --role '<ROLE NAME>' --scope "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMODS DB ACCOUNT NAME>"

The response includes the details for the role assignment created:

{
  "id": "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMOS DB ACCOUNT>/providers/Microsoft.Authorization/roleAssignments/5b44e628-394e-4e7b-bbc3-d6cd4f28f15b",
  "name": "5b44e628-394e-4e7b-bbc3-d6cd4f28f15b",
  "properties": {
    "principalId": "c0833082-6cc3-4a26-a1b1-c4b5f90a981f",
    "roleDefinitionId": "/subscriptions/<SUBSCRIPTION ID>/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8",
    "scope": "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMOS DB ACCOUNT>"
  },
  "resourceGroup": "<RESOURCE GROUP>",
  "type": "Microsoft.Authorization/roleAssignments"
}

Get an access token using the Linux VM's system-assigned managed identity and use it to call Azure Resource Manager

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

To complete these steps, you need an SSH client. If you are using Windows, you can use the SSH client in the Windows Subsystem for Linux. If you need assistance configuring your SSH client's keys, see How to Use SSH keys with Windows on Azure, or How to create and use an SSH public and private key pair for Linux VMs in Azure.

  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 are 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:

    curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https%3A%2F%2Fmanagement.azure.com%2F' -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":"eyJ0eXAiOi...",
     "expires_in":"3599",
     "expires_on":"1518503375",
     "not_before":"1518499475",
     "resource":"https://management.azure.com/",
     "token_type":"Bearer",
     "client_id":"1ef89848-e14b-465f-8780-bf541d325cd5"}
    

Get access keys from Azure Resource Manager to make Cosmos DB calls

Now use CURL to call Resource Manager using the access token retrieved in the previous section to retrieve the Cosmos DB account access key. Once we have the access key, we can query Cosmos DB. Be sure to replace the <SUBSCRIPTION ID>, <RESOURCE GROUP>, and <COSMOS DB ACCOUNT NAME> parameter values with your own values. Replace the <ACCESS TOKEN> value with the access token you retrieved earlier. If you want to retrieve read/write keys, use key operation type listKeys. If you want to retrieve read-only keys, use the key operation type readonlykeys:

curl 'https://management.azure.com/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMOS DB ACCOUNT NAME>/<KEY OPERATION TYPE>?api-version=2016-03-31' -X 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. For example, if you get the read-only keys:

{"primaryReadonlyMasterKey":"bWpDxS...dzQ==",
"secondaryReadonlyMasterKey":"38v5ns...7bA=="}

Now that you have the access key for the Cosmos DB account you can pass it to a Cosmos DB SDK and make calls to access the account. For a quick example, you can pass the access key to the Azure CLI. You can get the <COSMOS DB CONNECTION URL> from the Overview tab on the Cosmos DB account blade in the Azure portal. Replace the <ACCESS KEY> with the value you obtained above:

az cosmosdb collection show -c <COLLECTION ID> -d <DATABASE ID> --url-connection "<COSMOS DB CONNECTION URL>" --key <ACCESS KEY>

This CLI command returns details about the collection:

{
  "collection": {
    "_conflicts": "conflicts/",
    "_docs": "docs/",
    "_etag": "\"00006700-0000-0000-0000-5a8271e90000\"",
    "_rid": "Es5SAM2FDwA=",
    "_self": "dbs/Es5SAA==/colls/Es5SAM2FDwA=/",
    "_sprocs": "sprocs/",
    "_triggers": "triggers/",
    "_ts": 1518498281,
    "_udfs": "udfs/",
    "id": "Test",
    "indexingPolicy": {
      "automatic": true,
      "excludedPaths": [],
      "includedPaths": [
        {
          "indexes": [
            {
              "dataType": "Number",
              "kind": "Range",
              "precision": -1
            },
            {
              "dataType": "String",
              "kind": "Range",
              "precision": -1
            },
            {
              "dataType": "Point",
              "kind": "Spatial"
            }
          ],
          "path": "/*"
        }
      ],
      "indexingMode": "consistent"
    }
  },
  "offer": {
    "_etag": "\"00006800-0000-0000-0000-5a8271ea0000\"",
    "_rid": "f4V+",
    "_self": "offers/f4V+/",
    "_ts": 1518498282,
    "content": {
      "offerIsRUPerMinuteThroughputEnabled": false,
      "offerThroughput": 400
    },
    "id": "f4V+",
    "offerResourceId": "Es5SAM2FDwA=",
    "offerType": "Invalid",
    "offerVersion": "V2",
    "resource": "dbs/Es5SAA==/colls/Es5SAM2FDwA=/"
  }
}

Next steps

In this tutorial, you learned how to use a system-assigned managed identity on a Linux virtual machine to access Cosmos DB. To learn more about Cosmos DB see: