From ac57eedd5345754a86c886502f05b5c1e84654f2 Mon Sep 17 00:00:00 2001 From: becomeStar Date: Sun, 25 Jan 2026 12:43:57 +0900 Subject: [PATCH] xds: Remove isXdsSniEnabled flag and update xDS SNI tests Remove the isXdsSniEnabled environment variable guard and the legacy logic that falls back to the channel authority for SNI. This aligns the implementation with gRFC A101, ensuring no SNI is sent if it is not explicitly determined by xDS configurations. Update the test suite by removing the isXdsSniEnabled flag and deleting test case that specifically verified behavior when the flag was set to false. Additionally, add a new test case to verify that SNI is omitted when none of the A101 conditions are met, ensuring the SNI field is not sent in the TLS handshake. Ref #11784 --- .../security/SecurityProtocolNegotiators.java | 22 +- .../security/trust/CertificateUtils.java | 1 - .../security/trust/XdsX509TrustManager.java | 2 +- .../grpc/xds/XdsSecurityClientServerTest.java | 7 - .../SecurityProtocolNegotiatorsTest.java | 297 ++++++++---------- 5 files changed, 143 insertions(+), 186 deletions(-) diff --git a/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java b/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java index 37259afa1a9..09a70498c0b 100644 --- a/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java +++ b/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java @@ -215,23 +215,21 @@ public void handlerAdded(ChannelHandlerContext ctx) throws Exception { this.sslContextProviderSupplier = sslContextProviderSupplier; EnvoyServerProtoData.BaseTlsContext tlsContext = sslContextProviderSupplier.getTlsContext(); UpstreamTlsContext upstreamTlsContext = ((UpstreamTlsContext) tlsContext); - if (CertificateUtils.isXdsSniEnabled) { - String sniToUse = upstreamTlsContext.getAutoHostSni() - && !Strings.isNullOrEmpty(endpointHostname) - ? endpointHostname : upstreamTlsContext.getSni(); - if (sniToUse.isEmpty()) { - if (CertificateUtils.useChannelAuthorityIfNoSniApplicable) { - sniToUse = grpcHandler.getAuthority(); - } - autoSniSanValidationDoesNotApply = true; + + String sniToUse = upstreamTlsContext.getAutoHostSni() + && !Strings.isNullOrEmpty(endpointHostname) + ? endpointHostname : upstreamTlsContext.getSni(); + if (sniToUse.isEmpty()) { + if (CertificateUtils.useChannelAuthorityIfNoSniApplicable) { + sniToUse = grpcHandler.getAuthority(); } else { - autoSniSanValidationDoesNotApply = false; + sniToUse = ""; } - sni = sniToUse; + autoSniSanValidationDoesNotApply = true; } else { - sni = grpcHandler.getAuthority(); autoSniSanValidationDoesNotApply = false; } + sni = sniToUse; } @VisibleForTesting diff --git a/xds/src/main/java/io/grpc/xds/internal/security/trust/CertificateUtils.java b/xds/src/main/java/io/grpc/xds/internal/security/trust/CertificateUtils.java index ad030143f62..41a3980c123 100644 --- a/xds/src/main/java/io/grpc/xds/internal/security/trust/CertificateUtils.java +++ b/xds/src/main/java/io/grpc/xds/internal/security/trust/CertificateUtils.java @@ -30,7 +30,6 @@ * Contains certificate utility method(s). */ public final class CertificateUtils { - public static boolean isXdsSniEnabled = GrpcUtil.getFlag("GRPC_EXPERIMENTAL_XDS_SNI", true); public static boolean useChannelAuthorityIfNoSniApplicable = GrpcUtil.getFlag("GRPC_USE_CHANNEL_AUTHORITY_IF_NO_SNI_APPLICABLE", false); diff --git a/xds/src/main/java/io/grpc/xds/internal/security/trust/XdsX509TrustManager.java b/xds/src/main/java/io/grpc/xds/internal/security/trust/XdsX509TrustManager.java index e8e7243ce0e..01f25dda6c7 100644 --- a/xds/src/main/java/io/grpc/xds/internal/security/trust/XdsX509TrustManager.java +++ b/xds/src/main/java/io/grpc/xds/internal/security/trust/XdsX509TrustManager.java @@ -308,7 +308,7 @@ public void checkServerTrusted(X509Certificate[] chain, String authType) private List getAutoSniSanMatchers(SSLParameters sslParams) { List sniNamesToMatch = new ArrayList<>(); - if (CertificateUtils.isXdsSniEnabled && autoSniSanValidation) { + if (autoSniSanValidation) { List serverNames = sslParams.getServerNames(); if (serverNames != null) { for (SNIServerName serverName : serverNames) { diff --git a/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java b/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java index 9141147702f..c8ad9f1c670 100644 --- a/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java @@ -77,7 +77,6 @@ import io.grpc.xds.internal.security.SslContextProviderSupplier; import io.grpc.xds.internal.security.TlsContextManagerImpl; import io.grpc.xds.internal.security.certprovider.FileWatcherCertificateProviderProvider; -import io.grpc.xds.internal.security.trust.CertificateUtils; import io.netty.handler.ssl.NotSslRecordException; import java.io.File; import java.io.FileOutputStream; @@ -317,7 +316,6 @@ public void tlsClientServer_noAutoSniValidation_failureToMatchSubjAltNames() @Test public void tlsClientServer_autoSniValidation_sniInUtc() throws Exception { - CertificateUtils.isXdsSniEnabled = true; Path trustStoreFilePath = getCacertFilePathForTestCa(); try { setTrustStoreSystemProperties(trustStoreFilePath.toAbsolutePath().toString()); @@ -341,14 +339,12 @@ public void tlsClientServer_autoSniValidation_sniInUtc() } finally { Files.deleteIfExists(trustStoreFilePath); clearTrustStoreSystemProperties(); - CertificateUtils.isXdsSniEnabled = false; } } @Test public void tlsClientServer_autoSniValidation_sniFromHostname() throws Exception { - CertificateUtils.isXdsSniEnabled = true; Path trustStoreFilePath = getCacertFilePathForTestCa(); try { setTrustStoreSystemProperties(trustStoreFilePath.toAbsolutePath().toString()); @@ -375,14 +371,12 @@ public void tlsClientServer_autoSniValidation_sniFromHostname() } finally { Files.deleteIfExists(trustStoreFilePath); clearTrustStoreSystemProperties(); - CertificateUtils.isXdsSniEnabled = false; } } @Test public void tlsClientServer_autoSniValidation_noSniApplicable_usesMatcherFromCmnVdnCtx() throws Exception { - CertificateUtils.isXdsSniEnabled = true; Path trustStoreFilePath = getCacertFilePathForTestCa(); try { setTrustStoreSystemProperties(trustStoreFilePath.toAbsolutePath().toString()); @@ -406,7 +400,6 @@ public void tlsClientServer_autoSniValidation_noSniApplicable_usesMatcherFromCmn } finally { Files.deleteIfExists(trustStoreFilePath); clearTrustStoreSystemProperties(); - CertificateUtils.isXdsSniEnabled = false; } } diff --git a/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java b/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java index dcb2fa051a3..1a50a2cc567 100644 --- a/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java +++ b/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java @@ -54,7 +54,6 @@ import io.grpc.xds.internal.security.SecurityProtocolNegotiators.ClientSecurityHandler; import io.grpc.xds.internal.security.SecurityProtocolNegotiators.ClientSecurityProtocolNegotiator; import io.grpc.xds.internal.security.certprovider.CommonCertProviderTestUtils; -import io.grpc.xds.internal.security.trust.CertificateUtils; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; @@ -151,32 +150,27 @@ public void clientSecurityProtocolNegotiatorNewHandler_withTlsContextAttribute() @Test public void clientSecurityProtocolNegotiator_autoHostSni_hostnamePassedToClientSecurityHandlr() { - CertificateUtils.isXdsSniEnabled = true; - try { - UpstreamTlsContext upstreamTlsContext = - CommonTlsContextTestsUtil.buildUpstreamTlsContext( - CommonTlsContext.newBuilder().build(), "", true, false); - ClientSecurityProtocolNegotiator pn = - new ClientSecurityProtocolNegotiator(InternalProtocolNegotiators.plaintext()); - GrpcHttp2ConnectionHandler mockHandler = mock(GrpcHttp2ConnectionHandler.class); - ChannelLogger logger = mock(ChannelLogger.class); - doNothing().when(logger).log(any(ChannelLogLevel.class), anyString()); - when(mockHandler.getNegotiationLogger()).thenReturn(logger); - TlsContextManager mockTlsContextManager = mock(TlsContextManager.class); - when(mockHandler.getEagAttributes()) - .thenReturn( - Attributes.newBuilder() - .set(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, - new SslContextProviderSupplier(upstreamTlsContext, mockTlsContextManager)) - .set(XdsInternalAttributes.ATTR_ADDRESS_NAME, FAKE_AUTHORITY) - .build()); - ChannelHandler newHandler = pn.newHandler(mockHandler); - assertThat(newHandler).isNotNull(); - assertThat(newHandler).isInstanceOf(ClientSecurityHandler.class); - assertThat(((ClientSecurityHandler) newHandler).getSni()).isEqualTo(FAKE_AUTHORITY); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + UpstreamTlsContext upstreamTlsContext = + CommonTlsContextTestsUtil.buildUpstreamTlsContext( + CommonTlsContext.newBuilder().build(), "", true, false); + ClientSecurityProtocolNegotiator pn = + new ClientSecurityProtocolNegotiator(InternalProtocolNegotiators.plaintext()); + GrpcHttp2ConnectionHandler mockHandler = mock(GrpcHttp2ConnectionHandler.class); + ChannelLogger logger = mock(ChannelLogger.class); + doNothing().when(logger).log(any(ChannelLogLevel.class), anyString()); + when(mockHandler.getNegotiationLogger()).thenReturn(logger); + TlsContextManager mockTlsContextManager = mock(TlsContextManager.class); + when(mockHandler.getEagAttributes()) + .thenReturn( + Attributes.newBuilder() + .set(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, + new SslContextProviderSupplier(upstreamTlsContext, mockTlsContextManager)) + .set(XdsInternalAttributes.ATTR_ADDRESS_NAME, FAKE_AUTHORITY) + .build()); + ChannelHandler newHandler = pn.newHandler(mockHandler); + assertThat(newHandler).isNotNull(); + assertThat(newHandler).isInstanceOf(ClientSecurityHandler.class); + assertThat(((ClientSecurityHandler) newHandler).getSni()).isEqualTo(FAKE_AUTHORITY); } @Test @@ -235,110 +229,88 @@ protected void onException(Throwable throwable) { @Test public void sniInClientSecurityHandler_autoHostSniIsTrue_usesEndpointHostname() { - CertificateUtils.isXdsSniEnabled = true; - try { - Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = - CommonTlsContextTestsUtil - .buildUpstreamTlsContext("google_cloud_private_spiffe-client", true, "", true); - SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); - - ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); - - assertThat(clientSecurityHandler.getSni()).isEqualTo(HOSTNAME); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = + CommonTlsContextTestsUtil + .buildUpstreamTlsContext("google_cloud_private_spiffe-client", true, "", true); + SslContextProviderSupplier sslContextProviderSupplier = + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); + + ClientSecurityHandler clientSecurityHandler = + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); + + assertThat(clientSecurityHandler.getSni()).isEqualTo(HOSTNAME); } @Test public void sniInClientSecurityHandler_autoHostSni_endpointHostnameIsEmpty_usesSniFromUtc() { - CertificateUtils.isXdsSniEnabled = true; - try { - Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( - "google_cloud_private_spiffe-client", true, SNI_IN_UTC, true); - SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); - - ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, ""); - - assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( + "google_cloud_private_spiffe-client", true, SNI_IN_UTC, true); + SslContextProviderSupplier sslContextProviderSupplier = + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); + + ClientSecurityHandler clientSecurityHandler = + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, ""); + + assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); } @Test public void sniInClientSecurityHandler_autoHostSni_endpointHostnameIsNull_usesSniFromUtc() { - CertificateUtils.isXdsSniEnabled = true; - try { - Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( - "google_cloud_private_spiffe-client", true, SNI_IN_UTC, true); - SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); - - ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, null); - - assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( + "google_cloud_private_spiffe-client", true, SNI_IN_UTC, true); + SslContextProviderSupplier sslContextProviderSupplier = + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); + + ClientSecurityHandler clientSecurityHandler = + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, null); + + assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); } @Test public void sniInClientSecurityHandler_autoHostSniIsFalse_usesSniFromUpstreamTlsContext() { - CertificateUtils.isXdsSniEnabled = true; - try { - Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( - "google_cloud_private_spiffe-client", true, SNI_IN_UTC, false); - SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); - - ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); - - assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( + "google_cloud_private_spiffe-client", true, SNI_IN_UTC, false); + SslContextProviderSupplier sslContextProviderSupplier = + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); + + ClientSecurityHandler clientSecurityHandler = + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); + + assertThat(clientSecurityHandler.getSni()).isEqualTo(SNI_IN_UTC); } @Test - public void sniFeatureNotEnabled_usesChannelAuthorityForSni() { - CertificateUtils.isXdsSniEnabled = false; + public void sniInClientSecurityHandler_noSniConditionsMet_omitsSni() { Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = - CommonTlsContextTestsUtil - .buildUpstreamTlsContext("google_cloud_private_spiffe-client", true); + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = CommonTlsContextTestsUtil.buildUpstreamTlsContext( + "google_cloud_private_spiffe-client", true, "", false); SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); - assertThat(clientSecurityHandler.getSni()).isEqualTo(FAKE_AUTHORITY); + assertThat(clientSecurityHandler.getSni()).isEqualTo(""); } @Test @@ -503,60 +475,55 @@ public void nullTlsContext_nullFallbackProtocolNegotiator_expectException() { @Test public void clientSecurityProtocolNegotiatorNewHandler_fireProtocolNegotiationEvent() - throws InterruptedException, TimeoutException, ExecutionException { - CertificateUtils.isXdsSniEnabled = true; - try { - FakeClock executor = new FakeClock(); - CommonCertProviderTestUtils.register(executor); - Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils - .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, - CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); - UpstreamTlsContext upstreamTlsContext = - CommonTlsContextTestsUtil - .buildUpstreamTlsContext("google_cloud_private_spiffe-client", true); - - SslContextProviderSupplier sslContextProviderSupplier = - new SslContextProviderSupplier(upstreamTlsContext, - new TlsContextManagerImpl(bootstrapInfoForClient)); - ClientSecurityHandler clientSecurityHandler = - new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); - - pipeline.addLast(clientSecurityHandler); - channelHandlerCtx = pipeline.context(clientSecurityHandler); - assertNotNull(channelHandlerCtx); // non-null since we just added it - - // kick off protocol negotiation. - pipeline.fireUserEventTriggered(InternalProtocolNegotiationEvent.getDefault()); - final SettableFuture future = SettableFuture.create(); - sslContextProviderSupplier - .updateSslContext(new SslContextProvider.Callback(MoreExecutors.directExecutor()) { - @Override - public void updateSslContextAndExtendedX509TrustManager( - AbstractMap.SimpleImmutableEntry sslContextAndTm) { - future.set(sslContextAndTm); - } - - @Override - protected void onException(Throwable throwable) { - future.set(throwable); - } - }, false); - executor.runDueTasks(); - channel.runPendingTasks(); // need this for tasks to execute on eventLoop - Object fromFuture = future.get(5, TimeUnit.SECONDS); - assertThat(fromFuture).isInstanceOf(AbstractMap.SimpleImmutableEntry.class); - channel.runPendingTasks(); - channelHandlerCtx = pipeline.context(clientSecurityHandler); - assertThat(channelHandlerCtx).isNull(); - Object sslEvent = SslHandshakeCompletionEvent.SUCCESS; - - pipeline.fireUserEventTriggered(sslEvent); - channel.runPendingTasks(); // need this for tasks to execute on eventLoop - assertTrue(channel.isOpen()); - CommonCertProviderTestUtils.register0(); - } finally { - CertificateUtils.isXdsSniEnabled = false; - } + throws InterruptedException, TimeoutException, ExecutionException { + FakeClock executor = new FakeClock(); + CommonCertProviderTestUtils.register(executor); + Bootstrapper.BootstrapInfo bootstrapInfoForClient = CommonBootstrapperTestUtils + .buildBootstrapInfo("google_cloud_private_spiffe-client", CLIENT_KEY_FILE, + CLIENT_PEM_FILE, CA_PEM_FILE, null, null, null, null, null); + UpstreamTlsContext upstreamTlsContext = + CommonTlsContextTestsUtil + .buildUpstreamTlsContext("google_cloud_private_spiffe-client", true); + + SslContextProviderSupplier sslContextProviderSupplier = + new SslContextProviderSupplier(upstreamTlsContext, + new TlsContextManagerImpl(bootstrapInfoForClient)); + ClientSecurityHandler clientSecurityHandler = + new ClientSecurityHandler(grpcHandler, sslContextProviderSupplier, HOSTNAME); + + pipeline.addLast(clientSecurityHandler); + channelHandlerCtx = pipeline.context(clientSecurityHandler); + assertNotNull(channelHandlerCtx); // non-null since we just added it + + // kick off protocol negotiation. + pipeline.fireUserEventTriggered(InternalProtocolNegotiationEvent.getDefault()); + final SettableFuture future = SettableFuture.create(); + sslContextProviderSupplier + .updateSslContext(new SslContextProvider.Callback(MoreExecutors.directExecutor()) { + @Override + public void updateSslContextAndExtendedX509TrustManager( + AbstractMap.SimpleImmutableEntry sslContextAndTm) { + future.set(sslContextAndTm); + } + + @Override + protected void onException(Throwable throwable) { + future.set(throwable); + } + }, false); + executor.runDueTasks(); + channel.runPendingTasks(); // need this for tasks to execute on eventLoop + Object fromFuture = future.get(5, TimeUnit.SECONDS); + assertThat(fromFuture).isInstanceOf(AbstractMap.SimpleImmutableEntry.class); + channel.runPendingTasks(); + channelHandlerCtx = pipeline.context(clientSecurityHandler); + assertThat(channelHandlerCtx).isNull(); + Object sslEvent = SslHandshakeCompletionEvent.SUCCESS; + + pipeline.fireUserEventTriggered(sslEvent); + channel.runPendingTasks(); // need this for tasks to execute on eventLoop + assertTrue(channel.isOpen()); + CommonCertProviderTestUtils.register0(); } @Test