Skip to content

Commit e14d091

Browse files
authored
Merge pull request #28 from Azure-Samples/copilot/fix-27
Fix Azure Cosmos DB authentication to use managed identity instead of connection strings
2 parents 1a5662b + c32f380 commit e14d091

20 files changed

+766
-345
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
param cosmosAccountName string
2+
param apiPrincipalId string
3+
4+
// Create a role assignment for the API's managed identity to access Cosmos DB
5+
// Using the built-in "Cosmos DB Built-in Data Contributor" role
6+
resource apiCosmosRoleAssignment 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2024-05-15' = {
7+
name: '${cosmosAccountName}/${guid(apiPrincipalId, cosmosAccountName, '00000000-0000-0000-0000-000000000002')}'
8+
properties: {
9+
roleDefinitionId: '${resourceGroup().id}/providers/Microsoft.DocumentDB/databaseAccounts/${cosmosAccountName}/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002'
10+
principalId: apiPrincipalId
11+
scope: '${resourceGroup().id}/providers/Microsoft.DocumentDB/databaseAccounts/${cosmosAccountName}'
12+
}
13+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
3+
"contentVersion": "1.0.0.0",
4+
"metadata": {
5+
"_generator": {
6+
"name": "bicep",
7+
"version": "0.36.1.42791",
8+
"templateHash": "7411539156170877165"
9+
}
10+
},
11+
"parameters": {
12+
"cosmosAccountName": {
13+
"type": "string"
14+
},
15+
"apiPrincipalId": {
16+
"type": "string"
17+
}
18+
},
19+
"resources": [
20+
{
21+
"type": "Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments",
22+
"apiVersion": "2024-05-15",
23+
"name": "[format('{0}/{1}', parameters('cosmosAccountName'), guid(parameters('apiPrincipalId'), parameters('cosmosAccountName'), '00000000-0000-0000-0000-000000000002'))]",
24+
"properties": {
25+
"roleDefinitionId": "[format('{0}/providers/Microsoft.DocumentDB/databaseAccounts/{1}/sqlRoleDefinitions/00000000-0000-0000-0000-000000000002', resourceGroup().id, parameters('cosmosAccountName'))]",
26+
"principalId": "[parameters('apiPrincipalId')]",
27+
"scope": "[format('{0}/providers/Microsoft.DocumentDB/databaseAccounts/{1}', resourceGroup().id, parameters('cosmosAccountName'))]"
28+
}
29+
}
30+
]
31+
}

