Skip to content

Improve Azure Sandbox defaults - #19810

Open
Mitch Denny (mitchdenny) wants to merge 17 commits into
mainfrom
mitchdenny-azure-sandbox-defaults
Open

Improve Azure Sandbox defaults#19810
Mitch Denny (mitchdenny) wants to merge 17 commits into
mainfrom
mitchdenny-azure-sandbox-defaults

Conversation

@mitchdenny

Copy link
Copy Markdown
Member

Description

Azure Sandbox groups should work as compute environments without requiring every workload to opt in through PublishAsAzureSandbox. This change lets a simple AppHost add one sandbox group and one .NET project, with Aspire automatically assigning and deploying that project using sensible endpoint defaults.

PublishAsAzureSandbox now configures sandbox-specific runtime options only. With one compute environment, Aspire infers the sandbox group; with multiple environments, workloads select one through WithComputeEnvironment.

For .NET projects with the usual paired HTTP and HTTPS endpoints, the sandbox deployment now:

  • exposes one shared HTTP container port on 8080;
  • terminates TLS at the sandbox proxy and forwards HTTP to the container;
  • resolves both app-model endpoint references to the same HTTPS sandbox URL;
  • merges endpoint access policy on the shared target port and rejects conflicting policies.

Coverage includes automatic .NET project adoption, paired HTTP/HTTPS endpoint translation, multiple sandbox groups with one project each, and an Azure deployment E2E that verifies TLS termination and the 8080 backend port.

User-facing usage

C# AppHost:

#pragma warning disable ASPIREAZURE001

builder.AddAzureSandboxGroup("env");
builder.AddProject<Projects.ApiService>("api");

Sandbox options remain available without passing the environment:

builder.AddProject<Projects.ApiService>("api")
    .PublishAsAzureSandbox(new AzureSandboxOptions
    {
        Tier = AzureSandboxTier.Medium
    });

TypeScript AppHost:

await builder.addAzureSandboxGroup("env");

await api.publishAsAzureSandbox({
    tier: AzureSandboxTier.Medium
});

Breaking changes

The sandbox-group parameter was removed from PublishAsAzureSandbox. Existing callers should rely on single-environment inference or call WithComputeEnvironment(sandboxGroup) before PublishAsAzureSandbox(options) when multiple compute environments exist.

Security considerations

The integration now automatically exposes the first HTTP endpoint of an inferred .NET project through an authenticated sandbox port. Anonymous access remains opt-in through AzureSandboxEndpointOptions.Anonymous. The sandbox proxy terminates TLS, while traffic to the container uses HTTP on the shared target port.

Validation

  • 89 AzureSandboxesTests passed.
  • Aspire.Deployment.EndToEnd.Tests builds successfully.
  • Full repository build completed successfully with native compilation skipped.
  • Added an Azure deployment E2E for a .NET service with paired HTTP/HTTPS endpoints.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
Copilot AI balanced review requested due to automatic review settings August 31, 2026 01:28
@mitchdenny Mitch Denny (mitchdenny) added the breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. label Aug 31, 2026
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

Copy link
Copy Markdown
Contributor

🚀 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 -- 19810

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19810"
@github-actions github-actions Bot added the area-integrations Issues pertaining to Aspire Integrations packages label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #19810...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 1 High severity · 2 Medium severity

