1 /* 2 * Copyright 2021 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.xds; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static io.grpc.xds.XdsServerWrapper.ATTR_SERVER_ROUTING_CONFIG; 21 import static io.grpc.xds.internal.security.SecurityProtocolNegotiators.ATTR_SERVER_SSL_CONTEXT_PROVIDER_SUPPLIER; 22 import static org.junit.Assert.fail; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.when; 25 26 import com.google.common.collect.ImmutableList; 27 import com.google.common.collect.ImmutableMap; 28 import com.google.common.util.concurrent.SettableFuture; 29 import io.grpc.ServerInterceptor; 30 import io.grpc.internal.TestUtils.NoopChannelLogger; 31 import io.grpc.netty.GrpcHttp2ConnectionHandler; 32 import io.grpc.netty.InternalProtocolNegotiationEvent; 33 import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator; 34 import io.grpc.netty.ProtocolNegotiationEvent; 35 import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext; 36 import io.grpc.xds.EnvoyServerProtoData.FilterChain; 37 import io.grpc.xds.Filter.FilterConfig; 38 import io.grpc.xds.Filter.NamedFilterConfig; 39 import io.grpc.xds.FilterChainMatchingProtocolNegotiators.FilterChainMatchingHandler; 40 import io.grpc.xds.FilterChainMatchingProtocolNegotiators.FilterChainMatchingHandler.FilterChainSelector; 41 import io.grpc.xds.VirtualHost.Route; 42 import io.grpc.xds.XdsServerWrapper.ServerRoutingConfig; 43 import io.grpc.xds.internal.security.CommonTlsContextTestsUtil; 44 import io.grpc.xds.internal.security.SslContextProviderSupplier; 45 import io.netty.channel.ChannelHandler; 46 import io.netty.channel.ChannelHandlerContext; 47 import io.netty.channel.ChannelInboundHandlerAdapter; 48 import io.netty.channel.ChannelPipeline; 49 import io.netty.channel.ChannelPromise; 50 import io.netty.channel.embedded.EmbeddedChannel; 51 import io.netty.handler.codec.http2.DefaultHttp2Connection; 52 import io.netty.handler.codec.http2.DefaultHttp2ConnectionDecoder; 53 import io.netty.handler.codec.http2.DefaultHttp2ConnectionEncoder; 54 import io.netty.handler.codec.http2.DefaultHttp2FrameReader; 55 import io.netty.handler.codec.http2.DefaultHttp2FrameWriter; 56 import io.netty.handler.codec.http2.Http2ConnectionDecoder; 57 import io.netty.handler.codec.http2.Http2ConnectionEncoder; 58 import io.netty.handler.codec.http2.Http2Settings; 59 import java.net.InetSocketAddress; 60 import java.net.SocketAddress; 61 import java.net.UnknownHostException; 62 import java.util.ArrayList; 63 import java.util.Collections; 64 import java.util.HashMap; 65 import java.util.Map; 66 import java.util.concurrent.atomic.AtomicReference; 67 import org.junit.After; 68 import org.junit.Rule; 69 import org.junit.Test; 70 import org.junit.runner.RunWith; 71 import org.junit.runners.JUnit4; 72 import org.mockito.Mock; 73 import org.mockito.junit.MockitoJUnit; 74 import org.mockito.junit.MockitoRule; 75 76 @RunWith(JUnit4.class) 77 public class FilterChainMatchingProtocolNegotiatorsTest { 78 @Rule 79 public final MockitoRule mocks = MockitoJUnit.rule(); 80 81 private final GrpcHttp2ConnectionHandler grpcHandler = 82 FakeGrpcHttp2ConnectionHandler.newHandler(); 83 @Mock private TlsContextManager tlsContextManager; 84 private ProtocolNegotiationEvent event = InternalProtocolNegotiationEvent.getDefault(); 85 private ChannelPipeline pipeline; 86 private EmbeddedChannel channel; 87 private ChannelHandlerContext channelHandlerCtx; 88 @Mock 89 private ProtocolNegotiator mockDelegate; 90 private FilterChainSelectorManager selectorManager = new FilterChainSelectorManager(); 91 private static final EnvoyServerProtoData.FilterChainMatch DEFAULT_FILTER_CHAIN_MATCH = 92 EnvoyServerProtoData.FilterChainMatch.create( 93 0, 94 ImmutableList.of(), 95 ImmutableList.of(), 96 ImmutableList.of(), 97 EnvoyServerProtoData.ConnectionSourceType.ANY, 98 ImmutableList.of(), 99 ImmutableList.of(), 100 ""); 101 private static final HttpConnectionManager HTTP_CONNECTION_MANAGER = createRds("routing-config"); 102 private static final String LOCAL_IP = "10.1.2.3"; // dest 103 private static final String REMOTE_IP = "10.4.2.3"; // source 104 private static final int PORT = 7000; 105 private final AtomicReference<ServerRoutingConfig> noopConfig = new AtomicReference<>( 106 ServerRoutingConfig.create(ImmutableList.<VirtualHost>of(), 107 ImmutableMap.<Route, ServerInterceptor>of())); 108 final SettableFuture<SslContextProviderSupplier> sslSet = SettableFuture.create(); 109 final SettableFuture<AtomicReference<ServerRoutingConfig>> routingSettable = 110 SettableFuture.create(); 111 112 @After 113 @SuppressWarnings("FutureReturnValueIgnored") tearDown()114 public void tearDown() { 115 if (channel.isActive()) { 116 channel.close(); 117 channel.runPendingTasks(); 118 } 119 assertThat(selectorManager.getRegisterCount()).isEqualTo(0); 120 } 121 122 @Test nofilterChainMatch_defaultSslContext()123 public void nofilterChainMatch_defaultSslContext() throws Exception { 124 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 125 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 126 127 SslContextProviderSupplier defaultSsl = new SslContextProviderSupplier(createTls(), 128 tlsContextManager); 129 selectorManager.updateSelector(new FilterChainSelector( 130 new HashMap<FilterChain, AtomicReference<ServerRoutingConfig>>(), 131 defaultSsl, noopConfig)); 132 FilterChainMatchingHandler filterChainMatchingHandler = 133 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 134 setupChannel("172.168.1.1", "172.168.1.2", 80, filterChainMatchingHandler); 135 ChannelHandlerContext channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 136 assertThat(channelHandlerCtx).isNotNull(); 137 138 pipeline.fireUserEventTriggered(event); 139 channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 140 assertThat(channelHandlerCtx).isNull(); 141 142 channel.runPendingTasks(); 143 assertThat(sslSet.isDone()).isTrue(); 144 assertThat(sslSet.get()).isEqualTo(defaultSsl); 145 assertThat(routingSettable.get()).isEqualTo(noopConfig); 146 channelHandlerCtx = pipeline.context(next); 147 assertThat(channelHandlerCtx).isNotNull(); 148 } 149 150 @Test noFilterChainMatch_noDefaultSslContext()151 public void noFilterChainMatch_noDefaultSslContext() { 152 selectorManager.updateSelector(new FilterChainSelector( 153 new HashMap<FilterChain, AtomicReference<ServerRoutingConfig>>(), 154 null, new AtomicReference<ServerRoutingConfig>())); 155 FilterChainMatchingHandler filterChainMatchingHandler = 156 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 157 setupChannel("172.168.1.1", "172.168.2.2", 90, filterChainMatchingHandler); 158 channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 159 assertThat(channelHandlerCtx).isNotNull(); 160 161 assertThat(channel.closeFuture().isDone()).isFalse(); 162 pipeline.fireUserEventTriggered(event); 163 channel.runPendingTasks(); 164 assertThat(channel.closeFuture().isDone()).isTrue(); 165 } 166 167 @Test filterSelectorChange_drainsConnection()168 public void filterSelectorChange_drainsConnection() { 169 ChannelHandler next = new ChannelInboundHandlerAdapter(); 170 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 171 selectorManager.updateSelector(new FilterChainSelector( 172 new HashMap<FilterChain, AtomicReference<ServerRoutingConfig>>(), null, noopConfig)); 173 FilterChainMatchingHandler filterChainMatchingHandler = 174 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 175 setupChannel("172.168.1.1", "172.168.2.2", 90, filterChainMatchingHandler); 176 channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 177 assertThat(channelHandlerCtx).isNotNull(); 178 179 pipeline.fireUserEventTriggered(event); 180 channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 181 assertThat(channelHandlerCtx).isNull(); 182 183 channel.runPendingTasks(); 184 channelHandlerCtx = pipeline.context(next); 185 assertThat(channelHandlerCtx).isNotNull(); 186 // Force return value to Object, to avoid confusing javac of the type passed to assertThat() 187 Object msg = channel.readOutbound(); 188 assertThat(msg).isNull(); 189 190 selectorManager.updateSelector(new FilterChainSelector( 191 new HashMap<FilterChain, AtomicReference<ServerRoutingConfig>>(), null, noopConfig)); 192 assertThat(channel.readOutbound().getClass().getName()) 193 .isEqualTo("io.grpc.netty.GracefulServerCloseCommand"); 194 } 195 196 @Test singleFilterChainWithoutAlpn()197 public void singleFilterChainWithoutAlpn() throws Exception { 198 EnvoyServerProtoData.FilterChainMatch filterChainMatch = 199 EnvoyServerProtoData.FilterChainMatch.create( 200 0, 201 ImmutableList.of(), 202 ImmutableList.of(), 203 ImmutableList.of(), 204 EnvoyServerProtoData.ConnectionSourceType.ANY, 205 ImmutableList.of(), 206 ImmutableList.of(), 207 ""); 208 EnvoyServerProtoData.DownstreamTlsContext tlsContext = 209 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 210 EnvoyServerProtoData.FilterChain filterChain = EnvoyServerProtoData.FilterChain.create( 211 "filter-chain-foo", filterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext, 212 tlsContextManager); 213 214 selectorManager.updateSelector(new FilterChainSelector(ImmutableMap.of(filterChain, noopConfig), 215 null, new AtomicReference<ServerRoutingConfig>())); 216 FilterChainMatchingHandler filterChainMatchingHandler = 217 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 218 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 219 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 220 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 221 pipeline.fireUserEventTriggered(event); 222 channel.runPendingTasks(); 223 assertThat(sslSet.isDone()).isTrue(); 224 assertThat(sslSet.get()).isEqualTo(filterChain.sslContextProviderSupplier()); 225 assertThat(routingSettable.get()).isEqualTo(noopConfig); 226 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContext); 227 } 228 229 @Test singleFilterChainWithAlpn()230 public void singleFilterChainWithAlpn() throws Exception { 231 EnvoyServerProtoData.FilterChainMatch filterChainMatch = 232 EnvoyServerProtoData.FilterChainMatch.create( 233 0, 234 ImmutableList.of(), 235 ImmutableList.of("managed-mtls"), 236 ImmutableList.of(), 237 EnvoyServerProtoData.ConnectionSourceType.ANY, 238 ImmutableList.of(), 239 ImmutableList.of(), 240 ""); 241 EnvoyServerProtoData.DownstreamTlsContext tlsContext = 242 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 243 EnvoyServerProtoData.FilterChain filterChain = EnvoyServerProtoData.FilterChain.create( 244 "filter-chain-foo", filterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext, 245 tlsContextManager); 246 EnvoyServerProtoData.DownstreamTlsContext defaultTlsContext = 247 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 248 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 249 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, defaultTlsContext, 250 tlsContextManager); 251 selectorManager.updateSelector(new FilterChainSelector( 252 ImmutableMap.of(filterChain, randomConfig("no-match")), 253 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 254 FilterChainMatchingHandler filterChainMatchingHandler = 255 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 256 257 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 258 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 259 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 260 pipeline.fireUserEventTriggered(event); 261 channel.runPendingTasks(); 262 assertThat(sslSet.get()).isEqualTo(defaultFilterChain.sslContextProviderSupplier()); 263 assertThat(routingSettable.get()).isEqualTo(noopConfig); 264 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(defaultTlsContext); 265 } 266 267 @Test destPortFails_returnDefaultFilterChain()268 public void destPortFails_returnDefaultFilterChain() throws Exception { 269 EnvoyServerProtoData.DownstreamTlsContext tlsContextWithDestPort = 270 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 271 EnvoyServerProtoData.FilterChainMatch filterChainMatchWithDestPort = 272 EnvoyServerProtoData.FilterChainMatch.create( 273 PORT, 274 ImmutableList.of(), 275 ImmutableList.of("managed-mtls"), 276 ImmutableList.of(), 277 EnvoyServerProtoData.ConnectionSourceType.ANY, 278 ImmutableList.of(), 279 ImmutableList.of(), 280 ""); 281 EnvoyServerProtoData.FilterChain filterChainWithDestPort = 282 EnvoyServerProtoData.FilterChain.create( 283 "filter-chain-foo", filterChainMatchWithDestPort, HTTP_CONNECTION_MANAGER, 284 tlsContextWithDestPort, tlsContextManager); 285 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 286 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 287 EnvoyServerProtoData.FilterChain defaultFilterChain = 288 EnvoyServerProtoData.FilterChain.create( 289 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 290 tlsContextForDefaultFilterChain, tlsContextManager); 291 292 ServerRoutingConfig routingConfig = ServerRoutingConfig.create( 293 ImmutableList.of(createVirtualHost("virtual")), 294 ImmutableMap.<Route, ServerInterceptor>of()); 295 selectorManager.updateSelector(new FilterChainSelector( 296 ImmutableMap.of(filterChainWithDestPort, 297 new AtomicReference<ServerRoutingConfig>(routingConfig)), 298 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 299 300 FilterChainMatchingHandler filterChainMatchingHandler = 301 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 302 303 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 304 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 305 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 306 pipeline.fireUserEventTriggered(event); 307 channel.runPendingTasks(); 308 assertThat(sslSet.get()).isEqualTo(defaultFilterChain.sslContextProviderSupplier()); 309 assertThat(routingSettable.get()).isEqualTo(noopConfig); 310 assertThat(sslSet.get().getTlsContext()) 311 .isSameInstanceAs(tlsContextForDefaultFilterChain); 312 } 313 314 @Test destPrefixRangeMatch()315 public void destPrefixRangeMatch() throws Exception { 316 EnvoyServerProtoData.DownstreamTlsContext tlsContextMatch = 317 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 318 EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch = 319 EnvoyServerProtoData.FilterChainMatch.create( 320 0, 321 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.0", 24)), 322 ImmutableList.of(), 323 ImmutableList.of(), 324 EnvoyServerProtoData.ConnectionSourceType.ANY, 325 ImmutableList.of(), 326 ImmutableList.of(), 327 ""); 328 EnvoyServerProtoData.FilterChain filterChainWithMatch = EnvoyServerProtoData.FilterChain.create( 329 "filter-chain-foo", filterChainMatchWithMatch, HTTP_CONNECTION_MANAGER, 330 tlsContextMatch, tlsContextManager); 331 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 332 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 333 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 334 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 335 tlsContextForDefaultFilterChain, tlsContextManager); 336 337 selectorManager.updateSelector(new FilterChainSelector( 338 ImmutableMap.of(filterChainWithMatch, noopConfig), 339 defaultFilterChain.sslContextProviderSupplier(), randomConfig("no-match"))); 340 341 FilterChainMatchingHandler filterChainMatchingHandler = 342 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 343 344 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 345 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 346 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 347 pipeline.fireUserEventTriggered(event); 348 channel.runPendingTasks(); 349 assertThat(sslSet.get()).isEqualTo(filterChainWithMatch.sslContextProviderSupplier()); 350 assertThat(routingSettable.get()).isEqualTo(noopConfig); 351 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMatch); 352 } 353 354 @Test destPrefixRangeMismatch_returnDefaultFilterChain()355 public void destPrefixRangeMismatch_returnDefaultFilterChain() 356 throws Exception { 357 EnvoyServerProtoData.DownstreamTlsContext tlsContextMismatch = 358 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 359 // 10.2.2.0/24 doesn't match LOCAL_IP 360 EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch = 361 EnvoyServerProtoData.FilterChainMatch.create( 362 0, 363 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.2.2.0", 24)), 364 ImmutableList.of(), 365 ImmutableList.of(), 366 EnvoyServerProtoData.ConnectionSourceType.ANY, 367 ImmutableList.of(), 368 ImmutableList.of(), 369 ""); 370 EnvoyServerProtoData.FilterChain filterChainWithMismatch = 371 EnvoyServerProtoData.FilterChain.create( 372 "filter-chain-foo", filterChainMatchWithMismatch, HTTP_CONNECTION_MANAGER, 373 tlsContextMismatch, tlsContextManager); 374 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 375 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 376 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 377 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 378 tlsContextForDefaultFilterChain, tlsContextManager); 379 selectorManager.updateSelector(new FilterChainSelector( 380 ImmutableMap.of(filterChainWithMismatch, randomConfig("no-match")), 381 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 382 383 FilterChainMatchingHandler filterChainMatchingHandler = 384 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 385 386 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 387 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 388 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 389 pipeline.fireUserEventTriggered(event); 390 channel.runPendingTasks(); 391 assertThat(sslSet.isDone()).isTrue(); 392 assertThat(sslSet.get()).isEqualTo(defaultFilterChain.sslContextProviderSupplier()); 393 assertThat(routingSettable.get()).isEqualTo(noopConfig); 394 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextForDefaultFilterChain); 395 } 396 397 @Test dest0LengthPrefixRange()398 public void dest0LengthPrefixRange() 399 throws Exception { 400 EnvoyServerProtoData.DownstreamTlsContext tlsContext0Length = 401 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 402 // 10.2.2.0/24 doesn't match LOCAL_IP 403 EnvoyServerProtoData.FilterChainMatch filterChainMatch0Length = 404 EnvoyServerProtoData.FilterChainMatch.create( 405 0, 406 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.2.2.0", 0)), 407 ImmutableList.of(), 408 ImmutableList.of(), 409 EnvoyServerProtoData.ConnectionSourceType.ANY, 410 ImmutableList.of(), 411 ImmutableList.of(), 412 ""); 413 EnvoyServerProtoData.FilterChain filterChain0Length = EnvoyServerProtoData.FilterChain.create( 414 "filter-chain-foo", filterChainMatch0Length, HTTP_CONNECTION_MANAGER, 415 tlsContext0Length, tlsContextManager); 416 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 417 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 418 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 419 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 420 tlsContextForDefaultFilterChain, tlsContextManager); 421 422 selectorManager.updateSelector(new FilterChainSelector( 423 ImmutableMap.of(filterChain0Length, noopConfig), 424 defaultFilterChain.sslContextProviderSupplier(), 425 new AtomicReference<ServerRoutingConfig>())); 426 FilterChainMatchingHandler filterChainMatchingHandler = 427 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 428 429 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 430 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 431 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 432 pipeline.fireUserEventTriggered(event); 433 channel.runPendingTasks(); 434 assertThat(sslSet.get()).isEqualTo(filterChain0Length.sslContextProviderSupplier()); 435 assertThat(routingSettable.get()).isEqualTo(noopConfig); 436 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContext0Length); 437 } 438 439 @Test destPrefixRange_moreSpecificWins()440 public void destPrefixRange_moreSpecificWins() 441 throws Exception { 442 EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific = 443 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 444 EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific = 445 EnvoyServerProtoData.FilterChainMatch.create( 446 0, 447 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.0", 24)), 448 ImmutableList.of(), 449 ImmutableList.of(), 450 EnvoyServerProtoData.ConnectionSourceType.ANY, 451 ImmutableList.of(), 452 ImmutableList.of(), 453 ""); 454 EnvoyServerProtoData.FilterChain filterChainLessSpecific = 455 EnvoyServerProtoData.FilterChain.create( 456 "filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER, 457 tlsContextLessSpecific, tlsContextManager); 458 459 EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific = 460 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 461 EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific = 462 EnvoyServerProtoData.FilterChainMatch.create( 463 0, 464 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.2", 31)), 465 ImmutableList.of(), 466 ImmutableList.of(), 467 EnvoyServerProtoData.ConnectionSourceType.ANY, 468 ImmutableList.of(), 469 ImmutableList.of(), 470 ""); 471 EnvoyServerProtoData.FilterChain filterChainMoreSpecific = 472 EnvoyServerProtoData.FilterChain.create( 473 "filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER, 474 tlsContextMoreSpecific, 475 tlsContextManager); 476 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 477 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 478 tlsContextManager); 479 selectorManager.updateSelector(new FilterChainSelector( 480 ImmutableMap.of(filterChainLessSpecific, randomConfig("no-match"), 481 filterChainMoreSpecific, noopConfig), 482 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 483 484 FilterChainMatchingHandler filterChainMatchingHandler = 485 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 486 487 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 488 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 489 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 490 pipeline.fireUserEventTriggered(event); 491 channel.runPendingTasks(); 492 assertThat(sslSet.get()).isEqualTo(filterChainMoreSpecific.sslContextProviderSupplier()); 493 assertThat(routingSettable.get()).isEqualTo(noopConfig); 494 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMoreSpecific); 495 } 496 497 @Test destPrefixRange_emptyListLessSpecific()498 public void destPrefixRange_emptyListLessSpecific() 499 throws Exception { 500 EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific = 501 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 502 EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific = 503 EnvoyServerProtoData.FilterChainMatch.create( 504 0, 505 ImmutableList.of(), 506 ImmutableList.of(), 507 ImmutableList.of(), 508 EnvoyServerProtoData.ConnectionSourceType.ANY, 509 ImmutableList.of(), 510 ImmutableList.of(), 511 ""); 512 EnvoyServerProtoData.FilterChain filterChainLessSpecific = 513 EnvoyServerProtoData.FilterChain.create( 514 "filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER, 515 tlsContextLessSpecific, tlsContextManager); 516 517 EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific = 518 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 519 EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific = 520 EnvoyServerProtoData.FilterChainMatch.create( 521 0, 522 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("8.0.0.0", 5)), 523 ImmutableList.of(), 524 ImmutableList.of(), 525 EnvoyServerProtoData.ConnectionSourceType.ANY, 526 ImmutableList.of(), 527 ImmutableList.of(), 528 ""); 529 EnvoyServerProtoData.FilterChain filterChainMoreSpecific = 530 EnvoyServerProtoData.FilterChain.create( 531 "filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER, 532 tlsContextMoreSpecific, 533 tlsContextManager); 534 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 535 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 536 tlsContextManager); 537 selectorManager.updateSelector(new FilterChainSelector( 538 ImmutableMap.of(filterChainLessSpecific, randomConfig("no-match"), 539 filterChainMoreSpecific, noopConfig), 540 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 541 FilterChainMatchingHandler filterChainMatchingHandler = 542 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 543 544 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 545 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 546 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 547 pipeline.fireUserEventTriggered(event); 548 channel.runPendingTasks(); 549 assertThat(sslSet.get()).isEqualTo(filterChainMoreSpecific.sslContextProviderSupplier()); 550 assertThat(routingSettable.get()).isEqualTo(noopConfig); 551 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMoreSpecific); 552 } 553 554 @Test destPrefixRangeIpv6_moreSpecificWins()555 public void destPrefixRangeIpv6_moreSpecificWins() 556 throws Exception { 557 EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific = 558 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 559 EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific = 560 EnvoyServerProtoData.FilterChainMatch.create( 561 0, 562 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("FE80:0:0:0:0:0:0:0", 60)), 563 ImmutableList.of(), 564 ImmutableList.of(), 565 EnvoyServerProtoData.ConnectionSourceType.ANY, 566 ImmutableList.of(), 567 ImmutableList.of(), 568 ""); 569 EnvoyServerProtoData.FilterChain filterChainLessSpecific = 570 EnvoyServerProtoData.FilterChain.create( 571 "filter-chain-foo", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER, 572 tlsContextLessSpecific, tlsContextManager); 573 574 EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecific = 575 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 576 EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecific = 577 EnvoyServerProtoData.FilterChainMatch.create( 578 0, 579 ImmutableList.of( 580 EnvoyServerProtoData.CidrRange.create("FE80:0000:0000:0000:0202:0:0:0", 80)), 581 ImmutableList.of(), 582 ImmutableList.of(), 583 EnvoyServerProtoData.ConnectionSourceType.ANY, 584 ImmutableList.of(), 585 ImmutableList.of(), 586 ""); 587 EnvoyServerProtoData.FilterChain filterChainMoreSpecific = 588 EnvoyServerProtoData.FilterChain.create( 589 "filter-chain-bar", filterChainMatchMoreSpecific, HTTP_CONNECTION_MANAGER, 590 tlsContextMoreSpecific, tlsContextManager); 591 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 592 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 593 tlsContextManager); 594 selectorManager.updateSelector(new FilterChainSelector( 595 ImmutableMap.of(filterChainLessSpecific, randomConfig("no-match"), 596 filterChainMoreSpecific, noopConfig), 597 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 598 599 FilterChainMatchingHandler filterChainMatchingHandler = 600 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 601 602 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 603 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 604 605 setupChannel("FE80:0000:0000:0000:0202:B3FF:FE1E:8329", "2001:DB8::8:800:200C:417A", 606 15000, filterChainMatchingHandler); 607 pipeline.fireUserEventTriggered(event); 608 channel.runPendingTasks(); 609 assertThat(sslSet.get()).isEqualTo(filterChainMoreSpecific.sslContextProviderSupplier()); 610 assertThat(routingSettable.get()).isEqualTo(noopConfig); 611 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMoreSpecific); 612 } 613 614 @Test destPrefixRange_moreSpecificWith2Wins()615 public void destPrefixRange_moreSpecificWith2Wins() 616 throws Exception { 617 EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecificWith2 = 618 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 619 EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 = 620 EnvoyServerProtoData.FilterChainMatch.create( 621 0, 622 ImmutableList.of( 623 EnvoyServerProtoData.CidrRange.create("10.1.2.0", 24), 624 EnvoyServerProtoData.CidrRange.create(LOCAL_IP, 32)), 625 ImmutableList.of(), 626 ImmutableList.of(), 627 EnvoyServerProtoData.ConnectionSourceType.ANY, 628 ImmutableList.of(), 629 ImmutableList.of(), 630 ""); 631 EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 = 632 EnvoyServerProtoData.FilterChain.create( 633 "filter-chain-foo", filterChainMatchMoreSpecificWith2, HTTP_CONNECTION_MANAGER, 634 tlsContextMoreSpecificWith2, tlsContextManager); 635 636 EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific = 637 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 638 EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific = 639 EnvoyServerProtoData.FilterChainMatch.create( 640 0, 641 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.2", 31)), 642 ImmutableList.of(), 643 ImmutableList.of(), 644 EnvoyServerProtoData.ConnectionSourceType.ANY, 645 ImmutableList.of(), 646 ImmutableList.of(), 647 ""); 648 EnvoyServerProtoData.FilterChain filterChainLessSpecific = 649 EnvoyServerProtoData.FilterChain.create( 650 "filter-chain-bar", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER, 651 tlsContextLessSpecific, tlsContextManager); 652 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 653 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 654 tlsContextManager); 655 656 selectorManager.updateSelector(new FilterChainSelector( 657 ImmutableMap.of(filterChainMoreSpecificWith2, noopConfig, 658 filterChainLessSpecific, randomConfig("no-match")), 659 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 660 FilterChainMatchingHandler filterChainMatchingHandler = 661 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 662 663 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 664 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 665 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 666 pipeline.fireUserEventTriggered(event); 667 channel.runPendingTasks(); 668 assertThat(sslSet.get()).isEqualTo( 669 filterChainMoreSpecificWith2.sslContextProviderSupplier()); 670 assertThat(routingSettable.get()).isEqualTo(noopConfig); 671 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMoreSpecificWith2); 672 } 673 674 @Test sourceTypeMismatch_returnDefaultFilterChain()675 public void sourceTypeMismatch_returnDefaultFilterChain() throws Exception { 676 EnvoyServerProtoData.DownstreamTlsContext tlsContextMismatch = 677 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 678 EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMismatch = 679 EnvoyServerProtoData.FilterChainMatch.create( 680 0, 681 ImmutableList.of(), 682 ImmutableList.of(), 683 ImmutableList.of(), 684 EnvoyServerProtoData.ConnectionSourceType.SAME_IP_OR_LOOPBACK, 685 ImmutableList.of(), 686 ImmutableList.of(), 687 ""); 688 EnvoyServerProtoData.FilterChain filterChainWithMismatch = 689 EnvoyServerProtoData.FilterChain.create( 690 "filter-chain-foo", filterChainMatchWithMismatch, HTTP_CONNECTION_MANAGER, 691 tlsContextMismatch, tlsContextManager); 692 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 693 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 694 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 695 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 696 tlsContextForDefaultFilterChain, tlsContextManager); 697 selectorManager.updateSelector(new FilterChainSelector( 698 ImmutableMap.of(filterChainWithMismatch, randomConfig("no-match")), 699 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 700 FilterChainMatchingHandler filterChainMatchingHandler = 701 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 702 703 704 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 705 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 706 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 707 pipeline.fireUserEventTriggered(event); 708 channel.runPendingTasks(); 709 assertThat(sslSet.get()).isEqualTo(defaultFilterChain.sslContextProviderSupplier()); 710 assertThat(routingSettable.get()).isEqualTo(noopConfig); 711 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextForDefaultFilterChain); 712 } 713 714 @Test sourceTypeLocal()715 public void sourceTypeLocal() throws Exception { 716 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 717 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 718 EnvoyServerProtoData.DownstreamTlsContext tlsContextMatch = 719 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 720 EnvoyServerProtoData.FilterChainMatch filterChainMatchWithMatch = 721 EnvoyServerProtoData.FilterChainMatch.create( 722 0, 723 ImmutableList.of(), 724 ImmutableList.of(), 725 ImmutableList.of(), 726 EnvoyServerProtoData.ConnectionSourceType.SAME_IP_OR_LOOPBACK, 727 ImmutableList.of(), 728 ImmutableList.of(), 729 ""); 730 EnvoyServerProtoData.FilterChain filterChainWithMatch = EnvoyServerProtoData.FilterChain.create( 731 "filter-chain-foo", filterChainMatchWithMatch, HTTP_CONNECTION_MANAGER, tlsContextMatch, 732 tlsContextManager); 733 EnvoyServerProtoData.DownstreamTlsContext tlsContextForDefaultFilterChain = 734 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 735 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 736 "filter-chain-bar", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, 737 tlsContextForDefaultFilterChain, tlsContextManager); 738 739 selectorManager.updateSelector(new FilterChainSelector( 740 ImmutableMap.of(filterChainWithMatch, noopConfig), 741 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 742 FilterChainMatchingHandler filterChainMatchingHandler = 743 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 744 setupChannel(LOCAL_IP, LOCAL_IP, 15000, filterChainMatchingHandler); 745 pipeline.fireUserEventTriggered(event); 746 channel.runPendingTasks(); 747 assertThat(sslSet.get()).isEqualTo(filterChainWithMatch.sslContextProviderSupplier()); 748 assertThat(routingSettable.get()).isEqualTo(noopConfig); 749 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMatch); 750 } 751 752 @Test sourcePrefixRange_moreSpecificWith2Wins()753 public void sourcePrefixRange_moreSpecificWith2Wins() 754 throws Exception { 755 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 756 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 757 758 EnvoyServerProtoData.DownstreamTlsContext tlsContextMoreSpecificWith2 = 759 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 760 EnvoyServerProtoData.FilterChainMatch filterChainMatchMoreSpecificWith2 = 761 EnvoyServerProtoData.FilterChainMatch.create( 762 0, 763 ImmutableList.of(), 764 ImmutableList.of(), 765 ImmutableList.of( 766 EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24), 767 EnvoyServerProtoData.CidrRange.create(REMOTE_IP, 32)), 768 EnvoyServerProtoData.ConnectionSourceType.ANY, 769 ImmutableList.of(), 770 ImmutableList.of(), 771 ""); 772 EnvoyServerProtoData.FilterChain filterChainMoreSpecificWith2 = 773 EnvoyServerProtoData.FilterChain.create( 774 "filter-chain-foo", filterChainMatchMoreSpecificWith2, HTTP_CONNECTION_MANAGER, 775 tlsContextMoreSpecificWith2, tlsContextManager); 776 777 EnvoyServerProtoData.DownstreamTlsContext tlsContextLessSpecific = 778 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 779 EnvoyServerProtoData.FilterChainMatch filterChainMatchLessSpecific = 780 EnvoyServerProtoData.FilterChainMatch.create( 781 0, 782 ImmutableList.of(), 783 ImmutableList.of(), 784 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.4.2.2", 31)), 785 EnvoyServerProtoData.ConnectionSourceType.ANY, 786 ImmutableList.of(), 787 ImmutableList.of(), 788 ""); 789 EnvoyServerProtoData.FilterChain filterChainLessSpecific = 790 EnvoyServerProtoData.FilterChain.create( 791 "filter-chain-bar", filterChainMatchLessSpecific, HTTP_CONNECTION_MANAGER, 792 tlsContextLessSpecific, tlsContextManager); 793 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 794 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 795 tlsContextManager); 796 797 selectorManager.updateSelector(new FilterChainSelector( 798 ImmutableMap.of(filterChainMoreSpecificWith2, noopConfig, 799 filterChainLessSpecific, randomConfig("no-match")), 800 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 801 802 FilterChainMatchingHandler filterChainMatchingHandler = 803 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 804 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 805 pipeline.fireUserEventTriggered(event); 806 channel.runPendingTasks(); 807 assertThat(sslSet.get()).isEqualTo( 808 filterChainMoreSpecificWith2.sslContextProviderSupplier()); 809 assertThat(routingSettable.get()).isEqualTo(noopConfig); 810 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextMoreSpecificWith2); 811 } 812 813 @Test sourcePrefixRange_2Matchers_expectException()814 public void sourcePrefixRange_2Matchers_expectException() 815 throws UnknownHostException { 816 ChannelHandler next = new ChannelInboundHandlerAdapter() { 817 @Override 818 public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { 819 ProtocolNegotiationEvent e = (ProtocolNegotiationEvent)evt; 820 sslSet.set(InternalProtocolNegotiationEvent.getAttributes(e) 821 .get(ATTR_SERVER_SSL_CONTEXT_PROVIDER_SUPPLIER)); 822 } 823 }; 824 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 825 826 EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = 827 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 828 EnvoyServerProtoData.FilterChainMatch filterChainMatch1 = 829 EnvoyServerProtoData.FilterChainMatch.create( 830 0, 831 ImmutableList.of(), 832 ImmutableList.of(), 833 ImmutableList.of( 834 EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24), 835 EnvoyServerProtoData.CidrRange.create("192.168.10.2", 32)), 836 EnvoyServerProtoData.ConnectionSourceType.ANY, 837 ImmutableList.of(), 838 ImmutableList.of(), 839 ""); 840 EnvoyServerProtoData.FilterChain filterChain1 = EnvoyServerProtoData.FilterChain.create( 841 "filter-chain-foo", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1, 842 tlsContextManager); 843 844 EnvoyServerProtoData.DownstreamTlsContext tlsContext2 = 845 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 846 EnvoyServerProtoData.FilterChainMatch filterChainMatch2 = 847 EnvoyServerProtoData.FilterChainMatch.create( 848 0, 849 ImmutableList.of(), 850 ImmutableList.of(), 851 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24)), 852 EnvoyServerProtoData.ConnectionSourceType.ANY, 853 ImmutableList.of(), 854 ImmutableList.of(), 855 ""); 856 EnvoyServerProtoData.FilterChain filterChain2 = EnvoyServerProtoData.FilterChain.create( 857 "filter-chain-bar", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2, 858 tlsContextManager); 859 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 860 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, null); 861 862 selectorManager.updateSelector(new FilterChainSelector( 863 ImmutableMap.of(filterChain1, noopConfig, filterChain2, noopConfig), 864 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 865 866 FilterChainMatchingHandler filterChainMatchingHandler = 867 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 868 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 869 pipeline.fireUserEventTriggered(event); 870 channel.runPendingTasks(); 871 try { 872 channel.checkException(); 873 fail("expect exception!"); 874 } catch (IllegalStateException ise) { 875 assertThat(ise).hasMessageThat().isEqualTo("Found more than one matching filter chains. This " 876 + "should not be possible as ClientXdsClient validated the chains for uniqueness."); 877 assertThat(sslSet.isDone()).isFalse(); 878 channelHandlerCtx = pipeline.context(filterChainMatchingHandler); 879 assertThat(channelHandlerCtx).isNotNull(); 880 } 881 } 882 883 @Test sourcePortMatch_exactMatchWinsOverEmptyList()884 public void sourcePortMatch_exactMatchWinsOverEmptyList() throws Exception { 885 EnvoyServerProtoData.DownstreamTlsContext tlsContextEmptySourcePorts = 886 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 887 EnvoyServerProtoData.FilterChainMatch filterChainMatchEmptySourcePorts = 888 EnvoyServerProtoData.FilterChainMatch.create( 889 0, 890 ImmutableList.of(), 891 ImmutableList.of(), 892 ImmutableList.of( 893 EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24), 894 EnvoyServerProtoData.CidrRange.create("10.4.2.2", 31)), 895 EnvoyServerProtoData.ConnectionSourceType.ANY, 896 ImmutableList.of(), 897 ImmutableList.of(), 898 ""); 899 EnvoyServerProtoData.FilterChain filterChainEmptySourcePorts = 900 EnvoyServerProtoData.FilterChain.create( 901 "filter-chain-foo", filterChainMatchEmptySourcePorts, HTTP_CONNECTION_MANAGER, 902 tlsContextEmptySourcePorts, tlsContextManager); 903 904 EnvoyServerProtoData.DownstreamTlsContext tlsContextSourcePortMatch = 905 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 906 EnvoyServerProtoData.FilterChainMatch filterChainMatchSourcePortMatch = 907 EnvoyServerProtoData.FilterChainMatch.create( 908 0, 909 ImmutableList.of(), 910 ImmutableList.of(), 911 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.4.2.2", 31)), 912 EnvoyServerProtoData.ConnectionSourceType.ANY, 913 ImmutableList.of(7000, 15000), 914 ImmutableList.of(), 915 ""); 916 EnvoyServerProtoData.FilterChain filterChainSourcePortMatch = 917 EnvoyServerProtoData.FilterChain.create( 918 "filter-chain-bar", filterChainMatchSourcePortMatch, HTTP_CONNECTION_MANAGER, 919 tlsContextSourcePortMatch, tlsContextManager); 920 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 921 "filter-chain-baz", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 922 tlsContextManager); 923 924 selectorManager.updateSelector(new FilterChainSelector( 925 ImmutableMap.of(filterChainEmptySourcePorts, randomConfig("no-match"), 926 filterChainSourcePortMatch, noopConfig), 927 defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 928 929 FilterChainMatchingHandler filterChainMatchingHandler = 930 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 931 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 932 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 933 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 934 pipeline.fireUserEventTriggered(event); 935 channel.runPendingTasks(); 936 assertThat(sslSet.get()).isEqualTo(filterChainSourcePortMatch.sslContextProviderSupplier()); 937 assertThat(routingSettable.get()).isEqualTo(noopConfig); 938 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContextSourcePortMatch); 939 } 940 941 /** 942 * Create 6 filterChains: - 1st filter chain has dest port & specific prefix range but is 943 * eliminated due to dest port - 5 advance to next step: 1 is eliminated due to being less 944 * specific than the remaining 4. - 4 advance to 3rd step: source type external eliminates one 945 * with local source_type. - 3 advance to 4th step: more specific 2 get picked based on 946 * source-prefix range. - 5th step: out of 2 one with matching source port gets picked 947 */ 948 @Test filterChain_5stepMatch()949 public void filterChain_5stepMatch() throws Exception { 950 EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = 951 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "VA1"); 952 EnvoyServerProtoData.DownstreamTlsContext tlsContext2 = 953 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "VA2"); 954 EnvoyServerProtoData.DownstreamTlsContext tlsContext3 = 955 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT3", "VA3"); 956 EnvoyServerProtoData.DownstreamTlsContext tlsContext4 = 957 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT4", "VA4"); 958 EnvoyServerProtoData.DownstreamTlsContext tlsContext5 = 959 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT5", "VA5"); 960 EnvoyServerProtoData.DownstreamTlsContext tlsContext6 = 961 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT6", "VA6"); 962 963 // has dest port and specific prefix ranges: gets eliminated in step 1 964 EnvoyServerProtoData.FilterChainMatch filterChainMatch1 = 965 EnvoyServerProtoData.FilterChainMatch.create( 966 PORT, 967 ImmutableList.of(), 968 ImmutableList.of(), 969 ImmutableList.of(EnvoyServerProtoData.CidrRange.create(REMOTE_IP, 32)), 970 EnvoyServerProtoData.ConnectionSourceType.ANY, 971 ImmutableList.of(), 972 ImmutableList.of(), 973 ""); 974 EnvoyServerProtoData.FilterChain filterChain1 = EnvoyServerProtoData.FilterChain.create( 975 "filter-chain-1", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1, 976 tlsContextManager); 977 978 // next 5 use prefix range: 4 with prefixLen of 30 and last one with 29 979 980 // has single prefix range: and less specific source prefix range: gets eliminated in step 4 981 EnvoyServerProtoData.FilterChainMatch filterChainMatch2 = 982 EnvoyServerProtoData.FilterChainMatch.create( 983 0, 984 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.0", 30)), 985 ImmutableList.of(), 986 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.4.0.0", 16)), 987 EnvoyServerProtoData.ConnectionSourceType.ANY, 988 ImmutableList.of(), 989 ImmutableList.of(), 990 ""); 991 EnvoyServerProtoData.FilterChain filterChain2 = EnvoyServerProtoData.FilterChain.create( 992 "filter-chain-2", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2, 993 tlsContextManager); 994 995 // has prefix ranges with one not matching and source type local: gets eliminated in step 3 996 EnvoyServerProtoData.FilterChainMatch filterChainMatch3 = 997 EnvoyServerProtoData.FilterChainMatch.create( 998 0, 999 ImmutableList.of( 1000 EnvoyServerProtoData.CidrRange.create("192.168.2.0", 24), 1001 EnvoyServerProtoData.CidrRange.create("10.1.2.0", 30)), 1002 ImmutableList.of(), 1003 ImmutableList.of(), 1004 EnvoyServerProtoData.ConnectionSourceType.SAME_IP_OR_LOOPBACK, 1005 ImmutableList.of(), 1006 ImmutableList.of(), 1007 ""); 1008 EnvoyServerProtoData.FilterChain filterChain3 = EnvoyServerProtoData.FilterChain.create( 1009 "filter-chain-3", filterChainMatch3, HTTP_CONNECTION_MANAGER, tlsContext3, 1010 tlsContextManager); 1011 1012 // has prefix ranges with both matching and source type external but non matching source port: 1013 // gets eliminated in step 5 1014 EnvoyServerProtoData.FilterChainMatch filterChainMatch4 = 1015 EnvoyServerProtoData.FilterChainMatch.create( 1016 0, 1017 ImmutableList.of( 1018 EnvoyServerProtoData.CidrRange.create("10.1.0.0", 16), 1019 EnvoyServerProtoData.CidrRange.create("10.1.2.0", 30)), 1020 ImmutableList.of(), 1021 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24)), 1022 EnvoyServerProtoData.ConnectionSourceType.EXTERNAL, 1023 ImmutableList.of(16000, 9000), 1024 ImmutableList.of(), 1025 ""); 1026 EnvoyServerProtoData.FilterChain filterChain4 = 1027 EnvoyServerProtoData.FilterChain.create( 1028 "filter-chain-4", filterChainMatch4, HTTP_CONNECTION_MANAGER, tlsContext4, 1029 tlsContextManager); 1030 1031 // has prefix ranges with both matching and source type external and matching source port: this 1032 // gets selected 1033 EnvoyServerProtoData.FilterChainMatch filterChainMatch5 = 1034 EnvoyServerProtoData.FilterChainMatch.create( 1035 0, 1036 ImmutableList.of( 1037 EnvoyServerProtoData.CidrRange.create("10.1.0.0", 16), 1038 EnvoyServerProtoData.CidrRange.create("10.1.2.0", 30)), 1039 ImmutableList.of(), 1040 ImmutableList.of( 1041 EnvoyServerProtoData.CidrRange.create("10.4.2.0", 24), 1042 EnvoyServerProtoData.CidrRange.create("192.168.2.0", 24)), 1043 EnvoyServerProtoData.ConnectionSourceType.ANY, 1044 ImmutableList.of(15000, 8000), 1045 ImmutableList.of(), 1046 ""); 1047 EnvoyServerProtoData.FilterChain filterChain5 = 1048 EnvoyServerProtoData.FilterChain.create( 1049 "filter-chain-5", filterChainMatch5, HTTP_CONNECTION_MANAGER, tlsContext5, 1050 tlsContextManager); 1051 1052 // has prefix range with prefixLen of 29: gets eliminated in step 2 1053 EnvoyServerProtoData.FilterChainMatch filterChainMatch6 = 1054 EnvoyServerProtoData.FilterChainMatch.create( 1055 0, 1056 ImmutableList.of(EnvoyServerProtoData.CidrRange.create("10.1.2.0", 29)), 1057 ImmutableList.of(), 1058 ImmutableList.of(), 1059 EnvoyServerProtoData.ConnectionSourceType.ANY, 1060 ImmutableList.of(), 1061 ImmutableList.of(), 1062 ""); 1063 EnvoyServerProtoData.FilterChain filterChain6 = 1064 EnvoyServerProtoData.FilterChain.create( 1065 "filter-chain-6", filterChainMatch6, HTTP_CONNECTION_MANAGER, tlsContext6, 1066 tlsContextManager); 1067 1068 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 1069 "filter-chain-7", DEFAULT_FILTER_CHAIN_MATCH, HTTP_CONNECTION_MANAGER, null, 1070 tlsContextManager); 1071 1072 Map<FilterChain, AtomicReference<ServerRoutingConfig>> map = new HashMap<>(); 1073 map.put(filterChain1, randomConfig("1")); 1074 map.put(filterChain2, randomConfig("2")); 1075 map.put(filterChain3, randomConfig("3")); 1076 map.put(filterChain4, randomConfig("4")); 1077 map.put(filterChain5, noopConfig); 1078 map.put(filterChain6, randomConfig("6")); 1079 selectorManager.updateSelector(new FilterChainSelector( 1080 map, defaultFilterChain.sslContextProviderSupplier(), randomConfig("default"))); 1081 1082 FilterChainMatchingHandler filterChainMatchingHandler = 1083 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 1084 1085 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 1086 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 1087 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 1088 pipeline.fireUserEventTriggered(event); 1089 channel.runPendingTasks(); 1090 assertThat(sslSet.get()).isEqualTo(filterChain5.sslContextProviderSupplier()); 1091 assertThat(routingSettable.get()).isEqualTo(noopConfig); 1092 assertThat(sslSet.get().getTlsContext()).isSameInstanceAs(tlsContext5); 1093 } 1094 1095 @Test 1096 @SuppressWarnings("deprecation") filterChainMatch_unsupportedMatchers()1097 public void filterChainMatch_unsupportedMatchers() throws Exception { 1098 EnvoyServerProtoData.DownstreamTlsContext tlsContext1 = 1099 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT1", "ROOTCA"); 1100 EnvoyServerProtoData.DownstreamTlsContext tlsContext2 = 1101 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT2", "ROOTCA"); 1102 EnvoyServerProtoData.DownstreamTlsContext tlsContext3 = 1103 CommonTlsContextTestsUtil.buildTestInternalDownstreamTlsContext("CERT3", "ROOTCA"); 1104 1105 EnvoyServerProtoData.FilterChainMatch filterChainMatch1 = 1106 EnvoyServerProtoData.FilterChainMatch.create( 1107 0 /* destinationPort */, 1108 ImmutableList.of( 1109 EnvoyServerProtoData.CidrRange.create("10.1.0.0", 16)) /* prefixRange */, 1110 ImmutableList.of("managed-mtls", "h2") /* applicationProtocol */, 1111 ImmutableList.of() /* sourcePrefixRanges */, 1112 EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */, 1113 ImmutableList.of() /* sourcePorts */, 1114 ImmutableList.of("server1", "server2") /* serverNames */, 1115 "tls" /* transportProtocol */); 1116 1117 EnvoyServerProtoData.FilterChainMatch filterChainMatch2 = 1118 EnvoyServerProtoData.FilterChainMatch.create( 1119 0 /* destinationPort */, 1120 ImmutableList.of( 1121 EnvoyServerProtoData.CidrRange.create("10.0.0.0", 8)) /* prefixRange */, 1122 ImmutableList.of() /* applicationProtocol */, 1123 ImmutableList.of() /* sourcePrefixRanges */, 1124 EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */, 1125 ImmutableList.of() /* sourcePorts */, 1126 ImmutableList.of() /* serverNames */, 1127 "" /* transportProtocol */); 1128 1129 EnvoyServerProtoData.FilterChainMatch defaultFilterChainMatch = 1130 EnvoyServerProtoData.FilterChainMatch.create( 1131 0 /* destinationPort */, 1132 ImmutableList.of() /* prefixRange */, 1133 ImmutableList.of() /* applicationProtocol */, 1134 ImmutableList.of() /* sourcePrefixRanges */, 1135 EnvoyServerProtoData.ConnectionSourceType.ANY /* sourceType */, 1136 ImmutableList.of() /* sourcePorts */, 1137 ImmutableList.of() /* serverNames */, 1138 "" /* transportProtocol */); 1139 1140 EnvoyServerProtoData.FilterChain filterChain1 = EnvoyServerProtoData.FilterChain.create( 1141 "filter-chain-foo", filterChainMatch1, HTTP_CONNECTION_MANAGER, tlsContext1, 1142 mock(TlsContextManager.class)); 1143 EnvoyServerProtoData.FilterChain filterChain2 = EnvoyServerProtoData.FilterChain.create( 1144 "filter-chain-bar", filterChainMatch2, HTTP_CONNECTION_MANAGER, tlsContext2, 1145 mock(TlsContextManager.class)); 1146 1147 EnvoyServerProtoData.FilterChain defaultFilterChain = EnvoyServerProtoData.FilterChain.create( 1148 "filter-chain-baz", defaultFilterChainMatch, HTTP_CONNECTION_MANAGER, tlsContext3, 1149 mock(TlsContextManager.class)); 1150 1151 selectorManager.updateSelector(new FilterChainSelector( 1152 ImmutableMap.of(filterChain1, randomConfig("1"), filterChain2, randomConfig("2")), 1153 defaultFilterChain.sslContextProviderSupplier(), noopConfig)); 1154 1155 FilterChainMatchingHandler filterChainMatchingHandler = 1156 new FilterChainMatchingHandler(grpcHandler, selectorManager, mockDelegate); 1157 ChannelHandler next = captureAttrHandler(sslSet, routingSettable); 1158 when(mockDelegate.newHandler(grpcHandler)).thenReturn(next); 1159 setupChannel(LOCAL_IP, REMOTE_IP, 15000, filterChainMatchingHandler); 1160 pipeline.fireUserEventTriggered(event); 1161 channel.runPendingTasks(); 1162 assertThat(sslSet.get()).isEqualTo(defaultFilterChain.sslContextProviderSupplier()); 1163 assertThat(routingSettable.get()).isEqualTo(noopConfig); 1164 assertThat(sslSet.get().getTlsContext().getCommonTlsContext() 1165 .getTlsCertificateCertificateProviderInstance() 1166 .getCertificateName()).isEqualTo("CERT3"); 1167 } 1168 createRds(String name)1169 private static HttpConnectionManager createRds(String name) { 1170 return HttpConnectionManager.forRdsName(0L, name, 1171 new ArrayList<NamedFilterConfig>()); 1172 } 1173 createVirtualHost(String name)1174 private static VirtualHost createVirtualHost(String name) { 1175 return VirtualHost.create( 1176 name, Collections.singletonList("auth"), new ArrayList<Route>(), 1177 ImmutableMap.<String, FilterConfig>of()); 1178 } 1179 randomConfig(String domain)1180 private static AtomicReference<ServerRoutingConfig> randomConfig(String domain) { 1181 return new AtomicReference<>( 1182 ServerRoutingConfig.create(ImmutableList.of(createVirtualHost(domain)), 1183 ImmutableMap.<Route, ServerInterceptor>of()) 1184 ); 1185 } 1186 createTls()1187 private EnvoyServerProtoData.DownstreamTlsContext createTls() { 1188 return DownstreamTlsContext.fromEnvoyProtoDownstreamTlsContext( 1189 io.envoyproxy.envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext 1190 .getDefaultInstance()); 1191 } 1192 setupChannel(final String localIp, final String remoteIp, final int remotePort, FilterChainMatchingHandler matchingHandler)1193 private void setupChannel(final String localIp, final String remoteIp, final int remotePort, 1194 FilterChainMatchingHandler matchingHandler) { 1195 channel = 1196 new EmbeddedChannel() { 1197 @Override 1198 public SocketAddress localAddress() { 1199 return new InetSocketAddress(localIp, 80); 1200 } 1201 1202 @Override 1203 public SocketAddress remoteAddress() { 1204 return new InetSocketAddress(remoteIp, remotePort); 1205 } 1206 }; 1207 pipeline = channel.pipeline(); 1208 pipeline.addLast(matchingHandler); 1209 } 1210 captureAttrHandler( final SettableFuture<SslContextProviderSupplier> sslSet, final SettableFuture<AtomicReference<ServerRoutingConfig>> routingSettable)1211 private static ChannelHandler captureAttrHandler( 1212 final SettableFuture<SslContextProviderSupplier> sslSet, 1213 final SettableFuture<AtomicReference<ServerRoutingConfig>> routingSettable) { 1214 return new ChannelInboundHandlerAdapter() { 1215 @Override 1216 public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { 1217 ProtocolNegotiationEvent e = (ProtocolNegotiationEvent)evt; 1218 sslSet.set(InternalProtocolNegotiationEvent.getAttributes(e) 1219 .get(ATTR_SERVER_SSL_CONTEXT_PROVIDER_SUPPLIER)); 1220 routingSettable.set(InternalProtocolNegotiationEvent.getAttributes(e) 1221 .get(ATTR_SERVER_ROUTING_CONFIG)); 1222 } 1223 }; 1224 } 1225 1226 private static final class FakeGrpcHttp2ConnectionHandler extends GrpcHttp2ConnectionHandler { 1227 FakeGrpcHttp2ConnectionHandler( 1228 ChannelPromise channelUnused, 1229 Http2ConnectionDecoder decoder, 1230 Http2ConnectionEncoder encoder, 1231 Http2Settings initialSettings) { 1232 super(channelUnused, decoder, encoder, initialSettings, new NoopChannelLogger()); 1233 } 1234 1235 static FakeGrpcHttp2ConnectionHandler newHandler() { 1236 DefaultHttp2Connection conn = new DefaultHttp2Connection(/*server=*/ false); 1237 DefaultHttp2ConnectionEncoder encoder = 1238 new DefaultHttp2ConnectionEncoder(conn, new DefaultHttp2FrameWriter()); 1239 DefaultHttp2ConnectionDecoder decoder = 1240 new DefaultHttp2ConnectionDecoder(conn, encoder, new DefaultHttp2FrameReader()); 1241 Http2Settings settings = new Http2Settings(); 1242 return new FakeGrpcHttp2ConnectionHandler( 1243 /*channelUnused=*/ null, decoder, encoder, settings); 1244 } 1245 1246 @Override 1247 public String getAuthority() { 1248 return "authority"; 1249 } 1250 } 1251 } 1252