/** * Creates a netty SslContext for use when connecting to upstream servers. Retrieves the list of trusted root CAs * from the trustSource. When trustSource is true, no upstream certificate verification will be performed. * <b>This will make it possible for attackers to MITM communications with the upstream server</b>, so always * supply an appropriate trustSource except in extraordinary circumstances (e.g. testing with dynamically-generated * certificates). * * @param cipherSuites cipher suites to allow when connecting to the upstream server * @param trustSource the trust store that will be used to validate upstream servers' certificates, or null to accept all upstream server certificates * @return an SSLContext to connect to upstream servers with */ public static SslContext getUpstreamServerSslContext(Collection<String> cipherSuites, TrustSource trustSource) { SslContextBuilder sslContextBuilder = SslContextBuilder.forClient(); if (trustSource == null) { log.warn("Disabling upstream server certificate verification. This will allow attackers to intercept communications with upstream servers."); sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); } else { sslContextBuilder.trustManager(trustSource.getTrustedCAs()); } sslContextBuilder.ciphers(cipherSuites, SupportedCipherSuiteFilter.INSTANCE); try { return sslContextBuilder.build(); } catch (SSLException e) { throw new SslContextInitializationException("Error creating new SSL context for connection to upstream server", e); } }
private SslContext getSslContext() { SslContext sslCtx = null; final SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; try { sslCtx = SslContextBuilder.forClient() .sslProvider(provider) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .trustManager(InsecureTrustManagerFactory.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE, SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2)) .build(); } catch(SSLException exception) { return null; } return sslCtx; }
/** * Sets the {@link SslContext} of this {@link VirtualHost} from the specified {@link SessionProtocol}, * {@code keyCertChainFile}, {@code keyFile} and {@code keyPassword}. */ public B sslContext( SessionProtocol protocol, File keyCertChainFile, File keyFile, String keyPassword) throws SSLException { if (requireNonNull(protocol, "protocol") != SessionProtocol.HTTPS) { throw new IllegalArgumentException("unsupported protocol: " + protocol); } final SslContextBuilder builder = SslContextBuilder.forServer(keyCertChainFile, keyFile, keyPassword); builder.sslProvider(Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK); builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE); builder.applicationProtocolConfig(HTTPS_ALPN_CFG); sslContext(builder.build()); return self(); }
/** * This method will provide netty ssl context which supports HTTP2 over TLS using * Application Layer Protocol Negotiation (ALPN) * * @return instance of {@link SslContext} * @throws SSLException if any error occurred during building SSL context. */ public SslContext createHttp2TLSContext() throws SSLException { // If listener configuration does not include cipher suites , default ciphers required by the HTTP/2 // specification will be added. List<String> ciphers = sslConfig.getCipherSuites() != null && sslConfig.getCipherSuites().length > 0 ? Arrays .asList(sslConfig.getCipherSuites()) : Http2SecurityUtil.CIPHERS; SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; return SslContextBuilder.forServer(this.getKeyManagerFactory()) .trustManager(this.getTrustStoreFactory()) .sslProvider(provider) .ciphers(ciphers, SupportedCipherSuiteFilter.INSTANCE) .clientAuth(needClientAuth ? ClientAuth.REQUIRE : ClientAuth.NONE) .applicationProtocolConfig(new ApplicationProtocolConfig( ApplicationProtocolConfig.Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)).build(); }
static SslContext build(final Config conf) throws IOException, CertificateException { String tmpdir = conf.getString("application.tmpdir"); boolean http2 = conf.getBoolean("server.http2.enabled"); File keyStoreCert = toFile(conf.getString("ssl.keystore.cert"), tmpdir); File keyStoreKey = toFile(conf.getString("ssl.keystore.key"), tmpdir); String keyStorePass = conf.hasPath("ssl.keystore.password") ? conf.getString("ssl.keystore.password") : null; SslContextBuilder scb = SslContextBuilder.forServer(keyStoreCert, keyStoreKey, keyStorePass); if (conf.hasPath("ssl.trust.cert")) { scb.trustManager(toFile(conf.getString("ssl.trust.cert"), tmpdir)) .clientAuth(ClientAuth.REQUIRE); } if (http2) { SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; return scb.sslProvider(provider) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE, SelectedListenerFailureBehavior.ACCEPT, Arrays.asList(ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1))) .build(); } return scb.build(); }
private Block alpn(final SslProvider provider) { return unit -> { SslContextBuilder scb = unit.get(SslContextBuilder.class); expect(scb.sslProvider(provider)).andReturn(scb); expect(scb.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)) .andReturn(scb); ApplicationProtocolConfig apc = unit.constructor(ApplicationProtocolConfig.class) .args(Protocol.class, SelectorFailureBehavior.class, SelectedListenerFailureBehavior.class, List.class) .build(Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE, SelectedListenerFailureBehavior.ACCEPT, Arrays.asList(ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)); expect(scb.applicationProtocolConfig(apc)).andReturn(scb); }; }
@Override protected AbstractServerImplBuilder<?> getServerBuilder() { // Starts the server with HTTPS. try { SslProvider sslProvider = SslContext.defaultServerProvider(); if (sslProvider == SslProvider.OPENSSL && !OpenSsl.isAlpnSupported()) { // OkHttp only supports Jetty ALPN on OpenJDK. So if OpenSSL doesn't support ALPN, then we // are forced to use Jetty ALPN for Netty instead of OpenSSL. sslProvider = SslProvider.JDK; } SslContextBuilder contextBuilder = SslContextBuilder .forServer(TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key")); GrpcSslContexts.configure(contextBuilder, sslProvider); contextBuilder.ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE); return NettyServerBuilder.forPort(0) .flowControlWindow(65 * 1024) .maxMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) .sslContext(contextBuilder.build()); } catch (IOException ex) { throw new RuntimeException(ex); } }
@Override protected AbstractServerImplBuilder<?> getServerBuilder() { // Starts the server with HTTPS. try { return NettyServerBuilder.forPort(0) .flowControlWindow(65 * 1024) .maxMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) .sslContext(GrpcSslContexts .forServer(TestUtils.loadCert("server1.pem"), TestUtils.loadCert("server1.key")) .clientAuth(ClientAuth.REQUIRE) .trustManager(TestUtils.loadCert("ca.pem")) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE) .sslProvider(SslProvider.OPENSSL) .build()); } catch (IOException ex) { throw new RuntimeException(ex); } }
@Override protected ManagedChannel createChannel() { try { NettyChannelBuilder builder = NettyChannelBuilder .forAddress(TestUtils.testServerAddress(getPort())) .flowControlWindow(65 * 1024) .maxInboundMessageSize(AbstractInteropTest.MAX_MESSAGE_SIZE) .sslContext(GrpcSslContexts .forClient() .keyManager(TestUtils.loadCert("client.pem"), TestUtils.loadCert("client.key")) .trustManager(TestUtils.loadX509Cert("ca.pem")) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE) .sslProvider(SslProvider.OPENSSL) .build()); io.grpc.internal.TestingAccessor.setStatsImplementation( builder, createClientCensusStatsModule()); return builder.build(); } catch (Exception ex) { throw new RuntimeException(ex); } }
public static SslContext ctxForClient(NitmProxyConfig config) throws SSLException { SslContextBuilder builder = SslContextBuilder .forClient() .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(applicationProtocolConfig(config, config.isServerHttp2())); if (config.isInsecure()) { builder.trustManager(InsecureTrustManagerFactory.INSTANCE); } return builder.build(); }
public static SslContext ctxForServer(NitmProxyConfig config, String serverHost) throws SSLException { Certificate certificate = CertUtil.newCert(config.getCertFile(), config.getKeyFile(), serverHost); return SslContextBuilder .forServer(certificate.getKeyPair().getPrivate(), certificate.getChain()) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(applicationProtocolConfig(config, config.isClientHttp2())) .build(); }
Http2TestServerRunnable(File certFile, File keyFile) throws Exception { ApplicationProtocolConfig applicationProtocolConfig = new ApplicationProtocolConfig( Protocol.ALPN, SelectorFailureBehavior.NO_ADVERTISE, SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2); mSslCtx = new OpenSslServerContext(certFile, keyFile, null, null, Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE, applicationProtocolConfig, 0, 0); }
private static SslContextBuilder serverSslContext( InputStream keyCertChainFile, InputStream keyFile) { return SslContextBuilder.forServer(keyCertChainFile, keyFile, null) .sslProvider(Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(HTTPS_ALPN_CFG); }
private static SslContext configureTLS() throws CertificateException, SSLException { SelfSignedCertificate ssc = new SelfSignedCertificate(); ApplicationProtocolConfig apn = new ApplicationProtocolConfig( Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1); return SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null) .ciphers(CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(apn).build(); }
private static SslContext configureTLS() throws CertificateException, SSLException { SelfSignedCertificate ssc = new SelfSignedCertificate(); ApplicationProtocolConfig apn = new ApplicationProtocolConfig(Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both // OpenSsl and JDK providers. SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl // and JDK providers. SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1); return SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey(), null) .ciphers(CIPHERS, SupportedCipherSuiteFilter.INSTANCE).applicationProtocolConfig(apn).build(); }
private static SslContextBuilder configure(TlsConfig config, SslContextBuilder builder) { return builder .applicationProtocolConfig(config.getAlpnConfig()) .ciphers(config.getCiphers(), SupportedCipherSuiteFilter.INSTANCE) .clientAuth(config.getClientAuth()) .enableOcsp(config.isEnableOcsp()) .protocols(config.getProtocols()) .sessionCacheSize(config.getSessionCacheSize()) .sessionTimeout(config.getSessionTimeout()) .sslProvider(config.getSslProvider()); }
/** * Set ciphers and APN appropriate for gRPC. Precisely what is set is permitted to change, so if * an application requires particular settings it should override the options set here. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1784") @CanIgnoreReturnValue public static SslContextBuilder configure(SslContextBuilder builder, SslProvider provider) { return builder.sslProvider(provider) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(selectApplicationProtocolConfig(provider)); }
private static SslContext createSslContext() { try { File serverCert = TestUtils.loadCert("server1.pem"); File key = TestUtils.loadCert("server1.key"); return GrpcSslContexts.forServer(serverCert, key) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build(); } catch (IOException ex) { throw new RuntimeException(ex); } }
@Before public void setUp() throws Exception { File serverCert = TestUtils.loadCert("server1.pem"); File key = TestUtils.loadCert("server1.key"); sslContext = GrpcSslContexts.forServer(serverCert, key) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build(); engine = SSLContext.getDefault().createSSLEngine(); }
/** * Generates an {@link SslContext} using an impersonated certificate containing the information in the specified * certificateInfo. * * @param certificateInfo certificate information to impersonate * @return an SslContext that will present the impersonated certificate to the client */ private SslContext createImpersonatingSslContext(CertificateInfo certificateInfo) { long impersonationStart = System.currentTimeMillis(); // generate a public and private key pair for the forged certificate. the SslContext will send the impersonated certificate to clients // to impersonate the real upstream server, and will use the private key to encrypt the channel. KeyPair serverKeyPair = serverKeyGenerator.generate(); // get the CA root certificate and private key that will be used to sign the forced certificate X509Certificate caRootCertificate = rootCertificate.get().getCertificate(); PrivateKey caPrivateKey = rootCertificate.get().getPrivateKey(); if (caRootCertificate == null || caPrivateKey == null) { throw new IllegalStateException("A CA root certificate and private key are required to sign a server certificate. Root certificate was: " + caRootCertificate + ". Private key was: " + caPrivateKey); } // determine if the server private key was signed with an RSA private key. though TLS no longer requires the server // certificate to use the same private key type as the root certificate, Java bug JDK-8136442 prevents Java from creating a opening an SSL socket // if the CA and server certificates are not of the same type. see https://bugs.openjdk.java.net/browse/JDK-8136442 // note this only applies to RSA CAs signing EC server certificates; Java seems to properly handle EC CAs signing // RSA server certificates. if (EncryptionUtil.isEcKey(serverKeyPair.getPrivate()) && EncryptionUtil.isRsaKey(caPrivateKey)) { log.warn("CA private key is an RSA key and impersonated server private key is an Elliptic Curve key. JDK bug 8136442 may prevent the proxy server from creating connections to clients due to 'no cipher suites in common'."); } // create the forged server certificate and sign it with the root certificate and private key CertificateAndKey impersonatedCertificateAndKey = securityProviderTool.createServerCertificate( certificateInfo, caRootCertificate, caPrivateKey, serverKeyPair, serverCertificateMessageDigest); X509Certificate[] certChain = {impersonatedCertificateAndKey.getCertificate(), caRootCertificate}; SslContext sslContext; try { sslContext = SslContextBuilder.forServer(impersonatedCertificateAndKey.getPrivateKey(), certChain) .ciphers(clientCipherSuites, SupportedCipherSuiteFilter.INSTANCE) .build(); } catch (SSLException e) { throw new MitmException("Error creating SslContext for connection to client using impersonated certificate and private key", e); } long impersonationFinish = System.currentTimeMillis(); statistics.certificateCreated(impersonationStart, impersonationFinish); log.debug("Impersonated certificate for {} in {}ms", certificateInfo.getCommonName(), impersonationFinish - impersonationStart); return sslContext; }
public static void main(String[] args) throws Exception { // Configure SSL. final SslContext sslCtx; if (SSL) { SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; SelfSignedCertificate ssc = new SelfSignedCertificate(); sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()) .sslProvider(provider) /* NOTE: the cipher filter may not include all ciphers required by the HTTP/2 specification. * Please refer to the HTTP/2 specification for cipher requirements. */ .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)) .build(); } else { sslCtx = null; } // Configure the server. EventLoopGroup group = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.option(ChannelOption.SO_BACKLOG, 1024); b.group(group) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new Http2ServerInitializer(sslCtx)); Channel ch = b.bind(PORT).sync().channel(); System.err.println("Open your HTTP/2-enabled web browser and navigate to " + (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/'); ch.closeFuture().sync(); } finally { group.shutdownGracefully(); } }
THttp2Client(String uriStr, HttpHeaders defaultHeaders) throws TTransportException { uri = URI.create(uriStr); this.defaultHeaders = defaultHeaders; int port; switch (uri.getScheme()) { case "http": port = uri.getPort(); if (port < 0) { port = 80; } sslCtx = null; break; case "https": port = uri.getPort(); if (port < 0) { port = 443; } try { sslCtx = SslContextBuilder.forClient() .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .trustManager(InsecureTrustManagerFactory.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and // JDK providers. SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and // JDK providers. SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2)) .build(); } catch (SSLException e) { throw new TTransportException(TTransportException.UNKNOWN, e); } break; default: throw new IllegalArgumentException("unknown scheme: " + uri.getScheme()); } String host = uri.getHost(); if (host == null) { throw new IllegalArgumentException("host not specified: " + uriStr); } String path = uri.getPath(); if (path == null) { throw new IllegalArgumentException("path not specified: " + uriStr); } this.host = host; this.port = port; this.path = path; }
HttpClientPipelineConfigurator(HttpClientFactory clientFactory, SessionProtocol sessionProtocol) { this.clientFactory = clientFactory; if (sessionProtocol == HTTP || sessionProtocol == HTTPS) { httpPreference = HttpPreference.HTTP2_PREFERRED; } else if (sessionProtocol == H1 || sessionProtocol == H1C) { httpPreference = HttpPreference.HTTP1_REQUIRED; } else if (sessionProtocol == H2 || sessionProtocol == H2C) { httpPreference = HttpPreference.HTTP2_REQUIRED; } else { // Should never reach here. throw new Error(); } if (sessionProtocol.isTls()) { try { final SslContextBuilder builder = SslContextBuilder.forClient(); builder.sslProvider( Flags.useOpenSsl() ? SslProvider.OPENSSL : SslProvider.JDK); clientFactory.sslContextCustomizer().accept(builder); if (httpPreference == HttpPreference.HTTP2_REQUIRED || httpPreference == HttpPreference.HTTP2_PREFERRED) { builder.ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( ApplicationProtocolConfig.Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and // JDK providers. ApplicationProtocolConfig.SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK // providers. ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2)); } sslCtx = builder.build(); } catch (SSLException e) { throw new IllegalStateException("failed to create an SslContext", e); } } else { sslCtx = null; } }
public HTTP2Client(boolean ssl, String host, int port) throws Exception { try { final SslContext sslCtx; if (ssl) { SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; sslCtx = SslContextBuilder.forClient() .sslProvider(provider) .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE) .trustManager(InsecureTrustManagerFactory.INSTANCE) .applicationProtocolConfig(new ApplicationProtocolConfig( Protocol.ALPN, // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers. SelectorFailureBehavior.NO_ADVERTISE, // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers. SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2, ApplicationProtocolNames.HTTP_1_1)) .build(); } else { sslCtx = null; } workerGroup = new NioEventLoopGroup(); HTTP2ClientInitializer initializer = new HTTP2ClientInitializer(sslCtx, Integer.MAX_VALUE); // Configure the client. Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); b.remoteAddress(host, port); b.handler(initializer); // Start the client. channel = b.connect().syncUninterruptibly().channel(); log.info("Connected to [" + host + ':' + port + ']'); // Wait for the HTTP/2 upgrade to occur. HTTP2SettingsHandler http2SettingsHandler = initializer.settingsHandler(); http2SettingsHandler.awaitSettings(TestUtil.HTTP2_RESPONSE_TIME_OUT, TestUtil.HTTP2_RESPONSE_TIME_UNIT); responseHandler = initializer.responseHandler(); scheme = ssl ? HttpScheme.HTTPS : HttpScheme.HTTP; hostName = new AsciiString(host + ':' + port); } catch (Exception ex) { log.error("Error while initializing http2 client " + ex); this.close(); } }
private ProtocolNegotiator newNegotiator() throws IOException { File caCert = TestUtils.loadCert("ca.pem"); SslContext clientContext = GrpcSslContexts.forClient().trustManager(caCert) .ciphers(TestUtils.preferredTestCiphers(), SupportedCipherSuiteFilter.INSTANCE).build(); return ProtocolNegotiators.tls(clientContext, authority); }