| File: Provisioning\Internal\DefaultTokenCredentialProvider.cs | Web Access |
| Project: src\src\Aspire.Hosting.Azure\Aspire.Hosting.Azure.csproj (Aspire.Hosting.Azure) |
// 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; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Aspire.Hosting.Azure.Provisioning.Internal; internal class DefaultTokenCredentialProvider : ITokenCredentialProvider { private readonly ILogger<DefaultTokenCredentialProvider> _logger; private readonly IOptions<AzureProvisionerOptions> _options; private readonly DistributedApplicationExecutionContext _distributedApplicationExecutionContext; private TokenCredential? _credential; private string? _lastTenantId; private readonly object _lock = new(); public DefaultTokenCredentialProvider( ILogger<DefaultTokenCredentialProvider> logger, IOptions<AzureProvisionerOptions> options, DistributedApplicationExecutionContext distributedApplicationExecutionContext) { _logger = logger; _options = options; _distributedApplicationExecutionContext = distributedApplicationExecutionContext; } public TokenCredential TokenCredential { get { lock (_lock) { var currentTenantId = _options.Value.TenantId; // Recreate credential if tenant ID has changed or credential doesn't exist if (_credential == null || _lastTenantId != currentTenantId) { _credential = CreateCredential(currentTenantId); _lastTenantId = currentTenantId; } return _credential; } } } private TokenCredential CreateCredential(string? tenantId) { var credentialSetting = _options.Value.CredentialSource; var processTimeout = _options.Value.CredentialProcessTimeoutSeconds is { } timeoutSeconds ? TimeSpan.FromSeconds(timeoutSeconds) : (TimeSpan?)null; TokenCredential credential = credentialSetting switch { "AzureCli" => new AzureCliCredential(CreateAzureCliOptions(tenantId, processTimeout)), "AzurePowerShell" => new AzurePowerShellCredential(CreateAzurePowerShellOptions(tenantId, processTimeout)), "VisualStudio" => new VisualStudioCredential(CreateVisualStudioOptions(tenantId, processTimeout)), "AzureDeveloperCli" => new AzureDeveloperCliCredential(CreateAzureDeveloperCliOptions(tenantId, processTimeout)), "InteractiveBrowser" => new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions() { TenantId = tenantId }), // Use AzureCli as default for publish mode when no explicit credential source is set null or "Default" when _distributedApplicationExecutionContext.IsPublishMode => new AzureCliCredential(CreateAzureCliOptions(tenantId, processTimeout)), _ => CreateDefaultAzureCredential(tenantId, processTimeout) }; return credential; } internal void LogCredentialType() { var credential = TokenCredential; _logger.LogInformation("Using {credentialType} for provisioning.", credential.GetType().Name); } private static AzureCliCredentialOptions CreateAzureCliOptions(string? tenantId, TimeSpan? processTimeout) { var options = new AzureCliCredentialOptions { TenantId = tenantId, AdditionallyAllowedTenants = { "*" } }; if (processTimeout.HasValue) { options.ProcessTimeout = processTimeout.Value; } return options; } private static AzurePowerShellCredentialOptions CreateAzurePowerShellOptions(string? tenantId, TimeSpan? processTimeout) { var options = new AzurePowerShellCredentialOptions { TenantId = tenantId, AdditionallyAllowedTenants = { "*" } }; if (processTimeout.HasValue) { options.ProcessTimeout = processTimeout.Value; } return options; } private static VisualStudioCredentialOptions CreateVisualStudioOptions(string? tenantId, TimeSpan? processTimeout) { var options = new VisualStudioCredentialOptions { TenantId = tenantId, AdditionallyAllowedTenants = { "*" } }; if (processTimeout.HasValue) { options.ProcessTimeout = processTimeout.Value; } return options; } private static AzureDeveloperCliCredentialOptions CreateAzureDeveloperCliOptions(string? tenantId, TimeSpan? processTimeout) { var options = new AzureDeveloperCliCredentialOptions { TenantId = tenantId, AdditionallyAllowedTenants = { "*" } }; if (processTimeout.HasValue) { options.ProcessTimeout = processTimeout.Value; } return options; } private static DefaultAzureCredential CreateDefaultAzureCredential(string? tenantId, TimeSpan? processTimeout) { var options = new DefaultAzureCredentialOptions { TenantId = tenantId, ExcludeManagedIdentityCredential = true, ExcludeWorkloadIdentityCredential = true, ExcludeAzurePowerShellCredential = true, AdditionallyAllowedTenants = { "*" } }; if (processTimeout.HasValue) { options.CredentialProcessTimeout = processTimeout.Value; } return new DefaultAzureCredential(options); } }