Skip to content

Commit 4b22003

Browse files
authored
Merge branch 'main' into bug-bash-updates
2 parents 2fcded1 + caf1b39 commit 4b22003

8 files changed

Lines changed: 196 additions & 95 deletions

README.md

Lines changed: 27 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@
44

55
## Overview
66

7-
This solution accelerator provides a foundation template for deploying a Project within AI Foundry into a secure, private, isolated environment within Azure. The deployed features follow Microsoft's Well-Architected Framework (WAF) to establish isolated infrastructure for an AI Foundry Project, intended to move from a Proof of Concept state to a production-ready application.
7+
This is a foundational deployment solution for deploying an AI hub and project into an isolated environment (vNet) within Azure. The deployed features follow Microsoft's Well-Architected Framework [WAF](https://learn.microsoft.com/en-us/azure/well-architected/) to establish an isolated infrastructure for AI Foundry, intended to assist in moving from a Proof of Concept state to a production-ready application.
8+
9+
This template leverages Azure Verified Modules (AVM) and the Azure Developer CLI (AZD) to provision a WAF-aligned infrastructure for AI application development. This infrastructure includes AI Foundry elements, a virtual network (VNET), private endpoints, Key Vault, a storage account, and additional, optional WAF-aligned resources (such as Cosmos DB and SQL Server) that can be leveraged with Foundry developed projects.
10+
11+
The following deployment automates our recommended configuration to protect your data and resources; using Microsoft Entra ID role-based access control, a managed network, and private endpoints. We recommend disabling public network access for Azure OpenAI resources, Azure AI Search resources, and storage accounts (which will occur when deploying those optional services within this workflow). Using selected networks with IP rules isn't supported because the services' IP addresses are dynamic.
12+
13+
AI Foundry has two network isolation aspects, this repository will automate:
14+
1. Configuring the network isolation of the Azure AI Foundry hub and project managed compute (compute instance, serverless compute, managed online endpoint) [Configure Managed Network](https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/configure-managed-network)
15+
2. Configuring the virtual network, private end points and private link services to isolate resources to connect to the hub and project in a secure way. [Secure Data Playground](https://learn.microsoft.com/en-us/azure/ai-foundry/how-to/secure-data-playground)
816

9-
This template leverages Azure Verified Modules (AVM) and the Azure Developer CLI (AZD) to provision WAF-aligned infrastructure. This infrastructure includes AI Foundry elements, a virtual network (VNET), private endpoints, Key Vault, a storage account, and optional WAF-aligned resources (such as Cosmos DB and SQL Server) that can be leveraged with AI Foundry–developed projects.
1017

1118
## Architecture
1219
The diagram below illustrates the capabilities included in the template.
@@ -26,25 +33,28 @@ The diagram below illustrates the capabilities included in the template.
2633

2734
## Key Features
2835
### What solutions does this enable?
29-
- Deploy AI Foundry application into a secure environment
36+
- Deploys AI hub and AI project into a virtual network with all dependent services connected via private end points.
3037

31-
- Connect the application to essential Azure services while adhering to the best practices outlined in the Well Architected Framework
38+
- Configures AI Foundry, adhering to the best practices outlined in the Well Architected Framework.
3239

33-
- Provide the ability to select services to deploy that are relevant to the project
40+
- Provides the ability to add additional Azure services during deployment, configured to connect via isolation, to facilitate your AI project.
41+
(API Management, CosmosDB, Azure SQL DB, App Service)
3442

35-
## Prerequisites
43+
## Prerequisites and high-level steps
3644

37-
1. Azure subscription and Entra ID account with Contributor permissions.
38-
2. Install the [Azure Developer CLI (AZD)](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd?tabs=winget-windows%2Cbrew-mac%2Cscript-linux&pivots=os-windows)
39-
3. Validate [Required Roles and Scopes](Required_Roles_and_Scopes.md)
40-
4. (Optional) [GitHub Codespaces deployment](DeployViaCodeSpaces.md) - requires the user to be on a GitHub Team or Enterprise Cloud plan
45+
1. Have access to an Azure subscription and Entra ID account with Contributor permissions.
46+
2. Confirm the subscription you are deploying into has the [Required Roles and Scopes](Required_roles_scopes_resources.md) and
47+
3. If deploying from your [local environment](local_environment_steps.md) Install the [Azure Developer CLI (AZD)](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd?tabs=winget-windows%2Cbrew-mac%2Cscript-linux&pivots=os-windows)
48+
4. If deploying via [GitHub Codespaces](github_code_spaces_steps.md) - requires the user to be on a GitHub Team or Enterprise Cloud plan
49+
5. If leveraging [One-click deployment](#quick-deploy)
50+
6. If leveraging [GitHub Actions](github_actions_steps.md)
4151

4252
For additional documentation of the default enabled services of this solution accelerator, please see:
4353

4454
1. [Azure Open AI Service](https://learn.microsoft.com/en-us/azure/ai-services/openai/)
4555
2. [Azure AI Search](https://learn.microsoft.com/en-us/azure/search/)
46-
3. [Azure AI Foundry Hub](https://learn.microsoft.com/en-us/azure/ai-foundry/)
47-
4. [Azure AI Foundry Project](https://learn.microsoft.com/en-us/azure/ai-foundry/)
56+
3. [Azure AI hub](https://learn.microsoft.com/en-us/azure/ai-foundry/)
57+
4. [Azure AI project](https://learn.microsoft.com/en-us/azure/ai-foundry/)
4858
5. [Azure Container Registry](https://learn.microsoft.com/en-us/azure/container-registry/)
4959
6. [Azure Virtual Machines](https://learn.microsoft.com/en-us/azure/virtual-machines/)
5060
7. [Azure Storage](https://learn.microsoft.com/en-us/azure/storage/)
@@ -64,59 +74,16 @@ QUICK DEPLOY
6474
|---|---|---|
6575
[Steps to deploy with GitHub Codespaces](DeployViaCodeSpaces.md)
6676

67-
# Setup
68-
69-
### Clone Repository
70-
71-
```bash
72-
git clone https://github.com/microsoft/Deploy-Your-AI-Application-In-Production.git
73-
cd Deploy-Your-AI-Application-In-Production
74-
```
75-
76-
### Establish AZD Environment
77-
78-
This solution uses the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) to quickly provision and deploy infrastructure and applications to Azure.
79-
80-
To get started, authenticate with an Azure Subscription ([details](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/reference#azd-auth-login)):
81-
82-
```powershell
83-
azd auth login
84-
```
8577

86-
Establish new environment. Provide a name that represents the application domain:
8778

88-
```powershell
89-
azd env new '<app name>'
90-
```
79+
## Connect to and validate access to the new environment
80+
Follow the post deployment steps [Post Deployment Steps](post_deployment_steps.md) to connect to the isolated enviornment.
9181

92-
Optionally set environment variables via the following commands:
9382

94-
```powershell
95-
azd env set 'AZURE_VM_ADMIN_PASSWORD' '<secure password>'
96-
```
83+
## Deploy your application in the isolated environment
84+
- Provision additional production resources (data, storage, services) and configure secure access.
85+
- Leverage the Microsoft Learn documentation regarding deploying a web app within AI Foundry[Configure Web App](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/on-your-data-configuration#azure-ai-foundry-portal)
9786

98-
# Deploy
99-
100-
To provision the necessary Azure resources and deploy the application, run the azd up command:
101-
```powershell
102-
azd up
103-
```
104-
This will kick off an interactive console to provide required flags and parameters to deploy the infrastructure of a secure, WAF-aligned AI Foundry environment.
105-
106-
>- This deployment will take 15-20 minutes to provision the resources in your account. If you get an error or timeout with deployment, changing the location can help, as there may be availability constraints for the resources.
107-
>- Note the `.env` file created at `/.azure/<app name>`. These are the environment configuration output from running the `azd up` command. These values are names of resources created as part of the baseline infrastructure.
108-
109-
## Connect to & Check the New Environment
110-
1. In [Azure Portal](https://portal.azure.com), follow this Azure Bastion [guide](https://learn.microsoft.com/en-us/azure/bastion/bastion-connect-vm-rdp-windows#rdp) to access the network isolated AI Foundry hub & project.
111-
- Note: The provisioned Project in the [AI Foundry Portal](https://ai.azure.com) will not be accessible from your local computer because the Project is established in a secure, private network and is not directly accessible from the public internet.
112-
2. Confirm private services are accessible from within the secure Virtual Network by following these [test verification steps](./Verify_Services_On_Network.md) on the Virtual Machine within the VNET.
113-
114-
## Connect Your Model
115-
<!-- Add latest guidance in customer friendly language -->
116-
Configure AI model and settings in [AI Foundry Portal](https://ai.azure.com)
117-
118-
## Deploy your application in this production environment
119-
Provision additional production resources (data, storage, services) and configure secure access.
12087

12188
<h2>
12289
Supporting documents
@@ -129,15 +96,7 @@ Supporting documents
12996
- [Azure OpenAI Service - Documentation, quickstarts, API reference - Azure AI services | Microsoft Learn](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/use-your-data)
13097
- [Azure AI Content Understanding documentation](https://learn.microsoft.com/en-us/azure/ai-services/content-understanding/)
13198

132-
<!-- </br>
133-
Responsible AI Transparency FAQ
134-
</h2>
13599

136-
Please refer to [Transparency FAQ](./TRANSPARENCY_FAQ.md) for responsible AI transparency details of this solution accelerator. -->
137-
138-
<br/>
139-
<br/>
140-
<br/>
141100

142101
---
143102

File renamed without changes.

github_actions_steps.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# GitHub Actions Pipeline deployment steps (CI/CD)
2+
3+
These steps are coming soon!
4+
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ You can run this solution using GitHub Codespaces. The button will open a web-ba
5656
![image of prompts](img/provisioning/prompts.png)
5757
**Be sure to remember the vm password and vm username. This will be used in a later step. Because we are using FDPO subscriptions, we do not have access to Entra to create the SSO to the jump box at this time. You are still required to log into Azure once you connect to the virtual machine.
5858

59-
11. After completeing the required paramters that you were prompted for, the provisioning of resources will run and deploy the Network Isolated AI Foundry Hub, Project and dependent resources in about 20 minutes.
59+
11. After completeing the required paramters that you were prompted for, the provisioning of resources will run and deploy the Network Isolated AI hub, project and dependent resources in about 20 minutes.
6060

6161
# Post Deployment Steps:
6262
These steps will help to check that the isolated environment was set up correctly.

infra/main.bicep

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ module aiSearch 'br/public:avm/res/search/search-service:0.9.0' = {
228228
publicNetworkAccess: 'Disabled'
229229
disableLocalAuth: true
230230
sku: 'standard'
231+
partitionCount:1
232+
replicaCount:3
231233
roleAssignments: [
232234
{
233235
principalId: userObjectId
@@ -245,6 +247,11 @@ module aiSearch 'br/public:avm/res/search/search-service:0.9.0' = {
245247
roleDefinitionIdOrName: 'Search Service Contributor'
246248
}
247249
]
250+
diagnosticSettings: [
251+
{
252+
workspaceResourceId: logAnalyticsWorkspace.outputs.resourceId
253+
}
254+
]
248255
tags: allTags
249256
}
250257
}
@@ -277,31 +284,6 @@ module network './modules/virtualNetwork.bicep' = if (networkIsolation) {
277284
}
278285
}
279286

280-
module privateEndpoints './modules/privateEndpoints.bicep' = if (networkIsolation) {
281-
name: take('${name}-private-endpoints-deployment', 64)
282-
params: {
283-
subnetId: network.outputs.vmSubnetId
284-
blobStorageAccountPrivateEndpointName: toLower('pep-${storageAccount.outputs.name}-blob')
285-
fileStorageAccountPrivateEndpointName: toLower('pep-${storageAccount.outputs.name}-file')
286-
keyVaultPrivateEndpointName: toLower('pep-${keyvault.outputs.name}')
287-
acrPrivateEndpointName: acrEnabled ? toLower('pep-${containerRegistry.outputs.name}') : ''
288-
storageAccountId: storageAccount.outputs.resourceId
289-
keyVaultId: keyvault.outputs.resourceId
290-
acrId: acrEnabled ? containerRegistry.outputs.resourceId : ''
291-
hubWorkspacePrivateEndpointName: toLower('pep-${aiHub.outputs.name}')
292-
hubWorkspaceId: aiHub.outputs.resourceId
293-
aiServicesPrivateEndpointName: toLower('pep-${aiServices.outputs.name}')
294-
aiServicesId: aiServices.outputs.resourceId
295-
apiManagementPrivateEndpointName: apiManagementEnabled ? (toLower('pep-${apiManagementService.outputs.name}')) : ''
296-
apiManagementId: apiManagementEnabled ? apiManagementService.outputs.resourceId : ''
297-
aiSearchId: aiSearch.outputs.resourceId
298-
aiSearchPrivateEndpointName: toLower('pep-${aiSearch.outputs.name}')
299-
location: location
300-
tags: allTags
301-
}
302-
dependsOn: networkIsolation ? [apiManagementService] : []
303-
}
304-
305287
module virtualMachine './modules/virtualMachine.bicep' = if (networkIsolation) {
306288
name: take('${name}-virtual-machine-deployment', 64)
307289
params: {
@@ -573,6 +555,31 @@ module sqlServer 'modules/sqlServer.bicep' = if (sqlServerEnabled && networkIsol
573555
}
574556
}
575557

558+
module privateEndpoints './modules/privateEndpoints.bicep' = if (networkIsolation) {
559+
name: take('${name}-private-endpoints-deployment', 64)
560+
params: {
561+
subnetId: network.outputs.vmSubnetId
562+
blobStorageAccountPrivateEndpointName: toLower('pep-${storageAccount.outputs.name}-blob')
563+
fileStorageAccountPrivateEndpointName: toLower('pep-${storageAccount.outputs.name}-file')
564+
keyVaultPrivateEndpointName: toLower('pep-${keyvault.outputs.name}')
565+
acrPrivateEndpointName: acrEnabled ? toLower('pep-${containerRegistry.outputs.name}') : ''
566+
storageAccountId: storageAccount.outputs.resourceId
567+
keyVaultId: keyvault.outputs.resourceId
568+
acrId: acrEnabled ? containerRegistry.outputs.resourceId : ''
569+
hubWorkspacePrivateEndpointName: toLower('pep-${aiHub.outputs.name}')
570+
hubWorkspaceId: aiHub.outputs.resourceId
571+
aiServicesPrivateEndpointName: toLower('pep-${aiServices.outputs.name}')
572+
aiServicesId: aiServices.outputs.resourceId
573+
apiManagementPrivateEndpointName: apiManagementEnabled ? (toLower('pep-${apiManagementService.outputs.name}')) : ''
574+
apiManagementId: apiManagementEnabled ? apiManagementService.outputs.resourceId : ''
575+
aiSearchId: aiSearch.outputs.resourceId
576+
aiSearchPrivateEndpointName: toLower('pep-${aiSearch.outputs.name}')
577+
location: location
578+
tags: allTags
579+
}
580+
dependsOn: networkIsolation ? [apiManagementService] : []
581+
}
582+
576583
import { sqlDatabaseType, databasePropertyType, deploymentsType } from 'modules/customTypes.bicep'
577584
import { connectionType } from 'br/public:avm/res/machine-learning-services/workspace:0.10.1'
578585

infra/modules/privateEndpoints.bicep

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,13 @@ resource aiSearchPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' =
119119
tags: tags
120120
}
121121

122+
resource apiManagementPrivateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
123+
name: 'privatelink.apim.windows.net'
124+
location: 'global'
125+
tags: tags
126+
}
127+
128+
122129
// Virtual Network Links
123130
resource acrPrivateDnsZoneVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = if (!empty(acrId)) {
124131
parent: acrPrivateDnsZone
@@ -228,6 +235,18 @@ resource aiSearchPrivateDnsZoneVirtualNetworkLink 'Microsoft.Network/privateDnsZ
228235
}
229236
}
230237

238+
resource apiManagementPrivateDnsZoneVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
239+
parent: apiManagementPrivateDnsZone
240+
name: 'link_to_${toLower(virtualNetworkName)}'
241+
location: 'global'
242+
properties: {
243+
registrationEnabled: false
244+
virtualNetwork: {
245+
id: vnet.id
246+
}
247+
}
248+
}
249+
231250
// Private Endpoints
232251
resource blobStorageAccountPrivateEndpoint 'Microsoft.Network/privateEndpoints@2023-04-01' = {
233252
name: blobStorageAccountPrivateEndpointName
@@ -480,13 +499,27 @@ resource apiManagementPrivateEndpoint 'Microsoft.Network/privateEndpoints@2021-0
480499
properties: {
481500
privateLinkServiceId: apiManagementId
482501
groupIds: [
483-
'gateway'
502+
'Gateway'
484503
]
485504
}
486505
}
487506
]
488507
}
489508
}
509+
resource apiManagementPrivateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-11-01' = {
510+
parent: apiManagementPrivateEndpoint
511+
name: 'default'
512+
properties:{
513+
privateDnsZoneConfigs: [
514+
{
515+
name: replace(apiManagementPrivateDnsZone.name, '.', '-')
516+
properties:{
517+
privateDnsZoneId: apiManagementPrivateDnsZone.id
518+
}
519+
}
520+
]
521+
}
522+
}
490523

491524

492525
resource aiSearchPrivateEndpoint 'Microsoft.Network/privateEndpoints@2023-11-01' = {

local_environment_steps.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Local Environment Setup
2+
3+
### Clone Repository
4+
5+
```bash
6+
git clone https://github.com/microsoft/Deploy-Your-AI-Application-In-Production.git
7+
cd Deploy-Your-AI-Application-In-Production
8+
```
9+
10+
### Establish AZD Environment
11+
12+
This solution uses the [Azure Developer CLI](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview) to quickly provision and deploy infrastructure and applications to Azure.
13+
14+
To get started, authenticate with an Azure Subscription ([details](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/reference#azd-auth-login)):
15+
16+
```powershell
17+
azd auth login
18+
```
19+
20+
Establish new environment. Provide a name that represents the application domain:
21+
22+
```powershell
23+
azd env new '<app name>'
24+
```
25+
26+
Optionally set environment variables via the following commands:
27+
28+
```powershell
29+
azd env set 'AZURE_VM_ADMIN_PASSWORD' '<secure password>'
30+
```
31+
32+
# Deploy
33+
34+
To provision the necessary Azure resources and deploy the application, run the azd up command:
35+
```powershell
36+
azd up
37+
```
38+
This will kick off an interactive console to provide required flags and parameters to deploy the infrastructure of a secure, WAF-aligned AI Foundry environment.
39+
40+
>- This deployment will take 15-20 minutes to provision the resources in your account. If you get an error or timeout with deployment, changing the location can help, as there may be availability constraints for the resources.
41+
>- Note the `.env` file created at `/.azure/<app name>`. These are the environment configuration output from running the `azd up` command. These values are names of resources created as part of the baseline infrastructure.

0 commit comments

Comments
 (0)