New issues introduced by this change (3)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxesExtensions.csPublishAsAzureSandbox can now silently do nothing when no Azure sandbox group exists (or when the…
Medium severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxContainerDeployment.cs — This condition disables the documented automatic project endpoint whenever any endpoint is…
Medium severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxEndpointPropertyValueProvider.cs — Removing the external-endpoint guard makes the existing target-port fallback apply to containers…
What changed in this PR

Enables Azure Sandbox groups to automatically adopt workloads and adds sensible .NET HTTP/HTTPS deployment defaults.

Changes:

  • Simplifies PublishAsAzureSandbox to configure runtime options only.
  • Maps paired .NET endpoints to one TLS-terminated port on 8080.
  • Adds unit, polyglot, and Azure deployment coverage.
File Description
AzureSandboxesExtensions.cs Simplifies sandbox publishing API.
AzureSandboxContainerDeployment.cs Adds endpoint adoption and port merging.
AzureSandboxEndpointPropertyValueProvider.cs Resolves shared deployed endpoint URLs.
README.md Documents new defaults and API usage.
AzureSandboxesTests.cs Adds focused unit coverage.
AzureSandboxesDeploymentTests.cs Adds live .NET deployment validation.
TypeScript/​apphost.mts Updates generated TypeScript API usage.
Comment thread src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
@github-actions
github-actions Bot temporarily deployed to deployment-testing August 31, 2026 01:38 Inactive
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 43797078-ec60-4205-81cb-7cf510cb5f6e
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: None

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerOptionsAnnotation.cs:53

  • This also removes the public PublicEndpointReadyTimeout option, but the PR's Breaking changes section only documents removal of the sandbox-group parameter. Existing callers that set this option will stop compiling without any stated migration. Please document this removal and explain that deployment now relies on the provider operation/target-native readiness contract instead.
    /// <summary>
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 43797078-ec60-4205-81cb-7cf510cb5f6e
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #19810...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 1 High severity

New issues introduced by this change (1)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs — This step is still collected for a sandbox group marked ExcludeFromPublish, while Azure…
Suppressed comments (1)

src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxEndpointPropertyValueProvider.cs:180

  • This now resolves every endpoint by target port, so an internal endpoint can silently acquire an exposed endpoint's public URL. For example, a container with external public and internal admin endpoints both targeting 8080 will resolve an admin reference through the public sandbox port; the constructor previously rejected that reference. Limit target-port fallback to the automatically shared .NET project HTTP/HTTPS pair and preserve the external-endpoint check for other endpoints, with a regression test for an internal container endpoint sharing an exposed port.
            if (string.Equals(resolvedEndpoint.Endpoint.Name, endpointName, StringComparison.Ordinal))
            {
                return AzureSandboxContainerDeployment.ResolveSandboxTargetPort(resource.TargetResource, resolvedEndpoint);
Comment on lines +166 to +169
private async Task AddDashboardToPipelineSummaryAsync(PipelineStepContext context)
{
var scope = AzureSandboxContainerDeployment.CreateDataPlaneScope(this);
var dashboardUrl = GetDashboardUrl(scope.SubscriptionId, scope.ResourceGroupName, scope.SandboxGroupName);
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 43797078-ec60-4205-81cb-7cf510cb5f6e
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #19810...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 1 High severity

Pre-existing issues (1)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs — This step is still collected for a sandbox group marked ExcludeFromPublish, while Azure… View comment
Suppressed comments (1)

src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs:169

  • Pipeline steps are collected from excluded resources too, so an Azure sandbox group configured with ExcludeFromManifest() still runs this summary action during deploy. Because the excluded group is not provisioned, CreateDataPlaneScope then throws for the missing id/location outputs and breaks an otherwise valid deployment. Skip this action (or omit the step) when IsExcludedFromPublish() is true.
    private async Task AddDashboardToPipelineSummaryAsync(PipelineStepContext context)
    {
        var scope = AzureSandboxContainerDeployment.CreateDataPlaneScope(this);
        var dashboardUrl = GetDashboardUrl(scope.SubscriptionId, scope.ResourceGroupName, scope.SandboxGroupName);
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 43797078-ec60-4205-81cb-7cf510cb5f6e
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #19810...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 2 High severity

New issues introduced by this change (1)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxContainerDeployment.cs — This fallback also applies to an HTTPS-only project endpoint because HTTPS endpoints default to…
Pre-existing issues (1)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs — This step is still collected for a sandbox group marked ExcludeFromPublish, while Azure… View comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/Aspire.Hosting.Azure.Sandboxes/README.md:41

  • These C# blocks form one usage flow, but this block adds a second resource named api after api was already declared above. Copying the example therefore fails with a duplicate resource name. Configure the previously declared builder instead.
builder.AddProject<Projects.ApiService>("api")
    .PublishAsAzureSandbox(new AzureSandboxOptions
Comment on lines +1532 to +1536
// .NET project publishing uses ContainerPortReference for the shared HTTP/HTTPS
// destination when no target port is specified. Sandbox ingress terminates TLS,
// so both app-model endpoints route to the framework's HTTP container port.
return resource is ProjectResource && endpoint.Endpoint.Transport is "http" or "http2"
? DefaultContainerPort
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 43797078-ec60-4205-81cb-7cf510cb5f6e
@mitchdenny

Copy link
Copy Markdown
Member Author

/deployment-test

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

🚀 Deployment tests starting on PR #19810...

This will deploy to real Azure infrastructure. Results will be posted here when complete.

View workflow run

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Tests selector

3 / 99 PR test projects · 3 PR jobs · 2 advisory-only targets, from 11 changed files.

Selected PR test projects (3 / 99)

Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Tests, Aspire.Playground.Tests

Selected PR jobs (3)

extension-e2e, polyglot, typescript-api-compat

Advisory workflow impact (2)

  • Aspire.Deployment.EndToEnd.Tests (deployment workflow-only)
  • deployment-e2e (schedule/dispatch-only)

How these were chosen — grouped by what changed

🧪 tests/Aspire.Hosting.Azure.Tests/AzureCosmosDBExtensionsTests.cs (changed test)
1 directly: Aspire.Hosting.Azure.Tests
1 via the project graph: Aspire.Hosting.Azure.Kubernetes.Tests

📄 playground/CosmosEndToEnd/CosmosEndToEnd.AppHost/AppHost.cs (changed)
1 directly: Aspire.Playground.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerOptionsAnnotation.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxEndpointPropertyValueProvider.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🔧 src/Aspire.Hosting.Azure.Sandboxes/Internal/Adc/AzureDevComputeClient.cs (changed source)
1 directly: Aspire.Hosting.Azure.Tests

🧪 tests/Aspire.Deployment.EndToEnd.Tests/AzureSandboxesDeploymentTests.cs (changed test)
1 directly: Aspire.Deployment.EndToEnd.Tests

🧪 tests/Aspire.Hosting.Azure.Tests/AzureSandboxesTests.cs (changed test)
1 directly: Aspire.Hosting.Azure.Tests

Job reasons

Job Triggered by
deployment-e2e tests/Aspire.Deployment.EndToEnd.Tests/AzureSandboxesDeploymentTests.cs
• affected project Aspire.Hosting.Azure.Sandboxes
extension-e2e src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs, src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerOptionsAnnotation.cs, src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxEndpointPropertyValueProvider.cs, src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs, src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs, src/Aspire.Hosting.Azure.Sandboxes/Internal/Adc/AzureDevComputeClient.cs
• affected project Aspire.Hosting.Azure.Sandboxes
polyglot tests/PolyglotAppHosts/Aspire.Hosting.Azure.Sandboxes/TypeScript/apphost.mts
typescript-api-compat affected project Aspire.Hosting.Azure.Sandboxes

Selection computed for commit 0342cfc.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 2 High severity

Pre-existing issues (2)
Severity Finding
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxContainerDeployment.cs — This fallback also applies to an HTTPS-only project endpoint because HTTPS endpoints default to… View comment
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs — This step is still collected for a sandbox group marked ExcludeFromPublish, while Azure… View comment
Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerOptionsAnnotation.cs:53

  • PublicEndpointReadyTimeout is also being removed from the public AzureSandboxOptions surface (and therefore from the generated TypeScript options), but the PR's Breaking changes section only mentions the removed sandbox-group parameter. Please document this additional breaking change and its migration—namely that endpoint readiness is no longer configurable here—so existing callers have complete upgrade guidance.
    /// <summary>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-integrations Issues pertaining to Aspire Integrations packages breaking-change Issue or PR that represents a breaking API or functional change over a prerelease.

2 participants