|
| 1 | +--- |
| 2 | +title: Use a user-assigned Managed Service Identity (MSI) on a Linux VM to access Azure Cosmos DB |
| 3 | +description: A tutorial that walks you through the process of using a User-Assigned Managed Service Identity (MSI) on a Linux VM, to access Azure Cosmos DB. |
| 4 | +services: active-directory |
| 5 | +documentationcenter: |
| 6 | +author: daveba |
| 7 | +manager: mtillman |
| 8 | +editor: |
| 9 | + |
| 10 | +ms.service: active-directory |
| 11 | +ms.devlang: na |
| 12 | +ms.topic: article |
| 13 | +ms.tgt_pltfrm: na |
| 14 | +ms.workload: identity |
| 15 | +ms.date: 02/14/2018 |
| 16 | +ms.author: skwan |
| 17 | +ROBOTS: NOINDEX,NOFOLLOW |
| 18 | +--- |
| 19 | +# Use a user-assigned Managed Service Identity (MSI) on a Linux VM to access Azure Cosmos DB |
| 20 | + |
| 21 | +[!INCLUDE[preview-notice](~/includes/active-directory-msi-preview-notice-ua.md)] |
| 22 | + |
| 23 | +This tutorial shows you how to create and use a user-assigned Managed Service Identity (MSI) from a Linux Virtual Machine, then use it to access Azure Cosmos DB. You learn how to: |
| 24 | + |
| 25 | +> [!div class="checklist"] |
| 26 | +> * Create a User Assigned Managed Service Identity (MSI) |
| 27 | +> * Assign the user-assigned MSI to a Linux Virtual Machine |
| 28 | +> * Grant the MSI access to an Azure Cosmos DB instance |
| 29 | +> * Get an access token using the user-assigned MSI identity, and use it to access Azure Cosmos DB |
| 30 | +
|
| 31 | +## Prerequisites |
| 32 | + |
| 33 | +[!INCLUDE [msi-core-prereqs](~/includes/active-directory-msi-core-prereqs-ua.md)] |
| 34 | + |
| 35 | +[!INCLUDE [msi-tut-prereqs](~/includes/active-directory-msi-tut-prereqs.md)] |
| 36 | + |
| 37 | +To run the CLI script examples in this tutorial, you have two options: |
| 38 | + |
| 39 | +- Use [Azure Cloud Shell](~/articles/cloud-shell/overview.md) either from the Azure portal, or via the **Try It** button, located in the top right corner of each code block. |
| 40 | +- [Install the latest version of CLI 2.0](https://docs.microsoft.com/cli/azure/install-azure-cli) (2.0.23 or later) if you prefer to use a local CLI console. |
| 41 | + |
| 42 | +## Sign in to Azure |
| 43 | + |
| 44 | +Sign in to the Azure portal at [https://portal.azure.com](https://portal.azure.com). |
| 45 | + |
| 46 | +## Create a Linux virtual machine in a new resource group |
| 47 | + |
| 48 | +For this tutorial, we create a new Linux VM. You can also enable MSI on an existing VM. |
| 49 | + |
| 50 | +1. Click the **+ Create a resource** found on the upper left-hand corner of the Azure portal. |
| 51 | +2. Select **Compute**, and then select **Ubuntu Server 16.04 LTS VM**. |
| 52 | +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. |
| 53 | + |
| 54 | +  |
| 55 | + |
| 56 | +4. Choose a **Subscription** for the virtual machine in the dropdown. |
| 57 | +5. Under **Resource Group**, choose **Create New** and type the name of the resource group for this VM. When complete, click **OK**. |
| 58 | +6. Select the size for the VM. To see more sizes, select **View all** or change the Supported disk type filter. In the **Settings** blade, keep the defaults and click **OK**. |
| 59 | + |
| 60 | +## Create a user-assigned MSI |
| 61 | + |
| 62 | +1. If you are using the CLI console (instead of an Azure Cloud Shell session), start by signing in to Azure. Use an account that is associated with the Azure subscription under which you would like to create the new MSI: |
| 63 | + |
| 64 | + ```azurecli |
| 65 | + az login |
| 66 | + ``` |
| 67 | +
|
| 68 | +2. Create a user-assigned MSI using [az identity create](/cli/azure/identity#az_identity_create). The `-g` parameter specifies the resource group where the MSI is created, and the `-n` parameter specifies its name. Be sure to replace the `<RESOURCE GROUP>` and `<MSI NAME>` parameter values with your own values: |
| 69 | +
|
| 70 | + ```azurecli-interactive |
| 71 | + az identity create -g <RESOURCE GROUP> -n <MSI NAME> |
| 72 | + ``` |
| 73 | +
|
| 74 | + The response contains details for the user-assigned MSI created, similar to the following example (note the `clientId` and `id` values for your MSI, as they are used in later steps): |
| 75 | +
|
| 76 | + ```json |
| 77 | + { |
| 78 | + "clientId": "73444643-8088-4d70-9532-c3a0fdc190fz", |
| 79 | + "clientSecretUrl": "https://control-westcentralus.identity.azure.net/subscriptions/<SUBSCRIPTON ID>/resourcegroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<MSI NAME>/credentials?tid=5678&oid=9012&aid=123444643-8088-4d70-9532-c3a0fdc190fz", |
| 80 | + "id": "/subscriptions/<SUBSCRIPTON ID>/resourcegroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<MSI NAME>", |
| 81 | + "location": "westcentralus", |
| 82 | + "name": "<MSI NAME>", |
| 83 | + "principalId": "c0833082-6cc3-4a26-a1b1-c4b5f90a981f", |
| 84 | + "resourceGroup": "<RESOURCE GROUP>", |
| 85 | + "tags": {}, |
| 86 | + "tenantId": "733a8f0e-ec41-4e69-8ad8-971fc4b533bl", |
| 87 | + "type": "Microsoft.ManagedIdentity/userAssignedIdentities" |
| 88 | + } |
| 89 | + ``` |
| 90 | +
|
| 91 | +## Assign your user-assigned MSI to your Linux VM |
| 92 | +
|
| 93 | +Unlike a system-assigned MSI, a user-assigned MSI can be used by clients on multiple Azure resources. For this tutorial, you assign it to a single VM. You can also assign it to more than one VM. |
| 94 | +
|
| 95 | +Assign the user-assigned MSI to your Linux VM using [az vm assign-identity](/cli/azure/vm#az_vm_assign_identity). Be sure to replace the `<RESOURCE GROUP>` and `<VM NAME>` parameter values with your own values. Use the `id` property returned in the previous step for the `--identities` parameter value: |
| 96 | +
|
| 97 | +```azurecli-interactive |
| 98 | +az vm assign-identity -g <RESOURCE GROUP> -n <VM NAME> --identities "/subscriptions/<SUBSCRIPTION ID>/resourcegroups/<RESOURCE GROUP>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/<MSI NAME>" |
| 99 | +``` |
| 100 | + |
| 101 | +## Create a Cosmos DB account |
| 102 | + |
| 103 | +If you don't already have one, now create a Cosmos DB account. You can also skip this step and use an existing Cosmos DB account, if you prefer. |
| 104 | + |
| 105 | +1. Click the **+/Create new service** button found on the upper left-hand corner of the Azure portal. |
| 106 | +2. Click **Databases**, then **Azure Cosmos DB**, and a new "New account" panel displays. |
| 107 | +3. Enter an **ID** for the Cosmos DB account, which you use later. |
| 108 | +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. |
| 109 | +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. |
| 110 | +6. Click **Create**. |
| 111 | + |
| 112 | +## Create a collection in the Cosmos DB account |
| 113 | + |
| 114 | +Next, add a data collection in the Cosmos DB account that you can query in later steps. |
| 115 | + |
| 116 | +1. Navigate to your newly created Cosmos DB account. |
| 117 | +2. On the **Overview** tab click the **+/Add Collection** button, and an "Add Collection" panel slides out. |
| 118 | +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). |
| 119 | + |
| 120 | +## Grant your User Assigned MSI access to the Cosmos DB account access keys |
| 121 | + |
| 122 | +Cosmos DB does not natively support Azure AD authentication. However, you can use an MSI 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 user assigned MSI access to the keys to the Cosmos DB account. |
| 123 | + |
| 124 | +First grant the MSI 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 `<MSI PRINCIPALID>` with the `principalId` property returned by the `az identity create` command in [Create a user-assigned MSI](#create-a-user-assigned-msi). 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: |
| 125 | + |
| 126 | +```azurecli-interactive |
| 127 | +az role assignment create --assignee <MSI PRINCIPALID> --role '<ROLE NAME>' --scope "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMODS DB ACCOUNT NAME>" |
| 128 | +``` |
| 129 | + |
| 130 | +The response includes the details for the role assignment created: |
| 131 | + |
| 132 | +``` |
| 133 | +{ |
| 134 | + "id": "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMOS DB ACCOUNT>/providers/Microsoft.Authorization/roleAssignments/5b44e628-394e-4e7b-bbc3-d6cd4f28f15b", |
| 135 | + "name": "5b44e628-394e-4e7b-bbc3-d6cd4f28f15b", |
| 136 | + "properties": { |
| 137 | + "principalId": "c0833082-6cc3-4a26-a1b1-c4b5f90a981f", |
| 138 | + "roleDefinitionId": "/subscriptions/<SUBSCRIPTION ID>/providers/Microsoft.Authorization/roleDefinitions/fbdf93bf-df7d-467e-a4d2-9458aa1360c8", |
| 139 | + "scope": "/subscriptions/<SUBSCRIPTION ID>/resourceGroups/<RESOURCE GROUP>/providers/Microsoft.DocumentDB/databaseAccounts/<COSMOS DB ACCOUNT>" |
| 140 | + }, |
| 141 | + "resourceGroup": "<RESOURCE GROUP>", |
| 142 | + "type": "Microsoft.Authorization/roleAssignments" |
| 143 | +} |
| 144 | +``` |
| 145 | + |
| 146 | +## Get an access token using the User Assigned MSI and use it to call Azure Resource Manager |
| 147 | + |
| 148 | +For the remainder of the tutorial, work from the VM created earlier. |
| 149 | + |
| 150 | +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](https://msdn.microsoft.com/commandline/wsl/install_guide). If you need assistance configuring your SSH client's keys, see [How to Use SSH keys with Windows on Azure](../../virtual-machines/linux/ssh-from-windows.md), or [How to create and use an SSH public and private key pair for Linux VMs in Azure](../../virtual-machines/linux/mac-create-ssh-keys.md). |
| 151 | + |
| 152 | +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. |
| 153 | +2. Connect to your VM using your SSH client. |
| 154 | +3. Next, you are prompted to enter in your **Password** you added when creating the **Linux VM**. You should then be successfully signed in. |
| 155 | +4. Use CURL to get an access token for Azure Resource Manager. |
| 156 | + |
| 157 | + The CURL request and response for the access token is below. Replace <CLIENT ID> with the clientId value of your user assigned MSI: |
| 158 | + |
| 159 | + ```bash |
| 160 | + curl 'http://localhost:50342/oauth2/token?resource=https://management.azure.com/&client_id=<CLIENT ID>' -H "Metadata:true" |
| 161 | + ``` |
| 162 | + |
| 163 | + > [!NOTE] |
| 164 | + > 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. |
| 165 | + > In the following response, the access_token element as been shortened for brevity. |
| 166 | + |
| 167 | + ```bash |
| 168 | + {"access_token":"eyJ0eXAiOi...", |
| 169 | + "expires_in":"3599", |
| 170 | + "expires_on":"1518503375", |
| 171 | + "not_before":"1518499475", |
| 172 | + "resource":"https://management.azure.com/", |
| 173 | + "token_type":"Bearer", |
| 174 | + "client_id":"1ef89848-e14b-465f-8780-bf541d325cd5"} |
| 175 | + ``` |
| 176 | + |
| 177 | +## Get access keys from Azure Resource Manager to make Cosmos DB calls |
| 178 | + |
| 179 | +Now use CURL to call Resource Manager using the access token we 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`: |
| 180 | + |
| 181 | +```bash |
| 182 | +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>" |
| 183 | +``` |
| 184 | + |
| 185 | +> [!NOTE] |
| 186 | +> 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. |
| 187 | + |
| 188 | +The CURL response gives you the list of Keys. For example, if you get the read-only keys: |
| 189 | + |
| 190 | +```bash |
| 191 | +{"primaryReadonlyMasterKey":"bWpDxS...dzQ==", |
| 192 | +"secondaryReadonlyMasterKey":"38v5ns...7bA=="} |
| 193 | +``` |
| 194 | + |
| 195 | +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: |
| 196 | + |
| 197 | +```bash |
| 198 | +az cosmosdb collection show -c <COLLECTION ID> -d <DATABASE ID> --url-connection "<COSMOS DB CONNECTION URL>" --key <ACCESS KEY> |
| 199 | +``` |
| 200 | + |
| 201 | +This CLI command returns details about the collection: |
| 202 | + |
| 203 | +```bash |
| 204 | +{ |
| 205 | + "collection": { |
| 206 | + "_conflicts": "conflicts/", |
| 207 | + "_docs": "docs/", |
| 208 | + "_etag": "\"00006700-0000-0000-0000-5a8271e90000\"", |
| 209 | + "_rid": "Es5SAM2FDwA=", |
| 210 | + "_self": "dbs/Es5SAA==/colls/Es5SAM2FDwA=/", |
| 211 | + "_sprocs": "sprocs/", |
| 212 | + "_triggers": "triggers/", |
| 213 | + "_ts": 1518498281, |
| 214 | + "_udfs": "udfs/", |
| 215 | + "id": "Test", |
| 216 | + "indexingPolicy": { |
| 217 | + "automatic": true, |
| 218 | + "excludedPaths": [], |
| 219 | + "includedPaths": [ |
| 220 | + { |
| 221 | + "indexes": [ |
| 222 | + { |
| 223 | + "dataType": "Number", |
| 224 | + "kind": "Range", |
| 225 | + "precision": -1 |
| 226 | + }, |
| 227 | + { |
| 228 | + "dataType": "String", |
| 229 | + "kind": "Range", |
| 230 | + "precision": -1 |
| 231 | + }, |
| 232 | + { |
| 233 | + "dataType": "Point", |
| 234 | + "kind": "Spatial" |
| 235 | + } |
| 236 | + ], |
| 237 | + "path": "/*" |
| 238 | + } |
| 239 | + ], |
| 240 | + "indexingMode": "consistent" |
| 241 | + } |
| 242 | + }, |
| 243 | + "offer": { |
| 244 | + "_etag": "\"00006800-0000-0000-0000-5a8271ea0000\"", |
| 245 | + "_rid": "f4V+", |
| 246 | + "_self": "offers/f4V+/", |
| 247 | + "_ts": 1518498282, |
| 248 | + "content": { |
| 249 | + "offerIsRUPerMinuteThroughputEnabled": false, |
| 250 | + "offerThroughput": 400 |
| 251 | + }, |
| 252 | + "id": "f4V+", |
| 253 | + "offerResourceId": "Es5SAM2FDwA=", |
| 254 | + "offerType": "Invalid", |
| 255 | + "offerVersion": "V2", |
| 256 | + "resource": "dbs/Es5SAA==/colls/Es5SAM2FDwA=/" |
| 257 | + } |
| 258 | +} |
| 259 | +``` |
| 260 | + |
| 261 | +## Next steps |
| 262 | + |
| 263 | +- For an overview of MSI, see [Managed Service Identity (MSI) for Azure resources](msi-overview.md). |
| 264 | + |
| 265 | +Use the following comments section to provide feedback and help us refine and shape our content. |
0 commit comments