Skip to content

Commit 1946720

Browse files
author
Seth
committed
WAF - network role update and param cleanup
1 parent 3fef520 commit 1946720

4 files changed

Lines changed: 67 additions & 64 deletions

File tree

infra/main.bicep

Lines changed: 41 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,19 @@ param azureAiServiceLocation string = location
3939
param capacity int = 5
4040

4141
@description('Enable monitoring for the resources. This will enable Application Insights and Log Analytics. Defaults to false.')
42-
param enableMonitoring bool = true
42+
param enableMonitoring bool = false
4343

4444
@description('Enable scaling for the container apps. Defaults to false.')
45-
param enableScaling bool = true
45+
param enableScaling bool = false
4646

4747
@description('Enable redundancy for applicable resources. Defaults to false.')
48-
param enableRedundancy bool = true
48+
param enableRedundancy bool = false
4949

50-
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled.')
50+
@description('Optional. The secondary location for the Cosmos DB account if redundancy is enabled. Defaults to false.')
5151
param secondaryLocation string?
5252

53-
@description('Optional. Enable private networking for the resources. Set to true to enable private networking.')
54-
param enablePrivateNetworking bool = true
53+
@description('Optional. Enable private networking for the resources. Set to true to enable private networking. Defaults to false.')
54+
param enablePrivateNetworking bool = false
5555

5656
@description('Optional. Specifies the resource tags for all the resources. Tag "azd-env-name" is automatically added to all resources.')
5757
param tags object = {}
@@ -89,7 +89,7 @@ module appIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.
8989
}
9090
}
9191

92-
module aiFoundryProjectIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = {
92+
module aiFoundryIdentity 'br/public:avm/res/managed-identity/user-assigned-identity:0.4.1' = {
9393
name: take('identity-proj-${resourcesName}-deployment', 64)
9494
params: {
9595
name: 'id-proj-${resourcesName}'
@@ -98,12 +98,20 @@ module aiFoundryProjectIdentity 'br/public:avm/res/managed-identity/user-assigne
9898
}
9999
}
100100

101+
// used for foundry to create and approve managed virtual network and approve private endpoint connections
102+
// Ref: https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/configure-managed-network?tabs=portal#approval-of-private-endpoints
103+
var foundryNetworkConnectionApproverRoleAssignment = {
104+
principalId: aiFoundryIdentity.outputs.principalId
105+
principalType: 'ServicePrincipal'
106+
roleDefinitionIdOrName: 'b556d68e-0be0-4f35-a333-ad7ee1ce17ea' // Azure AI Enterprise Network Connection Approver
107+
}
108+
101109
module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (enableMonitoring || enablePrivateNetworking) {
102110
name: take('log-analytics-${resourcesName}-deployment', 64)
103111
params: {
104112
name: 'log-${resourcesName}'
105113
location: location
106-
skuName: 'PerGB2018'
114+
skuName: 'PerGB2018'
107115
dataRetention: 30
108116
diagnosticSettings: [{ useThisWorkspace: true }]
109117
tags: allTags
@@ -159,6 +167,7 @@ module storageAccount 'modules/storageAccount.bicep' = {
159167
principalType: 'ServicePrincipal'
160168
roleDefinitionIdOrName: 'Storage Blob Data Contributor'
161169
}
170+
foundryNetworkConnectionApproverRoleAssignment
162171
]
163172
}
164173
}
@@ -191,10 +200,11 @@ module azureAiServices 'modules/aiServices.bicep' = {
191200
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
192201
}
193202
{
194-
principalId: aiFoundryProjectIdentity.outputs.principalId
203+
principalId: aiFoundryIdentity.outputs.principalId
195204
principalType: 'ServicePrincipal'
196205
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
197206
}
207+
foundryNetworkConnectionApproverRoleAssignment
198208
]
199209
tags: allTags
200210
}
@@ -215,10 +225,11 @@ module keyVault 'modules/keyVault.bicep' = {
215225
} : null
216226
roleAssignments: [
217227
{
218-
principalId: aiFoundryProjectIdentity.outputs.principalId
228+
principalId: aiFoundryIdentity.outputs.principalId
219229
principalType: 'ServicePrincipal'
220230
roleDefinitionIdOrName: 'Key Vault Reader'
221231
}
232+
foundryNetworkConnectionApproverRoleAssignment
222233
]
223234
tags: allTags
224235
}
@@ -235,7 +246,7 @@ module azureAifoundry 'modules/aiFoundry.bicep' = {
235246
projectName: 'proj-${resourcesName}'
236247
storageAccountResourceId: storageAccount.outputs.resourceId
237248
keyVaultResourceId: keyVault.outputs.resourceId
238-
userAssignedIdentityResourceId: aiFoundryProjectIdentity.outputs.resourceId
249+
userAssignedIdentityResourceId: aiFoundryIdentity.outputs.resourceId
239250
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
240251
aiServicesName: azureAiServices.outputs.name
241252
privateNetworking: enablePrivateNetworking ? {
@@ -260,19 +271,22 @@ module cosmosDb 'modules/cosmosDb.bicep' = {
260271
params: {
261272
name: 'cosmos-${uniqueResourcesName}'
262273
location: location
263-
managedIdentityPrincipalId: appIdentity.outputs.principalId
274+
dataAccessIdentityPrincipalId: appIdentity.outputs.principalId
264275
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
265276
zoneRedundant: enableRedundancy
266277
secondaryLocation: enableRedundancy && !empty(secondaryLocation) ? secondaryLocation : ''
267278
privateNetworking: enablePrivateNetworking ? {
268279
virtualNetworkResourceId: network.outputs.vnetResourceId
269280
subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'data')).resourceId
270281
} : null
282+
roleAssignments: [
283+
foundryNetworkConnectionApproverRoleAssignment
284+
]
271285
tags: allTags
272286
}
273287
}
274288

