Add Azure Network Security Perimeter (NSP) support#15711
Add Azure Network Security Perimeter (NSP) support#15711eerhardt merged 10 commits intomicrosoft:mainfrom
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15711Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15711" |
Implement NSP resources for securing PaaS services (Storage, Key Vault, Cosmos DB, SQL) within a logical network boundary. NSPs are the PaaS-layer equivalent of VNets/NSGs, grouping resources so they can communicate internally while restricting public access via access rules. New APIs: - AddNetworkSecurityPerimeter() - creates an NSP with a default profile - WithAccessRule() - adds inbound/outbound rules (IP prefixes, subscriptions, FQDNs, service tags) - AssociateWith() - explicitly associates a PaaS resource with an NSP - AssociateAllPaaSResources() - auto-associates all IAzureNspAssociationTarget resources in the app model New types: - AzureNetworkSecurityPerimeterResource - AzureNspAccessRule (DTO for rule configuration) - IAzureNspAssociationTarget (implemented by Storage, KeyVault, CosmosDB, SQL) - NspAssociationTargetAnnotation (for provisioning dependency ordering) Associations use Enforced access mode by default. Generated Bicep targets the 2025-05-01 API version via Azure.Provisioning.Network 1.1.0-beta.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds initial Azure Network Security Perimeter (NSP) support to Aspire’s Azure hosting model so AppHosts can define an NSP, configure access rules, and associate eligible Azure resources for deployment-time perimeter enforcement.
Changes:
- Introduces
AddNetworkSecurityPerimeter,WithAccessRule, andAssociateWithAPIs plus new NSP resource/DTO types. - Extends several Azure resource types to be NSP-association targets and adds missing
idoutputs to generated Bicep where needed. - Updates Azure.Network README and refreshes package versions (notably
Azure.Provisioning.NetworkandAzure.Core) to support the new ARM API surface.
Reviewed changes
Copilot reviewed 36 out of 36 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.Azure.Tests/Snapshots/FoundryExtensionsTests.AddFoundry_GeneratesValidBicep#00.verified.bicep | Snapshot update to include id output for Foundry. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingLogAnalyticsWithResourceGroup.verified.bicep | Snapshot update to include id output for existing Log Analytics workspace. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/ExistingAzureResourceTests.SupportsExistingAzureOpenAIWithResourceGroup.verified.bicep | Snapshot update to include id output for existing Azure OpenAI resource. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureOpenAIExtensionsTests.AddAzureOpenAI_overrideLocalAuthDefault=True_useObsoleteApis=True.verified.bicep | Snapshot update to include id output for Azure OpenAI. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureOpenAIExtensionsTests.AddAzureOpenAI_overrideLocalAuthDefault=True_useObsoleteApis=False.verified.bicep | Snapshot update to include id output for Azure OpenAI. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureOpenAIExtensionsTests.AddAzureOpenAI_overrideLocalAuthDefault=False_useObsoleteApis=True.verified.bicep | Snapshot update to include id output for Azure OpenAI. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureOpenAIExtensionsTests.AddAzureOpenAI_overrideLocalAuthDefault=False_useObsoleteApis=False.verified.bicep | Snapshot update to include id output for Azure OpenAI. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_WithSubscriptionRule_GeneratesCorrectBicep.verified.bicep | New snapshot validating subscription-based access rule emission. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_WithStorageAssociation_GeneratesCorrectBicep.verified.bicep | New snapshot validating NSP association emission. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_WithParameterBasedAccessRules_GeneratesCorrectBicep.verified.bicep | New snapshot validating parameter-based rule references. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_WithMultipleAssociations_GeneratesCorrectBicep.verified.bicep | New snapshot validating multiple associations and access-mode variants. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_WithAccessRules_GeneratesCorrectBicep.verified.bicep | New snapshot validating basic inbound/outbound rule emission. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureNetworkSecurityPerimeterExtensionsTests.AddNetworkSecurityPerimeter_GeneratesCorrectBicep.verified.bicep | New snapshot validating baseline NSP + default profile. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureLogAnalyticsWorkspaceExtensionsTests.AddLogAnalyticsWorkspace.verified.bicep | Snapshot update to include id output for Log Analytics workspace. |
| tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ContainerAppEnvironmentWithCustomWorkspace#02.verified.bicep | Snapshot update to include id output for custom workspace. |
| tests/Aspire.Hosting.Azure.Tests/AzureNetworkSecurityPerimeterExtensionsTests.cs | New unit/snapshot tests covering NSP creation, rules, and associations. |
| src/Aspire.Hosting.Foundry/FoundryResource.cs | Marks Foundry as NSP-association-capable and exposes Id output reference. |
| src/Aspire.Hosting.Foundry/FoundryExtensions.cs | Adds id provisioning output for Foundry Bicep module. |
| src/Aspire.Hosting.Azure/IAzureNspAssociationTarget.cs | New interface to model resources that can be associated to an NSP. |
| src/Aspire.Hosting.Azure/AzureResourcePreparer.cs | Minor formatting-only change in preparer logic. |
| src/Aspire.Hosting.Azure.Storage/AzureStorageResource.cs | Implements NSP association target interface (uses existing Id output reference). |
| src/Aspire.Hosting.Azure.Sql/AzureSqlServerResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.ServiceBus/AzureServiceBusResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.Search/AzureSearchResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.OperationalInsights/AzureLogAnalyticsWorkspaceResource.cs | Implements NSP association target interface and exposes Id output reference. |
| src/Aspire.Hosting.Azure.OperationalInsights/AzureLogAnalyticsWorkspaceExtensions.cs | Adds id provisioning output for Log Analytics workspace Bicep module. |
| src/Aspire.Hosting.Azure.Network/README.md | Documents NSP usage in the Azure.Network hosting README. |
| src/Aspire.Hosting.Azure.Network/AzureNspAccessRule.cs | New DTO for expressing NSP access-rule configuration. |
| src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityPerimeterResource.cs | New resource type representing an NSP, including rule/association storage. |
| src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityPerimeterExtensions.cs | Core NSP APIs + Bicep generation for NSP/profile/rules/associations. |
| src/Aspire.Hosting.Azure.KeyVault/AzureKeyVaultResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.EventHubs/AzureEventHubsResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs | Implements NSP association target interface. |
| src/Aspire.Hosting.Azure.CognitiveServices/AzureOpenAIResource.cs | Implements NSP association target interface and exposes Id output reference. |
| src/Aspire.Hosting.Azure.CognitiveServices/AzureOpenAIExtensions.cs | Adds id provisioning output for Azure OpenAI Bicep module. |
| Directory.Packages.props | Bumps Azure.Provisioning.Network and Azure.Core versions needed for NSP support. |
src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityPerimeterExtensions.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityPerimeterExtensions.cs
Outdated
Show resolved
Hide resolved
src/Aspire.Hosting.Azure.Network/AzureNetworkSecurityPerimeterExtensions.cs
Show resolved
Hide resolved
| // Create a default profile | ||
| var profileIdentifier = Infrastructure.NormalizeBicepIdentifier($"{nsp.BicepIdentifier}_profile"); | ||
| var profile = new NetworkSecurityPerimeterProfile(profileIdentifier) | ||
| { | ||
| Name = "defaultProfile", | ||
| Parent = nsp, | ||
| }; | ||
| infra.Add(profile); |
There was a problem hiding this comment.
Note: I'm not currently publicly modeling a "profile" child resource. I'm not sure it is necessary for most usages.
We can easily add it in the future, and keep the existing easy APIs - the existing APIs will still apply to the "default" profile.
Let me know if you think this is a mistake.
|
Finding 2 — Duplicate |
mitchdenny
left a comment
There was a problem hiding this comment.
Finding 1 — Beta package dependency: Azure.Provisioning.Network is upgraded from stable 1.0.0 to pre-release 1.1.0-beta.2. We should wait until 1.1.0 ships as stable before merging this, so the existing VNet/NSG/PrivateEndpoint features don't ship on a pre-release dependency.
|
Follow-up: E2E deployment tests Can we file a follow-up issue to add E2E deployment tests for the NSP feature? Since this PR is from a fork, we can't add deployment E2E tests here (they require secrets/infrastructure), but it would be good to verify that the generated Bicep actually deploys successfully with real Azure resources — especially the association + access rule combinations. |
|
Finding 3 — Missing test for The duplicate name detection in [Fact]
public void AssociateWith_DuplicateAssociationName_Throws()
{
using var builder = TestDistributedApplicationBuilder.Create(DistributedApplicationOperation.Publish);
var nsp = builder.AddNetworkSecurityPerimeter("my-nsp");
var storage = builder.AddAzureStorage("storage");
storage.AssociateWith(nsp);
var exception = Assert.Throws<ArgumentException>(() => storage.AssociateWith(nsp));
Assert.Contains("storage-assoc", exception.Message, StringComparison.OrdinalIgnoreCase);
} |
|
Naming consistency: The NSP resource uses However, So the NSP resource has the right name here. We should consider a breaking change to rename |
mitchdenny
left a comment
There was a problem hiding this comment.
This looks good to me. We'll see if we need profile support. I think we might want to make a breaking change re NameOutput just for consistency.
|
One more question ... how do we feel about |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thanks for the review @mitchdenny.
I removed the duplicate output in the bicep. I kept the "Id" C# property- this will just have both.
We will get the Azure.Provisioning team to release stable. I will merge the PR and we can update to the stable version when it is ready. It will be before we branch for 13.3.
Yep, I will create a PR to add a new deployment test once this is merged.
Thanks for adding it to this PR.
Fixed with Rename NameOutput to NameOutputReference in Aspire.Hosting.Azure.Network (microsoft/aspire#16004)Rename NameOutput to NameOutputReference in Aspire.Hosting.Azure.Network (microsoft/aspire#16004)
Good suggestion, I renamed it to |
Adds a new deployment test that: - Uses the Starter App (ASP.NET Core/React) template - Adds Azure Container Apps environment - Adds Azure Storage (with Blobs) and Azure Key Vault - Creates a Network Security Perimeter (NSP) with a subscription-level inbound access rule for the current Azure subscription - Associates both Storage and Key Vault with the NSP - Wires the ASP.NET Core backend (ApiService) to connect to both Storage Blobs and Key Vault - Deploys to Azure and verifies the endpoints work This tests the end-to-end NSP flow added in PR microsoft#15711. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add NSP + Storage + KeyVault deployment E2E test Adds a new deployment test that: - Uses the Starter App (ASP.NET Core/React) template - Adds Azure Container Apps environment - Adds Azure Storage (with Blobs) and Azure Key Vault - Creates a Network Security Perimeter (NSP) with a subscription-level inbound access rule for the current Azure subscription - Associates both Storage and Key Vault with the NSP - Wires the ASP.NET Core backend (ApiService) to connect to both Storage Blobs and Key Vault - Deploys to Azure and verifies the endpoints work This tests the end-to-end NSP flow added in PR #15711. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix NSP deployment test: use .Server instead of .ApiService for React template The JsReact (ASP.NET Core/React) template uses {ProjectName}.Server for the API backend, not {ProjectName}.ApiService (which is used by the Blazor starter template). Also fixed the .WithHttpHealthCheck replacement to not include a trailing semicolon since the React template's chain continues with .WithExternalHttpEndpoints(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove az network perimeter list step that hangs on extension install prompt The az network perimeter list command can prompt to install an extension, causing the terminal to hang. Remove this non-essential verification step - NSP provisioning is already verified by the PIPELINE SUCCEEDED output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources (Storage, Key Vault, Cosmos DB, SQL, OpenAI, Event Hubs, Service Bus, AI Search) Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources (Storage, Key Vault, Cosmos DB, SQL, OpenAI, Event Hubs, Service Bus, AI Search) Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources (Storage, Key Vault, Cosmos DB, SQL, OpenAI, Event Hubs, Service Bus, AI Search) Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources (Storage, Key Vault, Cosmos DB, SQL, OpenAI, Event Hubs, Service Bus, AI Search) Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources (Storage, Key Vault, Cosmos DB, SQL, OpenAI, Event Hubs, Service Bus, AI Search) Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section on the Azure Virtual Network page covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources Also adds a shell What's new in Aspire 13.3 page with an NSP highlight and a sidebar entry. Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add documentation for the new NSP APIs introduced in microsoft/aspire#15711. The new section on the Azure Virtual Network page covers: - What NSPs are and why they're useful for PaaS service isolation - AddNetworkSecurityPerimeter() API - WithAccessRule() for inbound/outbound access rules - WithNetworkSecurityPerimeter() for associating PaaS resources - Enforced vs. Learning access modes - List of supported Azure resources Also adds a shell What's new in Aspire 13.3 page with an NSP highlight and a sidebar entry. Fixes #689 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Description
Implement NSP resources for securing PaaS services (Storage, Key Vault, Cosmos DB, SQL) within a logical network boundary. NSPs are the PaaS-layer equivalent of VNets/NSGs, grouping resources so they can communicate internally while restricting public access via access rules.
New APIs:
New types:
Associations use Enforced access mode by default. Generated Bicep targets the 2025-05-01 API version via Azure.Provisioning.Network 1.1.0-beta.2.
Checklist
<remarks />and<code />elements on your triple slash comments?aspire.devissue: