Skip to content

Commit 20ed8de

Browse files
Merge pull request #128 from meerakurup/mkurup-more
Updated 10, 15 and 25
2 parents f4545ba + 97f29e2 commit 20ed8de

35 files changed

+560
-1641
lines changed
Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# Deploy AI Foundry with a private network configuration
22

3-
This examples shows how to disable public network access for Azure AI Foundry.
3+
> **NOTE:** This examples shows how to disable public network access for Azure AI Foundry. This template includes:
4+
* PNA disabled Foundry resource (account) with private endpoint
45

5-
Coming soon.
6+
7+
## Steps
8+
9+
1. Create new (or use existing) resource group:
10+
11+
```bash
12+
az group create --name <new-rg-name> --location <your-selected-region>
13+
```
14+
15+
2. Deploy the main.bicep
16+
17+
```bash
18+
az deployment group create --resource-group <new-rg-name> --template-file main.bicep
19+
```
20+
21+
**NOTE:** To access your Foundry resource securely, please using either a VM, VPN, or ExpressRoute.

samples/microsoft/infrastructure-setup/10-private-network-basic/main.bicep

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@ param location string = 'eastus'
1414
@description('Name of the first project')
1515
param defaultProjectName string = '${aiFoundryName}-proj'
1616

17+
@description('Name of the virtual network')
18+
param vnetName string = 'private-vnet'
19+
20+
@description('Name of the private endpoint subnet')
21+
param peSubnetName string = 'pe-subnet'
22+
1723
/*
18-
Step 1: Create a Cognitive Services Account
24+
Step 1: Create an Account
1925
*/
2026
resource account 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
2127
name: aiFoundryName
@@ -42,8 +48,157 @@ resource account 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
4248
}
4349
}
4450

