xds: use fallback PN if you get exception while retrieving SslContextProvider (#7137)

This commit is contained in:
sanjaypujare 2020-06-18 10:08:39 -07:00 committed by GitHub
parent e76e7c23a8
commit 57ae04007d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 78 additions and 6 deletions

View File

@ -305,7 +305,11 @@ public final class SdsProtocolNegotiators {
return;
} else {
ctx.pipeline()
.replace(this, null, new ServerSdsHandler(grpcHandler, downstreamTlsContext));
.replace(
this,
null,
new ServerSdsHandler(
grpcHandler, downstreamTlsContext, fallbackProtocolNegotiator));
ProtocolNegotiationEvent pne = InternalProtocolNegotiationEvent.getDefault();
ctx.fireUserEventTriggered(pne);
return;
@ -321,10 +325,12 @@ public final class SdsProtocolNegotiators {
extends InternalProtocolNegotiators.ProtocolNegotiationHandler {
private final GrpcHttp2ConnectionHandler grpcHandler;
private final DownstreamTlsContext downstreamTlsContext;
@Nullable private final ProtocolNegotiator fallbackProtocolNegotiator;
ServerSdsHandler(
GrpcHttp2ConnectionHandler grpcHandler,
DownstreamTlsContext downstreamTlsContext) {
DownstreamTlsContext downstreamTlsContext,
ProtocolNegotiator fallbackProtocolNegotiator) {
super(
// superclass (InternalProtocolNegotiators.ProtocolNegotiationHandler) expects 'next'
// handler but we don't have a next handler _yet_. So we "disable" superclass's behavior
@ -338,6 +344,7 @@ public final class SdsProtocolNegotiators {
checkNotNull(grpcHandler, "grpcHandler");
this.grpcHandler = grpcHandler;
this.downstreamTlsContext = downstreamTlsContext;
this.fallbackProtocolNegotiator = fallbackProtocolNegotiator;
}
@Override
@ -345,10 +352,23 @@ public final class SdsProtocolNegotiators {
final BufferReadsHandler bufferReads = new BufferReadsHandler();
ctx.pipeline().addBefore(ctx.name(), null, bufferReads);
final SslContextProvider sslContextProvider =
TlsContextManagerImpl.getInstance()
.findOrCreateServerSslContextProvider(downstreamTlsContext);
SslContextProvider sslContextProviderTemp = null;
try {
sslContextProviderTemp =
TlsContextManagerImpl.getInstance()
.findOrCreateServerSslContextProvider(downstreamTlsContext);
} catch (Exception e) {
if (fallbackProtocolNegotiator == null) {
ctx.fireExceptionCaught(new CertStoreException("No certificate source found!", e));
return;
}
logger.log(Level.INFO, "Using fallback for {0}", ctx.channel().localAddress());
// Delegate rest of handshake to fallback handler
ctx.pipeline().replace(this, null, fallbackProtocolNegotiator.newHandler(grpcHandler));
ctx.pipeline().remove(bufferReads);
return;
}
final SslContextProvider sslContextProvider = sslContextProviderTemp;
sslContextProvider.addCallback(
new SslContextProvider.Callback() {

View File

@ -89,6 +89,18 @@ public class XdsSdsClientServerTest {
assertThat(unaryRpc("buddy", blockingStub)).isEqualTo("Hello buddy");
}
@Test
public void plaintextClientServer_withDefaultTlsContext() throws IOException, URISyntaxException {
DownstreamTlsContext defaultTlsContext =
EnvoyServerProtoData.DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
io.envoyproxy.envoy.api.v2.auth.DownstreamTlsContext.getDefaultInstance());
buildServerWithTlsContext(/* downstreamTlsContext= */ defaultTlsContext);
SimpleServiceGrpc.SimpleServiceBlockingStub blockingStub =
getBlockingStub(/* upstreamTlsContext= */ null, /* overrideAuthority= */ null);
assertThat(unaryRpc("buddy", blockingStub)).isEqualTo("Hello buddy");
}
@Test
public void nullFallbackProtocolNegotiator_expectException()
throws IOException, URISyntaxException {

View File

@ -245,6 +245,46 @@ public class SdsProtocolNegotiatorsTest {
.contains("ProtocolNegotiators.ServerTlsHandler");
}
@Test
public void serverSdsHandler_defaultDownstreamTlsContext_expectFallbackProtocolNegotiator()
throws IOException {
ChannelHandler mockChannelHandler = mock(ChannelHandler.class);
ProtocolNegotiator mockProtocolNegotiator = mock(ProtocolNegotiator.class);
when(mockProtocolNegotiator.newHandler(grpcHandler)).thenReturn(mockChannelHandler);
// we need InetSocketAddress instead of EmbeddedSocketAddress as localAddress for this test
channel =
new EmbeddedChannel() {
@Override
public SocketAddress localAddress() {
return new InetSocketAddress("172.168.1.1", 80);
}
};
pipeline = channel.pipeline();
DownstreamTlsContext downstreamTlsContext =
DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext(
io.envoyproxy.envoy.api.v2.auth.DownstreamTlsContext.getDefaultInstance());
XdsClientWrapperForServerSds xdsClientWrapperForServerSds =
XdsClientWrapperForServerSdsTest.createXdsClientWrapperForServerSds(
80, downstreamTlsContext);
SdsProtocolNegotiators.HandlerPickerHandler handlerPickerHandler =
new SdsProtocolNegotiators.HandlerPickerHandler(
grpcHandler, xdsClientWrapperForServerSds, mockProtocolNegotiator);
pipeline.addLast(handlerPickerHandler);
channelHandlerCtx = pipeline.context(handlerPickerHandler);
assertThat(channelHandlerCtx).isNotNull(); // should find HandlerPickerHandler
// kick off protocol negotiation: should replace HandlerPickerHandler with ServerSdsHandler
pipeline.fireUserEventTriggered(InternalProtocolNegotiationEvent.getDefault());
channelHandlerCtx = pipeline.context(handlerPickerHandler);
assertThat(channelHandlerCtx).isNull();
channel.runPendingTasks(); // need this for tasks to execute on eventLoop
Iterator<Map.Entry<String, ChannelHandler>> iterator = pipeline.iterator();
assertThat(iterator.next().getValue()).isSameInstanceAs(mockChannelHandler);
// no more handlers in the pipeline
assertThat(iterator.hasNext()).isFalse();
}
@Test
public void serverSdsHandler_nullTlsContext_expectFallbackProtocolNegotiator() {
ChannelHandler mockChannelHandler = mock(ChannelHandler.class);