Skip to content
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
4 changes: 1 addition & 3 deletions src/ImageBuilder/AcrContentClientFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 3 additions & 4 deletions src/ImageBuilder/AzureScopes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 1 addition & 5 deletions src/ImageBuilder/AzureTokenCredentialProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ internal class AzureTokenCredentialProvider : IAzureTokenCredentialProvider
/// due to token expiration.
/// </remarks>
/// <param name="serviceConnection">Details about the Azure DevOps service connection to use.</param>
/// <param name="scope">The scope to request for the token. This parameter is ignored; the credential
/// will request the appropriate scope when GetToken is called.</param>
/// <returns>A <see cref="TokenCredential"/> that can be used to authenticate to Azure services.</returns>
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";
Expand Down
22 changes: 17 additions & 5 deletions src/ImageBuilder/AzureTokenCredentialProviderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,23 @@ internal static class AzureTokenCredentialProviderExtensions
{
public static ValueTask<AccessToken> 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;
}
}
7 changes: 3 additions & 4 deletions src/ImageBuilder/Commands/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,11 @@ public BuildCommand(
return null;
}

var tokenCredential = _tokenCredentialProvider.GetCredential(
var tokenObject = _tokenCredentialProvider.GetToken(
Options.StorageServiceConnection,
AzureScopes.StorageAccountScope);
AzureScopes.StorageAccount);

var token = tokenCredential.GetToken(new TokenRequestContext(), CancellationToken.None).Token;
return token;
return tokenObject.Token;
});
}

Expand Down
4 changes: 1 addition & 3 deletions src/ImageBuilder/IAzureTokenCredentialProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
6 changes: 3 additions & 3 deletions src/ImageBuilder/McrStatusClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ public Task<CommitResultDetailed> GetCommitResultDetailedAsync(string commitDige
private async Task<T> SendRequestAsync<T>(Func<HttpRequestMessage> message)
{
HttpResponseMessage response = await _httpClient.SendRequestAsync(message, GetAccessTokenAsync, _httpPolicy);
return JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync())
return JsonConvert.DeserializeObject<T>(await response.Content.ReadAsStringAsync())
?? throw new InvalidOperationException("Failed to deserialize response from MCR Status API.");
}

private Task<string> 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);
}
}
2 changes: 1 addition & 1 deletion src/ImageBuilder/RegistryCredentialsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private async ValueTask<RegistryCredentials> 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);
}
Expand Down
11 changes: 4 additions & 7 deletions src/ImageBuilder/Services/KustoClientWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down
Loading