Skip to content

Commit 594bb22

Browse files
committed
Add GSA proxy bicep templates for standard agent BYO VNet setup
Add bicep modules to deploy a GSA AI Connector proxy VM with a BYO VNet, enabling egress traffic inspection and authentication for standard AI Foundry agent deployments. New files: main.bicep: Orchestrator template for full end-to-end deployment including VNet, GSA proxy, AI account, project, and capability host main.bicepparam / test-deploy.parameters.json: Parameter files with defaults modules/vnet.bicep: Creates VNet with agent subnet (delegated to Microsoft.App/environments) and GSA proxy subnet modules/gsa-proxy.bicep: Core module deploying: - GSA proxy subnet with NSG (allows VirtualNetwork traffic) - VM from GSA AI Connector marketplace image with managed identity - NIC with IP forwarding enabled - UDR routing 0/0 from agent subnet to proxy, with exceptions for AzureActiveDirectory, AzureResourceManager, AzureMonitor, GuestAndHybridManagement, AzureContainerRegistry, AzureKeyVault, and Storage service tags modules/agent-subnet-udr-association.bicep: Associates the UDR with the agent subnet while preserving existing delegation and NSG configuration modules/standard-dependent-resources.bicep: Creates Cosmos DB, AI Search, and Storage with cosmosDBZoneRedundant parameter for regions with AZ capacity constraints
1 parent ff0cd4e commit 594bb22

18 files changed

