Skip to content

Enable data-plane references for Azure Sandbox Groups - #19886

Draft
Mitch Denny (mitchdenny) wants to merge 1 commit into
mainfrom
mitchdenny-azure-sandbox-apis
Draft

Mitch Denny (mitchdenny) wants to merge 1 commit into
mainfrom
mitchdenny-azure-sandbox-apis

Conversation

@mitchdenny

@mitchdenny Mitch Denny (mitchdenny) commented Sep 3, 2026 •

Copy link
Copy Markdown
Member

Description

Azure Sandbox Groups are useful not only as Aspire compute environments, but also as a generic sandboxed compute fabric for applications hosted elsewhere. This change allows an application to reference a Sandbox Group as a data-plane resource while continuing to run in another compute environment, such as Azure Container Apps.

Referencing a Sandbox Group now:

  • Lazily activates and provisions the group in run mode.
  • Injects the regional endpoint, subscription, resource group, Sandbox Group name, and connection string.
  • Grants the referencing local principal or published workload identity the Container Apps SandboxGroup Data Owner role.
  • Supports existing Sandbox Groups without requiring compute-specific ACR configuration.
  • Avoids creating ACR and image-pull infrastructure unless the group is also used as a sandbox compute target.

A group can serve both purposes: select it for compute with WithComputeEnvironment(sandboxGroup) and optionally customize the workload with PublishAsAzureSandbox(). When a referenced group is the only compute environment, only explicitly selected or sandbox-opted-in workloads run there; merely referencing it does not move the consumer into a sandbox. Groups used only as compute environments retain the existing implicit-selection behavior.

The new AzureSandboxDataPlane playground demonstrates an Azure Container Apps-hosted TypeScript application creating an Ubuntu sandbox, executing a command, and deleting the sandbox through the preview data-plane SDK.

User-facing usage

C# AppHost:

var sandboxGroup = builder.AddAzureSandboxGroup("sandboxes");
var containerApps = builder.AddAzureContainerAppEnvironment("aca");

builder.AddNodeApp("agent", "../Agent", "server.ts")
    .WithHttpEndpoint(env: "PORT")
    .WithComputeEnvironment(containerApps)
    .WithReference(sandboxGroup)
    .PublishAsDockerFile();

TypeScript application:

const sandboxes = new SandboxGroupClient(
    new DefaultAzureCredential(),
    process.env.SANDBOXES_ENDPOINT!,
    process.env.SANDBOXES_SUBSCRIPTIONID!,
    process.env.SANDBOXES_RESOURCEGROUP!,
    process.env.SANDBOXES_SANDBOXGROUPNAME!);

Security considerations

The reference grants the built-in Container Apps SandboxGroup Data Owner role on the referenced Sandbox Group. In run mode, Aspire grants this role to the current Azure deployment principal. In publish mode, it is assigned to the referencing workload's managed identity. Authentication remains token-based through DefaultAzureCredential; no credentials are placed in the injected connection information.

Validation

  • All 115 AzureSandboxesTests pass after rebasing onto the updated Sandbox implementation in Improve Azure Sandbox defaults #19810.
  • Coverage includes mixed compute/data-plane use, call-order independence, self-reference, repeated preparation, existing groups, and cross-scope image-pull identities.
  • The TypeScript playground passes tsc --noEmit.
  • The playground AppHost builds without warnings.
  • Before the rebase, manually verified sandbox creation, command execution, and deletion against a provisioned Sandbox Group in West US 3.

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 September 3, 2026 04:58
@github-actions

github-actions Bot commented Sep 3, 2026

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 -- 19886

Or

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

@github-actions github-actions Bot added the area-integrations Issues pertaining to Aspire Integrations packages label Sep 3, 2026
@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

🟡 Changes recommended

Mixed compute usage is skipped, RBAC opt-out is overridden, and the playground exposes a privileged unauthenticated endpoint.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

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

New issues introduced by this change (6)
Severity Finding
High severity playground/​AzureSandboxDataPlane/​AzureSandboxDataPlane.AppHost/​AppHost.cs — This makes the playground publicly reachable, but its unauthenticated POST endpoint uses the…
High severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs — HasDataPlaneReferences is set by every WithReference, but RequiresAcrPullIdentity is only set…
Medium severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxesExtensions.cs — This unconditionally reinstates the default Data Owner role after ClearDefaultRoleAssignments()…
Low severity playground/​AzureSandboxDataPlane/​frontend/​public/​index.html — This output changes asynchronously after the button is activated, but it is not exposed as a live…
Low severity src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxesExtensions.cs — This new path changes real Azure provisioning, workload-identity RBAC, and deployed…
Low severity src/​Aspire.Hosting.Azure.Sandboxes/​README.md — The resource now exposes structured connection properties, but this ad hoc environment-variable…
What changed in this PR

Adds Azure Sandbox Groups as data-plane dependencies for applications hosted in other compute environments.

Changes:

  • Adds connection properties, lazy run-mode provisioning, and RBAC assignment.
  • Avoids ACR infrastructure for data-plane-only groups and expands tests/snapshots.
  • Adds documentation and an Azure Container Apps TypeScript playground.
