From 2f56310b187b8a28a58150e58d6a0b8045936f6a Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Thu, 16 Jan 2025 23:16:50 +0000 Subject: [PATCH 01/14] wip --- gax-java/dependencies.properties | 4 +- gax-java/gax-grpc/pom.xml | 2 + .../InstantiatingGrpcChannelProvider.java | 38 +++++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/gax-java/dependencies.properties b/gax-java/dependencies.properties index 5647d0022c..1188e885e6 100644 --- a/gax-java/dependencies.properties +++ b/gax-java/dependencies.properties @@ -37,8 +37,8 @@ version.io_grpc=1.69.0 # 2) Replace all characters which are neither alphabetic nor digits with the underscore ('_') character maven.com_google_api_grpc_proto_google_common_protos=com.google.api.grpc:proto-google-common-protos:2.50.0 maven.com_google_api_grpc_grpc_google_common_protos=com.google.api.grpc:grpc-google-common-protos:2.50.0 -maven.com_google_auth_google_auth_library_oauth2_http=com.google.auth:google-auth-library-oauth2-http:1.30.1 -maven.com_google_auth_google_auth_library_credentials=com.google.auth:google-auth-library-credentials:1.30.1 +maven.com_google_auth_google_auth_library_oauth2_http=com.google.auth:google-auth-library-oauth2-http:1.30.2-SNAPSHOT +maven.com_google_auth_google_auth_library_credentials=com.google.auth:google-auth-library-credentials:1.30.2-SNAPSHOT maven.io_opentelemetry_opentelemetry_api=io.opentelemetry:opentelemetry-api:1.45.0 maven.io_opencensus_opencensus_api=io.opencensus:opencensus-api:0.31.1 maven.io_opencensus_opencensus_contrib_grpc_metrics=io.opencensus:opencensus-contrib-grpc-metrics:0.31.1 diff --git a/gax-java/gax-grpc/pom.xml b/gax-java/gax-grpc/pom.xml index 1f919f66fc..f99bfae1e5 100644 --- a/gax-java/gax-grpc/pom.xml +++ b/gax-java/gax-grpc/pom.xml @@ -30,6 +30,7 @@ com.google.auth google-auth-library-credentials + 1.30.2-SNAPSHOT com.google.guava @@ -50,6 +51,7 @@ com.google.auth google-auth-library-oauth2-http + 1.30.2-SNAPSHOT io.grpc diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index ae4d7f9e51..530314eb79 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -319,8 +319,9 @@ private void logDirectPathMisconfig() { Level.WARNING, "Env var " + DIRECT_PATH_ENV_ENABLE_XDS - + " was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " - + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); + + " was found and set to TRUE, but DirectPath was not enabled for this client. If" + + " this is intended for this client, please note that this is a misconfiguration" + + " and set the attemptDirectPath option as well."); } // Case 2: Direct Path xDS was enabled via Builder. Direct Path Traffic Director must be set // (enabled with `setAttemptDirectPath(true)`) along with xDS. @@ -328,7 +329,9 @@ private void logDirectPathMisconfig() { else if (isDirectPathXdsEnabledViaBuilderOption()) { LOG.log( Level.WARNING, - "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); + "DirectPath is misconfigured. The DirectPath XDS option was set, but the" + + " attemptDirectPath option was not. Please set both the attemptDirectPath and" + + " attemptDirectPathXds options."); } } else { // Case 3: credential is not correctly set @@ -429,9 +432,35 @@ private ManagedChannel createSingleChannel() throws IOException { // Check DirectPath traffic. boolean useDirectPathXds = false; if (canUseDirectPath()) { + CallCredentials altsCallCreds = null; + if (true) { + // Create gRPC CallCredentials that can fetch DirectPath bound tokens. + if (credentials == null) { + altsCallCreds = + MoreCallCredentials.from( + ComputeEngineCredentials.newBuilder() + .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) + .build()); + } else if (credentials instanceof ComputeEngineCredentials) { + // ComputeEngineCredentials.Builder credsBuilder = + // ((ComputeEngineCredentials) credentials).toBuilder(); + // // We only set scopes and HTTP transport factory from the original credentials because + // // only those are used in gRPC CallCredentials to fetch request metadata. + altsCallCreds = + MoreCallCredentials.from( + ComputeEngineCredentials.newBuilder() + // .setScopes(credsBuilder.getScopes()) + // .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) + .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) + .build()); + } + } CallCredentials callCreds = MoreCallCredentials.from(credentials); ChannelCredentials channelCreds = - GoogleDefaultChannelCredentials.newBuilder().callCredentials(callCreds).build(); + GoogleDefaultChannelCredentials.newBuilder() + .callCredentials(callCreds) + .altsCallCredentials(altsCallCreds) + .build(); useDirectPathXds = isDirectPathXdsEnabled(); if (useDirectPathXds) { // google-c2p: CloudToProd(C2P) Directpath. This scheme is defined in @@ -755,6 +784,7 @@ public Integer getMaxInboundMetadataSize() { public Builder setKeepAliveTime(org.threeten.bp.Duration duration) { return setKeepAliveTimeDuration(toJavaTimeDuration(duration)); } + /** The time without read activity before sending a keepalive ping. */ public Builder setKeepAliveTimeDuration(java.time.Duration duration) { this.keepAliveTime = duration; From 88dc79590862b1893cfc55c6a8c961c5deeda89f Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 17 Jan 2025 00:05:39 +0000 Subject: [PATCH 02/14] wip++ --- .../InstantiatingGrpcChannelProvider.java | 51 +++++++++++-------- .../InstantiatingGrpcChannelProviderTest.java | 41 +++++++++++++-- 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index 530314eb79..254dad36ba 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -225,14 +225,18 @@ public TransportChannelProvider withEndpoint(String endpoint) { return toBuilder().setEndpoint(endpoint).build(); } - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ + /** + * @deprecated Please modify pool settings via {@link #toBuilder()} + */ @Deprecated @Override public boolean acceptsPoolSize() { return true; } - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ + /** + * @deprecated Please modify pool settings via {@link #toBuilder()} + */ @Deprecated @Override public TransportChannelProvider withPoolSize(int size) { @@ -433,24 +437,17 @@ private ManagedChannel createSingleChannel() throws IOException { boolean useDirectPathXds = false; if (canUseDirectPath()) { CallCredentials altsCallCreds = null; - if (true) { - // Create gRPC CallCredentials that can fetch DirectPath bound tokens. - if (credentials == null) { - altsCallCreds = - MoreCallCredentials.from( - ComputeEngineCredentials.newBuilder() - .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) - .build()); - } else if (credentials instanceof ComputeEngineCredentials) { - // ComputeEngineCredentials.Builder credsBuilder = - // ((ComputeEngineCredentials) credentials).toBuilder(); - // // We only set scopes and HTTP transport factory from the original credentials because - // // only those are used in gRPC CallCredentials to fetch request metadata. + // FIXME: Change the if condition. + if (true && credentials instanceof ComputeEngineCredentials) { + ComputeEngineCredentials.Builder credsBuilder = + ((ComputeEngineCredentials) credentials).toBuilder(); + // We only set scopes and HTTP transport factory from the original credentials because + // only those are used in gRPC CallCredentials to fetch request metadata. altsCallCreds = MoreCallCredentials.from( ComputeEngineCredentials.newBuilder() - // .setScopes(credsBuilder.getScopes()) - // .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) + .setScopes(credsBuilder.getScopes()) + .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) .build()); } @@ -704,7 +701,9 @@ public Builder setExecutor(Executor executor) { return this; } - /** @deprecated Please use {@link #setExecutor(Executor)}. */ + /** + * @deprecated Please use {@link #setExecutor(Executor)}. + */ @Deprecated public Builder setExecutorProvider(ExecutorProvider executorProvider) { return setExecutor((Executor) executorProvider.getExecutor()); @@ -839,26 +838,34 @@ public Boolean getKeepAliveWithoutCalls() { return keepAliveWithoutCalls; } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public int getPoolSize() { return channelPoolSettings.getInitialChannelCount(); } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setPoolSize(int poolSize) { channelPoolSettings = ChannelPoolSettings.staticallySized(poolSize); return this; } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setChannelsPerCpu(double multiplier) { return setChannelsPerCpu(multiplier, 100); } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setChannelsPerCpu(double multiplier, int maxChannels) { Preconditions.checkArgument(multiplier > 0, "multiplier must be positive"); diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index a58f9b8173..1ebabe08a5 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -626,7 +626,9 @@ private void createAndCloseTransportChannel(InstantiatingGrpcChannelProvider pro createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); + "DirectPath is misconfigured. The DirectPath XDS option was set, but the" + + " attemptDirectPath option was not. Please set both the attemptDirectPath and" + + " attemptDirectPathXds options."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } @@ -641,8 +643,10 @@ void testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSe createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " - + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); + "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath" + + " was not enabled for this client. If this is intended for this client, please" + + " note that this is a misconfiguration and set the attemptDirectPath option as" + + " well."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } @@ -719,6 +723,37 @@ public void canUseDirectPath_happyPath() throws IOException { envProvider.getenv( InstantiatingGrpcChannelProvider.DIRECT_PATH_ENV_DISABLE_DIRECT_PATH)) .thenReturn("false"); + // FIXME: Remove the following statement. + Mockito.when(computeEngineCredentials.toBuilder()) + .thenReturn(ComputeEngineCredentials.newBuilder()); + InstantiatingGrpcChannelProvider.Builder builder = + InstantiatingGrpcChannelProvider.newBuilder() + .setAttemptDirectPath(true) + .setCredentials(computeEngineCredentials) + .setEndpoint(DEFAULT_ENDPOINT) + .setEnvProvider(envProvider) + .setHeaderProvider(Mockito.mock(HeaderProvider.class)); + InstantiatingGrpcChannelProvider provider = + new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); + Truth.assertThat(provider.canUseDirectPath()).isTrue(); + + // verify this info is passed correctly to transport channel + TransportChannel transportChannel = provider.getTransportChannel(); + Truth.assertThat(((GrpcTransportChannel) transportChannel).isDirectPath()).isTrue(); + transportChannel.shutdownNow(); + } + + @Test + public void canUseDirectPath_happyPathWithBoundToken() throws IOException { + System.setProperty("os.name", "Linux"); + EnvironmentProvider envProvider = Mockito.mock(EnvironmentProvider.class); + Mockito.when( + envProvider.getenv( + InstantiatingGrpcChannelProvider.DIRECT_PATH_ENV_DISABLE_DIRECT_PATH)) + .thenReturn("false"); + // verifies the credentials gets called and returns a non-null builder. + Mockito.when(computeEngineCredentials.toBuilder()) + .thenReturn(ComputeEngineCredentials.newBuilder()); InstantiatingGrpcChannelProvider.Builder builder = InstantiatingGrpcChannelProvider.newBuilder() .setAttemptDirectPath(true) From 25003a91714ccf03df5df683db7eec77a12d6cb5 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 17 Jan 2025 18:00:01 +0000 Subject: [PATCH 03/14] wip++ --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 9 +++++++-- .../gax/grpc/InstantiatingGrpcChannelProviderTest.java | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index 254dad36ba..906c18b4d6 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -368,6 +368,12 @@ boolean isCredentialDirectPathCompatible() { return credentials instanceof ComputeEngineCredentials; } + @VisibleForTesting + boolean isDirectPathBoundTokenEnabled() { + // FIXME + return isCredentialDirectPathCompatible() && credentials instanceof ComputeEngineCredentials; + } + // DirectPath should only be used on Compute Engine. // Notice Windows is supported for now. @VisibleForTesting @@ -437,8 +443,7 @@ private ManagedChannel createSingleChannel() throws IOException { boolean useDirectPathXds = false; if (canUseDirectPath()) { CallCredentials altsCallCreds = null; - // FIXME: Change the if condition. - if (true && credentials instanceof ComputeEngineCredentials) { + if (isDirectPathBoundTokenEnabled()) { ComputeEngineCredentials.Builder credsBuilder = ((ComputeEngineCredentials) credentials).toBuilder(); // We only set scopes and HTTP transport factory from the original credentials because diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index 1ebabe08a5..c0bcd5beba 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -764,6 +764,7 @@ public void canUseDirectPath_happyPathWithBoundToken() throws IOException { InstantiatingGrpcChannelProvider provider = new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); Truth.assertThat(provider.canUseDirectPath()).isTrue(); + Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isTrue(); // verify this info is passed correctly to transport channel TransportChannel transportChannel = provider.getTransportChannel(); From 53d3206e428185f6e82e40234db9e33b80dee71e Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 17 Jan 2025 18:03:19 +0000 Subject: [PATCH 04/14] wip --- .../InstantiatingGrpcChannelProvider.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index ae4d7f9e51..3ee6b6fa58 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -126,16 +126,32 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP @Nullable private final Boolean allowNonDefaultServiceAccount; @VisibleForTesting final ImmutableMap directPathServiceConfig; @Nullable private final MtlsProvider mtlsProvider; + @Nullable private final List allowedHardBoundTokenTypes; @VisibleForTesting final Map headersWithDuplicatesRemoved = new HashMap<>(); @Nullable private final ApiFunction channelConfigurator; + /* + * Experimental feature + * + *

