From 8ddbe44ef692ac16331dcb22f0ae6174c60e9da2 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 14 Nov 2025 09:33:25 -0800 Subject: [PATCH 01/17] Single S2AChannelCredentials + use AdvancedTls. --- .../InstantiatingGrpcChannelProvider.java | 101 +++++++++++------- 1 file changed, 63 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 cc93542f17..5b6d22adb3 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 @@ -67,6 +67,8 @@ import io.grpc.TlsChannelCredentials; import io.grpc.alts.GoogleDefaultChannelCredentials; import io.grpc.auth.MoreCallCredentials; +import io.grpc.util.AdvancedTlsX509KeyManager; +import io.grpc.util.AdvancedTlsX509TrustManager; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; @@ -78,6 +80,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -161,6 +164,8 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP @Nullable private final ApiFunction channelConfigurator; + private static volatile ChannelCredentials s2aChannelCredentialsObject; + /* * Experimental feature * @@ -556,13 +561,19 @@ ChannelCredentials buildS2AChannelCredentials( */ @VisibleForTesting ChannelCredentials createMtlsToS2AChannelCredentials( - File trustBundle, File privateKey, File certChain) throws IOException { + File trustBundle, File privateKey, File certChain) + throws IOException, GeneralSecurityException { if (trustBundle == null || privateKey == null || certChain == null) { return null; } + AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager(); + keyManager.updateIdentityCredentials(certChain, privateKey); + AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder().build(); + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, executor); return TlsChannelCredentials.newBuilder() - .keyManager(privateKey, certChain) - .trustManager(trustBundle) + .keyManager(keyManager) + .trustManager(trustManager) .build(); } @@ -595,43 +606,57 @@ ChannelCredentials createPlaintextToS2AChannelCredentials(String plaintextAddres * @return {@link ChannelCredentials} configured to use S2A to create mTLS connection. */ ChannelCredentials createS2ASecuredChannelCredentials() { - SecureSessionAgentConfig config = s2aConfigProvider.getConfig(); - String plaintextAddress = config.getPlaintextAddress(); - String mtlsAddress = config.getMtlsAddress(); - if (Strings.isNullOrEmpty(mtlsAddress)) { - // 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."); - return createPlaintextToS2AChannelCredentials(plaintextAddress); - } - // Currently, MTLS to MDS is only available on GCE. See: - // https://cloud.google.com/compute/docs/metadata/overview#https-mds - // Try to load MTLS-MDS creds. - File rootFile = new File(MTLS_MDS_ROOT_PATH); - File certKeyFile = new File(MTLS_MDS_CERT_CHAIN_AND_KEY_PATH); - if (rootFile.isFile() && certKeyFile.isFile()) { - // Try to connect to S2A using mTLS. - ChannelCredentials mtlsToS2AChannelCredentials = null; - try { - mtlsToS2AChannelCredentials = - createMtlsToS2AChannelCredentials(rootFile, certKeyFile, certKeyFile); - } catch (IOException ignore) { - // 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: " - + ignore.getMessage()); - return createPlaintextToS2AChannelCredentials(plaintextAddress); + if (s2aChannelCredentialsObject == null) { + synchronized (InstantiatingGrpcChannelProvider.class) { + if (s2aChannelCredentialsObject == null) { + SecureSessionAgentConfig config = s2aConfigProvider.getConfig(); + String plaintextAddress = config.getPlaintextAddress(); + String mtlsAddress = config.getMtlsAddress(); + if (Strings.isNullOrEmpty(mtlsAddress)) { + // 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."); + s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentialsObject; + } + // Currently, MTLS to MDS is only available on GCE. See: + // https://cloud.google.com/compute/docs/metadata/overview#https-mds + // Try to load MTLS-MDS creds. + File rootFile = new File(MTLS_MDS_ROOT_PATH); + File certKeyFile = new File(MTLS_MDS_CERT_CHAIN_AND_KEY_PATH); + if (rootFile.isFile() && certKeyFile.isFile()) { + // Try to connect to S2A using mTLS. + ChannelCredentials mtlsToS2AChannelCredentials = null; + try { + mtlsToS2AChannelCredentials = + createMtlsToS2AChannelCredentials(rootFile, certKeyFile, certKeyFile); + } catch (IOException | GeneralSecurityException ignore) { + // 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: " + + ignore.getMessage()); + s2aChannelCredentialsObject = + createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentialsObject; + } + s2aChannelCredentialsObject = + buildS2AChannelCredentials(mtlsAddress, mtlsToS2AChannelCredentials); + return s2aChannelCredentialsObject; + } else { + // 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"); + s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentialsObject; + } + } } - return buildS2AChannelCredentials(mtlsAddress, mtlsToS2AChannelCredentials); - } else { - // 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"); - return createPlaintextToS2AChannelCredentials(plaintextAddress); } + return s2aChannelCredentialsObject; } private ManagedChannel createSingleChannel() throws IOException { From e35914fb7654d806a987a2bd849dda3add7a2a1e Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 14 Nov 2025 12:25:45 -0800 Subject: [PATCH 02/17] add comment. --- .../google/api/gax/grpc/InstantiatingGrpcChannelProvider.java | 2 ++ 1 file changed, 2 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 5b6d22adb3..85bec82298 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 @@ -164,6 +164,8 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP @Nullable private final ApiFunction channelConfigurator; + // This is initialized once for the lifetime of the application. This enables re-using + // channels to S2A. private static volatile ChannelCredentials s2aChannelCredentialsObject; /* From 217737b246d2a89a26234422700bb6aec45b2452 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 5 Dec 2025 13:44:14 -0800 Subject: [PATCH 03/17] address comments. --- .../grpc/InstantiatingGrpcChannelProvider.java | 17 +++++++++++++++-- 1 file changed, 15 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 85bec82298..1ca86974ad 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 @@ -569,9 +569,22 @@ ChannelCredentials createMtlsToS2AChannelCredentials( return null; } AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager(); - keyManager.updateIdentityCredentials(certChain, privateKey); + ScheduledExecutorService keyManagerExecutor = Executors.newSingleThreadScheduledExecutor( + r -> { + Thread t = new Thread(r, "s2a-key-manager-updater"); + t.setDaemon(true); + return t; + }); + + keyManager.updateIdentityCredentials(certChain, privateKey, 1, TimeUnit.HOURS, keyManagerExecutor); AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder().build(); - ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + ScheduledExecutorService trustManagerExecutor = Executors.newSingleThreadScheduledExecutor( + r -> { + Thread t = new Thread(r, "s2a-trust-manager-updater"); + t.setDaemon(true); + return t; + }); + trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, executor); return TlsChannelCredentials.newBuilder() .keyManager(keyManager) From 5f52e878a67c060d25384d6946c9498400428ed9 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 5 Dec 2025 13:46:11 -0800 Subject: [PATCH 04/17] correct variable name. --- .../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 1ca86974ad..cbc19a3ca8 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 @@ -585,7 +585,7 @@ ChannelCredentials createMtlsToS2AChannelCredentials( return t; }); - trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, executor); + trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, trustManagerExecutor); return TlsChannelCredentials.newBuilder() .keyManager(keyManager) .trustManager(trustManager) From 953e1a03dfd9af6f0b6521c4219f8256bdaeaa75 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Fri, 5 Dec 2025 14:12:57 -0800 Subject: [PATCH 05/17] move adv tls changes to another PR. --- .../InstantiatingGrpcChannelProvider.java | 28 ++----------------- 1 file changed, 3 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 cbc19a3ca8..b77fbbb346 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 @@ -67,8 +67,6 @@ import io.grpc.TlsChannelCredentials; import io.grpc.alts.GoogleDefaultChannelCredentials; import io.grpc.auth.MoreCallCredentials; -import io.grpc.util.AdvancedTlsX509KeyManager; -import io.grpc.util.AdvancedTlsX509TrustManager; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; @@ -80,7 +78,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.Executor; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @@ -563,32 +560,13 @@ ChannelCredentials buildS2AChannelCredentials( */ @VisibleForTesting ChannelCredentials createMtlsToS2AChannelCredentials( - File trustBundle, File privateKey, File certChain) - throws IOException, GeneralSecurityException { + File trustBundle, File privateKey, File certChain) throws IOException { if (trustBundle == null || privateKey == null || certChain == null) { return null; } - AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager(); - ScheduledExecutorService keyManagerExecutor = Executors.newSingleThreadScheduledExecutor( - r -> { - Thread t = new Thread(r, "s2a-key-manager-updater"); - t.setDaemon(true); - return t; - }); - - keyManager.updateIdentityCredentials(certChain, privateKey, 1, TimeUnit.HOURS, keyManagerExecutor); - AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder().build(); - ScheduledExecutorService trustManagerExecutor = Executors.newSingleThreadScheduledExecutor( - r -> { - Thread t = new Thread(r, "s2a-trust-manager-updater"); - t.setDaemon(true); - return t; - }); - - trustManager.updateTrustCredentials(trustBundle, 1, TimeUnit.HOURS, trustManagerExecutor); return TlsChannelCredentials.newBuilder() - .keyManager(keyManager) - .trustManager(trustManager) + .keyManager(privateKey, certChain) + .trustManager(trustBundle) .build(); } From 53b8b840bee71c99a75038330687a974f12f1643 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Mon, 5 Jan 2026 06:38:26 -0800 Subject: [PATCH 06/17] reduce nesting. --- .../InstantiatingGrpcChannelProvider.java | 83 ++++++++++--------- 1 file changed, 42 insertions(+), 41 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 b77fbbb346..980e2bf6ca 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 @@ -601,51 +601,52 @@ ChannelCredentials createPlaintextToS2AChannelCredentials(String plaintextAddres ChannelCredentials createS2ASecuredChannelCredentials() { if (s2aChannelCredentialsObject == null) { synchronized (InstantiatingGrpcChannelProvider.class) { - if (s2aChannelCredentialsObject == null) { - SecureSessionAgentConfig config = s2aConfigProvider.getConfig(); - String plaintextAddress = config.getPlaintextAddress(); - String mtlsAddress = config.getMtlsAddress(); - if (Strings.isNullOrEmpty(mtlsAddress)) { - // Fallback to plaintext connection to S2A. + if (s2aChannelCredentialsObject != null) { + return s2aChannelCredentialsObject; + } + SecureSessionAgentConfig config = s2aConfigProvider.getConfig(); + String plaintextAddress = config.getPlaintextAddress(); + String mtlsAddress = config.getMtlsAddress(); + if (Strings.isNullOrEmpty(mtlsAddress)) { + // 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."); + s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentialsObject; + } + // Currently, MTLS to MDS is only available on GCE. See: + // https://cloud.google.com/compute/docs/metadata/overview#https-mds + // Try to load MTLS-MDS creds. + File rootFile = new File(MTLS_MDS_ROOT_PATH); + File certKeyFile = new File(MTLS_MDS_CERT_CHAIN_AND_KEY_PATH); + if (rootFile.isFile() && certKeyFile.isFile()) { + // Try to connect to S2A using mTLS. + ChannelCredentials mtlsToS2AChannelCredentials = null; + try { + mtlsToS2AChannelCredentials = + createMtlsToS2AChannelCredentials(rootFile, certKeyFile, certKeyFile); + } catch (IOException | GeneralSecurityException ignore) { + // Fallback to plaintext-to-S2A connection on error. LOG.log( - Level.INFO, - "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); - s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); - return s2aChannelCredentialsObject; - } - // Currently, MTLS to MDS is only available on GCE. See: - // https://cloud.google.com/compute/docs/metadata/overview#https-mds - // Try to load MTLS-MDS creds. - File rootFile = new File(MTLS_MDS_ROOT_PATH); - File certKeyFile = new File(MTLS_MDS_CERT_CHAIN_AND_KEY_PATH); - if (rootFile.isFile() && certKeyFile.isFile()) { - // Try to connect to S2A using mTLS. - ChannelCredentials mtlsToS2AChannelCredentials = null; - try { - mtlsToS2AChannelCredentials = - createMtlsToS2AChannelCredentials(rootFile, certKeyFile, certKeyFile); - } catch (IOException | GeneralSecurityException ignore) { - // 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: " - + ignore.getMessage()); - s2aChannelCredentialsObject = - createPlaintextToS2AChannelCredentials(plaintextAddress); - return s2aChannelCredentialsObject; - } + 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: " + + ignore.getMessage()); s2aChannelCredentialsObject = - buildS2AChannelCredentials(mtlsAddress, mtlsToS2AChannelCredentials); - return s2aChannelCredentialsObject; - } else { - // 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"); - s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); + createPlaintextToS2AChannelCredentials(plaintextAddress); return s2aChannelCredentialsObject; } + s2aChannelCredentialsObject = + buildS2AChannelCredentials(mtlsAddress, mtlsToS2AChannelCredentials); + return s2aChannelCredentialsObject; + } else { + // 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"); + s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentialsObject; } } } From 6b047aee4be865c7b3d703f9dfe2e5c830c5d634 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Mon, 5 Jan 2026 07:14:38 -0800 Subject: [PATCH 07/17] add comment. --- .../google/api/gax/grpc/InstantiatingGrpcChannelProvider.java | 3 +++ 1 file changed, 3 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 980e2bf6ca..47d9284084 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 @@ -600,6 +600,9 @@ ChannelCredentials createPlaintextToS2AChannelCredentials(String plaintextAddres */ ChannelCredentials createS2ASecuredChannelCredentials() { if (s2aChannelCredentialsObject == null) { + // s2aChannelCredentialsObject is initialized once and shared by all instances of the class. + // To prevent a race on intialization, the object initilization is synchronizaed on the class + // object. synchronized (InstantiatingGrpcChannelProvider.class) { if (s2aChannelCredentialsObject != null) { return s2aChannelCredentialsObject; From 075db93c1cff36cf87a871c2f5e0268425b4f7c7 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Mon, 5 Jan 2026 07:21:11 -0800 Subject: [PATCH 08/17] don't catch exception that's not thrown. --- .../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 47d9284084..5c48158835 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 @@ -629,7 +629,7 @@ ChannelCredentials createS2ASecuredChannelCredentials() { try { mtlsToS2AChannelCredentials = createMtlsToS2AChannelCredentials(rootFile, certKeyFile, certKeyFile); - } catch (IOException | GeneralSecurityException ignore) { + } catch (IOException ignore) { // Fallback to plaintext-to-S2A connection on error. LOG.log( Level.WARNING, From 3266899de056c34137dd3a2e0fb3d1ee65690d01 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Mon, 5 Jan 2026 16:35:56 -0800 Subject: [PATCH 09/17] reset. --- .../grpc/InstantiatingGrpcChannelProvider.java | 15 ++++++++++++++- .../InstantiatingGrpcChannelProviderTest.java | 3 +++ 2 files changed, 17 insertions(+), 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 5c48158835..259eab3245 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 @@ -165,6 +165,19 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP // channels to S2A. private static volatile ChannelCredentials s2aChannelCredentialsObject; + /** + * Resets the s2aChannelCredentialsObject of the {@link InstantiatingGrpcChannelProvider} class + * for testing purposes. + * + *

This should only be called from tests. + */ + @VisibleForTesting + public static void resetS2AChannelCredentialsObjectForTests() { + synchronized (InstantiatingGrpcChannelProvider.class) { + s2aChannelCredentialsObject = null; + } + } + /* * Experimental feature * @@ -601,7 +614,7 @@ ChannelCredentials createPlaintextToS2AChannelCredentials(String plaintextAddres ChannelCredentials createS2ASecuredChannelCredentials() { if (s2aChannelCredentialsObject == null) { // s2aChannelCredentialsObject is initialized once and shared by all instances of the class. - // To prevent a race on intialization, the object initilization is synchronizaed on the class + // To prevent a race on initialization, the object initialization is synchronized on the class // object. synchronized (InstantiatingGrpcChannelProvider.class) { if (s2aChannelCredentialsObject != null) { 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 5c4dfca8c4..0934a5464a 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 @@ -1155,6 +1155,7 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .setS2AConfigProvider(s2aConfigProvider) .build(); assertThat(provider.createS2ASecuredChannelCredentials()).isNull(); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); } @Test @@ -1175,6 +1176,7 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .contains( "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); } @Test @@ -1197,6 +1199,7 @@ void createS2ASecuredChannelCredentials_returnsPlaintextToS2AS2AChannelCredentia .contains( "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist on filesystem, falling back to plaintext connection to S2A"); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); } @Test From 5aba3fcb27c7321470b6c31d8f708b77cf57ab5e Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Tue, 6 Jan 2026 14:07:26 -0800 Subject: [PATCH 10/17] format. --- .../google/api/gax/grpc/InstantiatingGrpcChannelProvider.java | 3 +-- 1 file changed, 1 insertion(+), 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 259eab3245..989a252464 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 @@ -648,8 +648,7 @@ ChannelCredentials createS2ASecuredChannelCredentials() { 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: " + ignore.getMessage()); - s2aChannelCredentialsObject = - createPlaintextToS2AChannelCredentials(plaintextAddress); + s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); return s2aChannelCredentialsObject; } s2aChannelCredentialsObject = From c7536e6f7dfb58e5a9ed135f357298ba70b0ac3e Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Wed, 7 Jan 2026 13:06:41 -0800 Subject: [PATCH 11/17] package private. --- .../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 989a252464..742d744c2c 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 @@ -172,7 +172,7 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP *

This should only be called from tests. */ @VisibleForTesting - public static void resetS2AChannelCredentialsObjectForTests() { + static void resetS2AChannelCredentialsObjectForTests() { synchronized (InstantiatingGrpcChannelProvider.class) { s2aChannelCredentialsObject = null; } From 71335fcbb8cecbe45b35ad894699da72709b4f67 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Wed, 7 Jan 2026 13:16:57 -0800 Subject: [PATCH 12/17] rename. --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 2 +- .../api/gax/grpc/InstantiatingGrpcChannelProviderTest.java | 6 +++--- 2 files changed, 4 insertions(+), 4 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 742d744c2c..6a50b60c8d 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 @@ -172,7 +172,7 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP *

This should only be called from tests. */ @VisibleForTesting - static void resetS2AChannelCredentialsObjectForTests() { + static void resetS2AChannelCredentials() { synchronized (InstantiatingGrpcChannelProvider.class) { s2aChannelCredentialsObject = null; } 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 0934a5464a..eb06be6d09 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 @@ -1155,7 +1155,7 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .setS2AConfigProvider(s2aConfigProvider) .build(); assertThat(provider.createS2ASecuredChannelCredentials()).isNull(); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test @@ -1176,7 +1176,7 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .contains( "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test @@ -1199,7 +1199,7 @@ void createS2ASecuredChannelCredentials_returnsPlaintextToS2AS2AChannelCredentia .contains( "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist on filesystem, falling back to plaintext connection to S2A"); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentialsObjectForTests(); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test From 77303c985ecbb0eba1d4adf5631de5538af58d4c Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Wed, 7 Jan 2026 16:21:58 -0800 Subject: [PATCH 13/17] rename s2aChannelCredentials. --- .../InstantiatingGrpcChannelProvider.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 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 6a50b60c8d..2309e21c8b 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 @@ -163,18 +163,18 @@ public final class InstantiatingGrpcChannelProvider implements TransportChannelP // This is initialized once for the lifetime of the application. This enables re-using // channels to S2A. - private static volatile ChannelCredentials s2aChannelCredentialsObject; + private static volatile ChannelCredentials s2aChannelCredentials; /** - * Resets the s2aChannelCredentialsObject of the {@link InstantiatingGrpcChannelProvider} class - * for testing purposes. + * Resets the s2aChannelCredentials of the {@link InstantiatingGrpcChannelProvider} class for + * testing purposes. * *

This should only be called from tests. */ @VisibleForTesting static void resetS2AChannelCredentials() { synchronized (InstantiatingGrpcChannelProvider.class) { - s2aChannelCredentialsObject = null; + s2aChannelCredentials = null; } } @@ -612,13 +612,13 @@ ChannelCredentials createPlaintextToS2AChannelCredentials(String plaintextAddres * @return {@link ChannelCredentials} configured to use S2A to create mTLS connection. */ ChannelCredentials createS2ASecuredChannelCredentials() { - if (s2aChannelCredentialsObject == null) { - // s2aChannelCredentialsObject is initialized once and shared by all instances of the class. + if (s2aChannelCredentials == null) { + // s2aChannelCredentials is initialized once and shared by all instances of the class. // To prevent a race on initialization, the object initialization is synchronized on the class // object. synchronized (InstantiatingGrpcChannelProvider.class) { - if (s2aChannelCredentialsObject != null) { - return s2aChannelCredentialsObject; + if (s2aChannelCredentials != null) { + return s2aChannelCredentials; } SecureSessionAgentConfig config = s2aConfigProvider.getConfig(); String plaintextAddress = config.getPlaintextAddress(); @@ -628,8 +628,8 @@ ChannelCredentials createS2ASecuredChannelCredentials() { LOG.log( Level.INFO, "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); - s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); - return s2aChannelCredentialsObject; + s2aChannelCredentials = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentials; } // Currently, MTLS to MDS is only available on GCE. See: // https://cloud.google.com/compute/docs/metadata/overview#https-mds @@ -648,24 +648,24 @@ ChannelCredentials createS2ASecuredChannelCredentials() { 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: " + ignore.getMessage()); - s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); - return s2aChannelCredentialsObject; + s2aChannelCredentials = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentials; } - s2aChannelCredentialsObject = + s2aChannelCredentials = buildS2AChannelCredentials(mtlsAddress, mtlsToS2AChannelCredentials); - return s2aChannelCredentialsObject; + return s2aChannelCredentials; } else { // 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"); - s2aChannelCredentialsObject = createPlaintextToS2AChannelCredentials(plaintextAddress); - return s2aChannelCredentialsObject; + s2aChannelCredentials = createPlaintextToS2AChannelCredentials(plaintextAddress); + return s2aChannelCredentials; } } } - return s2aChannelCredentialsObject; + return s2aChannelCredentials; } private ManagedChannel createSingleChannel() throws IOException { From 8930b0682a7f45aeb39e3b0615468ad925a22508 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Wed, 7 Jan 2026 16:31:26 -0800 Subject: [PATCH 14/17] add test. --- .../InstantiatingGrpcChannelProviderTest.java | 21 +++++++++++++++++++ 1 file changed, 21 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 eb06be6d09..f5396d27a0 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 @@ -1179,6 +1179,27 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } + @Test + void + createTwoS2ASecuredChannelCredentials_mtlsS2AAddressNull_returnsSamePlaintextToS2AS2AChannelCredentials() { + SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); + SecureSessionAgentConfig config = + SecureSessionAgentConfig.createBuilder().setPlaintextAddress("localhost:8080").build(); + Mockito.when(s2aConfigProvider.getConfig()).thenReturn(config); + InstantiatingGrpcChannelProvider provider = + InstantiatingGrpcChannelProvider.newBuilder() + .setS2AConfigProvider(s2aConfigProvider) + .build(); + assertThat(provider.createS2ASecuredChannelCredentials()).isNotNull(); + InstantiatingGrpcChannelProvider provider2 = + InstantiatingGrpcChannelProvider.newBuilder() + .setS2AConfigProvider(s2aConfigProvider) + .build(); + assertThat(provider2.createS2ASecuredChannelCredentials()).isNotNull(); + assertEquals(provider, provider2); + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); + } + @Test void createS2ASecuredChannelCredentials_returnsPlaintextToS2AS2AChannelCredentials() { SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); From d0e0255a4122fb566a32c09267d00efe986a4861 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 8 Jan 2026 14:50:42 -0800 Subject: [PATCH 15/17] move reset to front. --- .../gax/grpc/InstantiatingGrpcChannelProviderTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 f5396d27a0..6dea4d6b28 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 @@ -1147,6 +1147,7 @@ void createMtlsToS2AChannelCredentials_success() throws IOException { @Test void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); SecureSessionAgentConfig config = SecureSessionAgentConfig.createBuilder().build(); Mockito.when(s2aConfigProvider.getConfig()).thenReturn(config); @@ -1155,12 +1156,12 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .setS2AConfigProvider(s2aConfigProvider) .build(); assertThat(provider.createS2ASecuredChannelCredentials()).isNull(); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test void createS2ASecuredChannelCredentials_mtlsS2AAddressNull_returnsPlaintextToS2AS2AChannelCredentials() { + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); SecureSessionAgentConfig config = SecureSessionAgentConfig.createBuilder().setPlaintextAddress("localhost:8080").build(); @@ -1176,12 +1177,12 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .contains( "Cannot establish an mTLS connection to S2A because autoconfig endpoint did not return a mtls address to reach S2A."); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test void createTwoS2ASecuredChannelCredentials_mtlsS2AAddressNull_returnsSamePlaintextToS2AS2AChannelCredentials() { + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); SecureSessionAgentConfig config = SecureSessionAgentConfig.createBuilder().setPlaintextAddress("localhost:8080").build(); @@ -1197,11 +1198,11 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .build(); assertThat(provider2.createS2ASecuredChannelCredentials()).isNotNull(); assertEquals(provider, provider2); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test void createS2ASecuredChannelCredentials_returnsPlaintextToS2AS2AChannelCredentials() { + InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); SecureSessionAgent s2aConfigProvider = Mockito.mock(SecureSessionAgent.class); SecureSessionAgentConfig config = SecureSessionAgentConfig.createBuilder() @@ -1220,7 +1221,6 @@ void createS2ASecuredChannelCredentials_returnsPlaintextToS2AS2AChannelCredentia .contains( "Cannot establish an mTLS connection to S2A because MTLS to MDS credentials do not exist on filesystem, falling back to plaintext connection to S2A"); InstantiatingGrpcChannelProvider.LOG.removeHandler(logHandler); - InstantiatingGrpcChannelProvider.resetS2AChannelCredentials(); } @Test From 3d9f050f8e8cf9079390f07e24652f2b1196f842 Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 8 Jan 2026 14:55:13 -0800 Subject: [PATCH 16/17] compare channel creds. --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 5 +++++ .../api/gax/grpc/InstantiatingGrpcChannelProviderTest.java | 2 +- 2 files changed, 6 insertions(+), 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 2309e21c8b..b62dd08557 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 @@ -178,6 +178,11 @@ static void resetS2AChannelCredentials() { } } + @VisibleForTesting + static ChannelCredentials getS2AChannelCredentials() { + return s2aChannelCredentials; + } + /* * Experimental feature * 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 6dea4d6b28..a5af1f626e 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 @@ -1197,7 +1197,7 @@ void createS2ASecuredChannelCredentials_bothS2AAddressesNull_returnsNull() { .setS2AConfigProvider(s2aConfigProvider) .build(); assertThat(provider2.createS2ASecuredChannelCredentials()).isNotNull(); - assertEquals(provider, provider2); + assertEquals(provider.getS2AChannelCredentials(), provider2.getS2AChannelCredentials()); } @Test From 43958b347957d368255324c0466605940a7e4ded Mon Sep 17 00:00:00 2001 From: Riya Mehta Date: Thu, 8 Jan 2026 15:34:58 -0800 Subject: [PATCH 17/17] format. --- .../api/gax/grpc/InstantiatingGrpcChannelProvider.java | 6 ++++++ 1 file changed, 6 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 b62dd08557..5d31f830f2 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 @@ -178,6 +178,12 @@ static void resetS2AChannelCredentials() { } } + /** + * Returns the s2aChannelCredentials of the {@link InstantiatingGrpcChannelProvider} class for + * testing purposes. + * + *

This should only be called from tests. + */ @VisibleForTesting static ChannelCredentials getS2AChannelCredentials() { return s2aChannelCredentials;