Skip to content

Commit aefc04a

Browse files
authored
Updated configuring app settings for app services (#206)
1 parent caceeae commit aefc04a

7 files changed

Lines changed: 123 additions & 2 deletions

File tree

Sudoku.sln

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
23
# Visual Studio Version 18
34
VisualStudioVersion = 18.0.11222.15
45
MinimumVisualStudioVersion = 10.0.40219.1
@@ -42,6 +43,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{F2DF
4243
infra\modules\hostname.bicep = infra\modules\hostname.bicep
4344
infra\modules\keyvault.bicep = infra\modules\keyvault.bicep
4445
infra\modules\monitoring.bicep = infra\modules\monitoring.bicep
46+
infra\modules\roleassignments.bicep = infra\modules\roleassignments.bicep
4547
infra\modules\ssl.bicep = infra\modules\ssl.bicep
4648
infra\modules\storage.bicep = infra\modules\storage.bicep
4749
EndProjectSection

infra/main.bicep

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,23 @@ module compute 'modules/compute.bicep' = {
132132
customDomainName: customDomainName
133133
enableCustomDomain: enableCustomDomain
134134
appInsightsConnectionString: monitoring.outputs.appInsightsConnectionString
135+
keyVaultUri: keyvault.outputs.keyVaultUri
136+
cosmosDbEndpoint: storage.outputs.cosmosDbEndpoint
135137
}
136138
}
137139

140+
module roleassignments 'modules/roleassignments.bicep' = {
141+
name: 'roleassignments'
142+
params: {
143+
webAppPrincipalId: compute.outputs.webAppPrincipalId
144+
apiAppPrincipalId: compute.outputs.apiAppPrincipalId
145+
keyVaultName: keyVaultName
146+
cosmosDbAccountName: cosmosDbAccountName
147+
appConfigName: appConfigName
148+
}
149+
dependsOn: [storage, keyvault, appconfig]
150+
}
151+
138152
// Step 1: Bind the custom hostname to the web app (no SSL yet).
139153
// The managed certificate cannot be created until the hostname is bound.
140154
module hostname 'modules/hostname.bicep' = if (enableCustomDomain) {

infra/modules/compute.bicep

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ param appServicePlanSku string = 'B1'
77
param customDomainName string = 'sudoku.xenobiasoft.com'
88
param enableCustomDomain bool = false
99
param appInsightsConnectionString string
10+
param keyVaultUri string
11+
param cosmosDbEndpoint string
1012

1113
var corsAllowedOrigins = enableCustomDomain ? [
1214
'https://${customDomainName}'
@@ -113,6 +115,7 @@ resource webAppSettings 'Microsoft.Web/sites/config@2023-12-01' = {
113115
properties: {
114116
APPLICATIONINSIGHTS_CONNECTION_STRING: appInsightsConnectionString
115117
ApplicationInsightsAgent_EXTENSION_VERSION: '~3'
118+
'ConnectionStrings__AzureKeyVault': keyVaultUri
116119
}
117120
}
118121

@@ -179,6 +182,9 @@ resource apiAppSettings 'Microsoft.Web/sites/config@2023-12-01' = {
179182
properties: {
180183
APPLICATIONINSIGHTS_CONNECTION_STRING: appInsightsConnectionString
181184
ApplicationInsightsAgent_EXTENSION_VERSION: '~3'
185+
'ConnectionStrings__AzureKeyVault': keyVaultUri
186+
'CosmosDb__UseManagedIdentity': 'true'
187+
'CosmosDb__AccountEndpoint': cosmosDbEndpoint
182188
}
183189
}
184190

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
param webAppPrincipalId string
2+
param apiAppPrincipalId string
3+
param keyVaultName string
4+
param cosmosDbAccountName string
5+
param appConfigName string
6+
7+
// ---------------------------------------------------------------------------
8+
// Role definition IDs (built-in)
9+
// ---------------------------------------------------------------------------
10+
11+
var keyVaultSecretsUserRoleId = '4633458b-17de-408a-b874-0445c86b69e0'
12+
var appConfigDataReaderRoleId = '516239f1-63e1-4d78-a4de-a74fb236a071'
13+
14+
// Cosmos DB Built-in Data Contributor is a Cosmos DB SQL role, not a standard
15+
// Azure RBAC role — its ID is a well-known constant.
16+
var cosmosBuiltinDataContributorRoleId = '00000000-0000-0000-0000-000000000002'
17+
18+
// ---------------------------------------------------------------------------
19+
// Existing resource references
20+
// ---------------------------------------------------------------------------
21+
22+
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
23+
name: keyVaultName
24+
}
25+
26+
resource cosmosDbAccount 'Microsoft.DocumentDB/databaseAccounts@2024-05-15' existing = {
27+
name: cosmosDbAccountName
28+
}
29+
30+
resource appConfigStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = {
31+
name: appConfigName
32+
}
33+
34+
// ---------------------------------------------------------------------------
35+
// Key Vault — Secrets User for both apps
36+
// ---------------------------------------------------------------------------
37+
38+
resource webAppKeyVaultRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
39+
name: guid(webAppPrincipalId, keyVaultSecretsUserRoleId, keyVault.id)
40+
scope: keyVault
41+
properties: {
42+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultSecretsUserRoleId)
43+
principalId: webAppPrincipalId
44+
principalType: 'ServicePrincipal'
45+
}
46+
}
47+
48+
resource apiAppKeyVaultRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
49+
name: guid(apiAppPrincipalId, keyVaultSecretsUserRoleId, keyVault.id)
50+
scope: keyVault
51+
properties: {
52+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultSecretsUserRoleId)
53+
principalId: apiAppPrincipalId
54+
principalType: 'ServicePrincipal'
55+
}
56+
}
57+
58+
// ---------------------------------------------------------------------------
59+
// App Configuration — Data Reader for both apps
60+
// ---------------------------------------------------------------------------
61+
62+
resource webAppConfigRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
63+
name: guid(webAppPrincipalId, appConfigDataReaderRoleId, appConfigStore.id)
64+
scope: appConfigStore
65+
properties: {
66+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', appConfigDataReaderRoleId)
67+
principalId: webAppPrincipalId
68+
principalType: 'ServicePrincipal'
69+
}
70+
}
71+
72+
resource apiAppConfigRole 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
73+
name: guid(apiAppPrincipalId, appConfigDataReaderRoleId, appConfigStore.id)
74+
scope: appConfigStore
75+
properties: {
76+
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', appConfigDataReaderRoleId)
77+
principalId: apiAppPrincipalId
78+
principalType: 'ServicePrincipal'
79+
}
80+
}
81+
82+
// ---------------------------------------------------------------------------
83+
// Cosmos DB — Built-in Data Contributor for API only
84+
// (Blazor is a frontend and talks to the API via HTTP, not Cosmos DB directly)
85+
// ---------------------------------------------------------------------------
86+
87+
resource apiCosmosRole 'Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments@2024-05-15' = {
88+
parent: cosmosDbAccount
89+
name: guid(apiAppPrincipalId, cosmosDbAccount.id, cosmosBuiltinDataContributorRoleId)
90+
properties: {
91+
roleDefinitionId: '${cosmosDbAccount.id}/sqlRoleDefinitions/${cosmosBuiltinDataContributorRoleId}'
92+
principalId: apiAppPrincipalId
93+
scope: '/'
94+
}
95+
}

