-
Notifications
You must be signed in to change notification settings - Fork 21.1k
/
managed-identity-based-authentication.yml
365 lines (313 loc) · 15.9 KB
/
managed-identity-based-authentication.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
### YamlMime:HowTo
---
metadata:
title: Use system-assigned managed identities to access Azure Cosmos DB data
description: Learn how to configure a Microsoft Entra system-assigned managed identity (managed service identity) to access keys from Azure Cosmos DB.
author: seesharprun
ms.author: sidandrews
ms.reviewer: justipat
ms.date: 06/25/2024
ms.service: cosmos-db
ms.subservice: nosql
ms.topic: how-to
ms.custom:
- devx-track-csharp
- devx-track-azurecli
- subject-rbac-steps
- ge-structured-content-pilot
ai-usage: ai-assisted
title: |
Use system-assigned managed identities to access Azure Cosmos DB data
introduction: |
[!INCLUDE[NoSQL](includes/appliesto-nosql.md)]
In this article, you'll set up a *robust, key rotation agnostic* solution to access Azure Cosmos DB keys by using [managed identities](../active-directory/managed-identities-azure-resources/services-support-managed-identities.md) and [data plane role-based access control](how-to-setup-rbac.md). The example in this article uses Azure Functions, but you can use any service that supports managed identities.
You'll learn how to create a function app that can access Azure Cosmos DB data without needing to copy any Azure Cosmos DB keys. The function app will trigger when an HTTP request is made and then list all of the existing databases.
prerequisites:
summary: |
- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F).
- An existing Azure Cosmos DB API for NoSQL account. [Create an Azure Cosmos DB API for NoSQL account](nosql/quickstart-portal.md)
- An existing Azure Functions function app. [Create your first function in the Azure portal](../azure-functions/functions-create-function-app-portal.md)
- A system-assigned managed identity for the function app. [Add a system-assigned identity](../app-service/overview-managed-identity.md#add-a-system-assigned-identity)
- [Azure Functions Core Tools](../azure-functions/functions-run-local.md)
- To perform the steps in this article, install the [Azure CLI](/cli/azure/install-azure-cli) and [sign in to Azure](/cli/azure/authenticate-azure-cli).
## Prerequisite check
1. In a terminal or command window, store the names of your Azure Functions function app, Azure Cosmos DB account and resource group as shell variables named ``functionName``, ``cosmosName``, and ``resourceGroupName``.
```azurecli-interactive
# Variable for function app name
functionName="msdocs-function-app"
# Variable for Azure Cosmos DB account name
cosmosName="msdocs-cosmos-app"
# Variable for resource group name
resourceGroupName="msdocs-cosmos-functions-dotnet-identity"
```
> [!NOTE]
> These variables are reused in later steps. This example assumes your Azure Cosmos DB account name is ``msdocs-cosmos-app``, your function app name is ``msdocs-function-app`` and your resource group name is ``msdocs-cosmos-functions-dotnet-identity``.
2. View the function app's properties using the [``az functionapp show``](/cli/azure/functionapp#az-functionapp-show) command.
```azurecli-interactive
az functionapp show \
--resource-group $resourceGroupName \
--name $functionName
```
3. View the properties of the system-assigned managed identity for your function app using [``az webapp identity show``](/cli/azure/webapp/identity#az-webapp-identity-show).
```azurecli-interactive
az webapp identity show \
--resource-group $resourceGroupName \
--name $functionName
```
4. View the Azure Cosmos DB account's properties using [``az cosmosdb show``](/cli/azure/cosmosdb#az-cosmosdb-show).
```azurecli-interactive
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName
```
procedureSection:
- title: |
Create Azure Cosmos DB API for NoSQL databases
summary: |
In this step, you create two databases.
steps:
- |
In a terminal or command window, create a new ``products`` database using [``az cosmosdb sql database create``](/cli/azure/cosmosdb/sql/database#az-cosmosdb-sql-database-create).
```azurecli-interactive
az cosmosdb sql database create \
--resource-group $resourceGroupName \
--name products \
--account-name $cosmosName
```
- |
Create a new ``customers`` database.
```azurecli-interactive
az cosmosdb sql database create \
--resource-group $resourceGroupName \
--name customers \
--account-name $cosmosName
```
- title: |
Get Azure Cosmos DB API for NoSQL endpoint
summary: |
In this step, you query the document endpoint for the API for NoSQL account.
steps:
- |
Use ``az cosmosdb show`` with the **query** parameter set to ``documentEndpoint``. Record the result. You'll use this value in a later step.
```azurecli-interactive
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query documentEndpoint
cosmosEndpoint=$(
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query documentEndpoint \
--output tsv
)
echo $cosmosEndpoint
```
> [!NOTE]
> This variable is reused in a later step.
- title: |
Grant access to your Azure Cosmos DB account
summary: |
In this step, you assign a role to the function app's system-assigned managed identity. Azure Cosmos DB has multiple built-in roles that you can assign to the managed identity for control-plane access. For data-plane access, you create a new custom role with access to read metadata.
> [!TIP]
> For more information about the importance of least privilege access, see the [Lower exposure of privileged accounts](../security/fundamentals/identity-management-best-practices.md#lower-exposure-of-privileged-accounts) article.
steps:
- |
Use ``az cosmosdb show`` with the **query** parameter set to ``id``. Store the result in a shell variable named ``scope``.
```azurecli-interactive
scope=$(
az cosmosdb show \
--resource-group $resourceGroupName \
--name $cosmosName \
--query id \
--output tsv
)
echo $scope
```
> [!NOTE]
> This variable is reused in a later step.
- |
Use ``az webapp identity show`` with the **query** parameter set to ``principalId``. Store the result in a shell variable named ``principal``.
```azurecli-interactive
principal=$(
az webapp identity show \
--resource-group $resourceGroupName \
--name $functionName \
--query principalId \
--output tsv
)
echo $principal
```
- |
Create a new JSON file with the configuration of the new custom role.
```json
{
"RoleName": "Read Azure Cosmos DB Metadata",
"Type": "CustomRole",
"AssignableScopes": ["/"],
"Permissions": [{
"DataActions": [
"Microsoft.DocumentDB/databaseAccounts/readMetadata"
]
}]
}
```
> [!TIP]
> You can create a file in the Azure Cloud Shell using either `touch <filename>` or the built-in editor (`code .`). For more information, see [Azure Cloud Shell editor](../cloud-shell/using-cloud-shell-editor.md)
- |
Use [``az cosmosdb sql role definition create``](/cli/azure/cosmosdb/sql/role/definition#az-cosmosdb-sql-role-definition-create) to create a new role definition named ``Read Azure Cosmos DB Metadata`` using the custom JSON object.
```azurecli-interactive
az cosmosdb sql role definition create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--body @definition.json
```
> [!NOTE]
> In this example, the role definition is defined in a file named **definition.json**.
- |
Use [``az role assignment create``](/cli/azure/cosmosdb/sql/role/assignment#az-cosmosdb-sql-role-assignment-create) to assign the ``Read Azure Cosmos DB Metadata`` role to the system-assigned managed identity.
```azurecli-interactive
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-name "Read Azure Cosmos DB Metadata" \
--principal-id $principal \
--scope $scope
```
- title: |
Programmatically access the Azure Cosmos DB keys
summary: |
We now have a function app that has a system-assigned managed identity with the custom role. The following function app will query the Azure Cosmos DB account for a list of databases.
steps:
- |
Create a local function project with the ``--dotnet`` parameter in a folder named ``csmsfunc``. Change your shell's directory
```azurecli-interactive
func init csmsfunc --dotnet
cd csmsfunc
```
- |
Create a new function with the **template** parameter set to ``httptrigger`` and the **name** set to ``readdatabases``.
```azurecli-interactive
func new --template httptrigger --name readdatabases
```
- |
Add the [``Azure.Identity``](https://www.nuget.org/packages/Azure.Identity/) and [``Microsoft.Azure.Cosmos``](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/) NuGet package to the .NET project. Build the project using [``dotnet build``](/dotnet/core/tools/dotnet-build).
```azurecli-interactive
dotnet add package Azure.Identity
dotnet add package Microsoft.Azure.Cosmos
dotnet build
```
- |
Open the function code in an integrated developer environment (IDE).
> [!TIP]
> If you are using the Azure CLI locally or in the Azure Cloud Shell, you can open Visual Studio Code.
>
> ```azurecli
> code .
> ```
>
- |
Replace the code in the **readdatabases.cs** file with this sample function implementation. Save the updated file.
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace csmsfunc
{
public static class readdatabases
{
[FunctionName("readdatabases")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req,
ILogger log)
{
log.LogTrace("Start function");
CosmosClient client = new CosmosClient(
accountEndpoint: Environment.GetEnvironmentVariable("COSMOS_ENDPOINT", EnvironmentVariableTarget.Process),
new DefaultAzureCredential()
);
using FeedIterator<DatabaseProperties> iterator = client.GetDatabaseQueryIterator<DatabaseProperties>();
List<(string name, string uri)> databases = new();
while(iterator.HasMoreResults)
{
foreach(DatabaseProperties database in await iterator.ReadNextAsync())
{
log.LogTrace($"[Database Found]\t{database.Id}");
databases.Add((database.Id, database.SelfLink));
}
}
return new OkObjectResult(databases);
}
}
}
```
- title: |
(Optional) Run the function locally
summary: |
In a local environment, the [``DefaultAzureCredential``](/dotnet/api/azure.identity.defaultazurecredential) class uses various local credentials to determine the current identity. While running locally isn't required for the how-to, you can develop locally using your own identity or a service principal.
steps:
- |
Get your local account's principal identifier using [`az ad signed-in-user show`](/cli/azure/ad/signed-in-user#az-ad-signed-in-user-show).
```azurecli-interactive
az ad signed-in-user show --query "id"
```
- |
Assign your local account role-based access control access to the Azure Cosmos DB account using [`az cosmosdb sql role assignment create`](/cli/azure/cosmosdb/sql/role/assignment#az-cosmosdb-sql-role-assignment-create) command. Use the built-in "Cosmos DB Data Contributor" role with an id of `00000000-0000-0000-0000-000000000002`.
```azurecli-interactive
az cosmosdb sql role assignment create \
--resource-group $resourceGroupName \
--account-name $cosmosName \
--role-definition-id "00000000-0000-0000-0000-000000000002" \
--principal-id "<your-principal-id>" \
--scope "/"
```
- |
In the **local.settings.json** file, add a new setting named ``COSMOS_ENDPOINT`` in the **Values** object. The value of the setting should be the document endpoint you recorded earlier in this how-to guide.
```json
...
"Values": {
...
"COSMOS_ENDPOINT": "https://msdocs-cosmos-app.documents.azure.com:443/",
...
}
...
```
> [!NOTE]
> This JSON object has been shortened for brevity. This JSON object also includes a sample value that assumes your account name is ``msdocs-cosmos-app``.
- |
Run the function app
```azurecli
func start
```
- title: |
Deploy to Azure
summary: |
Once published, the ``DefaultAzureCredential`` class uses credentials from the environment or a managed identity. For this guide, the system-assigned managed identity will be used as a credential for the [``CosmosClient``](/dotnet/api/microsoft.azure.cosmos.cosmosclient) constructor.
steps:
- |
Set the ``COSMOS_ENDPOINT`` setting on the function app already deployed in Azure.
```azurecli-interactive
az functionapp config appsettings set \
--resource-group $resourceGroupName \
--name $functionName \
--settings "COSMOS_ENDPOINT=$cosmosEndpoint"
```
- |
Deploy your function app to Azure by reusing the ``functionName`` shell variable:
```azurecli-interactive
func azure functionapp publish $functionName
```
- |
[Test your function in the Azure portal](../azure-functions/functions-create-function-app-portal.md#test-the-function).
relatedContent:
- text: Secure Azure Cosmos DB keys using Azure Key Vault
url: store-credentials-key-vault.md
- text: Security baseline for Azure Cosmos DB
url: security-baseline.md