All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.thrift.transport.TSSLTransportFactory Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.thrift.transport;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.util.Arrays;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A Factory for providing and setting up Client and Server SSL wrapped TSocket and TServerSocket
 */
public class TSSLTransportFactory {

  private static final Logger LOGGER = LoggerFactory.getLogger(TSSLTransportFactory.class);

  /**
   * Get a SSL wrapped TServerSocket bound to the specified port. In this configuration the default
   * settings are used. Default settings are retrieved from System properties that are set.
   *
   * 

Example system properties: -Djavax.net.ssl.trustStore=<truststore location> * -Djavax.net.ssl.trustStorePassword=password -Djavax.net.ssl.keyStore=<keystore location> * -Djavax.net.ssl.keyStorePassword=password * * @param port server port * @return A SSL wrapped TServerSocket * @throws TTransportException when failed to create server socket */ public static TServerSocket getServerSocket(int port) throws TTransportException { return getServerSocket(port, 0); } /** * Get a default SSL wrapped TServerSocket bound to the specified port * * @param port * @param clientTimeout * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket(int port, int clientTimeout) throws TTransportException { return getServerSocket(port, clientTimeout, false, null); } /** * Get a default SSL wrapped TServerSocket bound to the specified port and interface * * @param port * @param clientTimeout * @param ifAddress * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket( int port, int clientTimeout, boolean clientAuth, InetAddress ifAddress) throws TTransportException { SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); return createServer(factory, port, clientTimeout, clientAuth, ifAddress, null); } /** * Get a configured SSL wrapped TServerSocket bound to the specified port and interface. Here the * TSSLTransportParameters are used to set the values for the algorithms, keystore, truststore and * other settings * * @param port * @param clientTimeout * @param ifAddress * @param params * @return A SSL wrapped TServerSocket * @throws TTransportException */ public static TServerSocket getServerSocket( int port, int clientTimeout, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { throw new TTransportException( "Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); } SSLContext ctx = createSSLContext(params); return createServer( ctx.getServerSocketFactory(), port, clientTimeout, params.clientAuth, ifAddress, params); } private static TServerSocket createServer( SSLServerSocketFactory factory, int port, int timeout, boolean clientAuth, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException { try { SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 100, ifAddress); serverSocket.setSoTimeout(timeout); serverSocket.setNeedClientAuth(clientAuth); if (params != null && params.cipherSuites != null) { serverSocket.setEnabledCipherSuites(params.cipherSuites); } return new TServerSocket( new TServerSocket.ServerSocketTransportArgs() .serverSocket(serverSocket) .clientTimeout(timeout)); } catch (Exception e) { throw new TTransportException("Could not bind to port " + port, e); } } /** * Get a default SSL wrapped TSocket connected to the specified host and port. All the client * methods return a bound connection. So there is no need to call open() on the TTransport. * * @param host * @param port * @param timeout * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket(String host, int port, int timeout) throws TTransportException { SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); return createClient(factory, host, port, timeout); } /** * Get a default SSL wrapped TSocket connected to the specified host and port. * * @param host * @param port * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket(String host, int port) throws TTransportException { return getClientSocket(host, port, 0); } /** * Get a custom configured SSL wrapped TSocket. The SSL settings are obtained from the passed in * TSSLTransportParameters. * * @param host * @param port * @param timeout * @param params * @return A SSL wrapped TSocket * @throws TTransportException */ public static TSocket getClientSocket( String host, int port, int timeout, TSSLTransportParameters params) throws TTransportException { if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) { throw new TTransportException( TTransportException.NOT_OPEN, "Either one of the KeyStore or TrustStore must be set for SSLTransportParameters"); } SSLContext ctx = createSSLContext(params); return createClient(ctx.getSocketFactory(), host, port, timeout); } private static SSLContext createSSLContext(TSSLTransportParameters params) throws TTransportException { SSLContext ctx; InputStream in = null; InputStream is = null; try { ctx = SSLContext.getInstance(params.protocol); TrustManagerFactory tmf = null; KeyManagerFactory kmf = null; if (params.isTrustStoreSet) { tmf = TrustManagerFactory.getInstance(params.trustManagerType); KeyStore ts = KeyStore.getInstance(params.trustStoreType); if (params.trustStoreStream != null) { in = params.trustStoreStream; } else { in = getStoreAsStream(params.trustStore); } ts.load(in, (params.trustPass != null ? params.trustPass.toCharArray() : null)); tmf.init(ts); } if (params.isKeyStoreSet) { kmf = KeyManagerFactory.getInstance(params.keyManagerType); KeyStore ks = KeyStore.getInstance(params.keyStoreType); if (params.keyStoreStream != null) { is = params.keyStoreStream; } else { is = getStoreAsStream(params.keyStore); } ks.load(is, params.keyPass.toCharArray()); kmf.init(ks, params.keyPass.toCharArray()); } if (params.isKeyStoreSet && params.isTrustStoreSet) { ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); } else if (params.isKeyStoreSet) { ctx.init(kmf.getKeyManagers(), null, null); } else { ctx.init(null, tmf.getTrustManagers(), null); } } catch (Exception e) { throw new TTransportException( TTransportException.NOT_OPEN, "Error creating the transport", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { LOGGER.warn("Unable to close stream", e); } } if (is != null) { try { is.close(); } catch (IOException e) { LOGGER.warn("Unable to close stream", e); } } } return ctx; } private static InputStream getStoreAsStream(String store) throws IOException { try { return new FileInputStream(store); } catch (FileNotFoundException e) { } InputStream storeStream; try { storeStream = new URL(store).openStream(); if (storeStream != null) { return storeStream; } } catch (MalformedURLException e) { } storeStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(store); if (storeStream != null) { return storeStream; } else { throw new IOException("Could not load file: " + store); } } private static TSocket createClient(SSLSocketFactory factory, String host, int port, int timeout) throws TTransportException { try { SSLSocket socket = (SSLSocket) factory.createSocket(host, port); socket.setSoTimeout(timeout); return new TSocket(socket); } catch (TTransportException tte) { throw tte; } catch (Exception e) { throw new TTransportException( TTransportException.NOT_OPEN, "Could not connect to " + host + " on port " + port, e); } } /** A Class to hold all the SSL parameters */ public static class TSSLTransportParameters { protected String protocol = "TLS"; protected String keyStore; protected InputStream keyStoreStream; protected String keyPass; protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm(); protected String keyStoreType = "JKS"; protected String trustStore; protected InputStream trustStoreStream; protected String trustPass; protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm(); protected String trustStoreType = "JKS"; protected String[] cipherSuites; protected boolean clientAuth = false; protected boolean isKeyStoreSet = false; protected boolean isTrustStoreSet = false; public TSSLTransportParameters() {} /** * Create parameters specifying the protocol and cipher suites * * @param protocol The specific protocol (TLS/SSL) can be specified with versions * @param cipherSuites */ public TSSLTransportParameters(String protocol, String[] cipherSuites) { this(protocol, cipherSuites, false); } /** * Create parameters specifying the protocol, cipher suites and if client authentication is * required * * @param protocol The specific protocol (TLS/SSL) can be specified with versions * @param cipherSuites * @param clientAuth */ public TSSLTransportParameters(String protocol, String[] cipherSuites, boolean clientAuth) { if (protocol != null) { this.protocol = protocol; } this.cipherSuites = cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null; this.clientAuth = clientAuth; } /** * Set the keystore, password, certificate type and the store type * * @param keyStore Location of the Keystore on disk * @param keyPass Keystore password * @param keyManagerType The default is X509 * @param keyStoreType The default is JKS */ public void setKeyStore( String keyStore, String keyPass, String keyManagerType, String keyStoreType) { this.keyStore = keyStore; this.keyPass = keyPass; if (keyManagerType != null) { this.keyManagerType = keyManagerType; } if (keyStoreType != null) { this.keyStoreType = keyStoreType; } isKeyStoreSet = true; } /** * Set the keystore, password, certificate type and the store type * * @param keyStoreStream Keystore content input stream * @param keyPass Keystore password * @param keyManagerType The default is X509 * @param keyStoreType The default is JKS */ public void setKeyStore( InputStream keyStoreStream, String keyPass, String keyManagerType, String keyStoreType) { this.keyStoreStream = keyStoreStream; setKeyStore("", keyPass, keyManagerType, keyStoreType); } /** * Set the keystore and password * * @param keyStore Location of the Keystore on disk * @param keyPass Keystore password */ public void setKeyStore(String keyStore, String keyPass) { setKeyStore(keyStore, keyPass, null, null); } /** * Set the keystore and password * * @param keyStoreStream Keystore content input stream * @param keyPass Keystore password */ public void setKeyStore(InputStream keyStoreStream, String keyPass) { setKeyStore(keyStoreStream, keyPass, null, null); } /** * Set the truststore, password, certificate type and the store type * * @param trustStore Location of the Truststore on disk * @param trustPass Truststore password * @param trustManagerType The default is X509 * @param trustStoreType The default is JKS */ public void setTrustStore( String trustStore, String trustPass, String trustManagerType, String trustStoreType) { this.trustStore = trustStore; this.trustPass = trustPass; if (trustManagerType != null) { this.trustManagerType = trustManagerType; } if (trustStoreType != null) { this.trustStoreType = trustStoreType; } isTrustStoreSet = true; } /** * Set the truststore, password, certificate type and the store type * * @param trustStoreStream Truststore content input stream * @param trustPass Truststore password * @param trustManagerType The default is X509 * @param trustStoreType The default is JKS */ public void setTrustStore( InputStream trustStoreStream, String trustPass, String trustManagerType, String trustStoreType) { this.trustStoreStream = trustStoreStream; setTrustStore("", trustPass, trustManagerType, trustStoreType); } /** * Set the truststore and password * * @param trustStore Location of the Truststore on disk * @param trustPass Truststore password */ public void setTrustStore(String trustStore, String trustPass) { setTrustStore(trustStore, trustPass, null, null); } /** * Set the truststore and password * * @param trustStoreStream Truststore content input stream * @param trustPass Truststore password */ public void setTrustStore(InputStream trustStoreStream, String trustPass) { setTrustStore(trustStoreStream, trustPass, null, null); } /** * Set if client authentication is required * * @param clientAuth */ public void requireClientAuth(boolean clientAuth) { this.clientAuth = clientAuth; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy