Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Deploy AI Foundry with a private network configuration

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

Coming soon.

## Steps

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

```bash
az group create --name <new-rg-name> --location <your-selected-region>
```

2. Deploy the main.bicep

```bash
az deployment group create --resource-group <new-rg-name> --template-file main.bicep
```

**NOTE:** To access your Foundry resource securely, please using either a VM, VPN, or ExpressRoute.
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ param location string = 'eastus'
@description('Name of the first project')
param defaultProjectName string = '${aiFoundryName}-proj'

@description('Name of the virtual network')
param vnetName string = 'private-vnet'

@description('Name of the private endpoint subnet')
param peSubnetName string = 'pe-subnet'

/*
Step 1: Create a Cognitive Services Account
Step 1: Create an Account
*/
resource account 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
name: aiFoundryName
Expand All @@ -42,8 +48,157 @@ resource account 'Microsoft.CognitiveServices/accounts@2025-04-01-preview' = {
}
}

/*
Step 2: Create a virtual network and private endpoint to access your private resource
*/

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2024-05-01' = {
name: vnetName
location: location
properties: {
addressSpace: {
addressPrefixes: [
'192.168.0.0/16'
]
}
subnets: [
{
name: peSubnetName
properties: {
addressPrefix: '192.168.0.0/24'
}
}
]
}
}

resource subnet 'Microsoft.Network/virtualNetworks/subnets@2024-05-01' = {
parent: virtualNetwork
name: peSubnetName
properties: {
addressPrefix: '192.168.0.0/24'
}
}

/*
Step 3: Create a private endpoint to access your private resource
*/

// Private endpoint for AI Services account
// - Creates network interface in customer hub subnet
// - Establishes private connection to AI Services account
resource aiAccountPrivateEndpoint 'Microsoft.Network/privateEndpoints@2024-05-01' = {
name: '${aiFoundryName}-private-endpoint'
location: resourceGroup().location
properties: {
subnet: {
id: subnet.id // Deploy in customer hub subnet
}
privateLinkServiceConnections: [
{
name: '${aiFoundryName}-private-link-service-connection'
properties: {
privateLinkServiceId: account.id
groupIds: [
'account' // Target AI Services account
]
}
}
]
}
}

/*
Step 5: Create a private DNS zone for the private endpoint
*/
resource aiServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.services.ai.azure.com'
location: 'global'
}

resource openAiPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.openai.azure.com'
location: 'global'
}

resource cognitiveServicesPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
name: 'privatelink.cognitiveservices.azure.com'
location: 'global'
}

// 2) Link AI Services and Azure OpenAI and Cognitive Services DNS Zone to VNet
resource aiServicesLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
parent: aiServicesPrivateDnsZone
location: 'global'
name: 'aiServices-link'
properties: {
virtualNetwork: {
id: virtualNetwork.id // Link to specified VNet
}
registrationEnabled: false // Don't auto-register VNet resources
}
}

resource aiOpenAILink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
parent: openAiPrivateDnsZone
location: 'global'
name: 'aiServicesOpenAI-link'
properties: {
virtualNetwork: {
id: virtualNetwork.id // Link to specified VNet
}
registrationEnabled: false // Don't auto-register VNet resources
}
}

resource cognitiveServicesLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = {
parent: cognitiveServicesPrivateDnsZone
location: 'global'
name: 'aiServicesCognitiveServices-link'
properties: {
virtualNetwork: {
id: virtualNetwork.id // Link to specified VNet
}
registrationEnabled: false // Don't auto-register VNet resources
}
}

// 3) DNS Zone Group for AI Services
resource aiServicesDnsGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2024-05-01' = {
parent: aiAccountPrivateEndpoint
name: '${aiFoundryName}-dns-group'
properties: {
privateDnsZoneConfigs: [
{
name: '${aiFoundryName}-dns-aiserv-config'
properties: {
privateDnsZoneId: aiServicesPrivateDnsZone.id
}
}
{
name: '${aiFoundryName}-dns-openai-config'
properties: {
privateDnsZoneId: openAiPrivateDnsZone.id
}
}
{
name: '${aiFoundryName}-dns-cogserv-config'
properties: {
privateDnsZoneId: cognitiveServicesPrivateDnsZone.id
}
}
]
}
dependsOn: [
aiServicesLink
cognitiveServicesLink
aiOpenAILink
]
}


/*
Step 3: Deploy gpt-4o model
Step 6: Deploy gpt-4o model
*/
resource modelDeployment 'Microsoft.CognitiveServices/accounts/deployments@2024-10-01'= {
parent: account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ if ($provisioningState -eq "Succeeded") {
}

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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

subscriptionId="$1"
resourcegroup="$2"
accountName="$3"

if [[ -z "$subscriptionId" || -z "$resourcegroup" || -z "$accountName" ]]; then
echo "Usage: $0 <subscriptionId> <resourcegroup> <accountName>"
exit 1
fi

while true; do
token=$(az account get-access-token --subscription "$subscriptionId" --query accessToken -o tsv)
uri="https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourcegroup/providers/Microsoft.CognitiveServices/accounts/$accountName/capabilityHosts/?api-version=2025-04-01-preview"
content=$(az rest --method get --uri "$uri" --headers "Authorization=Bearer $token")
provisioningState=$(echo "$content" | jq -r '.value[0].properties.provisioningState')

echo "Provisioning State: $provisioningState"

if [[ "$provisioningState" == "Succeeded" ]]; then
echo "Provisioning State: $provisioningState, Please proceed with project creation template."
break
fi

if [[ "$provisioningState" == "Failed" || "$provisioningState" == "Canceled" ]]; then
echo "Provisioning State: $provisioningState, project provisioning will not work."
break
fi

sleep 30
done
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
# Azure AI Agent Service: Standard Agent Setup 1RP with Private E2E Networking

README: NO WORKING DO NOT USE

> **NOTE:** This template is to set-up a network secured Standard Agent in AI Foundry. Includes:
* PNA disabled resources
* PE's to all resources
* Network injection enabled for Agents
* Virtual Network Address speace support for Class B or Class C e.g. 172.16.0.0/16 or 192.168.0.0/16

## Steps

See Instructions: https://microsoft-my.sharepoint.com/:w:/p/fosteramanda/ES-0A2WpCgVLrK3SH_7gT9YBBb8SZk639kKmU1AIpoeDJg?e=npAZWP

## Steps

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

```bash
az group create --name <new-rg-name> --location westus
az group create --name <new-rg-name> --location <your-rg-region>
```

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

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:

```bash
chmod +x CheckCapabilityHostReadiness.sh
./CheckCapabilityHostReadiness.sh "<your-sub-id>" "<new-rg-name>" "<your-aiservices-name>"
```

4. Deploy the main-project-caphost-create.bicep

```bash
az deployment group create --resource-group <new-rg-name> --template-file main-project-caphost-create.bicep.bicep
```
az deployment group create --resource-group <new-rg-name> --template-file main-project-caphost-create.bicep
```

After running this script, you are required to input the following values:

```
Please provide string value for 'accountName' (? for help): <your-account-name>
Please provide string value for 'projectName' (? for help): <your-project-name>
Please provide string value for 'aiSearchName' (? for help): <your-search-name>
Please provide string value for 'azureStorageName' (? for help): <your-storage-name>
Please provide string value for 'cosmosDBName' (? for help): <your-cosmosdb-name>
```

**NOTE:** To access your Foundry resource securely, please using either a VM, VPN, or ExpressRoute.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ param aiServices string = 'aiservices'

// Model deployment parameters
@description('The name of the model you want to deploy')
param modelName string = 'gpt-4o'
@description('The provider of your model')
param modelFormat string = 'OpenAI'
@description('The version of your model')
param modelVersion string = '2024-05-13'
@description('The sku of your model deployment')
param modelSkuName string = 'GlobalStandard'
@description('The tokens per minute (TPM) of your model deployment')
param modelCapacity int = 1
// param modelName string = 'gpt-4o'
// @description('The provider of your model')
// param modelFormat string = 'OpenAI'
// @description('The version of your model')
// param modelVersion string = '2024-05-13'
// @description('The sku of your model deployment')
// param modelSkuName string = 'GlobalStandard'
// @description('The tokens per minute (TPM) of your model deployment')
// param modelCapacity int = 1

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

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

var projectName = toLower('${firstProjectName}${uniqueSuffix}')
var cosmosDBName = toLower('${aiServices}${uniqueSuffix}cosmosdb')
Expand Down Expand Up @@ -97,12 +97,12 @@ module aiAccount 'modules-network-secured/ai-account-identity.bicep' = {
// workspace organization
accountName: accountName
location: location
modelName: modelName
modelFormat: modelFormat
modelVersion: modelVersion
modelSkuName: modelSkuName
modelCapacity: modelCapacity
subnetId: vnet.outputs.subnetId
// modelName: modelName
// modelFormat: modelFormat
// modelVersion: modelVersion
// modelSkuName: modelSkuName
// modelCapacity: modelCapacity
agentSubnetId: vnet.outputs.agentSubnetId
}
}
/*
Expand Down Expand Up @@ -198,7 +198,6 @@ module storageAccountRoleAssignment 'modules-network-secured/azure-storage-accou
name: 'storage-${azureStorageName}-${uniqueSuffix}-deployment'
scope: resourceGroup(azureStorageSubscriptionId, azureStorageResourceGroupName)
params: {
accountPrincipalId: aiAccount.outputs.accountPrincipalId
azureStorageName: aiDependencies.outputs.azureStorageName
projectPrincipalId: aiProject.outputs.projectPrincipalId
}
Expand Down Expand Up @@ -241,13 +240,6 @@ output projectPrincipalId string = aiProject.outputs.projectPrincipalId
output aiSearchConnection string = aiProject.outputs.aiSearchConnection
output azureStorageConnection string = aiProject.outputs.azureStorageConnection
output cosmosDBConnection string = aiProject.outputs.cosmosDBConnection
output cosmosDBSubscriptionId string = aiDependencies.outputs.cosmosDBSubscriptionId
output cosmosDBResourceGroupName string = aiDependencies.outputs.cosmosDBResourceGroupName
output aiSearchServiceSubscriptionId string = aiDependencies.outputs.aiSearchServiceSubscriptionId
output aiSearchServiceResourceGroupName string = aiDependencies.outputs.aiSearchServiceResourceGroupName
output azureStorageSubscriptionId string = aiDependencies.outputs.azureStorageSubscriptionId
output azureStorageResourceGroupName string = aiDependencies.outputs.azureStorageResourceGroupName

output subscriptionID string = subscription().subscriptionId
output resourceGroupName string = resourceGroup().name
output suffix string = uniqueSuffix
Loading
Loading