diff --git a/src/ImageBuilder/AcrContentClientFactory.cs b/src/ImageBuilder/AcrContentClientFactory.cs index fb4a5fb76..351139c4b 100644 --- a/src/ImageBuilder/AcrContentClientFactory.cs +++ b/src/ImageBuilder/AcrContentClientFactory.cs @@ -28,9 +28,7 @@ public IAcrContentClient Create(Acr acr, string repositoryName) $"Ensure the ACR is configured in the publish configuration with a valid service connection."); } - var tokenCredential = _tokenCredentialProvider.GetCredential( - acrConfig.ServiceConnection, - AzureScopes.ContainerRegistryScope); + var tokenCredential = _tokenCredentialProvider.GetCredential(acrConfig.ServiceConnection); var client = new ContainerRegistryContentClient(acr.RegistryUri, repositoryName, tokenCredential); var wrapper = new AcrContentClientWrapper(client); diff --git a/src/ImageBuilder/AzureScopes.cs b/src/ImageBuilder/AzureScopes.cs index 063ded04f..faf6662c0 100644 --- a/src/ImageBuilder/AzureScopes.cs +++ b/src/ImageBuilder/AzureScopes.cs @@ -7,8 +7,7 @@ namespace Microsoft.DotNet.ImageBuilder; internal static class AzureScopes { public const string ScopeSuffix = "/.default"; - public const string DefaultAzureManagementScope = "https://management.azure.com" + ScopeSuffix; - public const string ContainerRegistryScope = "https://containerregistry.azure.net" + ScopeSuffix; - public const string McrStatusScope = "api://c00053c3-a979-4ee6-b94e-941881e62d8e" + ScopeSuffix; - public const string StorageAccountScope = "https://storage.azure.com" + ScopeSuffix; + public const string Default = "https://management.azure.com" + ScopeSuffix; + public const string McrStatusApi = "api://c00053c3-a979-4ee6-b94e-941881e62d8e" + ScopeSuffix; + public const string StorageAccount = "https://storage.azure.com" + ScopeSuffix; } diff --git a/src/ImageBuilder/AzureTokenCredentialProvider.cs b/src/ImageBuilder/AzureTokenCredentialProvider.cs index c65fe2ea2..bdcb23e96 100644 --- a/src/ImageBuilder/AzureTokenCredentialProvider.cs +++ b/src/ImageBuilder/AzureTokenCredentialProvider.cs @@ -26,12 +26,8 @@ internal class AzureTokenCredentialProvider : IAzureTokenCredentialProvider /// due to token expiration. /// /// Details about the Azure DevOps service connection to use. - /// The scope to request for the token. This parameter is ignored; the credential - /// will request the appropriate scope when GetToken is called. /// A that can be used to authenticate to Azure services. - public TokenCredential GetCredential( - IServiceConnection? serviceConnection, - string scope = AzureScopes.DefaultAzureManagementScope) + public TokenCredential GetCredential(IServiceConnection? serviceConnection) { // Cache by service connection ID only. The TokenCredential handles different scopes internally. string cacheKey = serviceConnection?.Id ?? "default"; diff --git a/src/ImageBuilder/AzureTokenCredentialProviderExtensions.cs b/src/ImageBuilder/AzureTokenCredentialProviderExtensions.cs index 2ec893dc8..14c239981 100644 --- a/src/ImageBuilder/AzureTokenCredentialProviderExtensions.cs +++ b/src/ImageBuilder/AzureTokenCredentialProviderExtensions.cs @@ -12,11 +12,23 @@ internal static class AzureTokenCredentialProviderExtensions { public static ValueTask GetTokenAsync( this IAzureTokenCredentialProvider provider, - IServiceConnection serviceConnection, - string scope = AzureScopes.DefaultAzureManagementScope) + IServiceConnection? serviceConnection, + string scope = AzureScopes.Default) { - return provider - .GetCredential(serviceConnection, scope) - .GetTokenAsync(new TokenRequestContext([scope]), CancellationToken.None); + var credential = provider.GetCredential(serviceConnection); + var requestContext = new TokenRequestContext([scope]); + var token = credential.GetTokenAsync(requestContext, CancellationToken.None); + return token; + } + + public static AccessToken GetToken( + this IAzureTokenCredentialProvider provider, + IServiceConnection? serviceConnection, + string scope = AzureScopes.Default) + { + var credential = provider.GetCredential(serviceConnection); + var requestContext = new TokenRequestContext([scope]); + var token = credential.GetToken(requestContext, CancellationToken.None); + return token; } } diff --git a/src/ImageBuilder/Commands/BuildCommand.cs b/src/ImageBuilder/Commands/BuildCommand.cs index 3c7ba6218..1a1e306a8 100644 --- a/src/ImageBuilder/Commands/BuildCommand.cs +++ b/src/ImageBuilder/Commands/BuildCommand.cs @@ -86,11 +86,11 @@ public BuildCommand( return null; } - var tokenCredential = _tokenCredentialProvider.GetCredential(Options.StorageServiceConnection); - var requestContext = new TokenRequestContext([AzureScopes.StorageAccountScope]); - var tokenObject = tokenCredential.GetToken(requestContext, CancellationToken.None); - var token = tokenObject.Token; - return token; + var tokenObject = _tokenCredentialProvider.GetToken( + Options.StorageServiceConnection, + AzureScopes.StorageAccount); + + return tokenObject.Token; }); } diff --git a/src/ImageBuilder/IAzureTokenCredentialProvider.cs b/src/ImageBuilder/IAzureTokenCredentialProvider.cs index c7e551b24..8c18c1f90 100644 --- a/src/ImageBuilder/IAzureTokenCredentialProvider.cs +++ b/src/ImageBuilder/IAzureTokenCredentialProvider.cs @@ -8,7 +8,5 @@ namespace Microsoft.DotNet.ImageBuilder; #nullable enable public interface IAzureTokenCredentialProvider { - TokenCredential GetCredential( - IServiceConnection? serviceConnection, - string scope = AzureScopes.DefaultAzureManagementScope); + TokenCredential GetCredential(IServiceConnection? serviceConnection); } diff --git a/src/ImageBuilder/McrStatusClient.cs b/src/ImageBuilder/McrStatusClient.cs index 02ccc1d05..976b3a80c 100644 --- a/src/ImageBuilder/McrStatusClient.cs +++ b/src/ImageBuilder/McrStatusClient.cs @@ -70,16 +70,16 @@ public Task GetCommitResultDetailedAsync(string commitDige private async Task SendRequestAsync(Func message) { HttpResponseMessage response = await _httpClient.SendRequestAsync(message, GetAccessTokenAsync, _httpPolicy); - return JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()) + return JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()) ?? throw new InvalidOperationException("Failed to deserialize response from MCR Status API."); } private Task GetAccessTokenAsync() => _accessToken.GetValueAsync(async () => - (await _tokenCredentialProvider.GetTokenAsync(_serviceConnection, AzureScopes.McrStatusScope)).Token); + (await _tokenCredentialProvider.GetTokenAsync(_serviceConnection, AzureScopes.McrStatusApi)).Token); private Task RefreshAccessTokenAsync() => _accessToken.ResetValueAsync(async () => - (await _tokenCredentialProvider.GetTokenAsync(_serviceConnection, AzureScopes.McrStatusScope)).Token); + (await _tokenCredentialProvider.GetTokenAsync(_serviceConnection, AzureScopes.McrStatusApi)).Token); } } diff --git a/src/ImageBuilder/RegistryCredentialsProvider.cs b/src/ImageBuilder/RegistryCredentialsProvider.cs index 82ccc2d31..d6aecdc5e 100644 --- a/src/ImageBuilder/RegistryCredentialsProvider.cs +++ b/src/ImageBuilder/RegistryCredentialsProvider.cs @@ -54,7 +54,7 @@ private async ValueTask GetAcrCredentialsWithOAuthAsync(Reg TokenCredential tokenCredential = _tokenCredentialProvider.GetCredential(serviceConnection); var tenantGuid = Guid.Parse(serviceConnection.TenantId); - string token = (await tokenCredential.GetTokenAsync(new TokenRequestContext([AzureScopes.DefaultAzureManagementScope]), CancellationToken.None)).Token; + string token = (await tokenCredential.GetTokenAsync(new TokenRequestContext([AzureScopes.Default]), CancellationToken.None)).Token; string refreshToken = await OAuthHelper.GetRefreshTokenAsync(_httpClientProvider.GetClient(), acr, tenantGuid, token); return new RegistryCredentials(Guid.Empty.ToString(), refreshToken); } diff --git a/src/ImageBuilder/Services/KustoClientWrapper.cs b/src/ImageBuilder/Services/KustoClientWrapper.cs index 4f5189949..49c84e928 100644 --- a/src/ImageBuilder/Services/KustoClientWrapper.cs +++ b/src/ImageBuilder/Services/KustoClientWrapper.cs @@ -36,13 +36,10 @@ public async Task IngestFromCsvAsync( { _loggerService.WriteSubheading("INGESTING DATA INTO KUSTO"); - string clusterResource = $"https://{cluster}.kusto.windows.net"; - KustoConnectionStringBuilder connectionBuilder = - new KustoConnectionStringBuilder(clusterResource) - .WithAadAzureTokenCredentialsAuthentication( - _tokenCredentialProvider.GetCredential( - serviceConnection, - clusterResource + AzureScopes.ScopeSuffix)); + var connectionString = $"https://{cluster}.kusto.windows.net"; + var tokenCredential = _tokenCredentialProvider.GetCredential(serviceConnection); + var connectionBuilder = new KustoConnectionStringBuilder(connectionString) + .WithAadAzureTokenCredentialsAuthentication(tokenCredential); using (IKustoIngestClient client = KustoIngestFactory.CreateDirectIngestClient(connectionBuilder)) {