Lines changed: 1528 additions & 0 deletions
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# 46 - Standard Agent Setup with BYO VNet and GSA Proxy
2+
3+
This sample deploys an Azure AI Foundry agent setup with:
4+
5+
- **BYO Virtual Network** with agent subnet delegation (no private endpoints)
6+
- **GSA AI Connector proxy** VM for egress traffic control
7+
- **UDR (User Defined Route)** that routes `0.0.0.0/0` traffic from the agent subnet through the GSA proxy
8+
- **Service tag exceptions** in the UDR so critical Azure traffic bypasses the proxy
9+
10+
## Architecture Overview
11+
12+
```
13+
┌─────────────────────────────────────────────────────────────────┐
14+
│ Virtual Network (10.0.0.0/16) │
15+
│ │
16+
│ ┌───────────────────────────┐ ┌─────────────────────────────┐ │
17+
│ │ agent-subnet (10.0.0.0/24)│ │ gsa-proxy-subnet │ │
18+
│ │ │ │ (10.0.1.0/24) │ │
19+
│ │ Delegated to │ │ │ │
20+
│ │ Microsoft.App/environments│ │ ┌──────────────────────┐ │ │
21+
│ │ │ │ │ GSA Proxy VM │ │ │
22+
│ │ UDR: 0/0 → Proxy IP │ │ │ - Managed Identity │ │ │
23+
│ │ (with service tag │──│──│ - IP Forwarding: ON │ │ │
24+
│ │ exceptions) │ │ │ - NSG: VNet allowed │ │ │
25+
│ │ │ │ └──────────────────────┘ │ │
26+
│ └───────────────────────────┘ └─────────────────────────────┘ │
27+
└─────────────────────────────────────────────────────────────────┘
28+
29+
├── AI Services (publicNetworkAccess: Enabled)
30+
│ └── networkInjections: agent subnet
31+
├── AI Project
32+
├── Cosmos DB
33+
├── AI Search
34+
└── Storage Account
35+
```
36+
37+
## Key Differences from Other Setups
38+
39+
| Feature | 41-standard-agent | 15-private-network | **46-byovnet-gsa-proxy** |
40+
|---|---|---|---|
41+
| VNet ||||
42+
| Private Endpoints ||||
43+
| DNS Zones ||||
44+
| Public Network Access | Enabled | Disabled | **Enabled** |
45+
| Agent Subnet Delegation ||||
46+
| GSA Proxy ||||
47+
| UDR (egress control) ||||
48+
49+
## GSA Proxy Details
50+
51+
The GSA AI Connector is deployed from the Azure Marketplace:
52+
- **Publisher**: `microsoftcorporation1687208452115`
53+
- **Offer**: `gsaaiconnector1-preview`
54+
- **Plan**: `gsaaiconnectorplan1`
55+
56+
### VM Configuration
57+
- **Managed Identity**: System-assigned (enabled)
58+
- **IP Forwarding**: Enabled on the NIC (required for routing)
59+
- **NSG Rules**:
60+
- Inbound: Allow `VirtualNetwork` and `AzureLoadBalancer`; deny all other
61+
- Outbound: Allow `VirtualNetwork` and `Internet`
62+
63+
## UDR (User Defined Routes)
64+
65+
The agent subnet has a route table that sends all default (`0.0.0.0/0`) traffic through the GSA proxy VM as a virtual appliance. The following Azure service tags are **excepted** (routed directly to Internet):
66+
67+
| Service Tag | Purpose |
68+
|---|---|
69+
| `AzureActiveDirectory` | Entra ID authentication |
70+
| `AzureResourceManager` | ARM API calls |
71+
| `AzureMonitor` | Monitoring and diagnostics |
72+
| `GuestAndHybridManagement` | VM guest agent management |
73+
| `AzureContainerRegistry` | Container image pulls |
74+
| `AzureKeyVault` | Key Vault access |
75+
| `Storage` | Azure Storage access |
76+
77+
## Prerequisites
78+
79+
1. **Accept the marketplace terms** for the GSA AI Connector image before deploying:
80+
```bash
81+
az vm image terms accept \
82+
--publisher microsoftcorporation1687208452115 \
83+
--offer gsaaiconnector1-preview \
84+
--plan gsaaiconnectorplan1
85+
```
86+
87+
2. **Generate an SSH key pair** for the proxy VM:
88+
```bash
89+
ssh-keygen -t rsa -b 4096 -f ~/.ssh/gsa-proxy-key -N ""
90+
```
91+
92+
## Deployment
93+
94+
### Using Azure CLI with Bicep parameter file
95+
96+
```bash
97+
# Set your SSH public key
98+
export GSA_PROXY_SSH_PUBLIC_KEY=$(cat ~/.ssh/gsa-proxy-key.pub)
99+
100+
# Create resource group
101+
az group create --name rg-ai-agent-gsa-proxy --location eastus
102+
103+
# Deploy
104+
az deployment group create \
105+
--resource-group rg-ai-agent-gsa-proxy \
106+
--template-file main.bicep \
107+
--parameters main.bicepparam
108+
```
109+
110+
### Using inline parameters
111+
112+
```bash
113+
az deployment group create \
114+
--resource-group rg-ai-agent-gsa-proxy \
115+
--template-file main.bicep \
116+
--parameters \
117+
location=eastus \
118+
aiServices=foundy \
119+
gsaProxySshPublicKey="$(cat ~/.ssh/gsa-proxy-key.pub)"
120+
```
121+
122+
## Module Structure
123+
124+
```
125+
46-standard-agent-byovnet-gsa-proxy-setup/
126+
├── main.bicep # Orchestrator - deploys everything
127+
├── main.bicepparam # Parameter file
128+
├── README.md # This file
129+
└── modules/
130+
├── vnet.bicep # VNet with agent + proxy subnets
131+
├── gsa-proxy.bicep # GSA proxy VM, NIC, NSG, UDR
132+
├── agent-subnet-udr-association.bicep # Associates UDR to agent subnet
133+
├── ai-account-identity.bicep # AI Services with subnet injection
134+
├── ai-project-identity.bicep # AI Project
135+
├── standard-dependent-resources.bicep # Cosmos DB, AI Search, Storage
136+
├── add-project-capability-host.bicep # Capability host configuration
137+
├── validate-existing-resources.bicep # Validates BYO resources
138+
├── format-project-workspace-id.bicep # Workspace ID formatting
139+
├── ai-search-role-assignments.bicep # AI Search RBAC
140+
├── azure-storage-account-role-assignment.bicep # Storage RBAC
141+
├── blob-storage-container-role-assignments.bicep # Blob container RBAC
142+
├── cosmos-container-role-assignments.bicep # Cosmos container RBAC
143+
└── cosmosdb-account-role-assignment.bicep # Cosmos account RBAC
144+
```
145+
146+
## Parameters
147+
148+
| Parameter | Type | Default | Description |
149+
|---|---|---|---|
150+
| `location` | string | `eastus` | Azure region |
151+
| `aiServices` | string | `foundy` | AI Services resource name (max 9 chars) |
152+
| `firstProjectName` | string | `project` | Project resource name |
153+
| `vnetName` | string | `agent-vnet` | Virtual network name |
154+
| `vnetAddressPrefix` | string | `10.0.0.0/16` | VNet CIDR |
155+
| `agentSubnetPrefix` | string | `10.0.0.0/24` | Agent subnet CIDR |
156+
| `gsaProxySubnetPrefix` | string | `10.0.1.0/24` | GSA proxy subnet CIDR |
157+
| `gsaProxyVmSize` | string | `Standard_D2s_v3` | Proxy VM size |
158+
| `gsaProxySshPublicKey` | secure string | *(required)* | SSH public key for VM |
159+
| `modelName` | string | `gpt-4.1` | Model to deploy |
160+
| `modelCapacity` | int | `30` | TPM for model deployment |
161+
| `aiSearchResourceId` | string | `''` | Optional existing AI Search ARM ID |
162+
| `azureStorageAccountResourceId` | string | `''` | Optional existing Storage ARM ID |
163+
| `azureCosmosDBAccountResourceId` | string | `''` | Optional existing Cosmos DB ARM ID |

0 commit comments

Comments
 (0)