infra/app/db-avm.bicep

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,17 @@ param accountName string
22
param location string = resourceGroup().location
33
param tags object = {}
44
param cosmosDatabaseName string = ''
5-
param keyVaultResourceId string
6-
param connectionStringKey string = 'AZURE-COSMOS-CONNECTION-STRING'
7-
param collections array = [
5+
param containers array = [
86
{
97
name: 'TodoList'
10-
id: 'TodoList'
11-
shardKey: {
12-
keys: [
13-
'Hash'
14-
]
15-
}
16-
indexes: [
17-
{
18-
key: {
19-
keys: [
20-
'_id'
21-
]
22-
}
23-
}
8+
paths: [
9+
'/id'
2410
]
2511
}
2612
{
2713
name: 'TodoItem'
28-
id: 'TodoItem'
29-
shardKey: {
30-
keys: [
31-
'Hash'
32-
]
33-
}
34-
indexes: [
35-
{
36-
key: {
37-
keys: [
38-
'_id'
39-
]
40-
}
41-
}
14+
paths: [
15+
'/id'
4216
]
4317
}
4418
]
@@ -47,7 +21,7 @@ var defaultDatabaseName = 'Todo'
4721
var actualDatabaseName = !empty(cosmosDatabaseName) ? cosmosDatabaseName : defaultDatabaseName
4822

4923
module cosmos 'br/public:avm/res/document-db/database-account:0.6.0' = {
50-
name: 'cosmos-mongo'
24+
name: 'cosmos-sql'
5125
params: {
5226
locations: [
5327
{
@@ -58,20 +32,18 @@ module cosmos 'br/public:avm/res/document-db/database-account:0.6.0' = {
5832
]
5933
name: accountName
6034
location: location
61-
mongodbDatabases: [
35+
disableLocalAuth: true
36+
sqlDatabases: [
6237
{
6338
name: actualDatabaseName
6439
tags: tags
65-
collections: collections
40+
containers: containers
6641
}
6742
]
68-
secretsExportConfiguration: {
69-
keyVaultResourceId: keyVaultResourceId
70-
primaryWriteConnectionStringSecretName: connectionStringKey
71-
}
7243
}
7344
}
7445

75-
output connectionStringKey string = connectionStringKey
7646
output databaseName string = actualDatabaseName
7747
output endpoint string = cosmos.outputs.endpoint
48+
output accountName string = accountName
49+
output resourceId string = cosmos.outputs.resourceId

infra/main.bicep

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,8 @@ module api './app/api-appservice-avm.bicep' = {
7474
}
7575
appSettings: {
7676
AZURE_KEY_VAULT_ENDPOINT: keyVault.outputs.uri
77-
AZURE_COSMOS_CONNECTION_STRING_KEY: cosmos.outputs.connectionStringKey
7877
AZURE_COSMOS_DATABASE_NAME: cosmos.outputs.databaseName
79-
AZURE_COSMOS_ENDPOINT: 'https://${cosmos.outputs.databaseName}.documents.azure.com:443/'
78+
AZURE_COSMOS_ENDPOINT: cosmos.outputs.endpoint
8079
API_ALLOW_ORIGINS: web.outputs.SERVICE_WEB_URI
8180
SCM_DO_BUILD_DURING_DEPLOYMENT: true
8281
}
@@ -121,7 +120,16 @@ module cosmos './app/db-avm.bicep' = {
121120
accountName: !empty(cosmosAccountName) ? cosmosAccountName : '${abbrs.documentDBDatabaseAccounts}${resourceToken}'
122121
location: location
123122
tags: tags
124-
keyVaultResourceId: keyVault.outputs.resourceId
123+
}
124+
}
125+
126+
// Give the API managed identity access to Cosmos DB using built-in Data Contributor role
127+
module apiCosmosRoleAssignment './app/cosmos-role-assignment.bicep' = {
128+
name: 'api-cosmos-role'
129+
scope: rg
130+
params: {
131+
cosmosAccountName: cosmos.outputs.accountName
132+
apiPrincipalId: api.outputs.SERVICE_API_IDENTITY_PRINCIPAL_ID
125133
}
126134
}
127135

@@ -217,8 +225,8 @@ module apimApi 'br/public:avm/ptn/azd/apim-api:0.1.0' = if (useAPIM) {
217225
}
218226

219227
// Data outputs
220-
output AZURE_COSMOS_CONNECTION_STRING_KEY string = cosmos.outputs.connectionStringKey
221228
output AZURE_COSMOS_DATABASE_NAME string = cosmos.outputs.databaseName
229+
output AZURE_COSMOS_ENDPOINT string = cosmos.outputs.endpoint
222230

223231
// App outputs
224232
output APPLICATIONINSIGHTS_CONNECTION_STRING string = monitoring.outputs.applicationInsightsConnectionString

src/api/config/custom-environment-variables.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"database": {
3-
"connectionString": "AZURE_COSMOS_CONNECTION_STRING",
3+
"endpoint": "AZURE_COSMOS_ENDPOINT",
44
"databaseName": "AZURE_COSMOS_DATABASE_NAME"
55
},
66
"observability": {

src/api/config/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"database": {
3-
"connectionString": "",
3+
"endpoint": "",
44
"databaseName": "Todo"
55
},
66
"observability": {

src/api/config/test.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"database": {
3+
"endpoint": "https://mock-cosmos-endpoint.documents.azure.com:443/",
4+
"databaseName": "MockTodo"
5+
},
6+
"observability": {
7+
"connectionString": "InstrumentationKey=00000000-0000-0000-0000-000000000000",
8+
"roleName": "API"
9+
}
10+
}

0 commit comments

Comments
 (0)