File Description
Aspire.slnx Registers the new playground.
src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxGroupResource.cs Adds connection and reference capabilities.
src/​Aspire.Hosting.Azure.Sandboxes/​AzureSandboxesExtensions.cs Implements provisioning, RBAC, and ACR behavior.
src/​Aspire.Hosting.Azure.Sandboxes/​README.md Documents data-plane references.
tests/​Aspire.Hosting.Azure.Tests/​AzureSandboxesTests.cs Tests activation, properties, and RBAC.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.AddAzureSandboxResourcesGeneratesBicep#00.verified.bicep Captures new Bicep outputs.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.AddAzureSandboxResourcesGeneratesBicep#00.verified.json Captures manifest connection string.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.AddAzureSandboxResourcesGeneratesBicep#01.verified.bicep Captures new Bicep outputs.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.AddAzureSandboxResourcesGeneratesBicep#01.verified.json Captures manifest connection string.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.ExistingSandboxGroupCanBeReferencedWithoutComputeConfiguration.verified.bicep Covers existing-group references.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.ReferencedSandboxGroupActivatesRunModeProvisioningAndInjectsConnectionProperties.verified.bicep Covers lazy provisioning.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.SandboxGroupWithoutWorkloadIdentityEmitsImagePullIdentity.verified.bicep Updates identity scenario outputs.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.SandboxGroupWithSystemAssignedWorkloadIdentityAlsoEmitsImagePullIdentity.verified.bicep Updates system-identity outputs.
tests/​Aspire.Hosting.Azure.Tests/​Snapshots/​AzureSandboxesTests.WithNoManagedIdentityClearsGroupIdentityButPreservesComputeWorkloadIdentity.verified.bicep Updates no-managed-identity outputs.
playground/​AzureSandboxDataPlane/​aspire.config.json Selects the playground AppHost.
playground/​AzureSandboxDataPlane/​AzureSandboxDataPlane.AppHost/​AzureSandboxDataPlane.AppHost.csproj Defines AppHost dependencies.
playground/​AzureSandboxDataPlane/​AzureSandboxDataPlane.AppHost/​AppHost.cs Wires ACA, sandbox, and frontend.
playground/​AzureSandboxDataPlane/​frontend/​package.json Defines frontend dependencies and scripts.
playground/​AzureSandboxDataPlane/​frontend/​package-lock.json Locks npm dependencies.
playground/​AzureSandboxDataPlane/​frontend/​tsconfig.json Configures TypeScript checking.
playground/​AzureSandboxDataPlane/​frontend/​src/​server.ts Demonstrates sandbox lifecycle operations.
playground/​AzureSandboxDataPlane/​frontend/​public/​index.html Adds the playground UI.
Files not reviewed (1)
  • playground/AzureSandboxDataPlane/frontend/package-lock.json: Generated file

Comment on lines +9 to +10
.WithHttpEndpoint(env: "PORT")
.WithExternalHttpEndpoints()
Comment on lines +190 to 193
if (HasDataPlaneReferences && !RequiresAcrPullIdentity)
{
context.Model.Resources.Remove(DefaultContainerRegistry);
DefaultContainerRegistry = null;
return;
}
sandboxGroup.Resource.HasDataPlaneReferences = true;
EnsureRunModeDataPlaneResourceAdded(sandboxGroup);
RemoveUnusedDefaultContainerRegistry(sandboxGroup);
AddDefaultDataPlaneRoleAssignment(sandboxGroup);
<h1>Azure Sandbox data-plane playground</h1>
<p>Create an isolated Ubuntu sandbox, run a command through the Azure Container Apps Sandboxes data-plane SDK, and delete the sandbox.</p>
<button id="launch" type="button">Launch sandbox</button>
<pre id="output">Ready.</pre>
Comment on lines +187 to +190
sandboxGroup.Resource.HasDataPlaneReferences = true;
EnsureRunModeDataPlaneResourceAdded(sandboxGroup);
RemoveUnusedDefaultContainerRegistry(sandboxGroup);
AddDefaultDataPlaneRoleAssignment(sandboxGroup);
Comment on lines +94 to +98
In run mode, `AddAzureSandboxGroup` remains inactive until a resource references it. The reference provisions the group and injects:

* `ConnectionStrings__sandboxes`, containing `Endpoint`, `SubscriptionId`, `ResourceGroup`, and `SandboxGroupName`.
* `SANDBOXES_ENDPOINT` and `SANDBOXES_URI`, containing the regional Azure Dev Compute endpoint.
* `SANDBOXES_SUBSCRIPTIONID`, `SANDBOXES_RESOURCEGROUP`, and `SANDBOXES_SANDBOXGROUPNAME`.
@github-actions

github-actions Bot commented Sep 3, 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.

Copilot AI review requested due to automatic review settings September 6, 2026 02:19
@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Sep 6, 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.

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 encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Note

This error may be related to your runner configuration. You can now configure runners for Copilot code review separately from Copilot cloud agent by creating a copilot-code-review.yml file with your setup steps. Read the docs for details.

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.

app.use(express.json());
app.use(express.static(new URL("../public", import.meta.url).pathname));

app.post("/api/sandboxes", async (_request: Request, response: Response) => {
const port = Number(process.env.PORT ?? "3000");

app.use(express.json());
app.use(express.static(new URL("../public", import.meta.url).pathname));
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 88fcd28c-6729-4247-b113-1772ca88165c
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Tests selector

Selects the full PR test matrix + all PR-gated jobs (ALL) — a rule matching 'Aspire.slnx' selects ALL


Selection computed for commit d601ce8.

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.

@github-actions

github-actions Bot commented Oct 2, 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.

This branch has not been deployed

No deployments
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants