Skip to content

Commit

Permalink
feat: Full Endpoint Resolution from EndpointContext (#2313)
Browse files Browse the repository at this point in the history
* feat: Full endpoint resolution

* chore: Fix lint issues

* chore: Address PR comments

* chore: Do not set resolved universe domain for gdch

* chore: Move helper methods to the Builder class

* chore: Address PR comments

* chore: Add javadocs for universe domain
  • Loading branch information
lqiu96 committed Jan 2, 2024
1 parent 4f535a7 commit f499ced
Show file tree
Hide file tree
Showing 9 changed files with 489 additions and 89 deletions.
Expand Up @@ -295,6 +295,10 @@ private void logDirectPathMisconfig() {
Level.WARNING,
"DirectPath is misconfigured. DirectPath is only available in a GCE environment.");
}
if (!canUseDirectPathWithUniverseDomain()) {
LOG.log(
Level.WARNING, "DirectPath will only work in the the googleapis.com Universe Domain");
}
}
}
}
Expand Down Expand Up @@ -325,6 +329,10 @@ static boolean isOnComputeEngine() {
return false;
}

private boolean canUseDirectPathWithUniverseDomain() {
return endpoint.contains("googleapis.com");
}

@VisibleForTesting
ChannelCredentials createMtlsChannelCredentials() throws IOException, GeneralSecurityException {
if (mtlsProvider.useMtlsClientCertificate()) {
Expand Down Expand Up @@ -356,7 +364,10 @@ private ManagedChannel createSingleChannel() throws IOException {

// Check DirectPath traffic.
boolean useDirectPathXds = false;
if (isDirectPathEnabled() && isNonDefaultServiceAccountAllowed() && isOnComputeEngine()) {
if (isDirectPathEnabled()
&& isNonDefaultServiceAccountAllowed()
&& isOnComputeEngine()
&& canUseDirectPathWithUniverseDomain()) {
CallCredentials callCreds = MoreCallCredentials.from(credentials);
ChannelCredentials channelCreds =
GoogleDefaultChannelCredentials.newBuilder().callCredentials(callCreds).build();
Expand Down
Expand Up @@ -290,6 +290,7 @@ public void testDirectPathXdsEnabled() throws IOException {
InstantiatingGrpcChannelProvider.newBuilder()
.setAttemptDirectPath(true)
.setAttemptDirectPathXds()
.setEndpoint("test.googleapis.com:443")
.build();

assertThat(provider.isDirectPathXdsEnabled()).isTrue();
Expand Down Expand Up @@ -528,6 +529,7 @@ public void testLogDirectPathMisconfigWrongCredential() {
InstantiatingGrpcChannelProvider.newBuilder()
.setAttemptDirectPathXds()
.setAttemptDirectPath(true)
.setEndpoint("test.googleapis.com:443")
.build();
assertThat(logHandler.getAllMessages())
.contains(
Expand All @@ -545,6 +547,7 @@ public void testLogDirectPathMisconfigNotOnGCE() {
.setAttemptDirectPathXds()
.setAttemptDirectPath(true)
.setAllowNonDefaultServiceAccount(true)
.setEndpoint("test.googleapis.com:443")
.build();
if (!InstantiatingGrpcChannelProvider.isOnComputeEngine()) {
assertThat(logHandler.getAllMessages())
Expand All @@ -554,6 +557,22 @@ public void testLogDirectPathMisconfigNotOnGCE() {
InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler);
}

@Test
public void testLogDirectPathMisconfigNotInGDU() {
FakeLogHandler logHandler = new FakeLogHandler();
InstantiatingGrpcChannelProvider.LOG.addHandler(logHandler);
InstantiatingGrpcChannelProvider provider =
InstantiatingGrpcChannelProvider.newBuilder()
.setAttemptDirectPathXds()
.setAttemptDirectPath(true)
.setAllowNonDefaultServiceAccount(true)
.setEndpoint("test.random.endpoint.com:443")
.build();
assertThat(logHandler.getAllMessages())
.contains("DirectPath will only work in the the googleapis.com Universe Domain");
InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler);
}

private static class FakeLogHandler extends Handler {
List<LogRecord> records = new ArrayList<>();

Expand Down
6 changes: 6 additions & 0 deletions gax-java/gax/clirr-ignored-differences.xml
Expand Up @@ -25,4 +25,10 @@
<className>com/google/api/gax/rpc/TransportChannelProvider</className>
<method>* getEndpoint()</method>
</difference>
<!-- Add Universe Domain to ClientContext -->
<difference>
<differenceType>7013</differenceType>
<className>com/google/api/gax/rpc/ClientContext*</className>
<method>* *UniverseDomain*(*)</method>
</difference>
</differences>
Expand Up @@ -104,6 +104,9 @@ public abstract class ClientContext {
@Nullable
abstract String getServiceName();

@Nullable
public abstract String getUniverseDomain();

@Nullable
public abstract String getEndpoint();

Expand Down Expand Up @@ -157,15 +160,28 @@ public static ClientContext create(StubSettings settings) throws IOException {
final ScheduledExecutorService backgroundExecutor = backgroundExecutorProvider.getExecutor();

Credentials credentials = settings.getCredentialsProvider().getCredentials();
boolean usingGDCH = credentials instanceof GdchCredentials;
EndpointContext endpointContext =
EndpointContext.newBuilder()
.setServiceName(settings.getServiceName())
.setUniverseDomain(settings.getUniverseDomain())
.setClientSettingsEndpoint(settings.getEndpoint())
.setTransportChannelProviderEndpoint(
settings.getTransportChannelProvider().getEndpoint())
.setMtlsEndpoint(settings.getMtlsEndpoint())
.setSwitchToMtlsEndpointAllowed(settings.getSwitchToMtlsEndpointAllowed())
.setUsingGDCH(usingGDCH)
.build();
String endpoint = endpointContext.resolvedEndpoint();

String settingsGdchApiAudience = settings.getGdchApiAudience();
if (credentials instanceof GdchCredentials) {
if (usingGDCH) {
// We recompute the GdchCredentials with the audience
String audienceString;
if (!Strings.isNullOrEmpty(settingsGdchApiAudience)) {
audienceString = settingsGdchApiAudience;
} else if (!Strings.isNullOrEmpty(settings.getEndpoint())) {
audienceString = settings.getEndpoint();
} else if (!Strings.isNullOrEmpty(endpoint)) {
audienceString = endpoint;
} else {
throw new IllegalArgumentException("Could not infer GDCH api audience from settings");
}
Expand Down Expand Up @@ -204,16 +220,6 @@ public static ClientContext create(StubSettings settings) throws IOException {
if (transportChannelProvider.needsCredentials() && credentials != null) {
transportChannelProvider = transportChannelProvider.withCredentials(credentials);
}
EndpointContext endpointContext =
EndpointContext.newBuilder()
.setServiceName(settings.getServiceName())
.setClientSettingsEndpoint(settings.getEndpoint())
.setTransportChannelProviderEndpoint(
settings.getTransportChannelProvider().getEndpoint())
.setMtlsEndpoint(settings.getMtlsEndpoint())
.setSwitchToMtlsEndpointAllowed(settings.getSwitchToMtlsEndpointAllowed())
.build();
String endpoint = endpointContext.getResolvedEndpoint();
if (transportChannelProvider.needsEndpoint()) {
transportChannelProvider = transportChannelProvider.withEndpoint(endpoint);
}
Expand Down Expand Up @@ -264,6 +270,7 @@ public static ClientContext create(StubSettings settings) throws IOException {
.setClock(clock)
.setDefaultCallContext(defaultCallContext)
.setServiceName(settings.getServiceName())
.setUniverseDomain(settings.getUniverseDomain())
.setEndpoint(settings.getEndpoint())
.setQuotaProjectId(settings.getQuotaProjectId())
.setStreamWatchdog(watchdog)
Expand Down Expand Up @@ -332,6 +339,8 @@ public abstract static class Builder {
// Package-Private scope for internal use only. Shared between StubSettings and ClientContext
abstract Builder setServiceName(String serviceName);

public abstract Builder setUniverseDomain(String universeDomain);

public abstract Builder setEndpoint(String endpoint);

public abstract Builder setQuotaProjectId(String QuotaProjectId);
Expand Down

0 comments on commit f499ced

Please sign in to comment.