Networking & Security
Overview
The Mastra Agent Framework supports three levels of network isolation:
| Level | VNet | Service Endpoints | Private Endpoints | Use Case |
|---|---|---|---|---|
| Basic | Enabled | Enabled | Disabled | Development |
| Standard | Enabled | Enabled | Enabled | Staging |
| Full | Enabled | Enabled | Enabled | Production |
All environments use VNet by default. VNet is free and provides the foundation for Service Endpoints and Private Endpoints. The main cost difference is Private Endpoints (approximately 40 USD/month).
Network Architecture
Service Endpoints vs Private Endpoints
Service Endpoints (Free)
Service Endpoints extend the VNet identity to Azure services over the Azure backbone network.
| Pros | Cons |
|---|---|
| Free to use | Traffic still goes to public endpoint |
| Easy to configure | Limited to Azure-to-Azure traffic |
| No additional DNS needed | No protection from data exfiltration |
Configured for: Storage, SQL, Key Vault
Private Endpoints (Paid)
Private Endpoints create a private IP address in your VNet for the Azure service.
| Pros | Cons |
|---|---|
| True network isolation | Costs $7.30/month per endpoint |
| Traffic stays in VNet | Requires Private DNS configuration |
| Data exfiltration protection | More complex setup |
Configured for: Key Vault, SQL, Storage, AI Foundry, Function App (staging/prod only)
VNet Configuration
Why This Subnet Design?
The VNet is segmented into four purpose-specific subnets. This design follows Azure best practices for separating concerns, meeting Azure technical requirements, and enabling future scalability.
Design Principles
-
Separation of Concerns
- Compute resources (App Service, Function App) are isolated from data resources (databases, secrets)
- AI workloads have their own subnet to isolate potentially high-bandwidth model inference traffic
- Management resources are separated for future administrative access (Azure Bastion)
-
Azure Technical Requirements
- Delegated subnets cannot host Private Endpoints: The compute subnet must be delegated to
Microsoft.Web/serverFarmsfor VNet Integration. Azure prohibits Private Endpoints in delegated subnets, so we need separate subnets. - Private Endpoints require
privateEndpointNetworkPolicies: Disabled: This setting is incompatible with certain subnet features, so dedicated PE subnets are cleaner.
- Delegated subnets cannot host Private Endpoints: The compute subnet must be delegated to
-
Security Boundaries
- Each subnet can have its own Network Security Group (NSG) rules
- Traffic between subnets can be controlled and audited
- Blast radius is limited if one subnet is compromised
-
Scalability
- Each /24 subnet provides 251 usable IP addresses
- Easy to add new subnets for additional workloads (e.g., VMs, AKS, additional PEs)
- Address space (10.0.0.0/16) allows for 256 subnets
Subnet Layout
| Subnet | CIDR | Purpose | Delegations |
|---|---|---|---|
| compute-subnet | 10.0.1.0/24 | App Service & Function App VNet Integration | Microsoft.Web/serverFarms |
| data-subnet | 10.0.2.0/24 | Private Endpoints (KV, SQL, Storage, Function App) | None |
| ai-subnet | 10.0.3.0/24 | Private Endpoints (AI Foundry) | None |
| management-subnet | 10.0.4.0/24 | Reserved for Azure Bastion (future use) | None |
How Subnets Work Together
The subnets collaborate to enable secure communication between compute resources and backend services:
Traffic Flow:
- App Service/Function App in compute-subnet initiates outbound requests
- VNet Integration routes traffic through the VNet instead of the public internet
- Service Endpoints (dev) or Private Endpoints (staging/prod) receive the traffic
- Private DNS Zones resolve service hostnames to private IPs when using Private Endpoints
- Backend services (Key Vault, SQL, Storage) respond through the same path
Subnet Details
Compute Subnet (10.0.1.0/24)
Purpose: Host App Service and Function App with VNet Integration for secure outbound connectivity.
The compute subnet is the "front door" of the architecture. App Service and Function App are PaaS services that normally run outside your VNet. VNet Integration injects their outbound traffic into this subnet, allowing them to:
- Access Private Endpoints in other subnets
- Use Service Endpoints for secure Azure service access
- Be subject to VNet-level security controls (NSGs, route tables)
Why delegation is required:
Azure App Service VNet Integration requires the subnet to be "delegated" to Microsoft.Web/serverFarms. This tells Azure that the subnet is reserved for App Service instances and allows Azure to manage the network interfaces automatically.
Delegated subnets cannot host Private Endpoints. This is an Azure limitation. The compute subnet's delegation to App Service means we cannot place any Private Endpoints here—hence the need for separate data and AI subnets.
Key characteristics:
- Delegation:
Microsoft.Web/serverFarms(required for VNet Integration) - Service Endpoints: Storage, SQL, Key Vault, Cognitive Services (free alternative to PEs)
- Hosts: App Service outbound traffic, Function App outbound traffic
- Cannot host: Private Endpoints (due to delegation)
{
name: 'compute-subnet'
properties: {
addressPrefix: '10.0.1.0/24'
delegations: [{
name: 'app-service-delegation'
properties: { serviceName: 'Microsoft.Web/serverFarms' }
}]
serviceEndpoints: [
{ service: 'Microsoft.KeyVault' }
{ service: 'Microsoft.Sql' }
{ service: 'Microsoft.Storage' }
{ service: 'Microsoft.CognitiveServices' }
]
}
}
Data Subnet (10.0.2.0/24)
Purpose: Host Private Endpoints for data services (secrets, databases, storage) and inbound Function App access.
The data subnet is the "secure vault" of the architecture. It contains Private Endpoints that give Azure PaaS services private IP addresses within the VNet. This means:
- Traffic to Key Vault, SQL, and Storage never traverses the public internet
- Services are accessible only from within the VNet (or via VPN/ExpressRoute)
- Data exfiltration attacks are mitigated—attackers can't redirect traffic to rogue endpoints
Why data services are grouped together:
- Key Vault, SQL, and Storage all handle sensitive data (secrets, credentials, business data)
- Grouping them simplifies NSG rules and monitoring
- Consistent security posture across all data services
Why Function App PE is here (not in compute-subnet):
The Function App has two network paths:
- Outbound (Function App calling other services): Uses VNet Integration via compute-subnet
- Inbound (other services calling Function App): Uses Private Endpoint
Since the compute-subnet is delegated, the Function App's Private Endpoint must live in a non-delegated subnet. We place it in data-subnet because the Function App processes sensitive data and should be grouped with other protected resources.
Key characteristics:
- No delegation: Required to allow Private Endpoints
privateEndpointNetworkPolicies: Disabled: Required Azure setting for PE subnets- Hosts: Key Vault PE, SQL Server PE, Storage PE, Function App PE
- Service Endpoints: Also enabled as fallback for dev environments
{
name: 'data-subnet'
properties: {
addressPrefix: '10.0.2.0/24'
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
serviceEndpoints: [
{ service: 'Microsoft.KeyVault' }
{ service: 'Microsoft.Sql' }
{ service: 'Microsoft.Storage' }
]
}
}
AI Subnet (10.0.3.0/24)
Purpose: Isolate AI services Private Endpoints from data services for traffic separation and future scalability.
The AI subnet separates AI workloads from traditional data services. This separation provides:
Why a dedicated AI subnet?
-
Traffic Isolation: AI inference can be bandwidth-intensive. Separating AI traffic prevents it from competing with database and storage operations.
-
Different Security Profile: AI services (Azure OpenAI, Content Safety) have different compliance requirements than databases. Separate subnets allow different NSG rules.
-
Future Scalability: As AI workloads grow, you may need multiple AI Private Endpoints (different models, regions, or services). A dedicated subnet provides room to grow.
-
Cost Monitoring: Azure Cost Management can track costs by subnet, making it easier to attribute AI spending.
Key characteristics:
- Hosts: AI Foundry Private Endpoint (Azure OpenAI access)
- Service Endpoints: Cognitive Services (for non-PE scenarios)
privateEndpointNetworkPolicies: Disabled: Required for PE hosting
{
name: 'ai-subnet'
properties: {
addressPrefix: '10.0.3.0/24'
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
serviceEndpoints: [
{ service: 'Microsoft.CognitiveServices' }
]
}
}
Management Subnet (10.0.4.0/24)
Purpose: Reserved for administrative access and future management workloads.
The management subnet is currently empty but reserved for future use. Common uses include:
Potential future uses:
- Azure Bastion: Secure RDP/SSH access to VMs without exposing them to the internet
- Jump boxes: Administrative VMs for debugging or management tasks
- Azure Firewall: Centralized egress filtering (if needed)
- VPN Gateway: Site-to-site or point-to-site VPN termination
Why reserve it now?
- Adding subnets to an existing VNet can cause IP address conflicts
- Pre-allocating address space ensures clean network planning
- No cost impact—subnets are free
{
name: 'management-subnet'
properties: {
addressPrefix: '10.0.4.0/24'
}
}
Private Endpoints Configuration
Deployed Private Endpoints
| Resource | Group ID | Private DNS Zone | Subnet |
|---|---|---|---|
| Key Vault | vault | privatelink.vaultcore.azure.net | data-subnet |
| SQL Server | sqlServer | privatelink.database.windows.net | data-subnet |
| Storage Account | blob | privatelink.blob.core.windows.net | data-subnet |
| AI Foundry | account | privatelink.cognitiveservices.azure.com | ai-subnet |
| Function App | sites | privatelink.azurewebsites.net | data-subnet |
Why No Private Endpoints For
| Resource | Reason |
|---|---|
| Container Registry | Basic SKU doesn't support PE. ACR doesn't store sensitive business data. |
| Content Safety | Processes data transiently, doesn't store it. Uses managed identity. |
| Form Recognizer | Processes documents transiently. No persistent storage of business data. |
| AI Search | Optional service. Add PE if enabled and required. |
| App Service | Needs public access for APIM/external callers. |
Function App Private Endpoint Logic
// Only in staging/prod, not dev
var enableFunctionAppPrivateEndpoint =
enablePrivateEndpoints &&
enableVnet &&
deployFunctionApp &&
environment != 'dev'
Reasoning:
- Dev: Public access for debugging webhooks, testing APIs
- Staging/Prod: Private access since Function App processes sensitive data
Private DNS Zones
Private DNS Zones resolve Azure service hostnames to private IP addresses.
DNS Resolution Flow
DNS Zones Deployed
| Zone | Service |
|---|---|
privatelink.vaultcore.azure.net | Key Vault |
privatelink.database.windows.net | SQL Server |
privatelink.blob.core.windows.net | Storage Blob |
privatelink.cognitiveservices.azure.com | AI Foundry |
privatelink.azurewebsites.net | App Service / Function App |
Firewall Configuration
IP-Based Firewall Rules
For services without Private Endpoints, IP-based firewall rules restrict access:
param allowedIpAddresses array = [
'203.0.113.10' // Developer workstation
'198.51.100.0/24' // Office IP range
]
Applied to:
- Storage Account
- Key Vault
- SQL Server
Subnet-Based Rules
When VNet is enabled, compute subnet is automatically allowed:
allowedSubnetIds: enableVnet ? [vnet.outputs.computeSubnetId] : []
Security Best Practices
Development Environment
param enableVnet = true
param enablePrivateEndpoints = false
param enableServiceEndpoints = true
param enableNetworkLockdown = true
param enableAppAccessRestrictions = true
param allowedIpAddresses = ['<dev-team-ips>']
- VNet enabled with Service Endpoints; deny-by-default still applies to data services
- No Private Endpoints by default; this keeps cost low while preserving APIM-first ingress
- APIM-backed web apps stay publicly reachable on Consumption and rely on APIM/app-layer auth instead of App Service IP deny rules
Staging Environment
param enableVnet = true
param enablePrivateEndpoints = false
param enableServiceEndpoints = true
param enableNetworkLockdown = true
param enableAppAccessRestrictions = true
param allowedIpAddresses = ['<trusted-operator-ip>']
- Mirrors production's current service-endpoint + lockdown model for data services
- APIM remains the supported public edge
- APIM-backed web apps stay publicly reachable on Consumption and rely on APIM/app-layer auth instead of App Service IP deny rules
Production Environment
param enableVnet = true
param enablePrivateEndpoints = false
param enableServiceEndpoints = true
param enableNetworkLockdown = true
param enableAppAccessRestrictions = true
param allowedIpAddresses = ['<trusted-operator-ip>']
- Data services use Service Endpoints plus deny-by-default firewalls
- APIM-backed web apps stay publicly reachable on Consumption and rely on APIM/app-layer auth instead of App Service IP deny rules
- Only APIM should be treated as the supported public entrypoint
Troubleshooting
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| Can't reach Key Vault | DNS not resolving to private IP | Check Private DNS Zone is linked to VNet |
| SQL connection timeout | Firewall blocking | Add VNet subnet or IP to allowed list |
| ACR pull fails | Network rules blocking | ACR doesn't use Private Endpoints; check managed identity |
| Function App can't call storage | Missing Service Endpoint | Enable Storage service endpoint on compute subnet |
Verify Private Endpoint Resolution
From within the VNet (App Service console):
# Should resolve to private IP (10.x.x.x)
nslookup mykv.vault.azure.net
# Should NOT resolve to public IP (52.x.x.x, etc.)
Check Network Security
# List Private Endpoints
az network private-endpoint list \
--resource-group <rg-name> \
--output table
# Check Private DNS Zone links
az network private-dns link vnet list \
--resource-group <rg-name> \
--zone-name privatelink.vaultcore.azure.net \
--output table
Cost Considerations
| Component | Monthly Cost |
|---|---|
| VNet | Free |
| Subnets | Free |
| Service Endpoints | Free |
| Private Endpoint (each) | $7.30 |
| Private DNS Zone | $0.50 |
| VNet Link (per zone) | $0.10 |
Total for 5 Private Endpoints + 5 DNS Zones:
- Private Endpoints: 5 × $7.30 = $36.50/month
- DNS Zones: 5 × $0.50 = $2.50/month
- VNet Links: 5 × $0.10 = $0.50/month
- Total: ~$40/month
Private Endpoints are only deployed in staging and production environments. Development uses Service Endpoints (free) for basic security.