Skip to content

Commit

Permalink
Address review: Validate that client and credential universe domain a…
Browse files Browse the repository at this point in the history
…re the same.
  • Loading branch information
amanda-tarafa committed Jan 30, 2024
1 parent d74e859 commit 3189731
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,6 @@ public class SampleClientBuilder : ClientBuilderBase<CallInvoker>

public new string GetEffectiveEndpoint() => base.GetEffectiveEndpoint();



private readonly string _name;

/// <summary>
Expand Down Expand Up @@ -357,7 +355,7 @@ public override CallInvoker Build()
}

protected override ChannelPool GetChannelPool() => ChannelPool;

public void ResetChannelCreation()
{
EndpointUsedToCreateChannel = null;
Expand Down
79 changes: 37 additions & 42 deletions Google.Api.Gax.Grpc/GoogleCredentialExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,58 +12,53 @@
using System.Threading;
using System.Threading.Tasks;

namespace Google.Api.Gax.Grpc
namespace Google.Api.Gax.Grpc;

/// <summary>
/// Extension methods for Google credential universe domain validation.
/// </summary>
internal static class GoogleCredentialExtensions
{
/// <summary>
/// Extension methods for Google credential universe domain validation.
/// Returns a channel credential based on <paramref name="googleCredential"/>, that will validate its own universe domain
/// against <paramref name="universeDomain"/>.
/// </summary>
public static class GoogleCredentialExtensions
/// <param name="googleCredential">The Google credential to build the channel credentials from. Must not be null.</param>
/// <param name="universeDomain">The universe domain to validate against. Must not be null.
/// <see cref="GoogleCredential.GetUniverseDomainAsync(CancellationToken)"/> should result in the same value as this.</param>
internal static ChannelCredentials ToChannelCredentials(this GoogleCredential googleCredential, string universeDomain) =>
new GoogleCredentialWithUniverseDomainValidation(googleCredential, universeDomain).ToChannelCredentials();

private class GoogleCredentialWithUniverseDomainValidation : ITokenAccessWithHeaders
{
/// <summary>
/// Returns a channel credential based on <paramref name="googleCredential"/>, that will validate its own universe domain
/// against <paramref name="universeDomain"/>.
/// </summary>
/// <param name="googleCredential">The Google credential to build the channel credentials from. Must not be null.</param>
/// <param name="universeDomain">The universe domain to validate against. Must not be null.
/// <see cref="GoogleCredential.GetUniverseDomainAsync(CancellationToken)"/> should result in the same value as this.</param>
public static ChannelCredentials ToChannelCredentials(this GoogleCredential googleCredential, string universeDomain) =>
new GoogleCredentialWithUniverseDomainValidation(googleCredential, universeDomain).ToChannelCredentials();
private readonly ITokenAccessWithHeaders _underlying;
private readonly string _universeDomain;
private readonly Lazy<Task> _universeDomainsMatchCheckCache;

private class GoogleCredentialWithUniverseDomainValidation : ITokenAccessWithHeaders
public GoogleCredentialWithUniverseDomainValidation(GoogleCredential googleCredential, string universeDomain)
{
private readonly ITokenAccessWithHeaders _underlying;
private readonly string _universeDomain;
private readonly Lazy<Task<bool>> _universeDomainsMatchCache;

public GoogleCredentialWithUniverseDomainValidation(GoogleCredential googleCredential, string universeDomain)
{
_underlying = GaxPreconditions.CheckNotNull(googleCredential, nameof(googleCredential));
_universeDomain = GaxPreconditions.CheckNotNull(universeDomain, nameof(universeDomain));
_universeDomainsMatchCache = new Lazy<Task<bool>>(UniverseDomainsMatchUncached);
}
_underlying = GaxPreconditions.CheckNotNull(googleCredential, nameof(googleCredential));
_universeDomain = GaxPreconditions.CheckNotNull(universeDomain, nameof(universeDomain));
_universeDomainsMatchCheckCache = new Lazy<Task>(UniverseDomainsMatchCheckUncached);
}

public async Task<string> GetAccessTokenForRequestAsync(string authUri = null, CancellationToken cancellationToken = default)
{
// We don't need to check the actual value, this either returns true or throws.
await _universeDomainsMatchCache.Value.WithCancellationToken(cancellationToken).ConfigureAwait(false);
return await _underlying.GetAccessTokenForRequestAsync(authUri, cancellationToken).ConfigureAwait(false);
}
public async Task<string> GetAccessTokenForRequestAsync(string authUri = null, CancellationToken cancellationToken = default)
{
await _universeDomainsMatchCheckCache.Value.WithCancellationToken(cancellationToken).ConfigureAwait(false);
return await _underlying.GetAccessTokenForRequestAsync(authUri, cancellationToken).ConfigureAwait(false);
}

public async Task<AccessTokenWithHeaders> GetAccessTokenWithHeadersForRequestAsync(string authUri = null, CancellationToken cancellationToken = default)
{
// We don't need to check the actual value, this either returns true or throws.
await _universeDomainsMatchCache.Value.WithCancellationToken(cancellationToken).ConfigureAwait(false);
return await _underlying.GetAccessTokenWithHeadersForRequestAsync(authUri, cancellationToken).ConfigureAwait(false);
}
public async Task<AccessTokenWithHeaders> GetAccessTokenWithHeadersForRequestAsync(string authUri = null, CancellationToken cancellationToken = default)
{
await _universeDomainsMatchCheckCache.Value.WithCancellationToken(cancellationToken).ConfigureAwait(false);
return await _underlying.GetAccessTokenWithHeadersForRequestAsync(authUri, cancellationToken).ConfigureAwait(false);
}

private async Task<bool> UniverseDomainsMatchUncached()
private async Task UniverseDomainsMatchCheckUncached()
{
string credentialUniverseDomain = await (_underlying as GoogleCredential).GetUniverseDomainAsync(default).ConfigureAwait(false);
if (credentialUniverseDomain != _universeDomain)
{
string credentialUniverseDomain = await (_underlying as GoogleCredential).GetUniverseDomainAsync(default).ConfigureAwait(false);
if (credentialUniverseDomain == _universeDomain)
{
return true;
}

throw new InvalidOperationException(
$"The service client universe domain {_universeDomain} does not match the credential universe domain {credentialUniverseDomain}." +
$"You can configure the universe domain for your service client by using the UniverseDomain property on the corresponding client builder.");
Expand Down

0 comments on commit 3189731

Please sign in to comment.