Skip to content

Add Azure Network Security Perimeter (NSP) support#15711

Merged
eerhardt merged 10 commits intomicrosoft:mainfrom
eerhardt:AddNSPs
Apr 9, 2026
Merged

Add Azure Network Security Perimeter (NSP) support#15711
eerhardt merged 10 commits intomicrosoft:mainfrom
eerhardt:AddNSPs

Conversation

@eerhardt
Copy link
Copy Markdown
Member

@eerhardt eerhardt commented Mar 30, 2026

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:

  • AddNetworkSecurityPerimeter() - creates an NSP with a default profile
  • WithAccessRule() - adds inbound/outbound rules (IP prefixes, subscriptions, FQDNs)
  • AssociateWith() - explicitly associates a PaaS resource with an NSP

New types:

  • AzureNetworkSecurityPerimeterResource
  • AzureNspAccessRule (DTO for rule configuration)
  • IAzureNspAssociationTarget (implemented by Storage, KeyVault, CosmosDB, SQL)

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

  • Is this feature complete?
    • Yes
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • No
  • Does the change require an update in our Aspire docs?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 30, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15711

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15711"

eerhardt and others added 2 commits April 6, 2026 16:56
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>
@eerhardt eerhardt marked this pull request as ready for review April 7, 2026 21:29
Copilot AI review requested due to automatic review settings April 7, 2026 21:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and AssociateWith APIs plus new NSP resource/DTO types.
  • Extends several Azure resource types to be NSP-association targets and adds missing id outputs to generated Bicep where needed.
  • Updates Azure.Network README and refreshes package versions (notably Azure.Provisioning.Network and Azure.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.

Comment on lines +178 to +185
// Create a default profile
var profileIdentifier = Infrastructure.NormalizeBicepIdentifier($"{nsp.BicepIdentifier}_profile");
var profile = new NetworkSecurityPerimeterProfile(profileIdentifier)
{
Name = "defaultProfile",
Parent = nsp,
};
infra.Add(profile);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@eerhardt eerhardt requested a review from davidfowl April 7, 2026 22:18
@mitchdenny
Copy link
Copy Markdown
Member

Finding 2 — Duplicate id output in Log Analytics Bicep: The new output id string duplicates the existing output logAnalyticsWorkspaceId string (both emit workspace.Id). I assume the duplication is intentional for consistency — so that all IAzureNspAssociationTarget resources use a standard _outputs_id parameter naming convention in the NSP Bicep module. Just confirming that's the intent.

Copy link
Copy Markdown
Member

@mitchdenny mitchdenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mitchdenny
Copy link
Copy Markdown
Member

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.

@mitchdenny
Copy link
Copy Markdown
Member

Finding 3 — Missing test for AssociateWith duplicate association name validation

The duplicate name detection in AssociateWith (lines 144-149) is untested. There's a WithAccessRule_DuplicateName_Throws test but no corresponding test for associations. Proposed test:

[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);
}

@mitchdenny
Copy link
Copy Markdown
Member

Naming consistency: NameOutput vs NameOutputReference

The NSP resource uses NameOutputReference which initially looks inconsistent with the other Network resources in this package (VNet, NSG, NatGateway, PublicIP, PrivateEndpoint, PrivateDnsZone) which all use NameOutput.

However, NameOutputReference is actually the dominant convention across the rest of the repo — used by 24 resource types (KeyVault, Storage, CosmosDB, SQL, EventHubs, ServiceBus, OpenAI, Redis, Foundry, Search, SignalR, AppConfiguration, PostgreSQL, etc.). The 5 NameOutput usages are all confined to the Network package's VNet-family resources, making them the outliers.

So the NSP resource has the right name here. We should consider a breaking change to rename NameOutputNameOutputReference on the existing Network resources (AzureVirtualNetworkResource, AzureNetworkSecurityGroupResource, AzureNatGatewayResource, AzurePublicIPAddressResource, AzurePrivateEndpointResource, AzurePrivateDnsZoneResource) for consistency — either in this PR or as a follow-up.

Copy link
Copy Markdown
Member

@mitchdenny mitchdenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@mitchdenny
Copy link
Copy Markdown
Member

One more question ... how do we feel about AssociateWith(...) as a name. Do we think that this is a common pattern .. or should we do something like WithNetworkSecurityPerimeter(..)?

mitchdenny and others added 3 commits April 9, 2026 16:43
@eerhardt
Copy link
Copy Markdown
Member Author

eerhardt commented Apr 9, 2026

Thanks for the review @mitchdenny.

Finding 2 — Duplicate id output in Log Analytics Bicep

I removed the duplicate output in the bicep. I kept the "Id" C# property- this will just have both.

Finding 1 — Beta package dependency

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.

Follow-up: E2E deployment tests

Yep, I will create a PR to add a new deployment test once this is merged.

Finding 3 — Missing test for AssociateWith duplicate association name validation

Thanks for adding it to this PR.

Naming consistency: NameOutput vs NameOutputReference

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)

how do we feel about AssociateWith(...)

Good suggestion, I renamed it to WithNetworkSecurityPerimeter.

@eerhardt eerhardt enabled auto-merge (squash) April 9, 2026 22:52
@eerhardt eerhardt merged commit a3f2c72 into microsoft:main Apr 9, 2026
524 of 527 checks passed
@eerhardt eerhardt deleted the AddNSPs branch April 9, 2026 23:37
eerhardt added a commit to eerhardt/aspire that referenced this pull request Apr 10, 2026
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>
mitchdenny pushed a commit that referenced this pull request Apr 10, 2026
* 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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
eerhardt added a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
IEvangelist pushed a commit to microsoft/aspire.dev that referenced this pull request Apr 10, 2026
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>
@joperezr joperezr added this to the 13.3 milestone Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants