Skip to content

Breaking changes for .NET Aspire 9.2 #2892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions docs/compatibility/9.2/generated-bicep-updates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: "Breaking change - Role Assignments separated from Azure resource bicep"
description: "Learn about the breaking change in .NET Aspire 9.2 where role assignments are moved to separate bicep modules."
ms.date: 4/2/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs-aspire/issues/2911
---

# Role Assignments separated from Azure resource bicep

In .NET Aspire 9.2, role assignments for Azure resources are no longer included in the same bicep file as the resource. Instead, they're moved to separate bicep modules. This change affects how role assignments are customized during infrastructure configuration.

## Version introduced

.NET Aspire 9.2

## Previous behavior

Previously, when an Azure resource's bicep file was generated, default role assignments were included in the same bicep module as the resource. This allowed customization of role assignments in the `ConfigureInfrastructure` callback. For example:

```csharp
var storage = builder.AddAzureStorage("storage")
.ConfigureInfrastructure(infra =>
{
var roles = infra.GetProvisionableResources().OfType<RoleAssignment>().ToList();

foreach (var role in roles)
{
infra.Remove(role);
}

var storageAccount = infra.GetProvisionableResources().OfType<StorageAccount>().Single();
infra.Add(storageAccount.CreateRoleAssignment(StorageBuiltInRole.StorageBlobDataContributor, ...));
});
```

## New behavior

Role assignments are now moved to their own bicep modules. The `ConfigureInfrastructure` callback no longer contains any `RoleAssignment` instances. Instead, role assignments are configured using the `WithRoleAssignments` API. For example:

```csharp
var storage = builder.AddAzureStorage("storage");

builder.AddProject<Projects.AzureContainerApps_ApiService>("api")
.WithRoleAssignments(storage, StorageBuiltInRole.StorageBlobDataContributor);
```

## Type of breaking change