51+
/*
52+
Step 2: Create a virtual network and private endpoint to access your private resource
53+
*/
54+
55+
resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-05-01' = {
56+
name: vnetName
57+
location: location
58+
properties: {
59+
addressSpace: {
60+
addressPrefixes: [
61+
'192.168.0.0/16'
62+
]
63+
}
64+
subnets: [
65+
{
66+
name: peSubnetName
67+
properties: {
68+
addressPrefix: '192.168.0.0/24'
69+
}
70+
}
71+
]
72+
}
73+
}
74+
75+
resource subnet 'Microsoft.Network/virtualNetworks/subnets@2024-05-01' = {
76+
parent: virtualNetwork
77+
name: peSubnetName
78+
properties: {
79+
addressPrefix: '192.168.0.0/24'
80+
}
81+
}
82+
83+
/*
84+
Step 3: Create a private endpoint to access your private resource
85+
*/
86+
87+
// Private endpoint for AI Services account
88+
// - Creates network interface in customer hub subnet
89+
// - Establishes private connection to AI Services account
90+
resource aiAccountPrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
91+
name: '${aiFoundryName}-private-endpoint'
92+
location: resourceGroup().location
93+
properties: {
94+
subnet: {
95+
id: subnet.id // Deploy in customer hub subnet
96+
}
97+
privateLinkServiceConnections: [
98+
{
99+
name: '${aiFoundryName}-private-link-service-connection'
100+
properties: {
101+
privateLinkServiceId: account.id
102+
groupIds: [
103+
'account' // Target AI Services account
104+
]
105+
}
106+
}
107+
]
108+
}
109+
}
110+
111+
/*
112+
Step 5: Create a private DNS zone for the private endpoint
113+
*/
114+
resource aiServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
115+
name: 'privatelink.services.ai.azure.com'
116+
location: 'global'
117+
}
118+
119+
resource openAiPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
120+
name: 'privatelink.openai.azure.com'
121+
location: 'global'
122+
}
123+
124+
resource cognitiveServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
125+
name: 'privatelink.cognitiveservices.azure.com'
126+
location: 'global'
127+
}
128+
129+
// 2) Link AI Services and Azure OpenAI and Cognitive Services DNS Zone to VNet
130+
resource aiServicesLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
131+
parent: aiServicesPrivateDnsZone
132+
location: 'global'
133+
name: 'aiServices-link'
134+
properties: {
135+
virtualNetwork: {
136+
id: virtualNetwork.id // Link to specified VNet
137+
}
138+
registrationEnabled: false // Don't auto-register VNet resources
139+
}
140+
}
141+
142+
resource aiOpenAILink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
143+
parent: openAiPrivateDnsZone
144+
location: 'global'
145+
name: 'aiServicesOpenAI-link'
146+
properties: {
147+
virtualNetwork: {
148+
id: virtualNetwork.id // Link to specified VNet
149+
}
150+
registrationEnabled: false // Don't auto-register VNet resources
151+
}
152+
}
153+
154+
resource cognitiveServicesLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
155+
parent: cognitiveServicesPrivateDnsZone
156+
location: 'global'
157+
name: 'aiServicesCognitiveServices-link'
158+
properties: {
159+
virtualNetwork: {
160+
id: virtualNetwork.id // Link to specified VNet
161+
}
162+
registrationEnabled: false // Don't auto-register VNet resources
163+
}
164+
}
165+
166+
// 3) DNS Zone Group for AI Services
167+
resource aiServicesDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = {
168+
parent: aiAccountPrivateEndpoint
169+
name: '${aiFoundryName}-dns-group'
170+
properties: {
171+
privateDnsZoneConfigs: [
172+
{
173+
name: '${aiFoundryName}-dns-aiserv-config'
174+
properties: {
175+
privateDnsZoneId: aiServicesPrivateDnsZone.id
176+
}
177+
}
178+
{
179+
name: '${aiFoundryName}-dns-openai-config'
180+
properties: {
181+
privateDnsZoneId: openAiPrivateDnsZone.id
182+
}
183+
}
184+
{
185+
name: '${aiFoundryName}-dns-cogserv-config'
186+
properties: {
187+
privateDnsZoneId: cognitiveServicesPrivateDnsZone.id
188+
}
189+
}
190+
]
191+
}
192+
dependsOn: [
193+
aiServicesLink
194+
cognitiveServicesLink
195+
aiOpenAILink
196+
]
197+
}
198+
199+
45200
/*
46-
Step 3: Deploy gpt-4o model
201+
Step 6: Deploy gpt-4o model
47202
*/
48203
resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01'= {
49204
parent: account

samples/microsoft/infrastructure-setup/15-private-network-standard-agent-setup/CheckCapabilityHostReadiness.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if ($provisioningState -eq "Succeeded") {
1818
}
1919

2020
if ($provisioningState -eq "Failed" -or $provisioningState -eq "Canceled") {
21-
Write-Output "Provisioning State: $provisioningState, project provisionig will not work."
21+
Write-Output "Provisioning State: $provisioningState, project provisioning will not work."
2222
break;
2323
}
2424

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
subscriptionId="$1"
4+
resourcegroup="$2"
5+
accountName="$3"
6+
7+
if [[ -z "$subscriptionId" || -z "$resourcegroup" || -z "$accountName" ]]; then
8+
echo "Usage: $0 <subscriptionId> <resourcegroup> <accountName>"
9+
exit 1
10+
fi
11+
12+
while true; do
13+
token=$(az account get-access-token --subscription "$subscriptionId" --query accessToken -o tsv)
14+
uri="https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourcegroup/providers/Microsoft.CognitiveServices/accounts/$accountName/capabilityHosts/?api-version=2025-04-01-preview"
15+
content=$(az rest --method get --uri "$uri" --headers "Authorization=Bearer $token")
16+
provisioningState=$(echo "$content" | jq -r '.value[0].properties.provisioningState')
17+
18+
echo "Provisioning State: $provisioningState"
19+
20+
if [[ "$provisioningState" == "Succeeded" ]]; then
21+
echo "Provisioning State: $provisioningState, Please proceed with project creation template."
22+
break
23+
fi
24+
25+
if [[ "$provisioningState" == "Failed" || "$provisioningState" == "Canceled" ]]; then
26+
echo "Provisioning State: $provisioningState, project provisioning will not work."
27+
break
28+
fi
29+
30+
sleep 30
31+
done
Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
# Azure AI Agent Service: Standard Agent Setup 1RP with Private E2E Networking
22

3-
README: NO WORKING DO NOT USE
4-
53
> **NOTE:** This template is to set-up a network secured Standard Agent in AI Foundry. Includes:
64
* PNA disabled resources
75
* PE's to all resources
86
* Network injection enabled for Agents
7+
* Virtual Network Address speace support for Class B or Class C e.g. 172.16.0.0/16 or 192.168.0.0/16
98

10-
## Steps
11-
12-
See Instructions: https://microsoft-my.sharepoint.com/:w:/p/fosteramanda/ES-0A2WpCgVLrK3SH_7gT9YBBb8SZk639kKmU1AIpoeDJg?e=npAZWP
139

10+
## Steps
1411

1512
1. Create new (or use existing) resource group:
1613

1714
```bash
18-
az group create --name <new-rg-name> --location westus
15+
az group create --name <new-rg-name> --location <your-rg-region>
1916
```
2017

2118
2. Deploy the main-create.bicep
@@ -29,8 +26,27 @@ See Instructions: https://microsoft-my.sharepoint.com/:w:/p/fosteramanda/ES-0A2W
2926
.\CheckCapabilityHostReadiness.ps1 -subscriptionId "<your-sub-id>" -resourcegroup "<new-rg-name>" -accountname "<your-aiservices-name>"
3027
```
3128

29+
If you do not want to run the Powershell script, you can run a bash script instead, from the file CheckCapabilityHostReadiness.sh. Run the following two commands:
30+
31+
```bash
32+
chmod +x CheckCapabilityHostReadiness.sh
33+
./CheckCapabilityHostReadiness.sh "<your-sub-id>" "<new-rg-name>" "<your-aiservices-name>"
34+
```
35+
3236
4. Deploy the main-project-caphost-create.bicep
3337

3438
```bash
35-
az deployment group create --resource-group <new-rg-name> --template-file main-project-caphost-create.bicep.bicep
36-
```
39+
az deployment group create --resource-group <new-rg-name> --template-file main-project-caphost-create.bicep
40+
```
41+
42+
After running this script, you are required to input the following values:
43+
44+
```
45+
Please provide string value for 'accountName' (? for help): <your-account-name>
46+
Please provide string value for 'projectName' (? for help): <your-project-name>
47+
Please provide string value for 'aiSearchName' (? for help): <your-search-name>
48+
Please provide string value for 'azureStorageName' (? for help): <your-storage-name>
49+
Please provide string value for 'cosmosDBName' (? for help): <your-cosmosdb-name>
50+
```
51+
52+
**NOTE:** To access your Foundry resource securely, please using either a VM, VPN, or ExpressRoute.

samples/microsoft/infrastructure-setup/15-private-network-standard-agent-setup/main-create.bicep

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ param aiServices string = 'aiservices'
2525

2626
// Model deployment parameters
2727
@description('The name of the model you want to deploy')
28-
param modelName string = 'gpt-4o'
29-
@description('The provider of your model')
30-
param modelFormat string = 'OpenAI'
31-
@description('The version of your model')
32-
param modelVersion string = '2024-05-13'
33-
@description('The sku of your model deployment')
34-
param modelSkuName string = 'GlobalStandard'
35-
@description('The tokens per minute (TPM) of your model deployment')
36-
param modelCapacity int = 1
28+
// param modelName string = 'gpt-4o'
29+
// @description('The provider of your model')
30+
// param modelFormat string = 'OpenAI'
31+
// @description('The version of your model')
32+
// param modelVersion string = '2024-05-13'
33+
// @description('The sku of your model deployment')
34+
// param modelSkuName string = 'GlobalStandard'
35+
// @description('The tokens per minute (TPM) of your model deployment')
36+
// param modelCapacity int = 1
3737

3838
// Create a short, unique suffix, that will be unique to each resource group
3939
param deploymentTimestamp string = utcNow('yyyyMMddHHmmss')
@@ -51,11 +51,11 @@ param displayName string = 'project'
5151

