xds: Avoid NPE for no filter chain match on server-side

This commit is contained in:
Eric Anderson 2021-06-29 11:32:37 -05:00 committed by GitHub
parent 7644350ecb
commit 4814d975a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 6 deletions

View File

@ -313,7 +313,7 @@ public final class EnvoyServerProtoData {
/**
* Corresponds to Envoy proto message {@link io.envoyproxy.envoy.api.v2.listener.FilterChain}.
*/
static final class FilterChain {
public static final class FilterChain {
// Unique name for the FilterChain.
private final String name;
// TODO(sanjaypujare): flatten structure by moving FilterChainMatch class members here.
@ -391,7 +391,7 @@ public final class EnvoyServerProtoData {
* Corresponds to Envoy proto message {@link io.envoyproxy.envoy.api.v2.Listener} & related
* classes.
*/
static final class Listener {
public static final class Listener {
private final String name;
@Nullable
private final String address;
@ -399,7 +399,8 @@ public final class EnvoyServerProtoData {
@Nullable
private final FilterChain defaultFilterChain;
Listener(String name, @Nullable String address,
/** Construct a Listener. */
public Listener(String name, @Nullable String address,
List<FilterChain> filterChains, @Nullable FilterChain defaultFilterChain) {
this.name = checkNotNull(name, "name");
this.address = address;

View File

@ -238,6 +238,11 @@ public final class XdsClientWrapperForServerSds {
} else if (filterChains.size() == 1) {
return filterChains.get(0).getSslContextProviderSupplier();
}
if (listener.getDefaultFilterChain() == null) {
// close the connection
throw new RuntimeException(
"no matching filter chain. local: " + localInetAddr + " remote: " + remoteInetAddr);
}
return listener.getDefaultFilterChain().getSslContextProviderSupplier();
}
@ -428,7 +433,7 @@ public final class XdsClientWrapperForServerSds {
}
@VisibleForTesting
XdsClient.LdsResourceWatcher getListenerWatcher() {
public XdsClient.LdsResourceWatcher getListenerWatcher() {
return listenerWatcher;
}

View File

@ -37,7 +37,7 @@ import org.mockito.ArgumentCaptor;
/**
* Helper methods related to {@link XdsServerBuilder} and related classes.
*/
class XdsServerTestHelper {
public class XdsServerTestHelper {
private static final String SERVER_URI = "trafficdirector.googleapis.com";
private static final String NODE_ID =
@ -88,7 +88,8 @@ class XdsServerTestHelper {
}
}
static XdsClientWrapperForServerSds createXdsClientWrapperForServerSds(int port,
/** Create an XdsClientWrapperForServerSds with a mock XdsClient. */
public static XdsClientWrapperForServerSds createXdsClientWrapperForServerSds(int port,
TlsContextManager tlsContextManager) {
FakeXdsClientPoolFactory fakeXdsClientPoolFactory = new FakeXdsClientPoolFactory(
buildMockXdsClient(tlsContextManager));
@ -139,6 +140,11 @@ class XdsServerTestHelper {
registeredWatcher.onChanged(listenerUpdate);
}
public static void generateListenerUpdate(
XdsClient.LdsResourceWatcher registeredWatcher, EnvoyServerProtoData.Listener listener) {
registeredWatcher.onChanged(LdsUpdate.forTcpListener(listener));
}
static int findFreePort() throws IOException {
try (ServerSocket socket = new ServerSocket(0)) {
socket.setReuseAddress(true);

View File

@ -44,12 +44,14 @@ import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator;
import io.grpc.netty.InternalProtocolNegotiators;
import io.grpc.xds.Bootstrapper;
import io.grpc.xds.CommonBootstrapperTestUtils;
import io.grpc.xds.EnvoyServerProtoData;
import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext;
import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext;
import io.grpc.xds.InternalXdsAttributes;
import io.grpc.xds.TlsContextManager;
import io.grpc.xds.XdsClientWrapperForServerSds;
import io.grpc.xds.XdsClientWrapperForServerSdsTestMisc;
import io.grpc.xds.XdsServerTestHelper;
import io.grpc.xds.internal.sds.SdsProtocolNegotiators.ClientSdsHandler;
import io.grpc.xds.internal.sds.SdsProtocolNegotiators.ClientSdsProtocolNegotiator;
import io.netty.channel.ChannelHandler;
@ -72,6 +74,7 @@ import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.cert.CertStoreException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@ -348,6 +351,54 @@ public class SdsProtocolNegotiatorsTest {
}
}
@Test
public void noMatchingFilterChain_expectException() {
// 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);
}
@Override
public SocketAddress remoteAddress() {
return new InetSocketAddress("172.168.2.2", 90);
}
};
pipeline = channel.pipeline();
Bootstrapper.BootstrapInfo bootstrapInfoForServer = CommonBootstrapperTestUtils
.buildBootstrapInfo("google_cloud_private_spiffe-server", SERVER_1_KEY_FILE,
SERVER_1_PEM_FILE, CA_PEM_FILE, null, null, null, null);
TlsContextManagerImpl tlsContextManager = new TlsContextManagerImpl(bootstrapInfoForServer);
XdsClientWrapperForServerSds xdsClientWrapperForServerSds =
XdsServerTestHelper.createXdsClientWrapperForServerSds(80, tlsContextManager);
xdsClientWrapperForServerSds.start();
EnvoyServerProtoData.Listener listener = new EnvoyServerProtoData.Listener(
"listener1", "0.0.0.0", Arrays.<EnvoyServerProtoData.FilterChain>asList(), null);
XdsServerTestHelper.generateListenerUpdate(
xdsClientWrapperForServerSds.getListenerWatcher(), listener);
SdsProtocolNegotiators.HandlerPickerHandler handlerPickerHandler =
new SdsProtocolNegotiators.HandlerPickerHandler(grpcHandler, xdsClientWrapperForServerSds,
InternalProtocolNegotiators.serverPlaintext());
pipeline.addLast(handlerPickerHandler);
channelHandlerCtx = pipeline.context(handlerPickerHandler);
assertThat(channelHandlerCtx).isNotNull(); // should find HandlerPickerHandler
// kick off protocol negotiation
pipeline.fireUserEventTriggered(InternalProtocolNegotiationEvent.getDefault());
channelHandlerCtx = pipeline.context(handlerPickerHandler);
assertThat(channelHandlerCtx).isNotNull(); // HandlerPickerHandler still there
try {
channel.checkException();
fail("exception expected!");
} catch (Exception e) {
assertThat(e).hasMessageThat().contains("no matching filter chain");
}
}
@Test
public void clientSdsProtocolNegotiatorNewHandler_fireProtocolNegotiationEvent()
throws InterruptedException, TimeoutException, ExecutionException {