275-
var containerAppsEnvironmentName = 'cae-${resourcesName}${enablePrivateNetworking ? '-frontend' : ''}'
289+
var containerAppsEnvironmentName = 'cae-${resourcesName}'
276290

277291
module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.2' = {
278292
name: take('container-env-${resourcesName}-deployment', 64)
@@ -283,7 +297,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
283297
infrastructureResourceGroupName: '${resourceGroup().name}-ME-${containerAppsEnvironmentName}'
284298
location: location
285299
zoneRedundant: enableRedundancy && enablePrivateNetworking
286-
publicNetworkAccess: 'Enabled' // public access required for frontend (and backend if private networking is not enabled)
300+
publicNetworkAccess: 'Enabled' // public access required for frontend
287301
infrastructureSubnetResourceId: enablePrivateNetworking ? first(filter(network.outputs.subnets, s => s.name == 'web')).resourceId : null
288302
managedIdentities: {
289303
userAssignedResourceIds: [
@@ -308,7 +322,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
308322
}
309323
}
310324

311-
module containerAppFrontend 'br/public:avm/res/app/container-app:0.16.0' = {
325+
module containerAppFrontend 'br/public:avm/res/app/container-app:0.17.0' = {
312326
name: take('container-app-frontend-${resourcesName}-deployment', 64)
313327
params: {
314328
name: take('ca-${uniqueResourcesName}frontend', 32)
@@ -336,7 +350,7 @@ module containerAppFrontend 'br/public:avm/res/app/container-app:0.16.0' = {
336350
}
337351
]
338352
ingressTargetPort: 3000
339-
ingressExternal: true // public access required for frontend
353+
ingressExternal: true
340354
scaleSettings: {
341355
maxReplicas: enableScaling ? 3 : 1
342356
minReplicas: 1
@@ -355,52 +369,14 @@ module containerAppFrontend 'br/public:avm/res/app/container-app:0.16.0' = {
355369
}
356370
}
357371

358-
var containerAppsEnvironmentBackendName = 'cae-${resourcesName}-backend'
359-
360-
module containerAppsEnvironmentBackend 'br/public:avm/res/app/managed-environment:0.11.2' = if (enablePrivateNetworking) {
361-
name: take('container-env-backend-${resourcesName}-deployment', 64)
362-
#disable-next-line no-unnecessary-dependson
363-
dependsOn: [applicationInsights, logAnalyticsWorkspace] // required due to optional flags that could change dependency
364-
params: {
365-
name: containerAppsEnvironmentBackendName
366-
infrastructureResourceGroupName: '${resourceGroup().name}-ME-${containerAppsEnvironmentBackendName}'
367-
location: location
368-
zoneRedundant: enableRedundancy
369-
publicNetworkAccess: 'Disabled' // public access denied for backend
370-
infrastructureSubnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'app')).resourceId
371-
managedIdentities: {
372-
userAssignedResourceIds: [
373-
appIdentity.outputs.resourceId
374-
]
375-
}
376-
appInsightsConnectionString: enableMonitoring ? applicationInsights.outputs.connectionString : null
377-
appLogsConfiguration: enableMonitoring ? {
378-
destination: 'log-analytics'
379-
logAnalyticsConfiguration: {
380-
customerId: logAnalyticsWorkspace.outputs.logAnalyticsWorkspaceId
381-
sharedKey: logAnalyticsWorkspace.outputs.primarySharedKey
382-
}
383-
} : {}
384-
workloadProfiles: [ // NOTE: workload profiles are required for private networking
385-
{
386-
name: 'Consumption'
387-
workloadProfileType: 'Consumption'
388-
}
389-
]
390-
tags: allTags
391-
}
392-
}
393-
394-
var containerAppsEnvironmentResourceId = enablePrivateNetworking ? containerAppsEnvironmentBackend.outputs.resourceId : containerAppsEnvironment.outputs.resourceId
395-
396-
module containerAppBackend 'br/public:avm/res/app/container-app:0.16.0' = {
372+
module containerAppBackend 'br/public:avm/res/app/container-app:0.17.0' = {
397373
name: take('container-app-backend-${resourcesName}-deployment', 64)
398374
#disable-next-line no-unnecessary-dependson
399-
dependsOn: [applicationInsights, containerAppsEnvironmentBackend] // required due to optional flags that could change dependency
375+
dependsOn: [applicationInsights] // required due to optional flags that could change dependency
400376
params: {
401377
name: take('ca-${uniqueResourcesName}backend', 32)
402378
location: location
403-
environmentResourceId: containerAppsEnvironmentResourceId
379+
environmentResourceId: containerAppsEnvironment.outputs.resourceId
404380
managedIdentities: {
405381
userAssignedResourceIds: [
406382
appIdentity.outputs.resourceId
@@ -523,7 +499,13 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.16.0' = {
523499
}
524500
]
525501
ingressTargetPort: 8000
526-
ingressExternal: false // set to false to prevent public access
502+
ingressExternal: true
503+
// TODO - need way to set this CORS policy after frontend container app is deployed (issue is circular dependency since frontend needs backend to be deployed first)
504+
// corsPolicy: {
505+
// allowedOrigins: [
506+
// 'https://${containerAppFrontend.outputs.fqdn}'
507+
// ]
508+
// }
527509
scaleSettings: {
528510
maxReplicas: enableScaling ? 3 : 1
529511
minReplicas: 1
@@ -541,3 +523,4 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.16.0' = {
541523
tags: allTags
542524
}
543525
}
526+

infra/main.bicepparam

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using './main.bicep'
22

3-
param location = readEnvironmentVariable('AZURE_LOCATION','japaneast')
4-
param azureAiServiceLocation = location
5-
param environmentName = readEnvironmentVariable('AZURE_ENV_NAME','azdtemp')
6-
3+
param environmentName = readEnvironmentVariable('AZURE_ENV_NAME')
4+
param location = readEnvironmentVariable('AZURE_LOCATION')

infra/modules/aiFoundry.bicep

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,24 @@ module hub 'br/public:avm/res/machine-learning-services/workspace:0.12.1' = {
8484
associatedStorageAccountResourceId: storageAccountResourceId
8585
associatedApplicationInsightsResourceId: applicationInsightsResourceId
8686
publicNetworkAccess: privateNetworking != null ? 'Disabled' : 'Enabled'
87+
managedNetworkSettings: {
88+
isolationMode: privateNetworking != null ? 'AllowInternetOutbound' : 'Disabled'
89+
outboundRules: {
90+
cog_services_pep: {
91+
category: 'UserDefined'
92+
destination: {
93+
serviceResourceId: aiServices.id
94+
sparkEnabled: true
95+
subresourceTarget: 'account'
96+
}
97+
type: 'PrivateEndpoint'
98+
}
99+
}
100+
}
87101
managedIdentities: {
88102
systemAssigned: true
89103
}
104+
systemDatastoresAuthMode: 'Identity'
90105
diagnosticSettings: !empty(logAnalyticsWorkspaceResourceId) ? [{workspaceResourceId: logAnalyticsWorkspaceResourceId}] : []
91106
privateEndpoints: privateNetworking != null ? [
92107
{
@@ -133,6 +148,8 @@ module project 'br/public:avm/res/machine-learning-services/workspace:0.12.1' =
133148
sku: 'Standard'
134149
location: location
135150
hubResourceId: hub.outputs.resourceId
151+
hbiWorkspace: false
152+
systemDatastoresAuthMode: 'Identity'
136153
publicNetworkAccess: privateNetworking != null ? 'Disabled' : 'Enabled'
137154
managedIdentities: {
138155
userAssignedResourceIds: [userAssignedIdentityResourceId]

infra/modules/cosmosDb.bicep

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ param location string
88
param tags object = {}
99

1010
@description('Managed Identity princpial to assign data plane roles for the Cosmos DB Account.')
11-
param managedIdentityPrincipalId string
11+
param dataAccessIdentityPrincipalId string
1212

1313
@description('Optional. The resource ID of an existing Log Analytics workspace to associate with AI Foundry for monitoring.')
1414
param logAnalyticsWorkspaceResourceId string?
@@ -22,6 +22,9 @@ param secondaryLocation string?
2222
@description('Optional. Values to establish private networking for the Cosmos DB resource.')
2323
param privateNetworking resourcePrivateNetworkingType?
2424

25+
@description('Optional. Array of role assignments to create.')
26+
param roleAssignments roleAssignmentType[]?
27+
2528
module privateDnsZone 'br/public:avm/res/network/private-dns-zone:0.7.1' = if (privateNetworking != null && empty(privateNetworking.?privateDnsZoneResourceId)) {
2629
name: take('${name}-documents-pdns-deployment', 64)
2730
params: {
@@ -131,15 +134,17 @@ module cosmosAccount 'br/public:avm/res/document-db/database-account:0.15.0' = {
131134
]
132135
dataPlaneRoleAssignments: [
133136
{
134-
principalId: managedIdentityPrincipalId
137+
principalId: dataAccessIdentityPrincipalId
135138
roleDefinitionId: sqlContributorRoleDefinition.id
136139
}
137140
]
141+
roleAssignments: roleAssignments
138142
tags: tags
139143
}
140144
}
141145

142146
import { resourcePrivateNetworkingType } from 'customTypes.bicep'
147+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
143148

144149
output resourceId string = cosmosAccount.outputs.resourceId
145150
output name string = cosmosAccount.outputs.name

0 commit comments

Comments
 (0)