Azure Virtual Network
Это содержимое пока не доступно на вашем языке.
This article is the reference for the Aspire Azure Virtual Network integration. It enumerates the AppHost APIs — with examples for both AppHost.cs and apphost.mts — that you use to configure virtual networks, subnets, NAT gateways, network security groups (NSGs), private endpoints, and network security perimeters in your AppHost project.
Azure Virtual Network enables Azure resources to securely communicate with each other, the internet, and on-premises networks.
Hosting integration
Section titled “Hosting integration”The Azure Virtual Network hosting integration models network resources as the following types:
AzureVirtualNetworkResource: Represents an Azure Virtual Network.AzureSubnetResource: Represents a subnet within a virtual network.AzureNetworkSecurityGroupResource: Represents a network security group for traffic control.AzureNatGatewayResource: Represents a NAT gateway for deterministic outbound IP addresses.AzurePublicIPAddressResource: Represents a public IP address.AzureNetworkSecurityPerimeterResource: Represents an Azure Network Security Perimeter for PaaS service isolation.
Installation
Section titled “Installation”To start building an Aspire app that uses Azure Virtual Network, install the 📦 Aspire.Hosting.Azure.Network NuGet package:
aspire add azure-networkLearn more about aspire add in the
command reference.
This updates your aspire.config.json with the Azure Network hosting integration package:
{ "packages": { "Aspire.Hosting.Azure.Network": "13.5.3" }}aspire add azure-networkLearn more about aspire add in the
command reference.
Or, choose a manual installation approach:
#:package Aspire.Hosting.Azure.Network@*<PackageReference Include="Aspire.Hosting.Azure.Network" Version="*" />Add a virtual network
Section titled “Add a virtual network”To add a virtual network, call AddAzureVirtualNetwork (or addAzureVirtualNetwork) on the builder instance:
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const vnet = await builder.addAzureVirtualNetwork("vnet");
// After adding all resources, run the app...await builder.build().run();var builder = DistributedApplication.CreateBuilder(args);
var vnet = builder.AddAzureVirtualNetwork("vnet");
// After adding all resources, run the app...builder.Build().Run();By default, the virtual network uses the address prefix 10.0.0.0/16. You can specify a custom address prefix:
const vnet = await builder.addAzureVirtualNetwork('vnet', '10.1.0.0/16');var vnet = builder.AddAzureVirtualNetwork("vnet", "10.1.0.0/16");Add subnets
Section titled “Add subnets”Call AddSubnet (or addSubnet) on the virtual network builder to add a subnet with a name and address prefix:
const vnet = await builder.addAzureVirtualNetwork("vnet");
const subnet = vnet.addSubnet("my-subnet", "10.0.1.0/24");var vnet = builder.AddAzureVirtualNetwork("vnet");
var subnet = vnet.AddSubnet("my-subnet", "10.0.1.0/24");You can add multiple subnets with different address ranges to a single virtual network. Subnet address prefixes must fall within the virtual network’s address space (for example, 10.0.1.0/24 is valid within a 10.0.0.0/16 network).
Add NAT gateways
Section titled “Add NAT gateways”A NAT gateway provides deterministic outbound public IP addresses for subnet resources. Call AddNatGateway (or addNatGateway) to create a NAT gateway, then associate it with a subnet using WithNatGateway (or withNatGateway):
const natGateway = await builder.addNatGateway("nat");
const vnet = await builder.addAzureVirtualNetwork("vnet");const subnet = vnet.addSubnet("aca-subnet", "10.0.0.0/23") .withNatGateway(natGateway);var natGateway = builder.AddNatGateway("nat");
var vnet = builder.AddAzureVirtualNetwork("vnet");var subnet = vnet.AddSubnet("aca-subnet", "10.0.0.0/23").WithNatGateway(natGateway);By default, a public IP address is automatically created for the NAT gateway. To provide an explicit public IP address for full control, call AddPublicIPAddress (or addPublicIPAddress) and associate it with WithPublicIPAddress (or withPublicIPAddress):
const pip = await builder.addPublicIPAddress('nat-pip');const natGateway = await builder.addNatGateway('nat').withPublicIPAddress(pip);var pip = builder.AddPublicIPAddress("nat-pip");var natGateway = builder.AddNatGateway("nat") .WithPublicIPAddress(pip);For advanced settings like idle timeout or availability zones, use ConfigureInfrastructure.
Add network security groups
Section titled “Add network security groups”Network security groups (NSGs) control inbound and outbound traffic flow on subnets. The integration provides two APIs for configuring NSGs: a shorthand API for common scenarios and an explicit API for full control.
Shorthand API
Section titled “Shorthand API”The shorthand API uses fluent methods on subnet builders that automatically create an NSG, auto-increment priority, and auto-generate rule names:
const vnet = await builder.addAzureVirtualNetwork("vnet");
const subnet = vnet.addSubnet("web", "10.0.1.0/24") .allowInbound("443", "AzureLoadBalancer", undefined, "Tcp") .denyInbound(undefined, "Internet");var vnet = builder.AddAzureVirtualNetwork("vnet");
var subnet = vnet.AddSubnet("web", "10.0.1.0/24").AllowInbound(port: "443",from: AzureServiceTags.AzureLoadBalancer,protocol: SecurityRuleProtocol.Tcp).DenyInbound(from: AzureServiceTags.Internet);The available shorthand methods are:
AllowInbound(orallowInbound) — Allow inbound traffic.DenyInbound(ordenyInbound) — Deny inbound traffic.AllowOutbound(orallowOutbound) — Allow outbound traffic.DenyOutbound(ordenyOutbound) — Deny outbound traffic.
Priority auto-increments by 100 (100, 200, 300…) and rule names are auto-generated from the access, direction, port, and source (for example, allow-inbound-443-AzureLoadBalancer).
Explicit API
Section titled “Explicit API”For full control over security rules, create a standalone NSG with AddNetworkSecurityGroup (or addNetworkSecurityGroup) on the builder and attach it to a subnet with WithNetworkSecurityGroup (or withNetworkSecurityGroup):
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const vnet = await builder.addAzureVirtualNetwork("vnet");
const nsg = builder.addNetworkSecurityGroup("web-nsg") .withSecurityRule({ name: "allow-https", priority: 100, direction: "Inbound", access: "Allow", protocol: "Tcp", destinationPortRange: "443" });
const subnet = vnet.addSubnet("web-subnet", "10.0.1.0/24") .withNetworkSecurityGroup(nsg);var builder = DistributedApplication.CreateBuilder(args);
var vnet = builder.AddAzureVirtualNetwork("vnet");
var nsg = builder.AddNetworkSecurityGroup("web-nsg").WithSecurityRule(new AzureSecurityRule{Name = "allow-https",Priority = 100,Direction = SecurityRuleDirection.Inbound,Access = SecurityRuleAccess.Allow,Protocol = SecurityRuleProtocol.Tcp,DestinationPortRange = "443"});
var subnet = vnet.AddSubnet("web-subnet", "10.0.1.0/24").WithNetworkSecurityGroup(nsg);The AzureSecurityRule type provides sensible defaults—SourcePortRange, SourceAddressPrefix, and DestinationAddressPrefix all default to "*". The Name, Priority, Direction, Access, Protocol, and DestinationPortRange properties are required.
A single NSG can be shared across multiple subnets.
Delegate subnets to compute environments
Section titled “Delegate subnets to compute environments”Compute environment integrations that support regional virtual network integration expose a WithDelegatedSubnet (or withDelegatedSubnet in TypeScript) extension method that assigns a subnet to the environment, enabling subnet delegation so the environment can inject its infrastructure. For example, Azure Container Apps and Azure App Service both support WithDelegatedSubnet:
const vnet = await builder.addAzureVirtualNetwork("vnet");const acaSubnet = await vnet.addSubnet("aca-subnet", "10.0.0.0/24");const appServiceSubnet = await vnet.addSubnet("app-service-subnet", "10.0.1.0/24");
// Azure Container Apps environmentawait builder.addAzureContainerAppEnvironment("aca-env") .withDelegatedSubnet(acaSubnet);
// Azure App Service environmentawait builder.addAzureAppServiceEnvironment("app-service-env") .withDelegatedSubnet(appServiceSubnet);var vnet = builder.AddAzureVirtualNetwork("vnet");var acaSubnet = vnet.AddSubnet("aca-subnet", "10.0.0.0/24");var appServiceSubnet = vnet.AddSubnet("app-service-subnet", "10.0.1.0/24");
// Azure Container Apps environmentbuilder.AddAzureContainerAppEnvironment("aca-env") .WithDelegatedSubnet(acaSubnet);
// Azure App Service environment (requires ASPIREAZURE003 suppression)#pragma warning disable ASPIREAZURE003builder.AddAzureAppServiceEnvironment("app-service-env") .WithDelegatedSubnet(appServiceSubnet);#pragma warning restore ASPIREAZURE003Each compute environment delegates the subnet to its own Azure service (for example, App Service delegates to Microsoft.Web/serverFarms). Regional virtual network integration affects outbound traffic only—it doesn’t make ingress private and doesn’t enable Route All.
Delegate a subnet to an Azure service
Section titled “Delegate a subnet to an Azure service”For scenarios that aren’t covered by a compute environment’s WithDelegatedSubnet helper, call WithServiceDelegation (or withServiceDelegation in TypeScript) directly on the subnet builder to delegate it to a supported Azure service. The delegation name defaults to serviceName so you don’t have to repeat the value:
import { AzureSubnetServiceDelegations } from './.aspire/modules/aspire.mjs';
const vnet = await builder.addAzureVirtualNetwork("vnet");const subnet = await vnet.addSubnet("aci-subnet", "10.0.0.0/23");
await subnet.withServiceDelegation(AzureSubnetServiceDelegations.ContainerInstances);
// Or specify a custom delegation name.await subnet.withServiceDelegation( AzureSubnetServiceDelegations.ContainerInstances, { name: "aci-delegation" });var vnet = builder.AddAzureVirtualNetwork("vnet");var subnet = vnet.AddSubnet("aci-subnet", "10.0.0.0/23") .WithServiceDelegation(AzureSubnetServiceDelegations.ContainerInstances);
// Or specify a custom delegation name.subnet.WithServiceDelegation( AzureSubnetServiceDelegations.ContainerInstances, name: "aci-delegation");AzureSubnetServiceDelegations provides discoverable, well-known service identifiers so you don’t have to remember or duplicate the underlying Azure resource provider strings:
| Constant | Value |
|---|---|
ContainerInstances | Microsoft.ContainerInstance/containerGroups |
ContainerAppEnvironments | Microsoft.App/environments |
AppServiceEnvironments | Microsoft.Web/serverFarms |
ApplicationGatewayForContainers | Microsoft.ServiceNetworking/trafficControllers |
You can also pass another supported Azure resource provider path as serviceName if the service doesn’t have a well-known constant. Aspire models and emits one service delegation for a subnet, so use one compute-environment delegation helper or service delegation per subnet. Repeated direct WithServiceDelegation calls replace the previous service-delegation annotation, so the latest direct call wins. WithDelegatedSubnet allows an existing delegation for the same required service, but throws an InvalidOperationException when the subnet’s effective existing service delegation differs.
Add private endpoints
Section titled “Add private endpoints”Private endpoints enable secure connectivity to Azure services over a private network. Call AddPrivateEndpoint (or addPrivateEndpoint) on a subnet builder and pass the Azure resource to connect to:
const vnet = await builder.addAzureVirtualNetwork("vnet");const peSubnet = vnet.addSubnet("private-endpoints", "10.0.2.0/24");
const storage = await builder.addAzureStorage("storage");const blobs = storage.addBlobs("blobs");
peSubnet.addPrivateEndpoint(blobs);var vnet = builder.AddAzureVirtualNetwork("vnet");var peSubnet = vnet.AddSubnet("private-endpoints", "10.0.2.0/24");
var storage = builder.AddAzureStorage("storage");var blobs = storage.AddBlobs("blobs");
peSubnet.AddPrivateEndpoint(blobs);When you add a private endpoint, the following resources are automatically created:
- A Private DNS Zone for the service (for example,
privatelink.blob.core.windows.net). - A Virtual Network Link connecting the DNS zone to your virtual network.
- A DNS Zone Group on the private endpoint for automatic DNS registration.
- The target resource is automatically configured to deny public network access.
The private DNS zone ensures that services within the virtual network automatically resolve the target resource’s hostname to its private IP address. Resources that reference the target (for example, via WithReference) use the same connection information—DNS resolution handles routing traffic over the private network.
Override public network access
Section titled “Override public network access”To keep public access enabled on a resource that has a private endpoint, use ConfigureInfrastructure to override the automatic lockdown:
storage.ConfigureInfrastructure(infra =>{ var storageAccount = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single(); storageAccount.PublicNetworkAccess = StoragePublicNetworkAccess.Enabled;});Service-specific requirements
Section titled “Service-specific requirements”Azure Service Bus
Section titled “Azure Service Bus”Azure Service Bus requires the Premium tier to support private endpoints. When you add a private endpoint for a Service Bus resource, Aspire automatically sets the SKU to Premium.
Azure SQL Server
Section titled “Azure SQL Server”Azure SQL Server uses a deployment script to grant your application’s managed identity access to the SQL database. When you add a private endpoint for a SQL Server resource, the deployment script needs to run inside the virtual network via Azure Container Instances (ACI). Aspire automatically creates a delegated subnet and a storage account for the deployment script container. For details on customizing this behavior, see Admin deployment script.
Azure Container Registry
Section titled “Azure Container Registry”Azure Container Registry requires the Premium SKU to support private endpoints. When you add a private endpoint for an Azure Container Registry resource, Aspire automatically upgrades the SKU to Premium.
Add a network security perimeter
Section titled “Add a network security perimeter”Azure Network Security Perimeters (NSPs) provide a logical security boundary for Azure PaaS services such as Storage, Key Vault, Cosmos DB, and SQL. Where virtual networks and private endpoints secure connectivity at the infrastructure layer, NSPs operate at the PaaS layer—grouping resources so they can communicate with each other while restricting public access via access rules.
Why use a network security perimeter?
Section titled “Why use a network security perimeter?”NSPs complement private endpoints with a higher-level grouping model. Instead of configuring a private endpoint for every resource pair, you place all related PaaS resources inside a single perimeter. Resources within the perimeter communicate freely, and you define inbound and outbound access rules that apply to the entire boundary. This is useful when:
- You have many PaaS resources that need to talk to each other but shouldn’t be publicly accessible.
- You want a single set of access rules (IP ranges, subscription allow-lists, FQDN allow-lists) that apply uniformly to the group.
- You want to audit traffic before enforcing restrictions by using Learning mode.
Create a perimeter
Section titled “Create a perimeter”Call AddNetworkSecurityPerimeter (or addNetworkSecurityPerimeter) on the builder instance to create an NSP with a default profile:
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
const nsp = await builder.addNetworkSecurityPerimeter("my-nsp");
// After adding all resources, run the app...await builder.build().run();var builder = DistributedApplication.CreateBuilder(args);
var nsp = builder.AddNetworkSecurityPerimeter("my-nsp");
// After adding all resources, run the app...builder.Build().Run();Add access rules
Section titled “Add access rules”Access rules control traffic flowing into and out of the perimeter. Call WithAccessRule (or withAccessRule) and pass an AzureNspAccessRule to define a rule:
const nsp = await builder.addNetworkSecurityPerimeter("my-nsp") .withAccessRule({ name: "allow-my-ip", direction: "Inbound", addressPrefixes: ["203.0.113.0/24"] }) .withAccessRule({ name: "allow-outbound-fqdn", direction: "Outbound", fullyQualifiedDomainNames: ["*.blob.core.windows.net"] });var nsp = builder.AddNetworkSecurityPerimeter("my-nsp") .WithAccessRule(new AzureNspAccessRule { Name = "allow-my-ip", Direction = NetworkSecurityPerimeterAccessRuleDirection.Inbound, AddressPrefixes = { "203.0.113.0/24" } }) .WithAccessRule(new AzureNspAccessRule { Name = "allow-outbound-fqdn", Direction = NetworkSecurityPerimeterAccessRuleDirection.Outbound, FullyQualifiedDomainNames = { "*.blob.core.windows.net" } });The following properties are available on AzureNspAccessRule:
| Property | Direction | Description |
|---|---|---|
AddressPrefixes | Inbound | CIDR ranges allowed to reach the perimeter. |
Subscriptions | Inbound | Subscription resource IDs (format: /subscriptions/{id}) allowed access. |
FullyQualifiedDomainNames | Outbound | FQDNs that resources inside the perimeter can communicate with. |
Each property also has a corresponding *References variant (for example, AddressPrefixReferences) that accepts ReferenceExpression values resolved at deploy time.
Associate resources with a perimeter
Section titled “Associate resources with a perimeter”Call WithNetworkSecurityPerimeter (or withNetworkSecurityPerimeter) on a PaaS resource builder to associate it with an NSP:
const nsp = await builder.addNetworkSecurityPerimeter("my-nsp");
const storage = await builder.addAzureStorage("storage") .withNetworkSecurityPerimeter(nsp);const keyVault = await builder.addAzureKeyVault("kv") .withNetworkSecurityPerimeter(nsp);var nsp = builder.AddNetworkSecurityPerimeter("my-nsp");
var storage = builder.AddAzureStorage("storage").WithNetworkSecurityPerimeter(nsp);var keyVault = builder.AddAzureKeyVault("kv").WithNetworkSecurityPerimeter(nsp);Once associated, resources within the perimeter can communicate with each other, while public access is governed by the perimeter’s access rules.
The following Azure resources support NSP association:
- Azure AI Foundry
- Azure AI Search
- Azure Cosmos DB
- Azure Event Hubs
- Azure Key Vault
- Azure Log Analytics
- Azure OpenAI
- Azure Service Bus
- Azure SQL Server
- Azure Storage
Enforced vs. Learning mode
Section titled “Enforced vs. Learning mode”By default, associations use Enforced mode—resources within the perimeter can communicate with each other, and any public traffic that doesn’t match an access rule is blocked. You can switch to Learning mode to log violations without blocking traffic, which is helpful when onboarding resources to identify which access rules are needed before switching to enforced mode:
// Enforced mode (default) — blocks traffic that violates the rulesstorage.withNetworkSecurityPerimeter(nsp);
// Learning mode — logs violations without blockingkeyVault.withNetworkSecurityPerimeter(nsp, "Learning");// Enforced mode (default) — blocks traffic that violates the rulesstorage.WithNetworkSecurityPerimeter(nsp);
// Learning mode — logs violations without blockingkeyVault.WithNetworkSecurityPerimeter(nsp, NetworkSecurityPerimeterAssociationAccessMode.Learning);Complete example
Section titled “Complete example”The following example demonstrates a complete network topology with a virtual network, subnets, NSG rules, a NAT gateway, private endpoints, and an Azure Container Apps environment:
import { createBuilder } from './.aspire/modules/aspire.mjs';
const builder = await createBuilder();
// Create a virtual network with two subnetsconst vnet = await builder.addAzureVirtualNetwork("vnet");
// Container Apps subnet with NSG rules and NAT gatewayconst containerAppsSubnet = vnet.addSubnet("container-apps", "10.0.0.0/23") .allowInbound({ port: "443", from: "AzureLoadBalancer", protocol: "Tcp" }) .denyInbound({ from: "VirtualNetwork" }) .denyInbound({ from: "Internet" });
const natGateway = await builder.addNatGateway("nat");containerAppsSubnet.withNatGateway(natGateway);
// Private endpoints subnetconst peSubnet = vnet.addSubnet("private-endpoints", "10.0.2.0/27") .allowInbound({ port: "443", from: "VirtualNetwork", protocol: "Tcp" }) .denyInbound({ from: "Internet" });
// Configure the Container App Environment to use the VNet.await builder.addAzureContainerAppEnvironment("env") .withDelegatedSubnet(containerAppsSubnet);
// Add storage with private endpointsconst storage = await builder.addAzureStorage("storage");const blobs = storage.addBlobs("blobs");const queues = storage.addQueues("queues");
peSubnet.addPrivateEndpoint(blobs);peSubnet.addPrivateEndpoint(queues);
await builder.addProject("api", "../Api/Api.csproj") .withExternalHttpEndpoints() .withReference(blobs) .withReference(queues);
await builder.build().run();#pragma warning disable AZPROVISION001
using Aspire.Hosting.Azure;using Azure.Provisioning.Network;
var builder = DistributedApplication.CreateBuilder(args);
// Create a virtual network with two subnetsvar vnet = builder.AddAzureVirtualNetwork("vnet");
// Container Apps subnet with NSG rules and NAT gatewayvar containerAppsSubnet = vnet.AddSubnet("container-apps", "10.0.0.0/23").AllowInbound(port: "443",from: AzureServiceTags.AzureLoadBalancer,protocol: SecurityRuleProtocol.Tcp).DenyInbound(from: AzureServiceTags.VirtualNetwork).DenyInbound(from: AzureServiceTags.Internet);
var natGateway = builder.AddNatGateway("nat");containerAppsSubnet.WithNatGateway(natGateway);
// Private endpoints subnetvar peSubnet = vnet.AddSubnet("private-endpoints", "10.0.2.0/27").AllowInbound(port: "443",from: AzureServiceTags.VirtualNetwork,protocol: SecurityRuleProtocol.Tcp).DenyInbound(from: AzureServiceTags.Internet);
// Configure the Container App Environment to use the VNet.// WithDelegatedSubnet assigns the subnet to the ACA environment,// enabling subnet delegation so ACA can inject its infrastructure.// For more information, see: https://learn.microsoft.com/azure/container-apps/custom-virtual-networksbuilder.AddAzureContainerAppEnvironment("env").WithDelegatedSubnet(containerAppsSubnet);
// Add storage with private endpointsvar storage = builder.AddAzureStorage("storage");var blobs = storage.AddBlobs("blobs");var queues = storage.AddQueues("queues");
peSubnet.AddPrivateEndpoint(blobs);peSubnet.AddPrivateEndpoint(queues);
builder.AddProject<Projects.Api>("api").WithExternalHttpEndpoints().WithReference(blobs).WithReference(queues);
builder.Build().Run();