5252
//Existing standard Agent required resources
5353
@description('The AI Search Service full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.')
54-
param aiSearchResourceId string = '/subscriptions/562da9fc-fd6e-4f24-a6aa-99827a7f6f91/resourceGroups/rg-vpn-fdp-ni-eus/providers/Microsoft.Search/searchServices/aiservicesgckssearch'
54+
param aiSearchResourceId string = ''
5555
@description('The AI Storage Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.')
56-
param azureStorageAccountResourceId string = '/subscriptions/562da9fc-fd6e-4f24-a6aa-99827a7f6f91/resourceGroups/rg-vpn-fdp-ni-eus/providers/Microsoft.Storage/storageAccounts/aiservicesgcksstorage'
56+
param azureStorageAccountResourceId string = ''
5757
@description('The Cosmos DB Account full ARM Resource ID. This is an optional field, and if not provided, the resource will be created.')
58-
param azureCosmosDBAccountResourceId string = '/subscriptions/562da9fc-fd6e-4f24-a6aa-99827a7f6f91/resourceGroups/rg-vpn-fdp-ni-eus/providers/Microsoft.DocumentDB/databaseAccounts/aiservicesgckscosmosdb'
58+
param azureCosmosDBAccountResourceId string = ''
5959

6060
var projectName = toLower('${firstProjectName}${uniqueSuffix}')
6161
var cosmosDBName = toLower('${aiServices}${uniqueSuffix}cosmosdb')
@@ -97,12 +97,12 @@ module aiAccount 'modules-network-secured/ai-account-identity.bicep' = {
9797
// workspace organization
9898
accountName: accountName
9999
location: location
100-
modelName: modelName
101-
modelFormat: modelFormat
102-
modelVersion: modelVersion
103-
modelSkuName: modelSkuName
104-
modelCapacity: modelCapacity
105-
subnetId: vnet.outputs.subnetId
100+
// modelName: modelName
101+
// modelFormat: modelFormat
102+
// modelVersion: modelVersion
103+
// modelSkuName: modelSkuName
104+
// modelCapacity: modelCapacity
105+
agentSubnetId: vnet.outputs.agentSubnetId
106106
}
107107
}
108108
/*
@@ -198,7 +198,6 @@ module storageAccountRoleAssignment 'modules-network-secured/azure-storage-accou
198198
name: 'storage-${azureStorageName}-${uniqueSuffix}-deployment'
199199
scope: resourceGroup(azureStorageSubscriptionId, azureStorageResourceGroupName)
200200
params: {
201-
accountPrincipalId: aiAccount.outputs.accountPrincipalId
202201
azureStorageName: aiDependencies.outputs.azureStorageName
203202
projectPrincipalId: aiProject.outputs.projectPrincipalId
204203
}
@@ -241,13 +240,6 @@ output projectPrincipalId string = aiProject.outputs.projectPrincipalId
241240
output aiSearchConnection string = aiProject.outputs.aiSearchConnection
242241
output azureStorageConnection string = aiProject.outputs.azureStorageConnection
243242
output cosmosDBConnection string = aiProject.outputs.cosmosDBConnection
244-
output cosmosDBSubscriptionId string = aiDependencies.outputs.cosmosDBSubscriptionId
245-
output cosmosDBResourceGroupName string = aiDependencies.outputs.cosmosDBResourceGroupName
246-
output aiSearchServiceSubscriptionId string = aiDependencies.outputs.aiSearchServiceSubscriptionId
247-
output aiSearchServiceResourceGroupName string = aiDependencies.outputs.aiSearchServiceResourceGroupName
248-
output azureStorageSubscriptionId string = aiDependencies.outputs.azureStorageSubscriptionId
249-
output azureStorageResourceGroupName string = aiDependencies.outputs.azureStorageResourceGroupName
250-
251243
output subscriptionID string = subscription().subscriptionId
252244
output resourceGroupName string = resourceGroup().name
253245
output suffix string = uniqueSuffix

0 commit comments

Comments
 (0)