Skip to content

Improve discoverability of Azure deployment customization patterns #3712

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion docs/azure/azure-app-configuration-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ The preceding code:
- The <xref:Azure.Provisioning.AppConfiguration.AppConfigurationStore.SkuName?displayProperty=nameWithType> is assigned to `Free`.
- A tag is added to the App Configuration store with a key of `ExampleKey` and a value of `Example value`.

There are many more configuration options available to customize the Azure App Configuration resource. For more information, see <xref:Azure.Provisioning.AppConfiguration>. For more information, see [Azure.Provisioning customization](integrations-overview.md#azureprovisioning-customization).
There are many more configuration options available to customize the Azure App Configuration resource. For more information, see <xref:Azure.Provisioning.AppConfiguration>. For more information, see [Azure.Provisioning customization](integrations-overview.md#azureprovisioning-customization). For deployment-focused customization patterns, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

### Use existing Azure App Configuration resource

Expand Down
3 changes: 3 additions & 0 deletions docs/azure/integrations-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,9 @@ All .NET Aspire Azure hosting integrations expose various Azure resources, and t

Regardless of the Azure resource you're working with, to configure its underlying infrastructure, you chain a call to the <xref:Aspire.Hosting.AzureProvisioningResourceExtensions.ConfigureInfrastructure*> extension method. This method allows you to customize the infrastructure of the Azure resource by passing a `configure` delegate of type `Action<AzureResourceInfrastructure>`. The <xref:Aspire.Hosting.Azure.AzureResourceInfrastructure> type is a subclass of the <xref:Azure.Provisioning.Infrastructure?displayProperty=fullName>. This type exposes a massive API surface area for configuring the underlying infrastructure of the Azure resource.

> [!TIP]
> For comprehensive examples and deployment-focused patterns for customizing Azure infrastructure, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

Consider the following example:

:::code language="csharp" source="../snippets/azure/AppHost/Program.ConfigureInfrastructure.cs" id="infra":::
Expand Down
2 changes: 2 additions & 0 deletions docs/azureai/azureai-openai-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ The preceding code:
- The <xref:Azure.Provisioning.CognitiveServices.CognitiveServicesAccount.Sku?displayProperty=nameWithType> property is assigned to a new instance of <xref:Azure.Provisioning.CognitiveServices.CognitiveServicesSku> with an `E0` name and <xref:Azure.Provisioning.CognitiveServices.CognitiveServicesSkuTier.Enterprise?displayProperty=nameWithType> tier.
- A tag is added to the Cognitive Services resource with a key of `ExampleKey` and a value of `Example value`.

There are many more configuration options available to customize the Azure OpenAI resource. For more information, see <xref:Azure.Provisioning.CognitiveServices>. For more information, see [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization). For deployment-focused customization patterns, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

### Connect to an existing Azure OpenAI service

You might have an existing Azure OpenAI service that you want to connect to. You can chain a call to annotate that your <xref:Aspire.Hosting.ApplicationModel.AzureOpenAIResource> is an existing resource:
Expand Down
234 changes: 234 additions & 0 deletions docs/deployment/azure/customize-infrastructure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
---
title: Customize Azure deployment infrastructure
description: Learn how to customize Azure infrastructure resources during deployment using ConfigureInfrastructure and other customization patterns.
ms.topic: how-to
ms.date: 12/23/2024
---

# Customize Azure deployment infrastructure

.NET Aspire provides powerful capabilities to customize Azure infrastructure during deployment. While .NET Aspire offers sensible defaults for Azure resources, you often need to customize these resources to meet organizational requirements such as tagging policies, specific SKUs, networking configurations, or compliance standards.

This article demonstrates common patterns for customizing Azure infrastructure in .NET Aspire applications using the `ConfigureInfrastructure` API and other customization techniques.

## Prerequisites

- [.NET Aspire SDK](../../fundamentals/setup-tooling.md)
- An Azure subscription
- Basic understanding of [.NET Aspire app host](../../fundamentals/app-host-overview.md)

## Overview of infrastructure customization

All .NET Aspire Azure hosting integrations expose Azure resources that are subclasses of the <xref:Aspire.Hosting.Azure.AzureProvisioningResource> type. This enables a fluent API for customizing the infrastructure using the <xref:Aspire.Hosting.AzureProvisioningResourceExtensions.ConfigureInfrastructure*> extension method.

The `ConfigureInfrastructure` method allows you to:

- Modify resource properties like SKUs, tiers, and configurations
- Add tags for governance and cost management
- Configure networking and security settings
- Set up role assignments and permissions
- Customize generated Bicep templates

## Basic infrastructure customization

### Configure resource properties

Use `ConfigureInfrastructure` to modify basic properties of Azure resources:

:::code language="csharp" source="../../snippets/azure/AppHost/Program.ConfigureStorageInfra.cs" id="configure":::

The preceding code customizes an Azure Storage account by:

- Setting the access tier to `Cool`
- Upgrading the SKU to `PremiumZrs`
- Adding a custom tag

### Add tags for governance

Tags are essential for governance, cost management, and compliance. Here's how to add tags to various Azure resources:

:::code language="csharp" source="../../snippets/azure/AppHost/Program.ConfigureSqlServerInfra.cs" id="configure":::

### Configure SKUs and performance tiers

Customize performance characteristics by modifying SKUs:

:::code language="csharp" source="../../snippets/azure/AppHost/Program.ConfigureServiceBusInfra.cs" id="configure":::

## Advanced customization patterns

### Using external parameters

Flow configuration values from external parameters into your infrastructure:

```csharp
var environmentParam = builder.AddParameter("environment");
var costCenterParam = builder.AddParameter("cost-center");

var storage = builder.AddAzureStorage("storage")
.ConfigureInfrastructure(infra =>
{
var storageAccount = infra.GetProvisionableResources()
.OfType<StorageAccount>()
.Single();

// Use parameters in resource configuration
storageAccount.Tags.Add("Environment", environmentParam.AsProvisioningParameter(infra));
storageAccount.Tags.Add("CostCenter", costCenterParam.AsProvisioningParameter(infra));

// Conditional configuration based on environment
var env = environmentParam.AsProvisioningParameter(infra);
storageAccount.AccessTier = env == "Production"
? StorageAccountAccessTier.Hot
: StorageAccountAccessTier.Cool;
});
```

### Configure networking and security

Set up networking configurations and security settings:

```csharp
builder.AddAzureKeyVault("keyvault")
.ConfigureInfrastructure(infra =>
{
var keyVault = infra.GetProvisionableResources()
.OfType<KeyVaultService>()
.Single();

// Enable purge protection
keyVault.EnablePurgeProtection = true;

// Configure network access
keyVault.NetworkRuleSet = new KeyVaultNetworkRuleSet
{
DefaultAction = KeyVaultNetworkRuleAction.Deny,
IpRules =
{
new KeyVaultIPRule { Value = "203.0.113.0/24" }
}
};

keyVault.Tags.Add("SecurityLevel", "High");
});
```

### Multiple resource configuration

When working with resources that create multiple Azure components:

:::code language="csharp" source="../../snippets/azure/AppHost/Program.ConfigureEventHubsInfra.cs" id="configure":::

## Common customization scenarios

### Enterprise tagging strategy

Implement a consistent tagging strategy across all resources:

```csharp
public static class TaggingExtensions
{
public static IResourceBuilder<T> WithStandardTags<T>(
this IResourceBuilder<T> builder,
string owner,
string environment,
string costCenter)
where T : AzureProvisioningResource
{
return builder.ConfigureInfrastructure(infra =>
{
var resources = infra.GetProvisionableResources();

foreach (var resource in resources)
{
if (resource.Tags != null)
{
resource.Tags.Add("Owner", owner);
resource.Tags.Add("Environment", environment);
resource.Tags.Add("CostCenter", costCenter);
resource.Tags.Add("ManagedBy", "AspireApp");
resource.Tags.Add("CreatedDate", DateTime.UtcNow.ToString("yyyy-MM-dd"));
}
}
});
}
}

// Usage
builder.AddAzureStorage("storage")
.WithStandardTags("TeamAlpha", "Production", "Engineering");
```

### Cost optimization

Configure resources for cost optimization:

```csharp
builder.AddAzureAppConfiguration("config")
.ConfigureInfrastructure(infra =>
{
var appConfig = infra.GetProvisionableResources()
.OfType<AppConfigurationStore>()
.Single();

// Use Free tier for development
appConfig.SkuName = "Free";

// Disable features that incur costs
appConfig.EnablePurgeProtection = false;

appConfig.Tags.Add("CostOptimized", "true");
});
```

### Compliance and governance

Configure resources to meet compliance requirements:

```csharp
builder.AddAzureSqlServer("sql-server")
.ConfigureInfrastructure(infra =>
{
var sqlServer = infra.GetProvisionableResources()
.OfType<SqlServer>()
.Single();

// Enable Azure AD authentication
sqlServer.ActiveDirectoryAdministrator = new SqlServerExternalAdministrator
{
AdministratorType = "ActiveDirectory",
Login = "admin@contoso.com",
PrincipalType = "User"
};

// Configure audit settings
sqlServer.IsAuditEnabled = true;

// Add compliance tags
sqlServer.Tags.Add("ComplianceLevel", "SOC2");
sqlServer.Tags.Add("DataClassification", "Confidential");
});
```

## Working with custom Bicep templates

For advanced scenarios, you can also work with custom Bicep templates. For more information, see [Use custom Bicep templates](../../azure/integrations-overview.md#use-custom-bicep-templates).

## Best practices

1. **Consistent tagging**: Implement a standardized tagging strategy across all resources.

1. **Environment-specific configuration**: Use parameters to vary configuration based on deployment environment.

1. **Security by default**: Configure security settings like network restrictions and authentication in your infrastructure customizations.

1. **Cost awareness**: Consider cost implications when customizing SKUs and features.

1. **Documentation**: Document custom infrastructure patterns for your team.

## See also

- [Azure integrations overview](../../azure/integrations-overview.md)
- [Local Azure provisioning](../../azure/local-provisioning.md)
- [External parameters](../../fundamentals/external-parameters.md)
- [Deploy to Azure Container Apps](aca-deployment.md)
4 changes: 4 additions & 0 deletions docs/deployment/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ For more information on the schema of the manifest and how to run app host proje

.NET Aspire projects are designed to run in containerized environments. Azure Container Apps is a fully managed environment that enables you to run microservices and containerized applications on a serverless platform. The [Azure Container Apps](azure/aca-deployment.md) topic describes how to deploy Aspire apps to ACA manually, using bicep, or using the Azure Developer CLI (azd).

### Customize Azure infrastructure

When deploying to Azure, you can customize the infrastructure resources to meet organizational requirements such as tagging policies, specific SKUs, networking configurations, or compliance standards. .NET Aspire provides powerful APIs to customize Azure resources during deployment. For detailed examples and patterns, see [Customize Azure deployment infrastructure](azure/customize-infrastructure.md).

### Use Application Insights for .NET Aspire telemetry

.NET Aspire projects are designed to emit telemetry using OpenTelemetry which uses a provider model. .NET Aspire projects can direct their telemetry to Azure Monitor / Application Insights using the Azure Monitor telemetry distro. For more information, see [Use Application Insights for .NET Aspire telemetry](azure/application-insights.md) for step-by-step instructions.
Expand Down
2 changes: 1 addition & 1 deletion docs/messaging/azure-service-bus-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The preceding code:
- The <xref:Azure.Provisioning.ServiceBus.ServiceBusNamespace.Sku?displayProperty=nameWithType> created with a <xref:Azure.Provisioning.ServiceBus.ServiceBusSkuTier.Premium?displayProperty=nameWithType>
- A tag is added to the Service Bus namespace with a key of `ExampleKey` and a value of `Example value`.

There are many more configuration options available to customize the Azure Service Bus resource. For more information, see <xref:Azure.Provisioning.ServiceBus>. For more information, see [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization).
There are many more configuration options available to customize the Azure Service Bus resource. For more information, see <xref:Azure.Provisioning.ServiceBus>. For more information, see [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization). For deployment-focused customization patterns, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

### Connect to an existing Azure Service Bus namespace

Expand Down
2 changes: 2 additions & 0 deletions docs/real-time/azure-signalr-scenario.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ The preceding code:
- The <xref:Azure.Provisioning.SignalR.SignalRService.PublicNetworkAccess?displayProperty=nameWithType> property is set to `Enabled`.
- A tag is added to the SignalR service resource with a key of `ExampleKey` and a value of `Example value`.

There are many more configuration options available to customize the Azure SignalR resource. For more information, see <xref:Azure.Provisioning.SignalR>. For more information, see [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization). For deployment-focused customization patterns, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

### Connect to an existing Azure SignalR Service

You might have an existing Azure SignalR Service that you want to connect to. You can chain a call to annotate that your <xref:Aspire.Hosting.ApplicationModel.AzureSignalRResource> is an existing resource:
Expand Down
2 changes: 1 addition & 1 deletion docs/security/azure-security-key-vault-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The preceding code:
- The <xref:Azure.Provisioning.KeyVault.KeyVaultProperties.EnableRbacAuthorization?displayProperty=nameWithType> property is set to `true`.
- A tag is added to the resource with a key of `ExampleKey` and a value of `Example value`.

There are many more configuration options available to customize the Key Vault resource. For more information, see <xref:Azure.Provisioning.KeyVault> and [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization).
There are many more configuration options available to customize the Key Vault resource. For more information, see <xref:Azure.Provisioning.KeyVault> and [Azure.Provisioning customization](../azure/integrations-overview.md#azureprovisioning-customization). For deployment-focused customization patterns, see [Customize Azure deployment infrastructure](../deployment/azure/customize-infrastructure.md).

### Connect to an existing Azure Key Vault instance

Expand Down
33 changes: 33 additions & 0 deletions docs/snippets/azure/AppHost/Program.ConfigureSqlServerInfra.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Azure.Provisioning.Sql;

internal static partial class Program
{
public static void ConfigureSqlServerInfra(IDistributedApplicationBuilder builder)
{
// <configure>
var sql = builder.AddAzureSqlServer("sql-server")
.ConfigureInfrastructure(infra =>
{
var sqlServer = infra.GetProvisionableResources()
.OfType<SqlServer>()
.Single();

sqlServer.Tags.Add("Owner", "TeamAlpha");
sqlServer.Tags.Add("Environment", "Production");
sqlServer.Tags.Add("CostCenter", "Engineering");
});

// Configure database with additional tags
sql.AddDatabase("inventory-db")
.ConfigureInfrastructure(infra =>
{
var database = infra.GetProvisionableResources()
.OfType<SqlDatabase>()
.Single();

database.Tags.Add("Owner", "me");
database.Tags.Add("DataClassification", "Internal");
});
// </configure>
}
}
3 changes: 3 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,9 @@ items:
displayName: azure container apps,aca,azd
- name: Deploy using azd and CI/CD
href: deployment/azure/aca-deployment-github-actions.md
- name: Customize Azure deployment infrastructure
href: deployment/azure/customize-infrastructure.md
displayName: configureinfrastructure,tagging,bicep,customization,governance
- name: Use .NET Aspire with Application Insights
href: deployment/azure/application-insights.md
displayName: app insights
Expand Down