scripts/set-app-config.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set_key "CosmosDb:DatabaseName" "sudoku"
4848
set_key "CosmosDb:ContainerName" "games"
4949
set_key "CosmosDb:UseManagedIdentity" "true"
5050
set_key "CosmosDb:AccountEndpoint" "https://cosmos-sudoku-prod.documents.azure.com:443/"
51+
set_key "CosmosDb:ConnectionMode" "Direct"
5152

5253
# -----------------------------------------------------------------------------
5354
# Azure Storage

src/backend/Sudoku.Infrastructure/Configuration/CosmosDbOptions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Microsoft.Azure.Cosmos;
2+
13
namespace Sudoku.Infrastructure.Configuration;
24

35
public class CosmosDbOptions
@@ -9,4 +11,5 @@ public class CosmosDbOptions
911
public bool DisableSslValidation { get; set; }
1012
public bool UseManagedIdentity { get; set; }
1113
public string? AccountEndpoint { get; set; }
14+
public ConnectionMode ConnectionMode { get; set; } = ConnectionMode.Gateway;
1215
}

src/backend/Sudoku.Infrastructure/Configuration/InfrastructureServiceCollectionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ private IServiceCollection AddCosmosDbServices(IConfiguration configuration)
4747

4848
var clientOptions = new CosmosClientOptions
4949
{
50-
ConnectionMode = ConnectionMode.Direct,
50+
ConnectionMode = cosmosDbOptions?.ConnectionMode ?? ConnectionMode.Gateway,
5151
RequestTimeout = TimeSpan.FromSeconds(30),
5252
MaxRetryAttemptsOnRateLimitedRequests = 3,
5353
MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(15)

0 commit comments

Comments
 (0)