Skip to content

Commit 6d1d94c

Browse files
author
Seth
committed
WAF - naming and infra cleanup. networking adjustments (WIP)
1 parent cb250d1 commit 6d1d94c

10 files changed

Lines changed: 193 additions & 220 deletions

File tree

infra/main.bicep

Lines changed: 56 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
@minLength(3)
2-
@maxLength(20)
3-
@description('A unique application/env name for all resources in this deployment. This should be 3-20 characters long')
4-
param environmentName string
2+
@maxLength(16)
3+
@description('A unique application/solution name for all resources in this deployment. This should be 3-16 characters long.')
4+
param solutionName string
5+
6+
@maxLength(5)
7+
@description('A unique token for the solution. This is used to ensure resource names are unique for global resources. Defaults to a 5-character substring of the unique string generated from the subscription ID, resource group name, and solution name.')
8+
param solutionUniqueToken string = substring(uniqueString(subscription().id, resourceGroup().name, solutionName), 0, 5)
59

610
@minLength(3)
711
@description('Azure region for all services.')
@@ -57,14 +61,10 @@ param enablePrivateNetworking bool = false
5761
param tags object = {}
5862

5963
var allTags = union({
60-
'azd-env-name': environmentName
64+
'azd-env-name': solutionName
6165
}, tags)
6266

63-
var resourcesName = trim(replace(replace(replace(replace(replace(environmentName, '-', ''), '_', ''), '.', ''),'/', ''), ' ', ''))
64-
var resourcesToken = substring(uniqueString(subscription().id, location, resourcesName), 0, 5)
65-
var uniqueResourcesName = '${resourcesName}${resourcesToken}'
66-
67-
var appStorageContainerName = 'appstorage'
67+
var resourcesName = trim(replace(replace(replace(replace(replace('${solutionName}${solutionUniqueToken}', '-', ''), '_', ''), '.', ''),'/', ''), ' ', ''))
6868