This is a [behavioral change](../categories.md#behavioral-change).

## Reason for change

This change was necessary to implement the `WithRoleAssignments` APIs, which provide a more structured and flexible way to configure role assignments per application.

## Recommended action

To customize role assignments in .NET Aspire 9.2, use the `WithRoleAssignments` API instead of relying on the `ConfigureInfrastructure` callback. Update your code as shown in the [preceding example](#new-behavior).

## Affected APIs

- <xref:Aspire.Hosting.AzureProvisioningResourceExtensions.ConfigureInfrastructure``1(Aspire.Hosting.ApplicationModel.IResourceBuilder{``0},System.Action{Aspire.Hosting.Azure.AzureResourceInfrastructure})>
25 changes: 25 additions & 0 deletions docs/compatibility/9.2/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
title: Breaking changes in .NET Aspire 9.2
titleSuffix: ""
description: Navigate to the breaking changes in .NET Aspire 9.2.
ms.date: 04/02/2025
---

# Breaking changes in .NET Aspire 9.2

If you're migrating an app to .NET Aspire 9.2, the breaking changes listed here might affect you.

[!INCLUDE [binary-source-behavioral](../includes/binary-source-behavioral.md)]

> [!NOTE]
> This article is a work in progress. It's not a complete list of breaking changes in .NET Aspire 9.2.

## Breaking changes

| Title | Type of change | Introduced version |
|--|--|--|
| [AzureContainerApps infrastructure creates managed identity per container app](managed-identity-per-app.md) | Behavioral change | 9.2 |
| [KeyVault default role assignment changing from KeyVaultAdministrator to KeyVaultSecretsUser](keyvault-role-assignment-changes.md) | Behavioral change | 9.2 |
| [Role Assignments separated from Azure resource bicep](generated-bicep-updates.md) | Behavioral change | 9.2 |
| [With authentication API creates keyvault resource in the app model](withauthentication-changes.md) | Behavioral change | 9.2 |
| [WithCommand obsolete and new overload with CommandOptions](withcommand-obsolete.md) | Source incompatible | 9.2 |
59 changes: 59 additions & 0 deletions docs/compatibility/9.2/keyvault-role-assignment-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: "Breaking change - KeyVault default role assignment changing from KeyVaultAdministrator to KeyVaultSecretsUser"
description: "Learn about the breaking change in .NET Aspire 9.2 where the default role for Azure KeyVault applications changes to KeyVaultSecretsUser."
ms.date: 03/27/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs-aspire/issues/2899
---

# KeyVault default role assignment changing from KeyVaultAdministrator to KeyVaultSecretsUser

In .NET Aspire 9.2, the default role assigned to applications referencing Azure KeyVault has changed from <xref:Azure.Provisioning.KeyVault.KeyVaultBuiltInRole.KeyVaultAdministrator> to <xref:Azure.Provisioning.KeyVault.KeyVaultBuiltInRole.KeyVaultSecretsUser>. This change enhances security by limiting default privileges to only reading secrets. Applications requiring higher privileges must explicitly configure them.

## Version introduced

.NET Aspire 9.2

## Previous behavior

Previously, applications referencing Azure KeyVault were automatically granted the `KeyVaultAdministrator` role, which allowed full management of KeyVault settings.

## New behavior

Applications referencing Azure KeyVault are now granted the `KeyVaultSecretsUser` role by default, which restricts access to reading secrets. If higher privileges are required, they can be configured using the `WithRoleAssignments` API.

Example:

```csharp
using Azure.Provisioning.KeyVault;

var kv = builder.AddAzureKeyVault("kv");

builder.AddProject<Projects.ApiService>("api")
.WithRoleAssignments(kv, KeyVaultBuiltInRole.KeyVaultContributor);
```

## Type of breaking change

This is a [behavioral change](../categories.md#behavioral-change).

## Reason for change

The `KeyVaultAdministrator` role provides excessive privileges for most applications, as they typically only need to read secrets. Assigning the `KeyVaultSecretsUser` role by default improves security by adhering to the principle of least privilege.

## Recommended action

If your application requires higher privileges than the `KeyVaultSecretsUser` role, explicitly configure the necessary roles using the `WithRoleAssignments` API. For example:

```csharp
using Azure.Provisioning.KeyVault;

var kv = builder.AddAzureKeyVault("kv");

builder.AddProject<Projects.ApiService>("api")
.WithRoleAssignments(kv, KeyVaultBuiltInRole.KeyVaultContributor);
```

## Affected APIs

- <xref:Aspire.Hosting.AzureKeyVaultResourceExtensions.AddAzureKeyVault*>
54 changes: 54 additions & 0 deletions docs/compatibility/9.2/managed-identity-per-app.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
title: "Breaking change - AzureContainerApps infrastructure creates managed identity per container app"
description: "Learn about the breaking change in .NET Aspire 9.2 where each ContainerApp now has its own managed identity."
ms.date: 4/2/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs-aspire/issues/2914
---

# Azure Container Apps managed identity changes

Starting with .NET Aspire 9.2, each Azure Container App created using [📦 Aspire.Hosting.Azure.AppContainers](https://www.nuget.org/packages/Aspire.Hosting.Azure.AppContainers) NuGet package now has its own Azure Managed Identity. This change enables more granular role assignments for Azure resources but might require updates to applications that rely on shared managed identities.

## Version introduced

.NET Aspire 9.2

## Previous behavior

All ContainerApps shared a single Azure Managed Identity. This allowed applications to interact with Azure resources using a common identity.

## New behavior

Each ContainerApp now has its own unique Azure Managed Identity. This enables applications to have distinct role assignments for different Azure resources.

## Type of breaking change

This is a [behavioral change](../categories.md#behavioral-change).

## Reason for change

This change was introduced to support scenarios where applications require different role assignments for different Azure resources. By assigning a unique managed identity to each ContainerApp, applications can now operate with more granular access control.

## Recommended action

The recommended action is to update your Azure resources to use the new managed identities. This may include:

### Azure SQL Server

Grant access to all Azure Managed Identities that need to interact with the database. Follow the guidance in [Configure and manage Azure AD authentication with Azure SQL](/azure/azure-sql/database/authentication-aad-configure).

### Azure PostgreSQL

Grant necessary privileges to all Azure Managed Identities that need to interact with the database. Use the PostgreSQL documentation on [granting privileges](https://www.postgresql.org/docs/current/ddl-priv.html) as a reference. For example:

```sql
GRANT INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO <managed_identity_user>;
```

## Affected APIs

- `Aspire.Hosting.AzureContainerAppExtensions.AddAzureContainerAppsInfrastructure`
- `Aspire.Hosting.AzureContainerAppProjectExtensions.PublishAsAzureContainerApp`
- `Aspire.Hosting.AzureContainerAppExecutableExtensions.PublishAsAzureContainerApp`
- `Aspire.Hosting.AzureContainerAppContainerExtensions.PublishAsAzureContainerApp`
47 changes: 47 additions & 0 deletions docs/compatibility/9.2/withauthentication-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: "Breaking change - WithAccessKeyAuthentication and WithPasswordAuthentication create a keyvault resource in the app model"
description: "Learn about the breaking change in .NET Aspire 9.2 where key vault resources are now created or referenced directly in the app model."
ms.date: 3/25/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs-aspire/issues/2889
---

# With authentication API creates keyvault resource in the app model

Starting in .NET Aspire 9.2, calling any of the following methods:

- <xref:Aspire.Hosting.AzureRedisExtensions.WithAccessKeyAuthentication*?displayProperty=nameWithType>
- <xref:Aspire.Hosting.AzureCosmosExtensions.WithAccessKeyAuthentication*?displayProperty=nameWithType>
- <xref:Aspire.Hosting.AzurePostgresExtensions.WithPasswordAuthentication*?displayProperty=nameWithType>

Will now create (or add references to) a key vault resource directly in the app model. This change allows better customization and management of connection strings and secrets.

## Version introduced

.NET Aspire 9.2

## Previous behavior

Previously, calling `WithAccessKeyAuthentication` on CosmosDB or AzureRedis, or `WithPasswordAuthentication` on AzurePostgres, automatically created and managed Bicep resources. These resources were invisible to the app model and could not be managed or customized in C#.

## New behavior

In .NET Aspire 9.2, calling `WithAccessKeyAuthentication` or `WithPasswordAuthentication` adds an empty `keyVaultName` parameter as a known parameter in the Bicep file. The app model now directly creates the key vault resource or allows you to pass a reference to an existing AzureKeyVault resource where secrets will be stored. Key vault secret names for connection strings are now formatted as `connectionstrings--{resourcename}` to avoid conflicts with other connection strings.

## Type of breaking change

This is a [behavioral change](../categories.md#behavioral-change).

## Reason for change

This change moves resource management to the app host, making it easier to customize and manage resources. It allows sharing a key vault across multiple resources or using an existing key vault to manage connection strings and secrets.

## Recommended action

There is currently no workaround for this change. Ensure that your app model is updated to handle the new behavior for key vault resources and connection string management.

## Affected APIs

- <xref:Aspire.Hosting.AzureRedisExtensions.WithAccessKeyAuthentication*?displayProperty=nameWithType>
- <xref:Aspire.Hosting.AzureCosmosExtensions.WithAccessKeyAuthentication*?displayProperty=nameWithType>
- <xref:Aspire.Hosting.AzurePostgresExtensions.WithPasswordAuthentication*?displayProperty=nameWithType>
96 changes: 96 additions & 0 deletions docs/compatibility/9.2/withcommand-obsolete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "Breaking change - WithCommand obsolete and new overload with CommandOptions"
description: "Learn about the breaking change in .NET Aspire 9.2 where the WithCommand method overload with optional parameters is marked obsolete."
ms.date: 3/25/2025
ai-usage: ai-assisted
ms.custom: https://github.com/dotnet/docs-aspire/issues/2888
---

# WithCommand obsolete and new overload with CommandOptions

The <xref:Aspire.Hosting.ResourceBuilderExtensions.WithCommand*> method overload that accepted multiple optional parameters is now marked obsolete. A new overload that accepts an instance of `CommandOptions` has been introduced. This change requires updates to existing code to use the new overload.

## Version introduced

.NET Aspire 9.2

## Previous behavior

The `WithCommand` method overload that accepted multiple optional parameters was available and not marked as obsolete.

```csharp
var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithCommand(
name: "command-name",
displayName: "Command display name",
executeCommand: async (ExecuteCommandContext context) =>
{
// Command execution logic here
await Task.CompletedTask;
return CommandResults.Success();
},
updateState: (UpdateCommandStateContext context) =>
{
// State update logic here
return ResourceCommandState.Enabled;
},
displayDescription: "Command Description",
parameter: new[] { "", "" },
confirmationMessage: "Are you sure?",
iconName: "Icons",
iconVariant: "Red",
isHighlighted: false);
```

## New behavior

The existing <xref:Aspire.Hosting.ResourceBuilderExtensions.WithCommand*> method overload is now marked obsolete. A new overload that accepts an instance of `CommandOptions` should be used instead.

```csharp
var builder = DistributedApplication.CreateBuilder(args);

builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
.WithCommand(
name: "command-name",
displayName: "Command display name",
executeCommand: async (ExecuteCommandContext context) =>
{
// Command execution logic here
await Task.CompletedTask;
return CommandResults.Success();
},
commandOptions: new CommandOptions
{
UpdateState = (UpdateCommandStateContext context) =>
{
// State update logic here
return ResourceCommandState.Enabled;
},
Description = "Command Description",
Parameter = new[] { "", "" },
ConfirmationMessage = "Are you sure?",
IconName = "Icons",
IconVariant = "Red",
IsHighlighted = false
});
```

The only required parameters are the `name`, `displayName`, and `executeCommand`. The rest of the parameters are now encapsulated within the `CommandOptions` object, which provides a cleaner and more maintainable API.

## Type of breaking change

This is a [source incompatible](../categories.md#source-compatibility) change.

## Reason for change

This change was made following an API review to improve clarity and maintainability by consolidating optional parameters into a single `CommandOptions` object.

## Recommended action

Update your code to use the new `WithCommand` overload that accepts an instance of `CommandOptions`. Replace calls to the obsolete overload with the new overload.

## Affected APIs

- <xref:Aspire.Hosting.ResourceBuilderExtensions.WithCommand*>
4 changes: 4 additions & 0 deletions docs/compatibility/api-removal.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ ms.date: 10/24/2024
- By documenting it under [Breaking changes in .NET](breaking-changes.md).

In most cases, an API that shipped in a long-term support (LTS) release is obsoleted in the subsequent LTS release before it's removed. In rare cases, based on business needs, exceptions are made to obsolete an API before the subsequent LTS release. All obsoletions are documented and communicated to customers.

## See also

- [.NET Aspire Support Policy](https://dotnet.microsoft.com/platform/support/policy/aspire)
1 change: 1 addition & 0 deletions docs/compatibility/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ You can also view individual issues that detail the breaking changes introduced
## See also

- [API removal in .NET](api-removal.md)
- [.NET Aspire Support Policy](https://dotnet.microsoft.com/platform/support/policy/aspire)
- [.NET runtime compatibility](/dotnet/core/versions/#net-runtime-compatibility)
4 changes: 4 additions & 0 deletions docs/compatibility/categories.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ Forward compatibility refers to the ability of an existing consumer of an API to
Maintaining forward compatibility virtually precludes any changes or additions from version to version, since those changes prevent a consumer that targets a later version from running under an earlier version. Developers expect that a consumer that relies on a newer API may not function correctly against the older API.

Maintaining forward compatibility is not a goal of .NET Aspire.

## See also

- [.NET Aspire Support Policy](https://dotnet.microsoft.com/platform/support/policy/aspire)
Loading