private static SslProvider provider(NetworkSslConfig cfg) { switch (cfg.getProvider()) { case AUTO: { return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; } case JDK: { return SslProvider.JDK; } case OPEN_SSL: { return SslProvider.OPENSSL; } default: { throw new IllegalArgumentException("Unexpected SSL provider: " + cfg.getProvider()); } } }
private synchronized static SslContext createSslContext() throws SSLException { if (sslBuilder == null) { sslBuilder = GrpcSslContexts.forClient().ciphers(null); // gRPC uses tcnative / OpenSsl by default, if it's available. It defaults to alpn-boot // if tcnative is not in the classpath. if (OpenSsl.isAvailable()) { LOG.info( "SslContext: gRPC is using the OpenSSL provider (tcnactive jar - Open Ssl version: {})", OpenSsl.versionString()); } else { if (isJettyAlpnConfigured()) { // gRPC uses jetty ALPN as a backup to tcnative. LOG.info("SslContext: gRPC is using the JDK provider (alpn-boot jar)"); } else { LOG.info("SslContext: gRPC cannot be configured. Neither OpenSsl nor Alpn are available."); } } } return sslBuilder.build(); }
@Override public List<String> get() { List<String> ciphers; if (OpenSsl.isAvailable()) { // TODO: consider switching to the list of all available ciphers using OpenSsl.availableCipherSuites() ciphers = getBuiltInCipherList(); } else { ciphers = getEnabledJdkCipherSuites(); if (ciphers.isEmpty()) { // could not retrieve the list of enabled ciphers from the JDK SSLContext, so use the hard-coded list ciphers = getBuiltInCipherList(); } } return ciphers; }
/** * Creates a new SslContext object. * * @param cfg the cfg * @return the ssl context */ private synchronized SslContext createServerSslContext(IConfig cfg){ SslContext ctx = null; try{ SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK; if(provider.equals(SslProvider.OPENSSL)){ cfg.print("Using OpenSSL for network encryption."); } ctx = SslContextBuilder .forServer(new File(cfg.getCertFile()), new File(cfg.getKeyFile()), cfg.getKeyPassword()) .sslProvider(provider) .build(); }catch(Exception e){ LOG.log(Level.SEVERE, null, e); } return ctx; }
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; }
private void logOpenSSLInfos() { if (OpenSsl.isAvailable()) { log.info("Open SSL " + OpenSsl.versionString() + " ("+OpenSsl.version()+") available"); if(OpenSsl.version() < 0x10002000L) { log.warn("Outdated OpenSSL version detected. You should update to 1.0.2k or later. Currently installed: "+OpenSsl.versionString()); } if(!OpenSsl.supportsHostnameValidation()) { log.warn("Your OpenSSL version "+OpenSsl.versionString()+" does not support hostname verification. You should update to 1.0.2k or later."); } log.debug("Open SSL available ciphers " + OpenSsl.availableOpenSslCipherSuites()); } else { log.info("Open SSL not available (this is not an error, we simply fallback to built-in JDK SSL) because of " + OpenSsl.unavailabilityCause()); } }
@Test public void testAvailCiphersOpenSSL() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); // Set<String> openSSLAvailCiphers = new // HashSet<>(OpenSsl.availableCipherSuites()); // System.out.println("OpenSSL available ciphers: "+openSSLAvailCiphers); // ECDHE-RSA-AES256-SHA, ECDH-ECDSA-AES256-SHA, DH-DSS-DES-CBC-SHA, // ADH-AES256-SHA256, ADH-CAMELLIA128-SHA final Set<String> openSSLSecureCiphers = new HashSet<>(); for (final String secure : SSLConfigConstants.getSecureSSLCiphers(Settings.EMPTY, false)) { if (OpenSsl.isCipherSuiteAvailable(secure)) { openSSLSecureCiphers.add(secure); } } System.out.println("OpenSSL secure ciphers: " + openSSLSecureCiphers); Assert.assertTrue(openSSLSecureCiphers.size() > 0); }
@Parameters(name = "{index}: serverEngine = {0}, clientEngine = {1}") public static Collection<Object[]> data() throws Exception { List<SslContext> serverContexts = new ArrayList<SslContext>(); serverContexts.add(new JdkSslServerContext(CERT_FILE, KEY_FILE)); List<SslContext> clientContexts = new ArrayList<SslContext>(); clientContexts.add(new JdkSslClientContext(CERT_FILE)); boolean hasOpenSsl = OpenSsl.isAvailable(); if (hasOpenSsl) { serverContexts.add(new OpenSslServerContext(CERT_FILE, KEY_FILE)); clientContexts.add(new OpenSslClientContext(CERT_FILE)); } else { logger.warn("OpenSSL is unavailable and thus will not be tested.", OpenSsl.unavailabilityCause()); } List<Object[]> params = new ArrayList<Object[]>(); for (SslContext sc: serverContexts) { for (SslContext cc: clientContexts) { params.add(new Object[] { sc, cc }); } } return params; }
public SslContext getSslContext() throws UnRetriableException{ try { File certificateChainFile = getCertificateChainFile(); File certificateKeyFile = getCertificateKeyFile(); String keyPassword = getKeyPassword(); SslProvider sslProvider; if(OpenSsl.isAvailable()) { sslProvider = SslProvider.OPENSSL; }else{ sslProvider = SslProvider.JDK; } return SslContext.newServerContext(sslProvider, certificateChainFile, certificateKeyFile, keyPassword ); }catch (Exception e){ log.error(" getSSLEngine : problems when trying to initiate secure protocals", e); throw new UnRetriableException(e); } }
/** * 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(); }
@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); } }
@Before public void setUp() throws NoSuchAlgorithmException { executor = Executors.newSingleThreadScheduledExecutor(); if (sslProvider == SslProvider.OPENSSL) { Assume.assumeTrue(OpenSsl.isAvailable()); } if (sslProvider == SslProvider.JDK) { Assume.assumeTrue(Arrays.asList( SSLContext.getDefault().getSupportedSSLParameters().getCipherSuites()) .contains("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")); try { GrpcSslContexts.configure(SslContextBuilder.forClient(), SslProvider.JDK); } catch (IllegalArgumentException ex) { Assume.assumeNoException("Jetty ALPN does not seem available", ex); } } clientContextBuilder = GrpcSslContexts.configure(SslContextBuilder.forClient(), sslProvider); }
/** * Selects an SSL provider based on the availability of of an ALPN-capable native provider. * * @return an ALPN-capable native SSL provider if available, or else the JDK SSL provider */ public static SslProvider getSslProvider() { final SslProvider sslProvider; if (OpenSsl.isAvailable()) { if (OpenSsl.isAlpnSupported()) { log.info("Native SSL provider is available and supports ALPN; will use native provider."); sslProvider = SslProvider.OPENSSL_REFCNT; } else { log.info("Native SSL provider is available, but does not support ALPN; will use JDK SSL provider."); sslProvider = SslProvider.JDK; } } else { log.info("Native SSL provider not available; will use JDK SSL provider."); sslProvider = SslProvider.JDK; } return sslProvider; }
public GrpcClientInitializer(ClientOptions pClientOptions, List<ClientInterceptor> clientInterceptosr, int pInitialCapacity, int pMaximumSize) { LOG.info("Rpc client initializer with initial capacity {} and maximum size {} for channel pool.", pInitialCapacity, pInitialCapacity); LOG.info("Global client options: \n'{}'.", pClientOptions); if (!isAlpnProviderEnabled()) { LOG.error( "Neither Jetty ALPN nor OpenSSL are available. " + "OpenSSL unavailability cause:\n{}", OpenSsl.unavailabilityCause().toString()); throw new IllegalStateException("Neither Jetty ALPN nor OpenSSL via " + "netty-tcnative were properly configured."); } Preconditions .checkState( !AbstractNameResolverProvider.providers().isEmpty(), "No NameResolverProviders found via ServiceLoader, including for DNS. " + "This is probably due to a broken build. If using ProGuard, check your configuration"); globalClientOptions = pClientOptions; channelPool = createChannelPool(globalClientOptions, clientInterceptosr, pInitialCapacity, pMaximumSize); ClientMetrics.counter(MetricLevel.Info, "Initializer.active").inc(); }
/** * <p> * isAlpnProviderEnabled. * </p> * * @return a boolean. */ public static boolean isAlpnProviderEnabled() { final boolean openSslAvailable = OpenSsl.isAvailable(); final boolean jettyAlpnConfigured = isJettyAlpnConfigured(); LOG.debug("OpenSSL available: '{}'", openSslAvailable); LOG.debug("Jetty ALPN available: '{}'", jettyAlpnConfigured); return openSslAvailable || jettyAlpnConfigured; }
@Test public void openSSLAvailable() throws InterruptedException { assertThat( "OpenSsl unavailable:" + OpenSsl.unavailabilityCause(), OpenSsl.isAvailable(), equalTo(true)); assertThat( "OpenSsl suppose to be default", SslContext.defaultServerProvider(), equalTo(SslProvider.OPENSSL)); assertThat( "OpenSsl suppose to be default", SslContext.defaultClientProvider(), equalTo(SslProvider.OPENSSL)); }
@Test public void testEnsureOpenSSLAvailability() { //Assert.assertTrue("OpenSSL not available: "+String.valueOf(OpenSsl.unavailabilityCause()), OpenSsl.isAvailable()); final String OpenSSLOptional = System.getenv("SG_TEST_OPENSSL_OPT"); System.out.println("SG_TEST_OPENSSL_OPT "+OpenSSLOptional); if(!Boolean.parseBoolean(OpenSSLOptional)) { System.out.println("OpenSSL must be available"); Assert.assertTrue("OpenSSL not available: "+String.valueOf(OpenSsl.unavailabilityCause()), OpenSsl.isAvailable()); } else { System.out.println("OpenSSL can be available"); } }
public static boolean isOpenSslAvailable() { if (openSslAvailable != null) { return openSslAvailable; } if (ENABLE_OPENSSL && OpenSsl.isAvailable()) { OpenSsl.ensureAvailability(); openSslAvailable = true; } else { Throwable cause = OpenSsl.unavailabilityCause(); LOG.log(Level.INFO, "Native OpenSSL support is not available on this platform: " + cause); openSslAvailable = false; } return openSslAvailable; }
public SslProvider getSslProvider() { if (useOpenSsl) { if (!OpenSsl.isAvailable()) { throw new IllegalStateException("useOpenSsl = true and OpenSSL is not available"); } return SslProvider.OPENSSL; } return SslProvider.JDK; }
@Test public void standaloneWithOpenSsl() { assumeTrue(OpenSsl.isAvailable()); SslOptions sslOptions = SslOptions.builder() // .openSslProvider() // .truststore(TRUSTSTORE_FILE) // .build(); setOptions(sslOptions); verifyConnection(URI_VERIFY); }
@Test(expected = RedisConnectionException.class) public void standaloneWithOpenSslFailsWithWrongTruststore() { assumeTrue(OpenSsl.isAvailable()); SslOptions sslOptions = SslOptions.builder() // .openSslProvider() // .build(); setOptions(sslOptions); verifyConnection(URI_VERIFY); }
@Test public void http2jdk() throws Exception { new MockUnit(HttpHandler.class) .expect(ssl(null)) .expect(unit -> { unit.mockStatic(OpenSsl.class); expect(OpenSsl.isAlpnSupported()).andReturn(false); }) .expect(alpn(SslProvider.JDK)) .run(unit -> { assertNotNull(NettySslContext .build(conf.withValue("server.http2.enabled", ConfigValueFactory.fromAnyRef(true)))); }); }
@Test public void http2OpenSSL() throws Exception { new MockUnit(HttpHandler.class) .expect(ssl(null)) .expect(unit -> { unit.mockStatic(OpenSsl.class); expect(OpenSsl.isAlpnSupported()).andReturn(true); }) .expect(alpn(SslProvider.OPENSSL)) .run(unit -> { assertNotNull(NettySslContext .build(conf.withValue("server.http2.enabled", ConfigValueFactory.fromAnyRef(true)))); }); }
/** * Attempts to select the best {@link ApplicationProtocolConfig} for the given * {@link SslProvider}. */ private static ApplicationProtocolConfig selectApplicationProtocolConfig(SslProvider provider) { switch (provider) { case JDK: { if (JettyTlsUtil.isJettyAlpnConfigured()) { return ALPN; } if (JettyTlsUtil.isJettyNpnConfigured()) { return NPN; } if (JettyTlsUtil.isJava9AlpnAvailable()) { return ALPN; } // Use the ALPN cause since it is prefered. throw new IllegalArgumentException( "ALPN is not configured properly. See https://github.com/grpc/grpc-java/blob/master/SECURITY.md#troubleshooting" + " for more information.", JettyTlsUtil.getJettyAlpnUnavailabilityCause()); } case OPENSSL: { if (!OpenSsl.isAvailable()) { throw new IllegalArgumentException( "OpenSSL is not installed on the system.", OpenSsl.unavailabilityCause()); } return OpenSsl.isAlpnSupported() ? NPN_AND_ALPN : NPN; } default: throw new IllegalArgumentException("Unsupported provider: " + provider); } }
public static Collection<HekateTestContext> all() { List<NetworkSslConfig> sslProvider = new ArrayList<>(); // SSL disabled. if (HekateTestProps.is("NO_SSL_ENABLED")) { sslProvider.add(null); } // JDK SSL provider. if (HekateTestProps.is("SSL_JDK_ENABLED")) { sslProvider.add(new NetworkSslConfig() .withProvider(NetworkSslConfig.Provider.JDK) .withKeyStorePath(KEY_STORE_PATH) .withKeyStorePassword(KEY_STORE_PASSWORD) .withSslSessionCacheSize(1024) .withSslSessionCacheTimeout(10) ); } // OpenSSL provider. if (HekateTestProps.is("SSL_OPENSSL_ENABLED") && OpenSsl.isAvailable()) { sslProvider.add(new NetworkSslConfig() .withProvider(NetworkSslConfig.Provider.OPEN_SSL) .withKeyStorePath(KEY_STORE_PATH) .withKeyStorePassword(KEY_STORE_PASSWORD) .withSslSessionCacheSize(1024) .withSslSessionCacheTimeout(10) ); } List<NetworkTransportType> transports = new ArrayList<>(); if (HekateTestProps.is("NIO_ENABLED")) { transports.add(NetworkTransportType.NIO); } if (HekateTestProps.is("EPOLL_ENABLED") && Epoll.isAvailable()) { transports.add(NetworkTransportType.EPOLL); } assertFalse("Network transports are not configured", transports.isEmpty()); assertFalse("SSL transports are not configured", sslProvider.isEmpty()); return transports.stream() .flatMap(transport -> sslProvider.stream().flatMap(ssl -> Stream.of( new HekateTestContext(transport, Optional.ofNullable(ssl)) ) ) ).collect(toList()); }
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(); } }
@Bean @ConditionalOnMissingBean(TraceConsumer.class) TraceConsumer traceConsumer(Credentials credentials) throws IOException { Preconditions.checkState(OpenSsl.isAvailable(), "OpenSsl required"); return GrpcTraceConsumer.create(storageProperties.getApiHost(), credentials); }
@Provides static SslProvider provideSslProvider() { // Prefer OpenSSL. return OpenSsl.isAvailable() ? SslProvider.OPENSSL : SslProvider.JDK; }
@Test public void testEnsureOpenSSLAvailability() { Assume.assumeTrue(allowOpenSSL); Assert.assertTrue(String.valueOf(OpenSsl.unavailabilityCause()), OpenSsl.isAvailable()); }
@Override @Test public void testHttps() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testHttps(); }
@Override @Test public void testHttpsAndNodeSSL() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testHttpsAndNodeSSL(); }
@Override @Test public void testHttpPlainFail() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testHttpPlainFail(); }
@Override @Test public void testHttpsNoEnforce() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testHttpsNoEnforce(); }
@Override @Test public void testHttpsV3Fail() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testHttpsV3Fail(); }
@Override @Test(timeout=40000) public void testTransportClientSSL() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testTransportClientSSL(); }
@Override @Test(timeout=40000) public void testNodeClientSSL() throws Exception { Assume.assumeTrue(OpenSsl.isAvailable()); super.testNodeClientSSL(); }