6969
var modelDeployment = {
7070
name: 'gpt-4o'
@@ -98,14 +98,6 @@ module aiFoundryIdentity 'br/public:avm/res/managed-identity/user-assigned-ident
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-
109101
module logAnalyticsWorkspace 'br/public:avm/res/operational-insights/workspace:0.11.2' = if (enableMonitoring || enablePrivateNetworking) {
110102
name: take('log-analytics-${resourcesName}-deployment', 64)
111103
params: {
@@ -139,45 +131,12 @@ module network 'modules/network.bicep' = if (enablePrivateNetworking) {
139131
}
140132
}
141133

142-
module storageAccount 'modules/storageAccount.bicep' = {
143-
name: take('storage-account-${resourcesName}-deployment', 64)
144-
#disable-next-line no-unnecessary-dependson
145-
dependsOn: [logAnalyticsWorkspace, network] // required due to optional flags that could change dependency
146-
params: {
147-
name: take('st${uniqueResourcesName}', 24)
148-
location: location
149-
tags: allTags
150-
skuName: enableRedundancy ? 'Standard_GZRS' : 'Standard_LRS'
151-
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
152-
privateNetworking: enablePrivateNetworking ? {
153-
virtualNetworkResourceId: network.outputs.vnetResourceId
154-
subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'data')).resourceId
155-
} : null
156-
containers: [
157-
{
158-
name: appStorageContainerName
159-
properties: {
160-
publicAccess: 'None'
161-
}
162-
}
163-
]
164-
roleAssignments: [
165-
{
166-
principalId: appIdentity.outputs.principalId
167-
principalType: 'ServicePrincipal'
168-
roleDefinitionIdOrName: 'Storage Blob Data Contributor'
169-
}
170-
foundryNetworkConnectionApproverRoleAssignment
171-
]
172-
}
173-
}
174-
175-
module azureAiServices 'modules/aiServices.bicep' = {
134+
module aiServices 'modules/aiServices.bicep' = {
176135
name: take('aiservices-${resourcesName}-deployment', 64)
177136
#disable-next-line no-unnecessary-dependson
178137
dependsOn: [logAnalyticsWorkspace, network] // required due to optional flags that could change dependency
179138
params: {
180-
name: 'ais-${uniqueResourcesName}'
139+
name: 'ais-${resourcesName}'
181140
location: azureAiServiceLocation
182141
sku: 'S0'
183142
kind: 'AIServices'
@@ -190,7 +149,7 @@ module azureAiServices 'modules/aiServices.bicep' = {
190149
// ---------------------
191150
// privateNetworking: enablePrivateNetworking ? {
192151
// virtualNetworkResourceId: network.outputs.vnetResourceId
193-
// subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'ai')).resourceId
152+
// subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'peps')).resourceId
194153
// } : null
195154
// ---------------------
196155
roleAssignments: [
@@ -204,32 +163,64 @@ module azureAiServices 'modules/aiServices.bicep' = {
204163
principalType: 'ServicePrincipal'
205164
roleDefinitionIdOrName: 'Cognitive Services OpenAI Contributor'
206165
}
207-
foundryNetworkConnectionApproverRoleAssignment
208166
]
209167
tags: allTags
210168
}
211169
}
212170

171+
var appStorageContainerName = 'appstorage'
172+
173+
module storageAccount 'modules/storageAccount.bicep' = {
174+
name: take('storage-account-${resourcesName}-deployment', 64)
175+
#disable-next-line no-unnecessary-dependson
176+
dependsOn: [logAnalyticsWorkspace, network] // required due to optional flags that could change dependency
177+
params: {
178+
name: take('st${resourcesName}', 24)
179+
location: location
180+
tags: allTags
181+
skuName: enableRedundancy ? 'Standard_GZRS' : 'Standard_LRS'
182+
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
183+
privateNetworking: enablePrivateNetworking ? {
184+
virtualNetworkResourceId: network.outputs.vnetResourceId
185+
subnetResourceId: network.outputs.subnetPrivateEndpointsResourceId
186+
} : null
187+
containers: [
188+
{
189+
name: appStorageContainerName
190+
properties: {
191+
publicAccess: 'None'
192+
}
193+
}
194+
]
195+
roleAssignments: [
196+
{
197+
principalId: appIdentity.outputs.principalId
198+
principalType: 'ServicePrincipal'
199+
roleDefinitionIdOrName: 'Storage Blob Data Contributor'
200+
}
201+
]
202+
}
203+
}
204+
213205
module keyVault 'modules/keyVault.bicep' = {
214206
name: take('keyvault-${resourcesName}-deployment', 64)
215207
#disable-next-line no-unnecessary-dependson
216208
dependsOn: [logAnalyticsWorkspace, network] // required due to optional flags that could change dependency
217209
params: {
218-
name: take('kv-${uniqueResourcesName}', 24)
210+
name: take('kv-${resourcesName}', 24)
219211
location: location
220212
sku: 'standard'
221213
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
222214
privateNetworking: enablePrivateNetworking ? {
223215
virtualNetworkResourceId: network.outputs.vnetResourceId
224-
subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'data')).resourceId
216+
subnetResourceId: network.outputs.subnetPrivateEndpointsResourceId
225217
} : null
226218
roleAssignments: [
227219
{
228220
principalId: aiFoundryIdentity.outputs.principalId
229221
principalType: 'ServicePrincipal'
230222
roleDefinitionIdOrName: 'Key Vault Reader'
231223
}
232-
foundryNetworkConnectionApproverRoleAssignment
233224
]
234225
tags: allTags
235226
}
@@ -248,10 +239,10 @@ module azureAifoundry 'modules/aiFoundry.bicep' = {
248239
keyVaultResourceId: keyVault.outputs.resourceId
249240
userAssignedIdentityResourceId: aiFoundryIdentity.outputs.resourceId
250241
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
251-
aiServicesName: azureAiServices.outputs.name
242+
aiServicesName: aiServices.outputs.name
252243
privateNetworking: enablePrivateNetworking ? {
253244
virtualNetworkResourceId: network.outputs.vnetResourceId
254-
subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'ai')).resourceId
245+
subnetResourceId: network.outputs.subnetPrivateEndpointsResourceId
255246
} : null
256247
roleAssignments: [
257248
{
@@ -269,19 +260,16 @@ module cosmosDb 'modules/cosmosDb.bicep' = {
269260
#disable-next-line no-unnecessary-dependson
270261
dependsOn: [logAnalyticsWorkspace, network] // required due to optional flags that could change dependency
271262
params: {
272-
name: 'cosmos-${uniqueResourcesName}'
263+
name: 'cosmos-${resourcesName}'
273264
location: location
274265
dataAccessIdentityPrincipalId: appIdentity.outputs.principalId
275266
logAnalyticsWorkspaceResourceId: enableMonitoring ? logAnalyticsWorkspace.outputs.resourceId : ''
276267
zoneRedundant: enableRedundancy
277268
secondaryLocation: enableRedundancy && !empty(secondaryLocation) ? secondaryLocation : ''
278269
privateNetworking: enablePrivateNetworking ? {
279270
virtualNetworkResourceId: network.outputs.vnetResourceId
280-
subnetResourceId: first(filter(network.outputs.subnets, s => s.name == 'data')).resourceId
271+
subnetResourceId: network.outputs.subnetPrivateEndpointsResourceId
281272
} : null
282-
roleAssignments: [
283-
foundryNetworkConnectionApproverRoleAssignment
284-
]
285273
tags: allTags
286274
}
287275
}
@@ -298,7 +286,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
298286
location: location
299287
zoneRedundant: enableRedundancy && enablePrivateNetworking
300288
publicNetworkAccess: 'Enabled' // public access required for frontend
301-
infrastructureSubnetResourceId: enablePrivateNetworking ? first(filter(network.outputs.subnets, s => s.name == 'web')).resourceId : null
289+
infrastructureSubnetResourceId: enablePrivateNetworking ? network.outputs.subnetWebResourceId : null
302290
managedIdentities: {
303291
userAssignedResourceIds: [
304292
appIdentity.outputs.resourceId
@@ -325,7 +313,7 @@ module containerAppsEnvironment 'br/public:avm/res/app/managed-environment:0.11.
325313
module containerAppFrontend 'br/public:avm/res/app/container-app:0.17.0' = {
326314
name: take('container-app-frontend-${resourcesName}-deployment', 64)
327315
params: {
328-
name: take('ca-${uniqueResourcesName}frontend', 32)
316+
name: take('ca-${resourcesName}frontend', 32)
329317
location: location
330318
environmentResourceId: containerAppsEnvironment.outputs.resourceId
331319
managedIdentities: {
@@ -374,7 +362,7 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.17.0' = {
374362
#disable-next-line no-unnecessary-dependson
375363
dependsOn: [applicationInsights] // required due to optional flags that could change dependency
376364
params: {
377-
name: take('ca-${uniqueResourcesName}backend', 32)
365+
name: take('ca-${resourcesName}backend', 32)
378366
location: location
379367
environmentResourceId: containerAppsEnvironment.outputs.resourceId
380368
managedIdentities: {
@@ -417,7 +405,7 @@ module containerAppBackend 'br/public:avm/res/app/container-app:0.17.0' = {
417405
}
418406
{
419407
name: 'AZURE_OPENAI_ENDPOINT'
420-
value: 'https://${azureAiServices.outputs.name}.openai.azure.com/'
408+
value: 'https://${aiServices.outputs.name}.openai.azure.com/'
421409
}
422410
{
423411
name: 'MIGRATOR_AGENT_MODEL_DEPLOY'

infra/modules/aiFoundry.bicep

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ param aiServicesName string
3131
@description('Optional. Values to establish private networking for the AI Foundry resources.')
3232
param privateNetworking machineLearningPrivateNetworkingType?
3333

34+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
3435
@description('Optional. Array of role assignments to create.')
3536
param roleAssignments roleAssignmentType[]?
3637

@@ -86,7 +87,7 @@ module hub 'br/public:avm/res/machine-learning-services/workspace:0.12.1' = {
8687
publicNetworkAccess: privateNetworking != null ? 'Disabled' : 'Enabled'
8788
managedNetworkSettings: {
8889
isolationMode: privateNetworking != null ? 'AllowInternetOutbound' : 'Disabled'
89-
outboundRules: {
90+
outboundRules: privateNetworking != null ? {
9091
cog_services_pep: {
9192
category: 'UserDefined'
9293
destination: {
@@ -96,8 +97,8 @@ module hub 'br/public:avm/res/machine-learning-services/workspace:0.12.1' = {
9697
}
9798
type: 'PrivateEndpoint'
9899
}
99-
}
100-
}
100+
} : null
101+
}
101102
managedIdentities: {
102103
systemAssigned: true
103104
}
@@ -168,8 +169,6 @@ resource projectReference 'Microsoft.MachineLearningServices/workspaces@2024-10-
168169
dependsOn: [project]
169170
}
170171

171-
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
172-
173172
output projectName string = project.outputs.name
174173
output hubName string = hub.outputs.name
175174
output projectConnectionString string = '${split(projectReference.properties.discoveryUrl, '/')[2]};${subscription().subscriptionId};${resourceGroup().name};${projectReference.name}'

infra/modules/aiServices.bicep

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ param sku string = 'S0'
5151
@description('Optional. The resource ID of the Log Analytics workspace to use for diagnostic settings.')
5252
param logAnalyticsWorkspaceResourceId string?
5353

54+
import { deploymentType } from 'br/public:avm/res/cognitive-services/account:0.10.2'
5455
@description('Optional. Specifies the OpenAI deployments to create.')
5556
param deployments deploymentType[] = []
5657

58+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
5759
@description('Optional. Array of role assignments to create.')
5860
param roleAssignments roleAssignmentType[]?
5961

@@ -107,7 +109,7 @@ module cognitiveService 'br/public:avm/res/cognitive-services/account:0.10.2' =
107109
}
108110
deployments: deployments
109111
customSubDomainName: name
110-
disableLocalAuth: false // TODO - verify if this should remain false or be set dynamically via privateNetworking
112+
disableLocalAuth: false
111113
publicNetworkAccess: privateNetworking != null ? 'Disabled' : 'Enabled'
112114
diagnosticSettings: !empty(logAnalyticsWorkspaceResourceId) ? [
113115
{
@@ -133,9 +135,6 @@ module cognitiveService 'br/public:avm/res/cognitive-services/account:0.10.2' =
133135
}
134136
}
135137

136-
import { deploymentType } from 'br/public:avm/res/cognitive-services/account:0.10.2'
137-
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
138-
139138
output resourceId string = cognitiveService.outputs.resourceId
140139
output name string = cognitiveService.outputs.name
141140
output systemAssignedMIPrincipalId string? = cognitiveService.outputs.?systemAssignedMIPrincipalId

infra/modules/cosmosDb.bicep

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ param zoneRedundant bool
1919
@description('Optional. The secondary location for the Cosmos DB Account for failover and multiple writes.')
2020
param secondaryLocation string?
2121

22+
import { resourcePrivateNetworkingType } from 'customTypes.bicep'
2223
@description('Optional. Values to establish private networking for the Cosmos DB resource.')
2324
param privateNetworking resourcePrivateNetworkingType?
2425

26+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
2527
@description('Optional. Array of role assignments to create.')
2628
param roleAssignments roleAssignmentType[]?
2729

@@ -143,9 +145,6 @@ module cosmosAccount 'br/public:avm/res/document-db/database-account:0.15.0' = {
143145
}
144146
}
145147

146-
import { resourcePrivateNetworkingType } from 'customTypes.bicep'
147-
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
148-
149148
output resourceId string = cosmosAccount.outputs.resourceId
150149
output name string = cosmosAccount.outputs.name
151150
output endpoint string = cosmosAccount.outputs.endpoint

infra/modules/keyVault.bicep

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ param sku string = 'premium'
1717
@description('Optional. Resource ID of the Log Analytics workspace to use for diagnostic settings.')
1818
param logAnalyticsWorkspaceResourceId string?
1919

20+
import { resourcePrivateNetworkingType } from 'customTypes.bicep'
2021
@description('Optional. Values to establish private networking for the Key Vault resource.')
2122
param privateNetworking resourcePrivateNetworkingType?
2223

24+
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
2325
@description('Optional. Array of role assignments to create.')
2426
param roleAssignments roleAssignmentType[]?
2527

28+
import { secretType } from 'br/public:avm/res/key-vault/vault:0.12.1'
2629
@description('Optional. Array of secrets to create in the Key Vault.')
2730
param secrets secretType[]?
2831

@@ -85,9 +88,5 @@ module keyvault 'br/public:avm/res/key-vault/vault:0.12.1' = {
8588
}
8689
}
8790

88-
import { resourcePrivateNetworkingType } from 'customTypes.bicep'
89-
import { roleAssignmentType } from 'br/public:avm/utl/types/avm-common-types:0.5.1'
90-
import { secretType } from 'br/public:avm/res/key-vault/vault:0.12.1'
91-
9291
output resourceId string = keyvault.outputs.resourceId
9392
output name string = keyvault.outputs.name

0 commit comments

Comments
 (0)