Skip to content

Commit f656c8c

Browse files
updated the bicep file to comply with standards, assigned roles to the deployer, and revised the indexing scripts
1 parent 8ed289a commit f656c8c

File tree

6 files changed

+135
-131
lines changed

6 files changed

+135
-131
lines changed

infra/main.bicep

Lines changed: 64 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ module userAssignedIdentity 'br/public:avm/res/managed-identity/user-assigned-id
315315
// WAF recommendations for networking and connectivity: https://learn.microsoft.com/en-us/azure/well-architected/security/networking
316316
var networkSecurityGroupBackendResourceName = 'nsg-${solutionSuffix}-backend'
317317
module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) {
318-
name: take('avm.res.network.network-security-group.${networkSecurityGroupBackendResourceName}', 64)
318+
name: take('avm.res.network.network-security-group.backend.${networkSecurityGroupBackendResourceName}', 64)
319319
params: {
320320
name: networkSecurityGroupBackendResourceName
321321
location: location
@@ -345,7 +345,7 @@ module networkSecurityGroupBackend 'br/public:avm/res/network/network-security-g
345345

346346
var networkSecurityGroupBastionResourceName = 'nsg-${solutionSuffix}-bastion'
347347
module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) {
348-
name: take('avm.res.network.network-security-group.${networkSecurityGroupBastionResourceName}', 64)
348+
name: take('avm.res.network.network-security-group.bastion${networkSecurityGroupBastionResourceName}', 64)
349349
params: {
350350
name: networkSecurityGroupBastionResourceName
351351
location: location
@@ -501,7 +501,7 @@ module networkSecurityGroupBastion 'br/public:avm/res/network/network-security-g
501501

502502
var networkSecurityGroupAdministrationResourceName = 'nsg-${solutionSuffix}-administration'
503503
module networkSecurityGroupAdministration 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) {
504-
name: take('avm.res.network.network-security-group.${networkSecurityGroupAdministrationResourceName}', 64)
504+
name: take('avm.res.network.network-security-group.administration.${networkSecurityGroupAdministrationResourceName}', 64)
505505
params: {
506506
name: networkSecurityGroupAdministrationResourceName
507507
location: location
@@ -531,7 +531,7 @@ module networkSecurityGroupAdministration 'br/public:avm/res/network/network-sec
531531

532532
var networkSecurityGroupContainersResourceName = 'nsg-${solutionSuffix}-containers'
533533
module networkSecurityGroupContainers 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) {
534-
name: take('avm.res.network.network-security-group.${networkSecurityGroupContainersResourceName}', 64)
534+
name: take('avm.res.network.network-security-group.containers.${networkSecurityGroupContainersResourceName}', 64)
535535
params: {
536536
name: networkSecurityGroupContainersResourceName
537537
location: location
@@ -561,7 +561,7 @@ module networkSecurityGroupContainers 'br/public:avm/res/network/network-securit
561561

562562
var networkSecurityGroupWebsiteResourceName = 'nsg-${solutionSuffix}-website'
563563
module networkSecurityGroupWebsite 'br/public:avm/res/network/network-security-group:0.5.1' = if (enablePrivateNetworking) {
564-
name: take('avm.res.network.network-security-group.${networkSecurityGroupWebsiteResourceName}', 64)
564+
name: take('avm.res.network.network-security-group.website.${networkSecurityGroupWebsiteResourceName}', 64)
565565
params: {
566566
name: networkSecurityGroupWebsiteResourceName
567567
location: location
@@ -924,6 +924,8 @@ var privateDnsZones = [
924924
'privatelink.openai.azure.com'
925925
'privatelink.services.ai.azure.com'
926926
'privatelink.documents.azure.com'
927+
'privatelink.blob.core.windows.net'
928+
'privatelink.search.windows.net'
927929
]
928930

929931
// DNS Zone Index Constants
@@ -932,6 +934,8 @@ var dnsZoneIndex = {
932934
openAI: 1
933935
aiServices: 2
934936
cosmosDb: 3
937+
blob: 4
938+
search: 5
935939
}
936940

937941
// List of DNS zone indices that correspond to AI-related services.
@@ -973,10 +977,10 @@ module avmPrivateDnsZones 'br/public:avm/res/network/private-dns-zone:0.7.1' = [
973977
var useExistingAiFoundryAiProject = !empty(existingAiFoundryAiProjectResourceId)
974978
var aiFoundryAiServicesResourceGroupName = useExistingAiFoundryAiProject
975979
? split(existingAiFoundryAiProjectResourceId, '/')[4]
976-
: 'rg-${solutionSuffix}'
980+
: resourceGroup().name
977981
var aiFoundryAiServicesSubscriptionId = useExistingAiFoundryAiProject
978982
? split(existingAiFoundryAiProjectResourceId, '/')[2]
979-
: subscription().id
983+
: subscription().subscriptionId
980984
var aiFoundryAiServicesResourceName = useExistingAiFoundryAiProject
981985
? split(existingAiFoundryAiProjectResourceId, '/')[8]
982986
: 'aif-${solutionSuffix}'
@@ -1091,6 +1095,16 @@ module aiFoundryAiServices 'br:mcr.microsoft.com/bicep/avm/res/cognitive-service
10911095
principalId: userAssignedIdentity.outputs.principalId
10921096
principalType: 'ServicePrincipal'
10931097
}
1098+
{
1099+
roleDefinitionIdOrName: '53ca6127-db72-4b80-b1b0-d745d6d5456d' // Azure AI User
1100+
principalId: deployingUserPrincipalId
1101+
principalType: 'User'
1102+
}
1103+
{
1104+
roleDefinitionIdOrName: '64702f94-c441-49e6-a78b-ef80e0188fee' // Azure AI Developer
1105+
principalId: deployingUserPrincipalId
1106+
principalType: 'User'
1107+
}
10941108
]
10951109
// WAF aligned configuration for Monitoring
10961110
diagnosticSettings: enableMonitoring ? [{ workspaceResourceId: logAnalyticsWorkspaceResourceId }] : null
@@ -1146,6 +1160,9 @@ var aiFoundryAiProjectName = useExistingAiFoundryAiProject
11461160
var aiFoundryAiProjectEndpoint = useExistingAiFoundryAiProject
11471161
? existingAiFoundryAiServicesProject!.properties.endpoints['AI Foundry API']
11481162
: aiFoundryAiServicesProject!.outputs.apiEndpoint
1163+
var aiFoundryAiProjectPrincipalId = useExistingAiFoundryAiProject
1164+
? existingAiFoundryAiServicesProject!.identity.principalId
1165+
: aiFoundryAiServicesProject!.outputs.principalId
11491166

11501167
// ========== Cosmos DB ========== //
11511168
// WAF best practices for Cosmos DB: https://learn.microsoft.com/en-us/azure/well-architected/service-guides/cosmos-db
@@ -1187,7 +1204,10 @@ module cosmosDb 'br/public:avm/res/document-db/database-account:0.15.0' = {
11871204
'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/*'
11881205
'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/items/*'
11891206
]
1190-
assignments: [{ principalId: userAssignedIdentity.outputs.principalId }]
1207+
assignments: [
1208+
{ principalId: userAssignedIdentity.outputs.principalId }
1209+
{ principalId: deployingUserPrincipalId }
1210+
]
11911211
}
11921212
]
11931213
// WAF aligned configuration for Monitoring
@@ -1413,6 +1433,18 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = {
14131433
name: 'APP_ENV'
14141434
value: 'Prod'
14151435
}
1436+
{
1437+
name: 'AZURE_AI_SEARCH_CONNECTION_NAME'
1438+
value: searchService.outputs.name
1439+
}
1440+
{
1441+
name: 'AZURE_AI_SEARCH_INDEX_NAME'
1442+
value: aiSearchIndexName
1443+
}
1444+
{
1445+
name: 'AZURE_AI_SEARCH_ENDPOINT'
1446+
value: searchService.outputs.endpoint
1447+
}
14161448
{
14171449
name: 'AZURE_COGNITIVE_SERVICES'
14181450
value: 'https://cognitiveservices.azure.com/.default'
@@ -1449,18 +1481,6 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = {
14491481
name: 'SUPPORTED_MODELS'
14501482
value: ''
14511483
}
1452-
{
1453-
name: 'AZURE_AI_SEARCH_CONNECTION_NAME'
1454-
value: aiSearchConnectionName
1455-
}
1456-
{
1457-
name: 'AZURE_AI_SEARCH_INDEX_NAME'
1458-
value: ''
1459-
}
1460-
{
1461-
name: 'AZURE_AI_SEARCH_ENDPOINT'
1462-
value: searchService.outputs.endpoint
1463-
}
14641484
{
14651485
name: 'AZURE_AI_SEARCH_API_KEY'
14661486
value: ''
@@ -1477,10 +1497,6 @@ module containerApp 'br/public:avm/res/app/container-app:0.18.1' = {
14771497
name: 'AZURE_STORAGE_CONTAINER_NAME'
14781498
value: storageContainerName
14791499
}
1480-
{
1481-
name: 'AZURE_SEARCH_ENDPOINT'
1482-
value: searchService.outputs.endpoint
1483-
}
14841500
]
14851501
}
14861502
]
@@ -1670,21 +1686,6 @@ module webSite 'modules/web-sites.bicep' = {
16701686

16711687
// ========== Storage Account ========== //
16721688

1673-
module privateDnsZonesStorageAccount 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (enablePrivateNetworking ) {
1674-
name: take('avm.res.network.private-dns-zone.storage-account.${solutionSuffix}', 64)
1675-
params: {
1676-
name: 'privatelink.blob.core.windows.net'
1677-
enableTelemetry: enableTelemetry
1678-
virtualNetworkLinks: [
1679-
{
1680-
name: 'vnetlink-storage-account'
1681-
virtualNetworkResourceId: virtualNetwork.outputs.resourceId
1682-
}
1683-
]
1684-
tags: tags
1685-
}
1686-
}
1687-
16881689
var storageAccountName = replace('st${solutionSuffix}', '-', '')
16891690
param storageContainerName string = 'sample-dataset'
16901691
module avmStorageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
@@ -1725,15 +1726,16 @@ module avmStorageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
17251726
? [
17261727
{
17271728
name: 'pep-blob-${solutionSuffix}'
1729+
customNetworkInterfaceName: 'nic-blob-${solutionSuffix}'
17281730
privateDnsZoneGroup: {
17291731
privateDnsZoneGroupConfigs: [
17301732
{
17311733
name: 'storage-dns-zone-group-blob'
1732-
privateDnsZoneResourceId: privateDnsZonesStorageAccount.outputs.resourceId
1734+
privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.blob]!.outputs.resourceId
17331735
}
17341736
]
17351737
}
1736-
subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0]
1738+
subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0]
17371739
service: 'blob'
17381740
}
17391741
]
@@ -1757,22 +1759,8 @@ module avmStorageAccount 'br/public:avm/res/storage/storage-account:0.20.0' = {
17571759

17581760
// ========== Search Service ========== //
17591761

1760-
module privateDnsZonesSearchService 'br/public:avm/res/network/private-dns-zone:0.7.0' = if (enablePrivateNetworking ) {
1761-
name: take('avm.res.network.private-dns-zone.search-service.${solutionSuffix}', 64)
1762-
params: {
1763-
name: 'privatelink.search.windows.net'
1764-
enableTelemetry: enableTelemetry
1765-
virtualNetworkLinks: [
1766-
{
1767-
name: 'vnetlink-search-service'
1768-
virtualNetworkResourceId: virtualNetwork.outputs.resourceId
1769-
}
1770-
]
1771-
tags: tags
1772-
}
1773-
}
1774-
17751762
var searchServiceName = 'srch-${solutionSuffix}'
1763+
var aiSearchIndexName = 'sample-dataset-index'
17761764
module searchService 'br/public:avm/res/search/search-service:0.11.1' = {
17771765
name: take('avm.res.search.search-service.${solutionSuffix}', 64)
17781766
params: {
@@ -1793,7 +1781,7 @@ module searchService 'br/public:avm/res/search/search-service:0.11.1' = {
17931781
}
17941782
partitionCount: 1
17951783
replicaCount: 1
1796-
sku: 'standard'
1784+
sku: enableScalability ? 'standard' : 'basic'
17971785
tags: tags
17981786
roleAssignments: [
17991787
{
@@ -1806,19 +1794,30 @@ module searchService 'br/public:avm/res/search/search-service:0.11.1' = {
18061794
roleDefinitionIdOrName: 'Search Index Data Contributor'
18071795
principalType: 'User'
18081796
}
1797+
{
1798+
principalId: aiFoundryAiProjectPrincipalId
1799+
roleDefinitionIdOrName: 'Search Index Data Reader'
1800+
principalType: 'ServicePrincipal'
1801+
}
1802+
{
1803+
principalId: aiFoundryAiProjectPrincipalId
1804+
roleDefinitionIdOrName: 'Search Service Contributor'
1805+
principalType: 'ServicePrincipal'
1806+
}
18091807
]
18101808
privateEndpoints: enablePrivateNetworking
18111809
? [
18121810
{
18131811
name: 'pep-search-${solutionSuffix}'
1812+
customNetworkInterfaceName: 'nic-search-${solutionSuffix}'
18141813
privateDnsZoneGroup: {
18151814
privateDnsZoneGroupConfigs: [
18161815
{
1817-
privateDnsZoneResourceId: privateDnsZonesSearchService.outputs.resourceId
1816+
privateDnsZoneResourceId: avmPrivateDnsZones[dnsZoneIndex.search]!.outputs.resourceId
18181817
}
18191818
]
18201819
}
1821-
subnetResourceId: virtualNetwork.outputs.subnetResourceIds[0]
1820+
subnetResourceId: virtualNetwork!.outputs.subnetResourceIds[0]
18221821
service: 'searchService'
18231822
}
18241823
]
@@ -1829,11 +1828,9 @@ module searchService 'br/public:avm/res/search/search-service:0.11.1' = {
18291828
// ========== Search Service - AI Project Connection ========== //
18301829

18311830
var aiSearchConnectionName = 'aifp-srch-connection-${solutionSuffix}'
1832-
var aifSubscriptionId = useExistingAiFoundryAiProject ? split(existingAiFoundryAiProjectResourceId, '/')[2] : subscription().subscriptionId
1833-
var aifResourceGroup = useExistingAiFoundryAiProject ? split(existingAiFoundryAiProjectResourceId, '/')[4] : resourceGroup().name
1834-
module aiSearchFoundryConnection 'modules/aifp_search_connection.bicep' = {
1831+
module aiSearchFoundryConnection 'modules/aifp-connections.bicep' = {
18351832
name: take('aifp-srch-connection.${solutionSuffix}', 64)
1836-
scope: resourceGroup(aifSubscriptionId, aifResourceGroup)
1833+
scope: resourceGroup(aiFoundryAiServicesSubscriptionId, aiFoundryAiServicesResourceGroupName)
18371834
params: {
18381835
aiFoundryProjectName: aiFoundryAiProjectName
18391836
aiFoundryName: aiFoundryAiServicesResourceName
@@ -1861,8 +1858,9 @@ output webSiteDefaultHostname string = webSite.outputs.defaultHostname
18611858
output AZURE_STORAGE_BLOB_URL string = avmStorageAccount.outputs.serviceEndpoints.blob
18621859
output AZURE_STORAGE_ACCOUNT_NAME string = storageAccountName
18631860
output AZURE_STORAGE_CONTAINER_NAME string = storageContainerName
1864-
output AZURE_SEARCH_ENDPOINT string = searchService.outputs.endpoint
1865-
output AZURE_SEARCH_NAME string = searchService.outputs.name
1861+
output AZURE_AI_SEARCH_ENDPOINT string = searchService.outputs.endpoint
1862+
output AZURE_AI_SEARCH_NAME string = searchService.outputs.name
1863+
output AZURE_AI_SEARCH_INDEX_NAME string = aiSearchIndexName
18661864

18671865
output COSMOSDB_ENDPOINT string = 'https://${cosmosDbResourceName}.documents.azure.com:443/'
18681866
output COSMOSDB_DATABASE string = cosmosDbDatabaseName
@@ -1881,5 +1879,5 @@ output AZURE_AI_MODEL_DEPLOYMENT_NAME string = aiFoundryAiServicesModelDeploymen
18811879
output AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME string = aiFoundryAiServicesModelDeployment.name
18821880
output AZURE_AI_AGENT_ENDPOINT string = aiFoundryAiProjectEndpoint
18831881
output APP_ENV string = 'Prod'
1884-
output AI_FOUNDRY_RESOURCE_ID string = aiFoundryAiServices.outputs.resourceId
1882+
output AI_FOUNDRY_RESOURCE_ID string = !useExistingAiFoundryAiProject ? aiFoundryAiServices.outputs.resourceId : existingAiFoundryAiProjectResourceId
18851883
output COSMOSDB_ACCOUNT_NAME string = cosmosDbResourceName

infra/modules/ai-project.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,8 @@ output name string = aiProject.name
3838
@description('Required. Resource ID of the AI project.')
3939
output resourceId string = aiProject.id
4040

41+
@description('Required. Principal ID of the AI project managed identity.')
42+
output principalId string = aiProject.identity.principalId
43+
4144
@description('Required. API endpoint for the AI project.')
4245
output apiEndpoint string = aiProject!.properties.endpoints['AI Foundry API']
File renamed without changes.

infra/scripts/Process-Sample-Data.ps1

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ param(
44
[string]$StorageAccount,
55
[string]$BlobContainer,
66
[string]$AiSearch,
7+
[string]$AiSearchIndex,
78
[string]$ResourceGroup
89
)
910

@@ -17,7 +18,11 @@ if (-not $BlobContainer) {
1718
}
1819

1920
if (-not $AiSearch) {
20-
$AiSearch = $(azd env get-value AZURE_SEARCH_NAME)
21+
$AiSearch = $(azd env get-value AZURE_AI_SEARCH_NAME)
22+
}
23+
24+
if (-not $AiSearchIndex) {
25+
$AiSearchIndex = $(azd env get-value AZURE_AI_SEARCH_INDEX_NAME)
2126
}
2227

2328
if (-not $ResourceGroup) {
@@ -28,7 +33,7 @@ $AzSubscriptionId = $(azd env get-value AZURE_SUBSCRIPTION_ID)
2833

2934
# Check if all required arguments are provided
3035
if (-not $StorageAccount -or -not $BlobContainer -or -not $AiSearch) {
31-
Write-Host "Usage: .\infra\scripts\Process-Sample-Data.ps1 -StorageAccount <StorageAccount> -BlobContainer <StorageContainerName> -AiSearch <AISearchName> [-ResourceGroup <ResourceGroup>]"
36+
Write-Host "Usage: .\infra\scripts\Process-Sample-Data.ps1 -StorageAccount <StorageAccountName> -BlobContainer <StorageContainerName> -AiSearch <AISearchName> [-AiSearchIndex <AISearchIndexName>] [-ResourceGroup <ResourceGroupName>]"
3237
exit 1
3338
}
3439

@@ -219,7 +224,7 @@ Write-Host "Requirements installed"
219224

220225
# Run the Python script to index data
221226
Write-Host "Running the python script to index data"
222-
$process = Start-Process -FilePath $pythonCmd -ArgumentList "infra/scripts/index_datasets.py", $StorageAccount, $BlobContainer, $AiSearch -Wait -NoNewWindow -PassThru
227+
$process = Start-Process -FilePath $pythonCmd -ArgumentList "infra/scripts/index_datasets.py", $StorageAccount, $BlobContainer, $AiSearch, $AiSearchIndex -Wait -NoNewWindow -PassThru
223228

224229
if ($process.ExitCode -ne 0) {
225230
Write-Host "Error: Indexing python script execution failed."

0 commit comments

Comments
 (0)