use of io.netty.handler.ssl.ClientAuth in project flink by apache.
the class SSLUtils method createRestClientSSLEngineFactory.
/**
* Creates a {@link SSLHandlerFactory} to be used by the REST Clients.
*
* @param config The application configuration.
*/
public static SSLHandlerFactory createRestClientSSLEngineFactory(final Configuration config) throws Exception {
ClientAuth clientAuth = SecurityOptions.isRestSSLAuthenticationEnabled(config) ? ClientAuth.REQUIRE : ClientAuth.NONE;
SslContext sslContext = createRestNettySSLContext(config, true, clientAuth);
if (sslContext == null) {
throw new IllegalConfigurationException("SSL is not enabled for REST endpoints.");
}
return new SSLHandlerFactory(sslContext, -1, -1);
}
use of io.netty.handler.ssl.ClientAuth in project flink by apache.
the class SSLUtils method createInternalNettySSLContext.
/**
* Creates the SSL Context for internal SSL, if internal SSL is configured. For internal SSL,
* the client and server side configuration are identical, because of mutual authentication.
*/
@Nullable
private static SslContext createInternalNettySSLContext(Configuration config, boolean clientMode, SslProvider provider) throws Exception {
checkNotNull(config, "config");
if (!SecurityOptions.isInternalSSLEnabled(config)) {
return null;
}
String[] sslProtocols = getEnabledProtocols(config);
List<String> ciphers = Arrays.asList(getEnabledCipherSuites(config));
int sessionCacheSize = config.getInteger(SecurityOptions.SSL_INTERNAL_SESSION_CACHE_SIZE);
int sessionTimeoutMs = config.getInteger(SecurityOptions.SSL_INTERNAL_SESSION_TIMEOUT);
KeyManagerFactory kmf = getKeyManagerFactory(config, true, provider);
TrustManagerFactory tmf = getTrustManagerFactory(config, true);
ClientAuth clientAuth = ClientAuth.REQUIRE;
final SslContextBuilder sslContextBuilder;
if (clientMode) {
sslContextBuilder = SslContextBuilder.forClient().keyManager(kmf);
} else {
sslContextBuilder = SslContextBuilder.forServer(kmf);
}
return sslContextBuilder.sslProvider(provider).protocols(sslProtocols).ciphers(ciphers).trustManager(tmf).clientAuth(clientAuth).sessionCacheSize(sessionCacheSize).sessionTimeout(sessionTimeoutMs / 1000).build();
}
use of io.netty.handler.ssl.ClientAuth in project zuul by Netflix.
the class SslHandshakeInfoHandler method userEventTriggered.
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof SslHandshakeCompletionEvent) {
try {
SslHandshakeCompletionEvent sslEvent = (SslHandshakeCompletionEvent) evt;
if (sslEvent.isSuccess()) {
CurrentPassport.fromChannel(ctx.channel()).add(PassportState.SERVER_CH_SSL_HANDSHAKE_COMPLETE);
SslHandler sslhandler = ctx.channel().pipeline().get(SslHandler.class);
SSLSession session = sslhandler.engine().getSession();
ClientAuth clientAuth = whichClientAuthEnum(sslhandler);
Certificate serverCert = null;
X509Certificate peerCert = null;
if ((clientAuth == ClientAuth.REQUIRE || clientAuth == ClientAuth.OPTIONAL) && session.getPeerCertificates() != null && session.getPeerCertificates().length > 0) {
peerCert = (X509Certificate) session.getPeerCertificates()[0];
}
if (session.getLocalCertificates() != null && session.getLocalCertificates().length > 0) {
serverCert = session.getLocalCertificates()[0];
}
SslHandshakeInfo info = new SslHandshakeInfo(isSSlFromIntermediary, session.getProtocol(), session.getCipherSuite(), clientAuth, serverCert, peerCert);
ctx.channel().attr(ATTR_SSL_INFO).set(info);
// Metrics.
incrementCounters(sslEvent, info);
logger.debug("Successful SSL Handshake: {}", info);
} else {
String clientIP = ctx.channel().attr(SourceAddressChannelHandler.ATTR_SOURCE_ADDRESS).get();
Throwable cause = sslEvent.cause();
PassportState passportState = CurrentPassport.fromChannel(ctx.channel()).getState();
if (cause instanceof ClosedChannelException && (PassportState.SERVER_CH_INACTIVE.equals(passportState) || PassportState.SERVER_CH_IDLE_TIMEOUT.equals(passportState))) {
// Either client closed the connection without/before having completed a handshake, or
// the connection idle timed-out before handshake.
// NOTE: we were seeing a lot of these in prod and can repro by just telnetting to port and then closing terminal
// without sending anything.
// So don't treat these as SSL handshake failures.
logger.debug("Client closed connection or it idle timed-out without doing an ssl handshake. " + ", client_ip = " + clientIP + ", channel_info = " + ChannelUtils.channelInfoForLogging(ctx.channel()));
} else if (cause instanceof SSLException && cause.getMessage().contains("handshake timed out")) {
logger.debug("Client timed-out doing the ssl handshake. " + ", client_ip = " + clientIP + ", channel_info = " + ChannelUtils.channelInfoForLogging(ctx.channel()));
} else if (cause instanceof SSLException && cause.getMessage().contains("failure when writing TLS control frames")) {
// This can happen if the ClientHello is sent followed by a RST packet, before we can respond.
logger.debug("Client terminated handshake early." + ", client_ip = " + clientIP + ", channel_info = " + ChannelUtils.channelInfoForLogging(ctx.channel()));
} else {
String msg = "Unsuccessful SSL Handshake: " + sslEvent + ", client_ip = " + clientIP + ", channel_info = " + ChannelUtils.channelInfoForLogging(ctx.channel()) + ", error = " + cause;
if (cause instanceof ClosedChannelException) {
logger.debug(msg);
} else {
logger.debug(msg, cause);
}
incrementCounters(sslEvent, null);
}
}
} catch (Throwable e) {
logger.warn("Error getting the SSL handshake info.", e);
} finally {
// Now remove this handler from the pipeline as no longer needed once the ssl handshake has completed.
ctx.pipeline().remove(this);
}
} else if (evt instanceof SslCloseCompletionEvent) {
// TODO - increment a separate metric for this event?
} else if (evt instanceof SniCompletionEvent) {
logger.debug("SNI Parsing Complete: {}", evt);
SniCompletionEvent sniCompletionEvent = (SniCompletionEvent) evt;
if (sniCompletionEvent.isSuccess()) {
spectatorRegistry.counter("zuul.sni.parse.success").increment();
} else {
Throwable cause = sniCompletionEvent.cause();
spectatorRegistry.counter("zuul.sni.parse.failure", "cause", cause != null ? cause.getMessage() : "UNKNOWN").increment();
}
}
super.userEventTriggered(ctx, evt);
}
use of io.netty.handler.ssl.ClientAuth in project xipki by xipki.
the class HttpServers method buildSslContext.
private SslContext buildSslContext(HttpserverType conf) throws Exception {
TlsType tt = conf.getTls();
if (tt == null) {
return null;
}
KeystoreType kst = tt.getKeystore();
SslContextBuilder builder;
// key and certificate
if (kst == null) {
throw new IllegalArgumentException("no keystore is configured");
} else {
char[] kstPwd = passwordResolver.resolvePassword(kst.getPassword());
KeyStore ks = loadKeyStore(kst.getType(), kst.getStore(), kstPwd);
String alias = kst.getKeyAlias();
if (alias != null) {
if (!ks.isKeyEntry(alias)) {
throw new Exception("'" + alias + "' is not a valid key alias");
}
} else {
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String al = aliases.nextElement();
if (ks.isKeyEntry(al)) {
alias = al;
break;
}
}
if (alias == null) {
throw new Exception("found no key entries in the keystore");
}
}
char[] keypwd = (kst.getKeyPassword() == null) ? kstPwd : passwordResolver.resolvePassword(kst.getKeyPassword());
PrivateKey key = (PrivateKey) ks.getKey(alias, keypwd);
Certificate[] certs = ks.getCertificateChain(alias);
X509Certificate[] keyCertChain = new X509Certificate[certs.length];
for (int i = 0; i < certs.length; i++) {
keyCertChain[i] = (X509Certificate) certs[i];
}
builder = SslContextBuilder.forServer(key, keyCertChain);
}
boolean opensslAvailable = OpenSsl.isAvailable();
// providers
SslProvider sslProvider;
if (tt.getProvider() == null) {
if (!opensslAvailable) {
logOpenSslWarning();
}
sslProvider = SslContext.defaultServerProvider();
} else {
String providerStr = tt.getProvider();
String providerStr0 = providerStr.toLowerCase().replaceAll("[^a-z0-9]+", "");
if ("jdk".equals(providerStr0)) {
sslProvider = SslProvider.JDK;
} else if ("openssl".equals(providerStr0) || "opensslrefcnt".equals(providerStr0)) {
if (!opensslAvailable) {
logOpenSslWarning();
throw new Exception("OpenSSL not available");
}
sslProvider = "openssl".equals(providerStr0) ? SslProvider.OPENSSL : SslProvider.OPENSSL_REFCNT;
} else {
throw new Exception("unknwon SSL provider " + providerStr);
}
}
LOG.info("use SSL provider {}", sslProvider);
builder.sslProvider(sslProvider);
List<String> availableProtocols;
List<String> availableCiphersuits;
switch(sslProvider) {
case JDK:
SSLParameters sslParams = SSLContext.getDefault().getSupportedSSLParameters();
availableProtocols = Arrays.asList(sslParams.getProtocols());
availableCiphersuits = Arrays.asList(sslParams.getCipherSuites());
break;
case OPENSSL:
case OPENSSL_REFCNT:
// any way to get the supported protocols of OpenSSL?
availableProtocols = Arrays.asList("TLSv1.1", "TLSv1.2");
availableCiphersuits = new ArrayList<>(OpenSsl.availableJavaCipherSuites());
break;
default:
throw new RuntimeException("should not reach here, unknown SssProvider " + sslProvider);
}
// protocols
List<String> protocols;
if (tt.getProtocols() != null) {
protocols = tt.getProtocols().getProtocol();
} else {
protocols = Arrays.asList("TLSv1.1", "TLSv1.2");
}
final String[] strArray = new String[0];
Set<String> usedProtocols = new HashSet<>();
for (String protocol : protocols) {
boolean added = false;
for (String supported : availableProtocols) {
if (protocol.equalsIgnoreCase(supported)) {
usedProtocols.add(supported);
added = true;
break;
}
}
if (!added) {
LOG.warn("SSL Protocol {} unsupported, ignore it", protocol);
}
}
if (usedProtocols.isEmpty()) {
throw new Exception("None of the configured SSL protocols is supported");
}
LOG.info("use SSL protocols {}", usedProtocols);
builder.protocols(usedProtocols.toArray(strArray));
// canonicalize the cipher suites
boolean cipherWithTls = availableCiphersuits.get(0).startsWith("TLS_");
// cipher suites
Set<String> usedCipherSuites = new HashSet<>();
if (tt.getCiphersuites() != null) {
for (String cipherSuite : tt.getCiphersuites().getCiphersuite()) {
if (cipherSuite.length() < 5) {
LOG.warn("cipher suite {} unsupported, ignore it", cipherSuite);
continue;
}
String adaptedCipher;
if (cipherWithTls == cipherSuite.startsWith("TLS_")) {
adaptedCipher = cipherSuite;
} else {
if (cipherWithTls) {
adaptedCipher = "TLS_" + cipherSuite.substring(4);
} else {
adaptedCipher = "SSL_" + cipherSuite.substring(4);
}
}
boolean added = false;
for (String supported : availableCiphersuits) {
if (adaptedCipher.equalsIgnoreCase(supported)) {
usedCipherSuites.add(supported);
added = true;
break;
}
}
if (!added) {
LOG.warn("SSL cipher suite {} unsupported, ignore it", cipherSuite);
}
}
} else {
String[] excludeMiddlePatterns = { "_3DES", "_DES", "EMPTY", "EXPORT", "anno", "NULL" };
String[] excludeEndPatterns = { "MD5", "SHA" };
for (String cipherSuite : availableCiphersuits) {
boolean add = true;
for (String p : excludeMiddlePatterns) {
if (cipherSuite.contains(p)) {
add = false;
break;
}
}
if (add) {
for (String p : excludeEndPatterns) {
if (cipherSuite.endsWith(p)) {
add = false;
break;
}
}
}
if (add) {
usedCipherSuites.add(cipherSuite);
}
}
}
LOG.info("use SSL cipher suites {}", usedCipherSuites);
builder.ciphers(usedCipherSuites);
// client authentication
ClientAuth clientAuth;
String str = tt.getClientauth();
if ("none".equalsIgnoreCase(str)) {
clientAuth = ClientAuth.NONE;
} else if ("optional".equalsIgnoreCase(str)) {
clientAuth = ClientAuth.OPTIONAL;
} else if ("require".equalsIgnoreCase(str)) {
clientAuth = ClientAuth.REQUIRE;
} else {
throw new Exception("invalid client authentication '" + str + "'");
}
builder.clientAuth(clientAuth);
if (clientAuth != ClientAuth.NONE) {
TruststoreType tst = tt.getTruststore();
if (tst == null) {
throw new Exception("Client authentication is activated, but no truststore is configured");
}
char[] pwd = passwordResolver.resolvePassword(tst.getPassword());
KeyStore ks = loadKeyStore(tst.getType(), tst.getStore(), pwd);
List<X509Certificate> trustcerts = new LinkedList<>();
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = aliases.nextElement();
Certificate cert = ks.getCertificate(alias);
trustcerts.add((X509Certificate) cert);
}
if (trustcerts.isEmpty()) {
throw new Exception("No certificates found int the truststore. Please verify it via" + " JDK's keytool.");
}
builder.trustManager(trustcerts.toArray(new X509Certificate[0]));
}
return builder.build();
}
use of io.netty.handler.ssl.ClientAuth in project flink by apache.
the class SSLUtils method createRestServerSSLEngineFactory.
/**
* Creates a {@link SSLHandlerFactory} to be used by the REST Servers.
*
* @param config The application configuration.
*/
public static SSLHandlerFactory createRestServerSSLEngineFactory(final Configuration config) throws Exception {
ClientAuth clientAuth = SecurityOptions.isRestSSLAuthenticationEnabled(config) ? ClientAuth.REQUIRE : ClientAuth.NONE;
SslContext sslContext = createRestNettySSLContext(config, false, clientAuth);
if (sslContext == null) {
throw new IllegalConfigurationException("SSL is not enabled for REST endpoints.");
}
return new SSLHandlerFactory(sslContext, -1, -1);
}
Aggregations