xds: fix filterChainMatch for multiple matchers, 0-length prefixLength and empty prefixRange list (#7985)

This commit is contained in:
sanjaypujare 2021-03-18 10:22:35 -07:00 committed by GitHub
parent cd3b0c4412
commit a460f784c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 130 additions and 7 deletions

View File

@ -216,9 +216,10 @@ public final class XdsClientWrapperForServerSds {
filterChains = filterOnIpAddress(filterChains, remoteInetAddr.getAddress(), false);
filterChains = filterOnSourcePort(filterChains, remoteInetAddr.getPort());
// if we get more than 1, we ignore filterChains and use the defaultFilerChain
// although spec not clear for that case
if (filterChains.size() == 1) {
if (filterChains.size() > 1) {
// close the connection
throw new IllegalStateException("Found 2 matching filter-chains");
} else if (filterChains.size() == 1) {
return filterChains.get(0).getDownstreamTlsContext();
}
return curListener.getDefaultFilterChain().getDownstreamTlsContext();
@ -307,10 +308,10 @@ public final class XdsClientWrapperForServerSds {
? filterChainMatch.getPrefixRanges()
: filterChainMatch.getSourcePrefixRanges();
indexOfMatchingPrefixRange = -1;
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume there is perfect match
matchingPrefixLength = isIPv6 ? 128 : 32;
} else {
if (cidrRanges.isEmpty()) { // if there is no CidrRange assume 0-length match
matchingPrefixLength = 0;
} else {
matchingPrefixLength = -1;
int index = 0;
for (CidrRange cidrRange : cidrRanges) {
InetAddress cidrAddr = cidrRange.getAddressPrefix();
@ -357,7 +358,7 @@ public final class XdsClientWrapperForServerSds {
for (FilterChain filterChain : filterChains) {
QueueElement element = new QueueElement(filterChain, address, forDestination);
if (element.matchingPrefixLength > 0) {
if (element.matchingPrefixLength >= 0) {
heap.add(element);
}
}

View File

@ -17,6 +17,7 @@
package io.grpc.xds;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
import com.google.protobuf.InvalidProtocolBufferException;
@ -217,6 +218,37 @@ public class FilterChainMatchTest {
assertThat(tlsContext1).isSameInstanceAs(tlsContextForDefaultFilterChain);
}
@Test
public void dest0LengthPrefixRange()
throws UnknownHostException, InvalidProtocolBufferException {
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
DownstreamTlsContext tlsContext0Length =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
// 10.2.2.0/24 doesn't match LOCAL_IP
EnvoyServerProtoData.FilterChainMatch filterChainMatch0Length =
new EnvoyServerProtoData.FilterChainMatch(
0,
Arrays.asList(new EnvoyServerProtoData.CidrRange("10.2.2.0", 0)),
Arrays.<String>asList(),
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
EnvoyServerProtoData.ConnectionSourceType.ANY,
Arrays.<Integer>asList());
EnvoyServerProtoData.FilterChain filterChain0Length =
new EnvoyServerProtoData.FilterChain(filterChainMatch0Length, tlsContext0Length);
DownstreamTlsContext tlsContextForDefaultFilterChain =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
EnvoyServerProtoData.FilterChain defaultFilterChain =
new EnvoyServerProtoData.FilterChain(null, tlsContextForDefaultFilterChain);
EnvoyServerProtoData.Listener listener =
new EnvoyServerProtoData.Listener(
"listener1", LOCAL_IP, Arrays.asList(filterChain0Length), defaultFilterChain);
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
registeredWatcher.onChanged(listenerUpdate);
DownstreamTlsContext tlsContext1 =
xdsClientWrapperForServerSds.getDownstreamTlsContext(channel);
assertThat(tlsContext1).isSameInstanceAs(tlsContext0Length);
}
@Test
public void destPrefixRange_moreSpecificWins()
throws UnknownHostException, InvalidProtocolBufferException {
@ -261,6 +293,50 @@ public class FilterChainMatchTest {
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
}
@Test
public void destPrefixRange_emptyListLessSpecific()
throws UnknownHostException, InvalidProtocolBufferException {
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
DownstreamTlsContext tlsContextLessSpecific =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific =
new EnvoyServerProtoData.FilterChainMatch(
0,
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
Arrays.<String>asList(),
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
EnvoyServerProtoData.ConnectionSourceType.ANY,
Arrays.<Integer>asList());
EnvoyServerProtoData.FilterChain filterChainLessSpecific =
new EnvoyServerProtoData.FilterChain(filterChainMatchLessSpecific, tlsContextLessSpecific);
DownstreamTlsContext tlsContextMoreSpecific =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific =
new EnvoyServerProtoData.FilterChainMatch(
0,
Arrays.asList(new EnvoyServerProtoData.CidrRange("8.0.0.0", 5)),
Arrays.<String>asList(),
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
EnvoyServerProtoData.ConnectionSourceType.ANY,
Arrays.<Integer>asList());
EnvoyServerProtoData.FilterChain filterChainMoreSpecific =
new EnvoyServerProtoData.FilterChain(filterChainMatchMoreSpecific, tlsContextMoreSpecific);
EnvoyServerProtoData.FilterChain defaultFilterChain =
new EnvoyServerProtoData.FilterChain(null, null);
EnvoyServerProtoData.Listener listener =
new EnvoyServerProtoData.Listener(
"listener1",
LOCAL_IP,
Arrays.asList(filterChainLessSpecific, filterChainMoreSpecific),
defaultFilterChain);
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
registeredWatcher.onChanged(listenerUpdate);
DownstreamTlsContext tlsContext1 =
xdsClientWrapperForServerSds.getDownstreamTlsContext(channel);
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecific);
}
@Test
public void destPrefixRangeIpv6_moreSpecificWins()
throws UnknownHostException, InvalidProtocolBufferException {
@ -457,6 +533,52 @@ public class FilterChainMatchTest {
assertThat(tlsContext1).isSameInstanceAs(tlsContextMoreSpecificWith2);
}
@Test
public void sourcePrefixRange_2Matchers_expectException()
throws UnknownHostException, InvalidProtocolBufferException {
setupChannel(LOCAL_IP, REMOTE_IP, 15000);
DownstreamTlsContext tlsContext1 =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1");
EnvoyServerProtoData.FilterChainMatch filterChainMatch1 =
new EnvoyServerProtoData.FilterChainMatch(
0,
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
Arrays.<String>asList(),
Arrays.asList(
new EnvoyServerProtoData.CidrRange("10.4.2.0", 24),
new EnvoyServerProtoData.CidrRange("192.168.10.2", 32)),
EnvoyServerProtoData.ConnectionSourceType.ANY,
Arrays.<Integer>asList());
EnvoyServerProtoData.FilterChain filterChain1 =
new EnvoyServerProtoData.FilterChain(filterChainMatch1, tlsContext1);
DownstreamTlsContext tlsContext2 =
CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2");
EnvoyServerProtoData.FilterChainMatch filterChainMatch2 =
new EnvoyServerProtoData.FilterChainMatch(
0,
Arrays.<EnvoyServerProtoData.CidrRange>asList(),
Arrays.<String>asList(),
Arrays.asList(new EnvoyServerProtoData.CidrRange("10.4.2.0", 24)),
EnvoyServerProtoData.ConnectionSourceType.ANY,
Arrays.<Integer>asList());
EnvoyServerProtoData.FilterChain filterChain2 =
new EnvoyServerProtoData.FilterChain(filterChainMatch2, tlsContext2);
EnvoyServerProtoData.FilterChain defaultFilterChain =
new EnvoyServerProtoData.FilterChain(null, null);
EnvoyServerProtoData.Listener listener =
new EnvoyServerProtoData.Listener(
"listener1", LOCAL_IP, Arrays.asList(filterChain1, filterChain2), defaultFilterChain);
XdsClient.LdsUpdate listenerUpdate = new XdsClient.LdsUpdate(listener);
registeredWatcher.onChanged(listenerUpdate);
try {
xdsClientWrapperForServerSds.getDownstreamTlsContext(channel);
fail("expect exception!");
} catch (IllegalStateException ise) {
assertThat(ise).hasMessageThat().isEqualTo("Found 2 matching filter-chains");
}
}
@Test
public void sourcePortMatch_exactMatchWinsOverEmptyList()
throws UnknownHostException, InvalidProtocolBufferException {