diff --git a/Directory.Packages.props b/Directory.Packages.props index 51294fb633a..292a7a25773 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -179,7 +179,7 @@ - + diff --git a/src/Aspire.Hosting.Azure.CosmosDB/Aspire.Hosting.Azure.CosmosDB.csproj b/src/Aspire.Hosting.Azure.CosmosDB/Aspire.Hosting.Azure.CosmosDB.csproj index 298f0428ee8..79abc63d90e 100644 --- a/src/Aspire.Hosting.Azure.CosmosDB/Aspire.Hosting.Azure.CosmosDB.csproj +++ b/src/Aspire.Hosting.Azure.CosmosDB/Aspire.Hosting.Azure.CosmosDB.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs index 2a7ef992c47..176169dc0fd 100644 --- a/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs +++ b/src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBExtensions.cs @@ -10,7 +10,6 @@ using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Aspire.Hosting.Azure.CosmosDB; -using Azure.Identity; using Azure.Provisioning; using Azure.Provisioning.CosmosDB; using Azure.Provisioning.Expressions; @@ -213,7 +212,7 @@ static CosmosClient CreateCosmosClient(string connectionString) if (Uri.TryCreate(connectionString, UriKind.Absolute, out var uri)) { - return new CosmosClient(uri.OriginalString, new DefaultAzureCredential(), clientOptions); + return new CosmosClient(uri.OriginalString, AzureCredentialHelper.CreateDefaultAzureCredential(), clientOptions); } else { diff --git a/src/Aspire.Hosting.Azure.Kusto/Aspire.Hosting.Azure.Kusto.csproj b/src/Aspire.Hosting.Azure.Kusto/Aspire.Hosting.Azure.Kusto.csproj index bca8049a36c..20043c9186f 100644 --- a/src/Aspire.Hosting.Azure.Kusto/Aspire.Hosting.Azure.Kusto.csproj +++ b/src/Aspire.Hosting.Azure.Kusto/Aspire.Hosting.Azure.Kusto.csproj @@ -22,6 +22,7 @@ + diff --git a/src/Aspire.Hosting.Azure.Kusto/AzureKustoBuilderExtensions.cs b/src/Aspire.Hosting.Azure.Kusto/AzureKustoBuilderExtensions.cs index e05aebd3beb..c498aa161d0 100644 --- a/src/Aspire.Hosting.Azure.Kusto/AzureKustoBuilderExtensions.cs +++ b/src/Aspire.Hosting.Azure.Kusto/AzureKustoBuilderExtensions.cs @@ -6,7 +6,6 @@ using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; -using Azure.Identity; using Azure.Provisioning; using Azure.Provisioning.Kusto; using Kusto.Data; @@ -305,7 +304,7 @@ private static KustoConnectionStringBuilder GetConnectionStringBuilder(AzureKust { // When running against Azure, we use the DefaultAzureCredential to authenticate // with the Kusto server. - builder = builder.WithAadAzureTokenCredentialsAuthentication(new DefaultAzureCredential()); + builder = builder.WithAadAzureTokenCredentialsAuthentication(AzureCredentialHelper.CreateDefaultAzureCredential()); } return builder; diff --git a/src/Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.Storage.csproj b/src/Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.Storage.csproj index 22676cd859d..a616f417fe2 100644 --- a/src/Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.Storage.csproj +++ b/src/Aspire.Hosting.Azure.Storage/Aspire.Hosting.Azure.Storage.csproj @@ -11,6 +11,7 @@ + diff --git a/src/Aspire.Hosting.Azure.Storage/AzureStorageExtensions.cs b/src/Aspire.Hosting.Azure.Storage/AzureStorageExtensions.cs index d5903e7be76..441e0f77229 100644 --- a/src/Aspire.Hosting.Azure.Storage/AzureStorageExtensions.cs +++ b/src/Aspire.Hosting.Azure.Storage/AzureStorageExtensions.cs @@ -6,7 +6,6 @@ using Aspire.Hosting.ApplicationModel; using Aspire.Hosting.Azure; using Aspire.Hosting.Azure.Storage; -using Azure.Identity; using Azure.Provisioning; using Azure.Provisioning.Storage; using Azure.Storage.Blobs; @@ -644,7 +643,7 @@ private static BlobServiceClient CreateBlobServiceClient(string connectionString { if (Uri.TryCreate(connectionString, UriKind.Absolute, out var uri)) { - return new BlobServiceClient(uri, new DefaultAzureCredential()); + return new BlobServiceClient(uri, AzureCredentialHelper.CreateDefaultAzureCredential()); } else { @@ -656,7 +655,7 @@ private static QueueServiceClient CreateQueueServiceClient(string connectionStri { if (Uri.TryCreate(connectionString, UriKind.Absolute, out var uri)) { - return new QueueServiceClient(uri, new DefaultAzureCredential()); + return new QueueServiceClient(uri, AzureCredentialHelper.CreateDefaultAzureCredential()); } else { diff --git a/src/Components/Aspire.Azure.AI.Inference/Aspire.Azure.AI.Inference.csproj b/src/Components/Aspire.Azure.AI.Inference/Aspire.Azure.AI.Inference.csproj index 7926621c583..20c6d7d0fa5 100644 --- a/src/Components/Aspire.Azure.AI.Inference/Aspire.Azure.AI.Inference.csproj +++ b/src/Components/Aspire.Azure.AI.Inference/Aspire.Azure.AI.Inference.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Components/Aspire.Azure.AI.Inference/AspireAzureAIInferenceExtensions.cs b/src/Components/Aspire.Azure.AI.Inference/AspireAzureAIInferenceExtensions.cs index 6c3fda8c2d3..9324efc1e6f 100644 --- a/src/Components/Aspire.Azure.AI.Inference/AspireAzureAIInferenceExtensions.cs +++ b/src/Components/Aspire.Azure.AI.Inference/AspireAzureAIInferenceExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Azure.AI.Inference; using Aspire.Azure.Common; using Azure; @@ -8,7 +9,6 @@ using Azure.Core; using Azure.Core.Extensions; using Azure.Core.Pipeline; -using Azure.Identity; using Microsoft.Extensions.AI; using Microsoft.Extensions.Azure; using Microsoft.Extensions.Configuration; @@ -159,7 +159,7 @@ protected override IAzureClientBuilder + diff --git a/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs b/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs index 1168f8aaa25..76e07b2f791 100644 --- a/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs +++ b/src/Components/Aspire.Azure.AI.OpenAI/AspireAzureOpenAIExtensions.cs @@ -2,12 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ClientModel; +using Aspire; using Aspire.Azure.AI.OpenAI; using Aspire.Azure.Common; using Azure.AI.OpenAI; using Azure.Core; using Azure.Core.Extensions; -using Azure.Identity; using Microsoft.Extensions.Azure; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -111,7 +111,7 @@ protected override IAzureClientBuilder + diff --git a/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs b/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs index 85012ac89ad..7914850254f 100644 --- a/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs +++ b/src/Components/Aspire.Azure.Messaging.EventHubs/EventHubsComponent.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Azure.Common; using Aspire.Azure.Messaging.EventHubs; using Azure.Core; -using Azure.Identity; using Azure.Messaging.EventHubs; using Azure.Messaging.EventHubs.Producer; using HealthChecks.Azure.Messaging.EventHubs; @@ -45,7 +45,7 @@ protected override IHealthCheck CreateHealthCheck(TClient client, TSettings sett // If no connection is provided use TokenCredential if (string.IsNullOrEmpty(settings.ConnectionString)) { - _healthCheckClient = new EventHubProducerClient(settings.FullyQualifiedNamespace, settings.EventHubName, settings.Credential ?? new DefaultAzureCredential(), producerClientOptions); + _healthCheckClient = new EventHubProducerClient(settings.FullyQualifiedNamespace, settings.EventHubName, settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential(), producerClientOptions); } // If no specific EventHubName is provided, it has to be in the connection string else if (string.IsNullOrEmpty(settings.EventHubName)) diff --git a/src/Components/Aspire.Azure.Messaging.EventHubs/README.md b/src/Components/Aspire.Azure.Messaging.EventHubs/README.md index 93163cf97cd..965fce911cc 100644 --- a/src/Components/Aspire.Azure.Messaging.EventHubs/README.md +++ b/src/Components/Aspire.Azure.Messaging.EventHubs/README.md @@ -74,7 +74,7 @@ And then the connection information will be retrieved from the `ConnectionString #### Fully Qualified Namespace -The recommended approach is to use a fully qualified namespace, which works with the `AzureMessagingEventHubsSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use a fully qualified namespace, which works with the `AzureMessagingEventHubsSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Messaging.ServiceBus/README.md b/src/Components/Aspire.Azure.Messaging.ServiceBus/README.md index 0877f1d5cc7..3015206b1e2 100644 --- a/src/Components/Aspire.Azure.Messaging.ServiceBus/README.md +++ b/src/Components/Aspire.Azure.Messaging.ServiceBus/README.md @@ -54,7 +54,7 @@ And then the connection information will be retrieved from the `ConnectionString #### Fully Qualified Namespace -The recommended approach is to use a fully qualified namespace, which works with the `AzureMessagingServiceBusSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use a fully qualified namespace, which works with the `AzureMessagingServiceBusSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Messaging.WebPubSub/README.md b/src/Components/Aspire.Azure.Messaging.WebPubSub/README.md index 9e2ebab0779..784da04f37e 100644 --- a/src/Components/Aspire.Azure.Messaging.WebPubSub/README.md +++ b/src/Components/Aspire.Azure.Messaging.WebPubSub/README.md @@ -54,7 +54,7 @@ And then the connection information will be retrieved from the `ConnectionString #### Use the service endpoint -The recommended approach is to use the service endpoint, which works with the `AzureMessagingWebPubSubSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use the service endpoint, which works with the `AzureMessagingWebPubSubSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL.csproj b/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL.csproj index 0c8a4f4d3bd..5ad55ab70f9 100644 --- a/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL.csproj +++ b/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/README.md b/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/README.md index 6d7a1b3d0c5..dbda3a4b40f 100644 --- a/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/README.md +++ b/src/Components/Aspire.Azure.Npgsql.EntityFrameworkCore.PostgreSQL/README.md @@ -108,7 +108,7 @@ or builder.EnrichAzureNpgsqlDbContext(settings => settings.DisableHealthChecks = true); ``` -Use the `AzureNpgsqlEntityFrameworkCorePostgreSQLSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +Use the `AzureNpgsqlEntityFrameworkCorePostgreSQLSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). If the connection string contains a username and a password then the credential will be ignored. diff --git a/src/Components/Aspire.Azure.Npgsql/Aspire.Azure.Npgsql.csproj b/src/Components/Aspire.Azure.Npgsql/Aspire.Azure.Npgsql.csproj index 28a8039f233..f8da2752715 100644 --- a/src/Components/Aspire.Azure.Npgsql/Aspire.Azure.Npgsql.csproj +++ b/src/Components/Aspire.Azure.Npgsql/Aspire.Azure.Npgsql.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Components/Aspire.Azure.Npgsql/README.md b/src/Components/Aspire.Azure.Npgsql/README.md index e2fdbdcc73d..a8c4d7dd899 100644 --- a/src/Components/Aspire.Azure.Npgsql/README.md +++ b/src/Components/Aspire.Azure.Npgsql/README.md @@ -90,7 +90,7 @@ Also you can pass the `Action configureSettings` delegate t builder.AddAzureNpgsqlDataSource("postgresdb", settings => settings.DisableHealthChecks = true); ``` -Use the `AzureNpgsqlSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +Use the `AzureNpgsqlSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). If the connection string contains a username and a password then the credential will be ignored. diff --git a/src/Components/Aspire.Azure.Search.Documents/Aspire.Azure.Search.Documents.csproj b/src/Components/Aspire.Azure.Search.Documents/Aspire.Azure.Search.Documents.csproj index f73b35a255b..529b4b8d2b0 100644 --- a/src/Components/Aspire.Azure.Search.Documents/Aspire.Azure.Search.Documents.csproj +++ b/src/Components/Aspire.Azure.Search.Documents/Aspire.Azure.Search.Documents.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs b/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs index 84c61c683cc..294c288ecb2 100644 --- a/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs +++ b/src/Components/Aspire.Azure.Search.Documents/AspireAzureSearchExtensions.cs @@ -1,12 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Azure.Common; using Aspire.Azure.Search.Documents; using Azure; using Azure.Core; using Azure.Core.Extensions; -using Azure.Identity; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using Microsoft.Extensions.Azure; @@ -87,7 +87,7 @@ protected override IAzureClientBuilder A } else { - return new SearchIndexClient(settings.Endpoint, settings.Credential ?? new DefaultAzureCredential(), options); + return new SearchIndexClient(settings.Endpoint, settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential(), options); } }); } diff --git a/src/Components/Aspire.Azure.Search.Documents/README.md b/src/Components/Aspire.Azure.Search.Documents/README.md index 3380819e83f..9784aa920d5 100644 --- a/src/Components/Aspire.Azure.Search.Documents/README.md +++ b/src/Components/Aspire.Azure.Search.Documents/README.md @@ -72,7 +72,7 @@ And then the connection string will be retrieved from the `ConnectionStrings` co #### Account Endpoint -The recommended approach is to use an Endpoint, which works with the `AzureSearchSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use an Endpoint, which works with the `AzureSearchSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj b/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj index adacd3c83a8..49b48cdc274 100644 --- a/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj +++ b/src/Components/Aspire.Azure.Security.KeyVault/Aspire.Azure.Security.KeyVault.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs index 98c7b51d9f7..d92e8823c5c 100644 --- a/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs +++ b/src/Components/Aspire.Azure.Security.KeyVault/AspireKeyVaultExtensions.cs @@ -1,11 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Azure.Common; using Aspire.Azure.Security.KeyVault; using Azure.Core.Extensions; using Azure.Extensions.AspNetCore.Configuration.Secrets; -using Azure.Identity; using Azure.Security.KeyVault.Certificates; using Azure.Security.KeyVault.Keys; using Azure.Security.KeyVault.Secrets; @@ -204,6 +204,6 @@ private static SecretClient GetSecretClient( throw new InvalidOperationException($"VaultUri is missing. It should be provided in 'ConnectionStrings:{connectionName}' or under the 'VaultUri' key in the '{DefaultConfigSectionName}' configuration section."); } - return new SecretClient(settings.VaultUri, settings.Credential ?? new DefaultAzureCredential(), clientOptions); + return new SecretClient(settings.VaultUri, settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential(), clientOptions); } } diff --git a/src/Components/Aspire.Azure.Security.KeyVault/README.md b/src/Components/Aspire.Azure.Security.KeyVault/README.md index 090dd5ba974..b0f0a0fb4ed 100644 --- a/src/Components/Aspire.Azure.Security.KeyVault/README.md +++ b/src/Components/Aspire.Azure.Security.KeyVault/README.md @@ -104,7 +104,7 @@ When using a connection string from the `ConnectionStrings` configuration sectio builder.AddAzureKeyVaultClient("secretConnectionName"); ``` -And then the vault URI will be retrieved from the `ConnectionStrings` configuration section. The vault URI which works with the `AzureSecurityKeyVaultSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +And then the vault URI will be retrieved from the `ConnectionStrings` configuration section. The vault URI which works with the `AzureSecurityKeyVaultSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Storage.Blobs/README.md b/src/Components/Aspire.Azure.Storage.Blobs/README.md index 816d394712a..ecfb252c086 100644 --- a/src/Components/Aspire.Azure.Storage.Blobs/README.md +++ b/src/Components/Aspire.Azure.Storage.Blobs/README.md @@ -54,7 +54,7 @@ And then the connection information will be retrieved from the `ConnectionString #### Service URI -The recommended approach is to use a ServiceUri, which works with the `AzureStorageBlobsSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use a ServiceUri, which works with the `AzureStorageBlobsSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Storage.Files.DataLake/README.md b/src/Components/Aspire.Azure.Storage.Files.DataLake/README.md index 744762bc432..aa1654970ad 100644 --- a/src/Components/Aspire.Azure.Storage.Files.DataLake/README.md +++ b/src/Components/Aspire.Azure.Storage.Files.DataLake/README.md @@ -57,7 +57,7 @@ And then the connection information will be retrieved from the `ConnectionString #### Service URI -The recommended approach is to use a ServiceUri, which works with the `AzureDataLakeSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use a ServiceUri, which works with the `AzureDataLakeSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Azure.Storage.Queues/README.md b/src/Components/Aspire.Azure.Storage.Queues/README.md index 4bdbd7eb9d3..a646abad5e7 100644 --- a/src/Components/Aspire.Azure.Storage.Queues/README.md +++ b/src/Components/Aspire.Azure.Storage.Queues/README.md @@ -54,7 +54,7 @@ And then the connection string will be retrieved from the `ConnectionStrings` co #### Service URI -The recommended approach is to use a ServiceUri, which works with the `AzureStorageQueuesSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use a ServiceUri, which works with the `AzureStorageQueuesSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Microsoft.Azure.Cosmos/Aspire.Microsoft.Azure.Cosmos.csproj b/src/Components/Aspire.Microsoft.Azure.Cosmos/Aspire.Microsoft.Azure.Cosmos.csproj index cc44f63fc4f..808c03d8955 100644 --- a/src/Components/Aspire.Microsoft.Azure.Cosmos/Aspire.Microsoft.Azure.Cosmos.csproj +++ b/src/Components/Aspire.Microsoft.Azure.Cosmos/Aspire.Microsoft.Azure.Cosmos.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs b/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs index 4b9644317b1..455992fdae4 100644 --- a/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs +++ b/src/Components/Aspire.Microsoft.Azure.Cosmos/AspireMicrosoftAzureCosmosExtensions.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Hosting.Azure.CosmosDB; using Aspire.Microsoft.Azure.Cosmos; -using Azure.Identity; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -272,7 +272,7 @@ internal static CosmosClient GetCosmosClient(string connectionName, MicrosoftAzu } else if (settings.AccountEndpoint is not null) { - var credential = settings.Credential ?? new DefaultAzureCredential(); + var credential = settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential(); return new CosmosClient(settings.AccountEndpoint.OriginalString, credential, clientOptions); } else diff --git a/src/Components/Aspire.Microsoft.Azure.Cosmos/README.md b/src/Components/Aspire.Microsoft.Azure.Cosmos/README.md index 8baf9081d85..0f6f5a72953 100644 --- a/src/Components/Aspire.Microsoft.Azure.Cosmos/README.md +++ b/src/Components/Aspire.Microsoft.Azure.Cosmos/README.md @@ -54,7 +54,7 @@ And then the connection string will be retrieved from the `ConnectionStrings` co #### Account Endpoint -The recommended approach is to use an AccountEndpoint, which works with the `MicrosoftAzureCosmosSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +The recommended approach is to use an AccountEndpoint, which works with the `MicrosoftAzureCosmosSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/Aspire.Microsoft.Azure.StackExchangeRedis.csproj b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/Aspire.Microsoft.Azure.StackExchangeRedis.csproj index b80e2801465..aebee0345e9 100644 --- a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/Aspire.Microsoft.Azure.StackExchangeRedis.csproj +++ b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/Aspire.Microsoft.Azure.StackExchangeRedis.csproj @@ -9,6 +9,10 @@ true + + + + diff --git a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/AspireMicrosoftAzureStackExchangeRedisExtensions.cs b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/AspireMicrosoftAzureStackExchangeRedisExtensions.cs index 244dc9b8b4e..e19b7e13730 100644 --- a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/AspireMicrosoftAzureStackExchangeRedisExtensions.cs +++ b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/AspireMicrosoftAzureStackExchangeRedisExtensions.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.StackExchange.Redis; using Azure.Core; -using Azure.Identity; using Microsoft.Extensions.DependencyInjection; using StackExchange.Redis; using StackExchange.Redis.Configuration; @@ -19,7 +19,7 @@ public static class AspireMicrosoftAzureStackExchangeRedisExtensions /// Configures the Redis client to use Azure AD authentication for connecting to Azure Cache for Redis. /// /// The to configure. - /// The to use for Azure AD authentication. If , will be used. + /// The to use for Azure AD authentication. If , a default credential will be used. /// The for method chaining. /// /// This extension method configures the Redis client to authenticate with Azure Cache for Redis using Azure AD (Entra ID) instead of access keys. @@ -40,7 +40,7 @@ public static AspireRedisClientBuilder WithAzureAuthentication(this AspireRedisC if (configurationOptions.EndPoints.Any(ep => azureOptionsProvider.IsMatch(ep) || azureManagedOptionsProvider.IsMatch(ep))) { // only set up Azure AD authentication if the endpoint indicates it's an Azure Cache for Redis instance - credential ??= new DefaultAzureCredential(); + credential ??= AzureCredentialHelper.CreateDefaultAzureCredential(); // Configure Microsoft.Azure.StackExchangeRedis for Azure AD authentication // Note: Using GetAwaiter().GetResult() is acceptable here because this is configuration-time setup diff --git a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/README.md b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/README.md index 01bae90347a..c6d4f28def9 100644 --- a/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/README.md +++ b/src/Components/Aspire.Microsoft.Azure.StackExchangeRedis/README.md @@ -73,7 +73,7 @@ builder.AddRedisClientBuilder("cache") ### Configure Azure AD authentication -Use the `WithAzureAuthentication` method to establish a connection using Azure AD authentication. If no credential is provided, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +Use the `WithAzureAuthentication` method to establish a connection using Azure AD authentication. If no credential is provided, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```csharp builder.AddRedisClientBuilder("cache") diff --git a/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/Aspire.Microsoft.EntityFrameworkCore.Cosmos.csproj b/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/Aspire.Microsoft.EntityFrameworkCore.Cosmos.csproj index c54074dff29..98b87265847 100644 --- a/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/Aspire.Microsoft.EntityFrameworkCore.Cosmos.csproj +++ b/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/Aspire.Microsoft.EntityFrameworkCore.Cosmos.csproj @@ -14,6 +14,7 @@ + diff --git a/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/AspireAzureEFCoreCosmosExtensions.cs b/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/AspireAzureEFCoreCosmosExtensions.cs index be5e35c1b0a..b167e303e64 100644 --- a/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/AspireAzureEFCoreCosmosExtensions.cs +++ b/src/Components/Aspire.Microsoft.EntityFrameworkCore.Cosmos/AspireAzureEFCoreCosmosExtensions.cs @@ -5,7 +5,6 @@ using Aspire; using Aspire.Hosting.Azure.CosmosDB; using Aspire.Microsoft.EntityFrameworkCore.Cosmos; -using Azure.Identity; using Microsoft.Azure.Cosmos; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Cosmos.Infrastructure.Internal; @@ -135,7 +134,7 @@ void ConfigureDbContext(DbContextOptionsBuilder dbContextOptionsBuilder) } else if (settings.AccountEndpoint is not null) { - var credential = settings.Credential ?? new DefaultAzureCredential(); + var credential = settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential(); dbContextOptionsBuilder.UseCosmos(settings.AccountEndpoint.OriginalString, credential, settings.DatabaseName, UseCosmosBody); } else diff --git a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj index 621a2dc43e9..4640f7ff7a2 100644 --- a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj +++ b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/AspireAppConfigurationExtensions.cs b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/AspireAppConfigurationExtensions.cs index e255197d430..1f78adf8082 100644 --- a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/AspireAppConfigurationExtensions.cs +++ b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/AspireAppConfigurationExtensions.cs @@ -1,11 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Aspire; using Aspire.Azure.Common; using Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration; using Azure.Core.Pipeline; using Azure.Core; -using Azure.Identity; using Microsoft.Extensions.Configuration.AzureAppConfiguration; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -75,7 +75,7 @@ public static void AddAzureAppConfiguration( { if (settings.ConnectionString is null) { - options.Connect(settings.Endpoint, settings.Credential ?? new DefaultAzureCredential()); + options.Connect(settings.Endpoint, settings.Credential ?? AzureCredentialHelper.CreateDefaultAzureCredential()); } else { diff --git a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/README.md b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/README.md index b64fc3e47fe..7ec190aa7bf 100644 --- a/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/README.md +++ b/src/Components/Aspire.Microsoft.Extensions.Configuration.AzureAppConfiguration/README.md @@ -91,7 +91,7 @@ When using a connection string from the `ConnectionStrings` configuration sectio builder.AddAzureAppConfiguration("appConfigConnectionName"); ``` -And then the App Configuration endpoint will be retrieved from the `ConnectionStrings` configuration section. The App Configuration store URI works with the `AzureAppConfigurationSettings.Credential` property to establish a connection. If no credential is configured, the [DefaultAzureCredential](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential) is used. +And then the App Configuration endpoint will be retrieved from the `ConnectionStrings` configuration section. The App Configuration store URI works with the `AzureAppConfigurationSettings.Credential` property to establish a connection. If no credential is configured, a [default TokenCredential is created based on the current environment](https://aka.ms/aspire/default-azure-credential). ```json { diff --git a/src/Components/Common/ManagedIdentityTokenCredentialHelpers.cs b/src/Components/Common/ManagedIdentityTokenCredentialHelpers.cs index ae1474bb590..5cd8b34bf1f 100644 --- a/src/Components/Common/ManagedIdentityTokenCredentialHelpers.cs +++ b/src/Components/Common/ManagedIdentityTokenCredentialHelpers.cs @@ -3,7 +3,6 @@ using System.Text.Json; using Azure.Core; -using Azure.Identity; using Npgsql; namespace Aspire; @@ -18,7 +17,7 @@ internal static class ManagedIdentityTokenCredentialHelpers public static bool ConfigureEntraIdAuthentication(this NpgsqlDataSourceBuilder dataSourceBuilder, TokenCredential? credential) { - credential ??= new DefaultAzureCredential(); + credential ??= AzureCredentialHelper.CreateDefaultAzureCredential(); var configuredAuth = false; // The connection string requires the username to be provided. Since it will depend on the Managed Identity that is used diff --git a/src/Shared/AzureCredentialHelper.cs b/src/Shared/AzureCredentialHelper.cs new file mode 100644 index 00000000000..c8c5f81bb8f --- /dev/null +++ b/src/Shared/AzureCredentialHelper.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Azure.Core; +using Azure.Identity; + +namespace Aspire; + +internal static class AzureCredentialHelper +{ + /// + /// Creates a for code that can run in local development or deployed to Azure. + /// + internal static TokenCredential CreateDefaultAzureCredential() + { + if (Environment.GetEnvironmentVariable(DefaultAzureCredential.DefaultEnvironmentVariableName) is not null) + { + return new DefaultAzureCredential(DefaultAzureCredential.DefaultEnvironmentVariableName); + } + + if (Environment.GetEnvironmentVariable("AZURE_CLIENT_ID") is not null) + { + // When we don't see DefaultEnvironmentVariableName, but we do see AZURE_CLIENT_ID, + // we just use ManagedIdentityCredential because that's the only credential type that + // Aspire Hosting enables by default. + // If this doesn't work for applications, they can override the TokenCredential in their settings. + return new ManagedIdentityCredential(new ManagedIdentityCredentialOptions()); + } + + // when we can't detect a known Azure environment, fall back to the development credential + return CreateDevelopmentAzureCredential(); + } + + /// + /// Creates a optimized for local development by excluding + /// credential types not applicable on developer machines. + /// + private static TokenCredential CreateDevelopmentAzureCredential() + { + return new DefaultAzureCredential(new DefaultAzureCredentialOptions + { + ExcludeEnvironmentCredential = true, + ExcludeWorkloadIdentityCredential = true, + ExcludeManagedIdentityCredential = true + }); + } +} diff --git a/tests/Aspire.Azure.Search.Documents.Tests/ConformanceTests.cs b/tests/Aspire.Azure.Search.Documents.Tests/ConformanceTests.cs index 571055b01ba..cd7a2f47c3e 100644 --- a/tests/Aspire.Azure.Search.Documents.Tests/ConformanceTests.cs +++ b/tests/Aspire.Azure.Search.Documents.Tests/ConformanceTests.cs @@ -17,10 +17,7 @@ public class ConformanceTests : ConformanceTests ServiceLifetime.Singleton; - protected override string[] RequiredLogCategories => [ - "Azure.Core", - "Azure.Identity" - ]; + protected override string[] RequiredLogCategories => ["Azure.Identity"]; protected override bool SupportsKeyedRegistrations => true;