{@link HardBoundTokenTypes} specifies if hard bound tokens should be used if DirectPath + * or S2A is used to estabilsh a connection to Google APIs. + * + */ + public enum HardBoundTokenTypes { + // Use ALTS bound tokens when using DirectPath + ALTS, + // Use MTLS bound tokens when using S2A + MTLS_S2A + } + private InstantiatingGrpcChannelProvider(Builder builder) { this.processorCount = builder.processorCount; this.executor = builder.executor; this.headerProvider = builder.headerProvider; this.endpoint = builder.endpoint; + this.allowedHardBoundTokenTypes = builder.allowedHardBoundTokenTypes; this.mtlsProvider = builder.mtlsProvider; this.envProvider = builder.envProvider; this.interceptorProvider = builder.interceptorProvider; @@ -620,6 +636,7 @@ public static final class Builder { @Nullable private Boolean attemptDirectPathXds; @Nullable private Boolean allowNonDefaultServiceAccount; @Nullable private ImmutableMap directPathServiceConfig; + @Nullable private List allowedHardBoundTokenTypes; private Builder() { processorCount = Runtime.getRuntime().availableProcessors(); @@ -700,6 +717,30 @@ public Builder setEndpoint(String endpoint) { return this; } + /* + * Sets the allowed hard bound token types for this TransportChannelProvider. + * + *

This is optional; if it is not provided, bearer tokens will be used. + * + *

Examples: + * + *

allowedValues is {HardBoundTokenTypes.ALTS}: If DirectPath is used to create the channel, + * use hard ALTS-bound tokens for requests sent on that channel. + * + *

allowedValues is {HardBoundTokenTypes.MTLS_S2A}: If MTLS via S2A is used to create the + * channel, use hard MTLS-bound tokens for requests sent on that channel. + * + *

allowedValues is {HardBoundTokenTypes.ALTS, HardBoundTokenTypes.MTLS_S2A}: if DirectPath + * is used to create the channel, use hard ALTS-bound tokens for requests sent on that channel. + * If MTLS via S2A is used to create the channel, use hard MTLS-bound tokens for requests sent + * on that channel. + */ + @InternalApi + public Builder setAllowHardBoundTokenTypes(List allowedValues) { + this.allowedHardBoundTokenTypes = allowedValues; + return this; + } + @VisibleForTesting Builder setMtlsProvider(MtlsProvider mtlsProvider) { this.mtlsProvider = mtlsProvider; From d11c03f23f094be53bbe7b757395e77a49d2f6e4 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 17 Jan 2025 18:19:37 +0000 Subject: [PATCH 05/14] wip++ --- .../InstantiatingGrpcChannelProvider.java | 61 ++++++++----------- .../InstantiatingGrpcChannelProviderTest.java | 6 +- 2 files changed, 29 insertions(+), 38 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index bd45032794..0b0f34aa29 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -241,18 +241,14 @@ public TransportChannelProvider withEndpoint(String endpoint) { return toBuilder().setEndpoint(endpoint).build(); } - /** - * @deprecated Please modify pool settings via {@link #toBuilder()} - */ + /** @deprecated Please modify pool settings via {@link #toBuilder()} */ @Deprecated @Override public boolean acceptsPoolSize() { return true; } - /** - * @deprecated Please modify pool settings via {@link #toBuilder()} - */ + /** @deprecated Please modify pool settings via {@link #toBuilder()} */ @Deprecated @Override public TransportChannelProvider withPoolSize(int size) { @@ -386,8 +382,14 @@ boolean isCredentialDirectPathCompatible() { @VisibleForTesting boolean isDirectPathBoundTokenEnabled() { - // FIXME - return isCredentialDirectPathCompatible() && credentials instanceof ComputeEngineCredentials; + if (allowedHardBoundTokenTypes == null || !(credentials instanceof ComputeEngineCredentials)) + return false; + for (HardBoundTokenTypes boundTokenTypes : allowedHardBoundTokenTypes) { + if (boundTokenTypes == HardBoundTokenTypes.ALTS) { + return true; + } + } + return false; } // DirectPath should only be used on Compute Engine. @@ -460,18 +462,17 @@ private ManagedChannel createSingleChannel() throws IOException { if (canUseDirectPath()) { CallCredentials altsCallCreds = null; if (isDirectPathBoundTokenEnabled()) { - ComputeEngineCredentials.Builder credsBuilder = - ((ComputeEngineCredentials) credentials).toBuilder(); - // We only set scopes and HTTP transport factory from the original credentials because - // only those are used in gRPC CallCredentials to fetch request metadata. - altsCallCreds = - MoreCallCredentials.from( - ComputeEngineCredentials.newBuilder() - .setScopes(credsBuilder.getScopes()) - .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) - .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) - .build()); - } + ComputeEngineCredentials.Builder credsBuilder = + ((ComputeEngineCredentials) credentials).toBuilder(); + // We only set scopes and HTTP transport factory from the original credentials because + // only those are used in gRPC CallCredentials to fetch request metadata. + altsCallCreds = + MoreCallCredentials.from( + ComputeEngineCredentials.newBuilder() + .setScopes(credsBuilder.getScopes()) + .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) + .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) + .build()); } CallCredentials callCreds = MoreCallCredentials.from(credentials); ChannelCredentials channelCreds = @@ -723,9 +724,7 @@ public Builder setExecutor(Executor executor) { return this; } - /** - * @deprecated Please use {@link #setExecutor(Executor)}. - */ + /** @deprecated Please use {@link #setExecutor(Executor)}. */ @Deprecated public Builder setExecutorProvider(ExecutorProvider executorProvider) { return setExecutor((Executor) executorProvider.getExecutor()); @@ -884,34 +883,26 @@ public Boolean getKeepAliveWithoutCalls() { return keepAliveWithoutCalls; } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public int getPoolSize() { return channelPoolSettings.getInitialChannelCount(); } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setPoolSize(int poolSize) { channelPoolSettings = ChannelPoolSettings.staticallySized(poolSize); return this; } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setChannelsPerCpu(double multiplier) { return setChannelsPerCpu(multiplier, 100); } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setChannelsPerCpu(double multiplier, int maxChannels) { Preconditions.checkArgument(multiplier > 0, "multiplier must be positive"); diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index c0bcd5beba..e78c7d64a3 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -39,6 +39,7 @@ import com.google.api.core.ApiFunction; import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider.Builder; +import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider.HardBoundTokenTypes; import com.google.api.gax.rpc.FixedHeaderProvider; import com.google.api.gax.rpc.HeaderProvider; import com.google.api.gax.rpc.TransportChannel; @@ -723,9 +724,6 @@ public void canUseDirectPath_happyPath() throws IOException { envProvider.getenv( InstantiatingGrpcChannelProvider.DIRECT_PATH_ENV_DISABLE_DIRECT_PATH)) .thenReturn("false"); - // FIXME: Remove the following statement. - Mockito.when(computeEngineCredentials.toBuilder()) - .thenReturn(ComputeEngineCredentials.newBuilder()); InstantiatingGrpcChannelProvider.Builder builder = InstantiatingGrpcChannelProvider.newBuilder() .setAttemptDirectPath(true) @@ -736,6 +734,7 @@ public void canUseDirectPath_happyPath() throws IOException { InstantiatingGrpcChannelProvider provider = new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); Truth.assertThat(provider.canUseDirectPath()).isTrue(); + Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isFalse(); // verify this info is passed correctly to transport channel TransportChannel transportChannel = provider.getTransportChannel(); @@ -758,6 +757,7 @@ public void canUseDirectPath_happyPathWithBoundToken() throws IOException { InstantiatingGrpcChannelProvider.newBuilder() .setAttemptDirectPath(true) .setCredentials(computeEngineCredentials) + .setAllowHardBoundTokenTypes(Collections.singletonList(HardBoundTokenTypes.ALTS)) .setEndpoint(DEFAULT_ENDPOINT) .setEnvProvider(envProvider) .setHeaderProvider(Mockito.mock(HeaderProvider.class)); From 0b734aee0fdd633ec2ce795722f00872fb331fe7 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Tue, 21 Jan 2025 23:16:52 +0000 Subject: [PATCH 06/14] one more test case --- .../InstantiatingGrpcChannelProviderTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index e78c7d64a3..dce31e9786 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -742,6 +742,28 @@ public void canUseDirectPath_happyPath() throws IOException { transportChannel.shutdownNow(); } + @Test + public void canUseDirectPath_boundTokenNotEnabledWithNonComputeCredentials() { + System.setProperty("os.name", "Linux"); + Credentials credentials = Mockito.mock(Credentials.class); + EnvironmentProvider envProvider = Mockito.mock(EnvironmentProvider.class); + Mockito.when( + envProvider.getenv( + InstantiatingGrpcChannelProvider.DIRECT_PATH_ENV_DISABLE_DIRECT_PATH)) + .thenReturn("false"); + InstantiatingGrpcChannelProvider.Builder builder = + InstantiatingGrpcChannelProvider.newBuilder() + .setAttemptDirectPath(true) + .setAllowHardBoundTokenTypes(Collections.singletonList(HardBoundTokenTypes.ALTS)) + .setCredentials(credentials) + .setEndpoint(DEFAULT_ENDPOINT) + .setEnvProvider(envProvider); + InstantiatingGrpcChannelProvider provider = + new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); + Truth.assertThat(provider.canUseDirectPath()).isFalse(); + Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isFalse(); + } + @Test public void canUseDirectPath_happyPathWithBoundToken() throws IOException { System.setProperty("os.name", "Linux"); From 64a439957b63dd40869d77630acad538ca4167bc Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Tue, 21 Jan 2025 23:18:47 +0000 Subject: [PATCH 07/14] tweak comment --- .../api/gax/grpc/InstantiatingGrpcChannelProviderTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index dce31e9786..e3b1981c40 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -772,7 +772,7 @@ public void canUseDirectPath_happyPathWithBoundToken() throws IOException { envProvider.getenv( InstantiatingGrpcChannelProvider.DIRECT_PATH_ENV_DISABLE_DIRECT_PATH)) .thenReturn("false"); - // verifies the credentials gets called and returns a non-null builder. + // verify the credentials gets called and returns a non-null builder. Mockito.when(computeEngineCredentials.toBuilder()) .thenReturn(ComputeEngineCredentials.newBuilder()); InstantiatingGrpcChannelProvider.Builder builder = From 7c0ec559d0d8d41fb02759bda6bdd537f72b54ee Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 31 Jan 2025 17:48:22 +0000 Subject: [PATCH 08/14] remove local snapshots in pom.xml --- gax-java/gax-grpc/pom.xml | 2 -- 1 file changed, 2 deletions(-) diff --git a/gax-java/gax-grpc/pom.xml b/gax-java/gax-grpc/pom.xml index ddece9052d..839314ce67 100644 --- a/gax-java/gax-grpc/pom.xml +++ b/gax-java/gax-grpc/pom.xml @@ -30,7 +30,6 @@ com.google.auth google-auth-library-credentials - 1.30.2-SNAPSHOT com.google.guava @@ -51,7 +50,6 @@ com.google.auth google-auth-library-oauth2-http - 1.30.2-SNAPSHOT io.grpc From 71f2e520e858864ce511ec915e1ea00c96917704 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Wed, 5 Feb 2025 21:35:43 +0000 Subject: [PATCH 09/14] wip --- .../InstantiatingGrpcChannelProvider.java | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index 5b412aad7b..127eaeb58a 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -139,6 +139,7 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP @Nullable private final Boolean keepAliveWithoutCalls; private final ChannelPoolSettings channelPoolSettings; @Nullable private final Credentials credentials; + @Nullable private final CallCredentials altsCallCredentials; @Nullable private final ChannelPrimer channelPrimer; @Nullable private final Boolean attemptDirectPath; @Nullable private final Boolean attemptDirectPathXds; @@ -277,14 +278,18 @@ public TransportChannelProvider withUseS2A(boolean useS2A) { return toBuilder().setUseS2A(useS2A).build(); } - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ + /** + * @deprecated Please modify pool settings via {@link #toBuilder()} + */ @Deprecated @Override public boolean acceptsPoolSize() { return true; } - /** @deprecated Please modify pool settings via {@link #toBuilder()} */ + /** + * @deprecated Please modify pool settings via {@link #toBuilder()} + */ @Deprecated @Override public TransportChannelProvider withPoolSize(int size) { @@ -420,12 +425,8 @@ boolean isCredentialDirectPathCompatible() { boolean isDirectPathBoundTokenEnabled() { if (allowedHardBoundTokenTypes == null || !(credentials instanceof ComputeEngineCredentials)) return false; - for (HardBoundTokenTypes boundTokenTypes : allowedHardBoundTokenTypes) { - if (boundTokenTypes == HardBoundTokenTypes.ALTS) { - return true; - } - } - return false; + return allowedHardBoundTokenTypes.stream() + .anyMatch(val -> val.equals(HardBoundTokenTypes.ALTS)); } // DirectPath should only be used on Compute Engine. @@ -575,7 +576,8 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext connection to S2A. LOG.log( Level.INFO, - "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); + "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a" + + " mtls address to reach S2A."); return createPlaintextToS2AChannelCredentials(plaintextAddress); } // Currently, MTLS to MDS is only available on GCE. See: @@ -593,7 +595,9 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext-to-S2A connection on error. LOG.log( Level.WARNING, - "Cannot establish an mTLS connection to S2A due to error creating MTLS to MDS TlsChannelCredentials credentials, falling back to plaintext connection to S2A: " + "Cannot establish an mTLS connection to S2A due to error creating MTLS to MDS" + + " TlsChannelCredentials credentials, falling back to plaintext connection to S2A:" + + " " + ignore.getMessage()); return createPlaintextToS2AChannelCredentials(plaintextAddress); } @@ -602,7 +606,8 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext-to-S2A connection if MTLS-MDS creds do not exist. LOG.log( Level.INFO, - "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist on filesystem, falling back to plaintext connection to S2A"); + "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist" + + " on filesystem, falling back to plaintext connection to S2A"); return createPlaintextToS2AChannelCredentials(plaintextAddress); } } @@ -628,17 +633,14 @@ private ManagedChannel createSingleChannel() throws IOException { if (canUseDirectPath()) { CallCredentials altsCallCreds = null; if (isDirectPathBoundTokenEnabled()) { - ComputeEngineCredentials.Builder credsBuilder = - ((ComputeEngineCredentials) credentials).toBuilder(); // We only set scopes and HTTP transport factory from the original credentials because // only those are used in gRPC CallCredentials to fetch request metadata. altsCallCreds = MoreCallCredentials.from( - ComputeEngineCredentials.newBuilder() - .setScopes(credsBuilder.getScopes()) - .setHttpTransportFactory(credsBuilder.getHttpTransportFactory()) - .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) - .build()); + ((ComputeEngineCredentials) credentials) + .toBuilder() + .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) + .build()); } CallCredentials callCreds = MoreCallCredentials.from(credentials); ChannelCredentials channelCreds = @@ -844,6 +846,7 @@ public static final class Builder { @Nullable private Boolean keepAliveWithoutCalls; @Nullable private ApiFunction channelConfigurator; @Nullable private Credentials credentials; + @Nullable private CallCredentials altsCallCredentials; @Nullable private ChannelPrimer channelPrimer; private ChannelPoolSettings channelPoolSettings; @Nullable private Boolean attemptDirectPath; @@ -873,6 +876,7 @@ private Builder(InstantiatingGrpcChannelProvider provider) { this.keepAliveWithoutCalls = provider.keepAliveWithoutCalls; this.channelConfigurator = provider.channelConfigurator; this.credentials = provider.credentials; + this.altsCallCredentials = provider.altsCallCredentials; this.channelPrimer = provider.channelPrimer; this.channelPoolSettings = provider.channelPoolSettings; this.attemptDirectPath = provider.attemptDirectPath; @@ -908,7 +912,9 @@ public Builder setExecutor(Executor executor) { return this; } - /** @deprecated Please use {@link #setExecutor(Executor)}. */ + /** + * @deprecated Please use {@link #setExecutor(Executor)}. + */ @Deprecated public Builder setExecutorProvider(ExecutorProvider executorProvider) { return setExecutor((Executor) executorProvider.getExecutor()); @@ -937,6 +943,7 @@ Builder setUseS2A(boolean useS2A) { this.useS2A = useS2A; return this; } + /* * Sets the allowed hard bound token types for this TransportChannelProvider. * @@ -1066,26 +1073,34 @@ public Boolean getKeepAliveWithoutCalls() { return keepAliveWithoutCalls; } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public int getPoolSize() { return channelPoolSettings.getInitialChannelCount(); } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setPoolSize(int poolSize) { channelPoolSettings = ChannelPoolSettings.staticallySized(poolSize); return this; } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setChannelsPerCpu(double multiplier) { return setChannelsPerCpu(multiplier, 100); } - /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ + /** + * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} + */ @Deprecated public Builder setChannelsPerCpu(double multiplier, int maxChannels) { Preconditions.checkArgument(multiplier > 0, "multiplier must be positive"); From 84c9be40b23eb99ab0683c05b47b590406892346 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Wed, 5 Feb 2025 21:56:56 +0000 Subject: [PATCH 10/14] move the alts call creds creation into the builder --- .../InstantiatingGrpcChannelProvider.java | 76 +++++++------------ .../InstantiatingGrpcChannelProviderTest.java | 6 +- 2 files changed, 32 insertions(+), 50 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index bb9bf2e326..f61afb2ca9 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -192,6 +192,7 @@ private InstantiatingGrpcChannelProvider(Builder builder) { this.channelPoolSettings = builder.channelPoolSettings; this.channelConfigurator = builder.channelConfigurator; this.credentials = builder.credentials; + this.altsCallCredentials = builder.altsCallCredentials; this.mtlsS2ACallCredentials = builder.mtlsS2ACallCredentials; this.channelPrimer = builder.channelPrimer; this.attemptDirectPath = builder.attemptDirectPath; @@ -282,18 +283,14 @@ public TransportChannelProvider withUseS2A(boolean useS2A) { return toBuilder().setUseS2A(useS2A).build(); } - /** - * @deprecated Please modify pool settings via {@link #toBuilder()} - */ + /** @deprecated Please modify pool settings via {@link #toBuilder()} */ @Deprecated @Override public boolean acceptsPoolSize() { return true; } - /** - * @deprecated Please modify pool settings via {@link #toBuilder()} - */ + /** @deprecated Please modify pool settings via {@link #toBuilder()} */ @Deprecated @Override public TransportChannelProvider withPoolSize(int size) { @@ -380,9 +377,8 @@ private void logDirectPathMisconfig() { Level.WARNING, "Env var " + DIRECT_PATH_ENV_ENABLE_XDS - + " was found and set to TRUE, but DirectPath was not enabled for this client. If" - + " this is intended for this client, please note that this is a misconfiguration" - + " and set the attemptDirectPath option as well."); + + " was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " + + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); } // Case 2: Direct Path xDS was enabled via Builder. Direct Path Traffic Director must be set // (enabled with `setAttemptDirectPath(true)`) along with xDS. @@ -390,9 +386,7 @@ private void logDirectPathMisconfig() { else if (isDirectPathXdsEnabledViaBuilderOption()) { LOG.log( Level.WARNING, - "DirectPath is misconfigured. The DirectPath XDS option was set, but the" - + " attemptDirectPath option was not. Please set both the attemptDirectPath and" - + " attemptDirectPathXds options."); + "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); } } else { // Case 3: credential is not correctly set @@ -425,14 +419,6 @@ boolean isCredentialDirectPathCompatible() { return credentials instanceof ComputeEngineCredentials; } - @VisibleForTesting - boolean isDirectPathBoundTokenEnabled() { - if (allowedHardBoundTokenTypes == null || !(credentials instanceof ComputeEngineCredentials)) - return false; - return allowedHardBoundTokenTypes.stream() - .anyMatch(val -> val.equals(HardBoundTokenTypes.ALTS)); - } - // DirectPath should only be used on Compute Engine. // Notice Windows is supported for now. @VisibleForTesting @@ -635,22 +621,11 @@ private ManagedChannel createSingleChannel() throws IOException { // Check DirectPath traffic. boolean useDirectPathXds = false; if (canUseDirectPath()) { - CallCredentials altsCallCreds = null; - if (isDirectPathBoundTokenEnabled()) { - // We only set scopes and HTTP transport factory from the original credentials because - // only those are used in gRPC CallCredentials to fetch request metadata. - altsCallCreds = - MoreCallCredentials.from( - ((ComputeEngineCredentials) credentials) - .toBuilder() - .setGoogleAuthTransport(ComputeEngineCredentials.GoogleAuthTransport.ALTS) - .build()); - } CallCredentials callCreds = MoreCallCredentials.from(credentials); ChannelCredentials channelCreds = GoogleDefaultChannelCredentials.newBuilder() .callCredentials(callCreds) - .altsCallCredentials(altsCallCreds) + .altsCallCredentials(altsCallCredentials) .build(); useDirectPathXds = isDirectPathXdsEnabled(); if (useDirectPathXds) { @@ -926,9 +901,7 @@ public Builder setExecutor(Executor executor) { return this; } - /** - * @deprecated Please use {@link #setExecutor(Executor)}. - */ + /** @deprecated Please use {@link #setExecutor(Executor)}. */ @Deprecated public Builder setExecutorProvider(ExecutorProvider executorProvider) { return setExecutor((Executor) executorProvider.getExecutor()); @@ -1090,34 +1063,26 @@ public Boolean getKeepAliveWithoutCalls() { return keepAliveWithoutCalls; } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public int getPoolSize() { return channelPoolSettings.getInitialChannelCount(); } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setPoolSize(int poolSize) { channelPoolSettings = ChannelPoolSettings.staticallySized(poolSize); return this; } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setChannelsPerCpu(double multiplier) { return setChannelsPerCpu(multiplier, 100); } - /** - * @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} - */ + /** @deprecated Please use {@link #setChannelPoolSettings(ChannelPoolSettings)} */ @Deprecated public Builder setChannelsPerCpu(double multiplier, int maxChannels) { Preconditions.checkArgument(multiplier > 0, "multiplier must be positive"); @@ -1220,6 +1185,18 @@ boolean isMtlsS2AHardBoundTokensEnabled() { .anyMatch(val -> val.equals(HardBoundTokenTypes.MTLS_S2A)); } + boolean isDirectPathBoundTokenEnabled() { + // If the list of allowed hard bound token types is empty or doesn't contain + // {@code HardBoundTokenTypes.ALTS}, the {@code credentials} are null or not of type + // {@code ComputeEngineCredentials} then DirectPath hard bound tokens should not be used. + // DirectPath hard bound tokens should only be used on ALTS channels. + if (allowedHardBoundTokenTypes == null + || this.credentials == null + || !(credentials instanceof ComputeEngineCredentials)) return false; + return allowedHardBoundTokenTypes.stream() + .anyMatch(val -> val.equals(HardBoundTokenTypes.ALTS)); + } + CallCredentials createHardBoundTokensCallCredentials( ComputeEngineCredentials.GoogleAuthTransport googleAuthTransport, ComputeEngineCredentials.BindingEnforcement bindingEnforcement) { @@ -1242,6 +1219,11 @@ public InstantiatingGrpcChannelProvider build() { ComputeEngineCredentials.GoogleAuthTransport.MTLS, ComputeEngineCredentials.BindingEnforcement.ON); } + if (isDirectPathBoundTokenEnabled()) { + this.altsCallCredentials = + createHardBoundTokensCallCredentials( + ComputeEngineCredentials.GoogleAuthTransport.ALTS, null); + } InstantiatingGrpcChannelProvider instantiatingGrpcChannelProvider = new InstantiatingGrpcChannelProvider(this); instantiatingGrpcChannelProvider.removeApiKeyCredentialDuplicateHeaders(); diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index 76e3b94dc0..a703e15ff2 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -740,10 +740,10 @@ public void canUseDirectPath_happyPath() throws IOException { .setEndpoint(DEFAULT_ENDPOINT) .setEnvProvider(envProvider) .setHeaderProvider(Mockito.mock(HeaderProvider.class)); + Truth.assertThat(builder.isDirectPathBoundTokenEnabled()).isFalse(); InstantiatingGrpcChannelProvider provider = new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); Truth.assertThat(provider.canUseDirectPath()).isTrue(); - Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isFalse(); // verify this info is passed correctly to transport channel TransportChannel transportChannel = provider.getTransportChannel(); @@ -767,10 +767,10 @@ public void canUseDirectPath_boundTokenNotEnabledWithNonComputeCredentials() { .setCredentials(credentials) .setEndpoint(DEFAULT_ENDPOINT) .setEnvProvider(envProvider); + Truth.assertThat(builder.isDirectPathBoundTokenEnabled()).isFalse(); InstantiatingGrpcChannelProvider provider = new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); Truth.assertThat(provider.canUseDirectPath()).isFalse(); - Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isFalse(); } @Test @@ -792,10 +792,10 @@ public void canUseDirectPath_happyPathWithBoundToken() throws IOException { .setEndpoint(DEFAULT_ENDPOINT) .setEnvProvider(envProvider) .setHeaderProvider(Mockito.mock(HeaderProvider.class)); + Truth.assertThat(builder.isDirectPathBoundTokenEnabled()).isTrue(); InstantiatingGrpcChannelProvider provider = new InstantiatingGrpcChannelProvider(builder, GCE_PRODUCTION_NAME_AFTER_2016); Truth.assertThat(provider.canUseDirectPath()).isTrue(); - Truth.assertThat(provider.isDirectPathBoundTokenEnabled()).isTrue(); // verify this info is passed correctly to transport channel TransportChannel transportChannel = provider.getTransportChannel(); From 2287136a0e3db04ed76f4fc2ab0ece4c0c8c153d Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Wed, 5 Feb 2025 21:59:41 +0000 Subject: [PATCH 11/14] revert some out-of-scope format changes --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 10 +++------- .../gax/grpc/InstantiatingGrpcChannelProviderTest.java | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index f61afb2ca9..90ec0f6597 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -566,8 +566,7 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext connection to S2A. LOG.log( Level.INFO, - "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a" - + " mtls address to reach S2A."); + "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); return createPlaintextToS2AChannelCredentials(plaintextAddress); } // Currently, MTLS to MDS is only available on GCE. See: @@ -585,9 +584,7 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext-to-S2A connection on error. LOG.log( Level.WARNING, - "Cannot establish an mTLS connection to S2A due to error creating MTLS to MDS" - + " TlsChannelCredentials credentials, falling back to plaintext connection to S2A:" - + " " + "Cannot establish an mTLS connection to S2A due to error creating MTLS to MDS TlsChannelCredentials credentials, falling back to plaintext connection to S2A: " + ignore.getMessage()); return createPlaintextToS2AChannelCredentials(plaintextAddress); } @@ -596,8 +593,7 @@ ChannelCredentials createS2ASecuredChannelCredentials() { // Fallback to plaintext-to-S2A connection if MTLS-MDS creds do not exist. LOG.log( Level.INFO, - "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist" - + " on filesystem, falling back to plaintext connection to S2A"); + "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist on filesystem, falling back to plaintext connection to S2A"); return createPlaintextToS2AChannelCredentials(plaintextAddress); } } diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index a703e15ff2..b138d09b5e 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -636,9 +636,7 @@ private void createAndCloseTransportChannel(InstantiatingGrpcChannelProvider pro createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "DirectPath is misconfigured. The DirectPath XDS option was set, but the" - + " attemptDirectPath option was not. Please set both the attemptDirectPath and" - + " attemptDirectPathXds options."); + "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } @@ -653,10 +651,8 @@ void testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSe createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath" - + " was not enabled for this client. If this is intended for this client, please" - + " note that this is a misconfiguration and set the attemptDirectPath option as" - + " well."); + "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " + + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } From 391829a3c06bcbddf33103522f953e5b85d6f44b Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Wed, 5 Feb 2025 22:03:20 +0000 Subject: [PATCH 12/14] format --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 2 ++ .../api/gax/grpc/InstantiatingGrpcChannelProviderTest.java | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index 90ec0f6597..307ae83928 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -618,6 +618,8 @@ private ManagedChannel createSingleChannel() throws IOException { boolean useDirectPathXds = false; if (canUseDirectPath()) { CallCredentials callCreds = MoreCallCredentials.from(credentials); + // altsCallCredentials may be null and will be correctly ignored by + // GoogleDefaultChannelCredentials. ChannelCredentials channelCreds = GoogleDefaultChannelCredentials.newBuilder() .callCredentials(callCreds) diff --git a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java index b138d09b5e..86203ce47d 100644 --- a/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java +++ b/gax-java/gax-grpc/src/test/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProviderTest.java @@ -636,7 +636,7 @@ private void createAndCloseTransportChannel(InstantiatingGrpcChannelProvider pro createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); + "DirectPath is misconfigured. The DirectPath XDS option was set, but the attemptDirectPath option was not. Please set both the attemptDirectPath and attemptDirectPathXds options."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } @@ -651,8 +651,8 @@ void testLogDirectPathMisconfig_AttemptDirectPathNotSetAndAttemptDirectPathXdsSe createAndCloseTransportChannel(provider); assertThat(logHandler.getAllMessages()) .contains( - "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " - + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); + "Env var GOOGLE_CLOUD_ENABLE_DIRECT_PATH_XDS was found and set to TRUE, but DirectPath was not enabled for this client. If this is intended for " + + "this client, please note that this is a misconfiguration and set the attemptDirectPath option as well."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); } From 80ee66104e36cb4614bb00d487d0334174f2b276 Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 7 Feb 2025 22:05:48 +0000 Subject: [PATCH 13/14] check emptiness --- .../google/api/gax/grpc/InstantiatingGrpcChannelProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index 307ae83928..bc730e7ae4 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -1188,7 +1188,7 @@ boolean isDirectPathBoundTokenEnabled() { // {@code HardBoundTokenTypes.ALTS}, the {@code credentials} are null or not of type // {@code ComputeEngineCredentials} then DirectPath hard bound tokens should not be used. // DirectPath hard bound tokens should only be used on ALTS channels. - if (allowedHardBoundTokenTypes == null + if (allowedHardBoundTokenTypes.isEmpty() || this.credentials == null || !(credentials instanceof ComputeEngineCredentials)) return false; return allowedHardBoundTokenTypes.stream() From beefd822af618a3fbcc926e022c9ffda40a5adce Mon Sep 17 00:00:00 2001 From: Luwei Ge Date: Fri, 7 Feb 2025 22:50:36 +0000 Subject: [PATCH 14/14] comment --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java index bc730e7ae4..b75ba746f9 100644 --- a/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java +++ b/gax-java/gax-grpc/src/main/java/com/google/api/gax/grpc/InstantiatingGrpcChannelProvider.java @@ -618,8 +618,9 @@ private ManagedChannel createSingleChannel() throws IOException { boolean useDirectPathXds = false; if (canUseDirectPath()) { CallCredentials callCreds = MoreCallCredentials.from(credentials); - // altsCallCredentials may be null and will be correctly ignored by - // GoogleDefaultChannelCredentials. + // altsCallCredentials may be null and GoogleDefaultChannelCredentials + // will solely use callCreds. Otherwise it uses altsCallCredentials + // for DirectPath connections and callCreds for CloudPath fallbacks. ChannelCredentials channelCreds = GoogleDefaultChannelCredentials.newBuilder() .callCredentials(callCreds)