Repository navigation
Enable data-plane references for Azure Sandbox Groups - #19886
Mitch Denny (mitchdenny) wants to merge 1 commit into
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19886Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19886" |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
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
New issues introduced by this change (6)
| Severity | Finding |
|---|---|
playground/AzureSandboxDataPlane/AzureSandboxDataPlane.AppHost/AppHost.cs — This makes the playground publicly reachable, but its unauthenticated POST endpoint uses the… |
|
src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxGroupResource.cs — HasDataPlaneReferences is set by every WithReference, but RequiresAcrPullIdentity is only set… |
|
src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs — This unconditionally reinstates the default Data Owner role after ClearDefaultRoleAssignments()… |
|
playground/AzureSandboxDataPlane/frontend/public/index.html — This output changes asynchronously after the button is activated, but it is not exposed as a live… |
|
src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxesExtensions.cs — This new path changes real Azure provisioning, workload-identity RBAC, and deployed… |
|
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
| .WithHttpEndpoint(env: "PORT") | ||
| .WithExternalHttpEndpoints() |
| 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> |
| sandboxGroup.Resource.HasDataPlaneReferences = true; | ||
| EnsureRunModeDataPlaneResourceAdded(sandboxGroup); | ||
| RemoveUnusedDefaultContainerRegistry(sandboxGroup); | ||
| AddDefaultDataPlaneRoleAssignment(sandboxGroup); |
| 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`. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
991141e to
17e0cd9
Compare
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The externally exposed privileged endpoint lacks authentication, and deployed identity/RBAC behavior lacks end-to-end coverage.
Get a fresh assessment by requesting another Copilot review.
Review tier: Balanced
Findings: 3
Open findings (8)
Protect the privileged sandbox endpoint · NewHasDataPlaneReferencesis set by everyWithReference, butRequiresAcrPullIdentityis only set… This makes the playground publicly reachable, but its unauthenticated POST endpoint uses the… Convert the file URL before serving static content · New This unconditionally reinstates the default Data Owner role afterClearDefaultRoleAssignments()… The resource now exposes structured connection properties, but this ad hoc environment-variable… This new path changes real Azure provisioning, workload-identity RBAC, and deployed… This output changes asynchronously after the button is activated, but it is not exposed as a live…
Files not reviewed (1)
- playground/AzureSandboxDataPlane/frontend/package-lock.json: Generated file
| 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
17e0cd9 to
d601ce8
Compare
Tests selectorSelects the full PR test matrix + all PR-gated jobs (ALL) — a rule matching 'Aspire.slnx' selects ALL Selection computed for commit |
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The public unauthenticated mutation endpoint, RBAC opt-out regression, and missing live deployment coverage must be addressed.
Review effort: Balanced
Findings: 3
Open (8)
Protect the privileged sandbox endpointHasDataPlaneReferencesis set by everyWithReference, butRequiresAcrPullIdentityis only set… This makes the playground publicly reachable, but its unauthenticated POST endpoint uses the… Convert the file URL before serving static content This unconditionally reinstates the default Data Owner role afterClearDefaultRoleAssignments()… The resource now exposes structured connection properties, but this ad hoc environment-variable… This new path changes real Azure provisioning, workload-identity RBAC, and deployed… This output changes asynchronously after the button is activated, but it is not exposed as a live…
Files not reviewed (1)
- playground/AzureSandboxDataPlane/frontend/package-lock.json: Generated file
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |






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:
A group can serve both purposes: select it for compute with
WithComputeEnvironment(sandboxGroup)and optionally customize the workload withPublishAsAzureSandbox(). 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
AzureSandboxDataPlaneplayground 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:
TypeScript application:
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
AzureSandboxesTestspass after rebasing onto the updated Sandbox implementation in Improve Azure Sandbox defaults #19810.tsc --noEmit.Fixes # (issue)
Checklist
<remarks />and<code />elements on your triple slash comments?