IGNITE-323 Extracted SSLFactory.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/26a038c8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/26a038c8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/26a038c8 Branch: refs/heads/ignite-323 Commit: 26a038c8fed0ebb9a0ddf7facfd8063ad9df7fb5 Parents: 4c5a663 Author: nikolay_tikhonov <ntikho...@gridgain.com> Authored: Tue Jul 21 21:00:34 2015 +0300 Committer: nikolay_tikhonov <ntikho...@gridgain.com> Committed: Tue Jul 21 21:00:34 2015 +0300 ---------------------------------------------------------------------- .../configuration/ConnectorConfiguration.java | 32 ++ .../configuration/IgniteConfiguration.java | 12 +- .../client/ssl/GridSslBasicContextFactory.java | 3 + .../client/ssl/GridSslContextFactory.java | 5 +- .../rest/protocols/tcp/GridTcpRestProtocol.java | 17 +- .../communication/tcp/TcpCommunicationSpi.java | 12 +- .../spi/discovery/tcp/TcpDiscoverySpi.java | 4 +- .../apache/ignite/ssl/SslContextFactory.java | 455 +++++++++++++++++++ .../org/apache/ignite/ssl/package-info.java | 22 + .../GridAbstractCommunicationSelfTest.java | 2 +- .../discovery/AbstractDiscoverySelfTest.java | 2 +- .../discovery/tcp/TcpDiscoverySslSelfTest.java | 2 +- .../ignite/testframework/GridTestUtils.java | 20 + .../IgniteSpiDiscoverySelfTestSuite.java | 1 - 14 files changed, 568 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/configuration/ConnectorConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/ConnectorConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/ConnectorConfiguration.java index 970c54b..a518cd8 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/ConnectorConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/ConnectorConfiguration.java @@ -19,8 +19,12 @@ package org.apache.ignite.configuration; import org.apache.ignite.*; import org.apache.ignite.internal.client.ssl.*; +import org.apache.ignite.ssl.*; + import org.jetbrains.annotations.*; +import javax.cache.configuration.*; +import javax.net.ssl.*; import java.net.*; /** @@ -99,6 +103,9 @@ public class ConnectorConfiguration { /** SSL context factory for rest binary server. */ private GridSslContextFactory sslCtxFactory; + /** SSL context factory for rest binary server. */ + private Factory<SSLContext> sslFactory; + /** Port range */ private int portRange = DFLT_PORT_RANGE; @@ -429,7 +436,9 @@ public class ConnectorConfiguration { * * @return SslContextFactory instance. * @see GridSslContextFactory + * @deprecated Use {@link #getSslFactory()} instead. */ + @Deprecated public GridSslContextFactory getSslContextFactory() { return sslCtxFactory; } @@ -440,12 +449,35 @@ public class ConnectorConfiguration { * {@link #setSslEnabled(boolean)} is set to {@code true}. * * @param sslCtxFactory Instance of {@link GridSslContextFactory} + * @deprecated Use {@link #setSslFactory(Factory)} instead. */ + @Deprecated public void setSslContextFactory(GridSslContextFactory sslCtxFactory) { this.sslCtxFactory = sslCtxFactory; } /** + * Gets context factory that will be used for creating a secure socket layer of rest binary server. + * + * @return SSL context factory instance. + * @see SslContextFactory + */ + public Factory<SSLContext> getSslFactory() { + return sslFactory; + } + + /** + * Sets instance of {@link Factory<SSLContext>} that will be used to create an instance of {@code SSLContext} + * for Secure Socket Layer on TCP binary protocol. This factory will only be used if + * {@link #setSslEnabled(boolean)} is set to {@code true}. + * + * @param sslFactory Instance of {@link Factory<SSLContext>} + */ + public void setSslFactory(Factory<SSLContext> sslFactory) { + this.sslFactory = sslFactory; + } + + /** * Gets number of ports to try if configured port is already in use. * * @return Number of ports to try. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java index bd16fbe..ddcc1f8 100644 --- a/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java +++ b/modules/core/src/main/java/org/apache/ignite/configuration/IgniteConfiguration.java @@ -53,6 +53,7 @@ import org.apache.ignite.spi.loadbalancing.*; import org.apache.ignite.spi.loadbalancing.roundrobin.*; import org.apache.ignite.spi.swapspace.*; import org.apache.ignite.spi.swapspace.file.*; +import org.apache.ignite.ssl.*; import javax.cache.configuration.*; import javax.cache.event.*; @@ -60,6 +61,7 @@ import javax.cache.expiry.*; import javax.cache.integration.*; import javax.cache.processor.*; import javax.management.*; +import javax.net.ssl.*; import java.io.*; import java.lang.management.*; import java.util.*; @@ -406,7 +408,7 @@ public class IgniteConfiguration { private Serializable consistentId; /** SSL connection factory. */ - private GridSslContextFactory sslCtxFactory; + private Factory<SSLContext> sslCtxFactory; /** * Creates valid grid configuration with all default values. @@ -1314,9 +1316,9 @@ public class IgniteConfiguration { * Sets SSL context factory that will be used for creating a secure socket layer. * * @param sslCtxFactory Ssl context factory. - * @see GridSslContextFactory + * @see SslContextFactory */ - public IgniteConfiguration setSslContextFactory(GridSslContextFactory sslCtxFactory) { + public IgniteConfiguration setSslContextFactory(Factory<SSLContext> sslCtxFactory) { this.sslCtxFactory = sslCtxFactory; return this; @@ -1326,9 +1328,9 @@ public class IgniteConfiguration { * Returns SSL context factory that will be used for creating a secure socket layer. * * @return SSL connection factory. - * @see GridSslContextFactory + * @see SslContextFactory */ - public GridSslContextFactory getSslContextFactory() { + public Factory<SSLContext> getSslContextFactory() { return sslCtxFactory; } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslBasicContextFactory.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslBasicContextFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslBasicContextFactory.java index 92c34e0..d9a1f9d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslBasicContextFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslBasicContextFactory.java @@ -19,6 +19,7 @@ package org.apache.ignite.internal.client.ssl; import org.apache.ignite.internal.util.typedef.internal.*; +import javax.cache.configuration.*; import javax.net.ssl.*; import java.io.*; import java.security.*; @@ -37,7 +38,9 @@ import java.util.*; * factory.setTrustManagers(GridSslBasicContextFactory.getDisabledTrustManager()); * // Rest of initialization. * </pre> + * @deprecated Use {@link Factory<SSLContext>} instead. */ +@Deprecated public class GridSslBasicContextFactory implements GridSslContextFactory { /** Default key store type. */ public static final String DFLT_STORE_TYPE = "JKS"; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslContextFactory.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslContextFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslContextFactory.java index 8a9cd13..7ae1995 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslContextFactory.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/client/ssl/GridSslContextFactory.java @@ -17,14 +17,17 @@ package org.apache.ignite.internal.client.ssl; +import javax.cache.configuration.*; import javax.net.ssl.*; /** * This interface provides creation of SSL context both for server and client use. * <p> * Usually, it is enough to configure context from a particular key and trust stores, this functionality is provided - * in {@link org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory}. + * in {@link GridSslBasicContextFactory}. + * @deprecated Use {@link Factory<SSLContext>} instead. */ +@Deprecated public interface GridSslContextFactory { /** * Creates SSL context based on factory settings. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java index 9b6f353..c37c17d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/protocols/tcp/GridTcpRestProtocol.java @@ -35,6 +35,7 @@ import org.apache.ignite.marshaller.jdk.*; import org.apache.ignite.spi.*; import org.jetbrains.annotations.*; +import javax.cache.configuration.*; import javax.net.ssl.*; import java.io.*; import java.net.*; @@ -106,13 +107,23 @@ public class GridTcpRestProtocol extends GridRestProtocolAdapter { SSLContext sslCtx = null; if (cfg.isSslEnabled()) { - GridSslContextFactory factory = cfg.getSslContextFactory(); + Factory<SSLContext> igniteFactory = ctx.config().getSslContextFactory(); - if (factory == null) + Factory<SSLContext> factory = cfg.getSslFactory(); + + // This factory deprecated and will be removed. + GridSslContextFactory depFactory = cfg.getSslContextFactory(); + + if (factory == null && depFactory == null && igniteFactory == null) // Thrown SSL exception instead of IgniteCheckedException for writing correct warning message into log. throw new SSLException("SSL is enabled, but SSL context factory is not specified."); - sslCtx = factory.createSslContext(); + if (factory != null) + sslCtx = factory.create(); + else if (depFactory != null) + sslCtx = depFactory.createSslContext(); + else + sslCtx = igniteFactory.create(); } int lastPort = cfg.getPort() + cfg.getPortRange() - 1; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java index 36b8ee4..4d5052d 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java @@ -1505,7 +1505,7 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter if (isSslEnabled()) { GridNioSslFilter sslFilter = - new GridNioSslFilter(ignite.configuration().getSslContextFactory().createSslContext(), log); + new GridNioSslFilter(ignite.configuration().getSslContextFactory().create(), log); sslFilter.directMode(true); @@ -1556,6 +1556,10 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter return srvr; } catch (IgniteCheckedException e) { + if (X.hasCause(e, SSLException.class)) + throw new IgniteSpiException("Failed to create SSL context. SSL factory: " + + ignite.configuration().getSslContextFactory() + '.', e); + lastEx = e; if (log.isDebugEnabled()) @@ -1565,10 +1569,6 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter onException("Failed to bind to local port (will try next port within range) [port=" + port + ", locHost=" + locHost + ']', e); } - catch (SSLException e) { - throw new IgniteSpiException("Failed to create SSL context. SSL factory: " - + ignite.configuration().getSslContextFactory() + '.', e); - } } // If free port wasn't found. @@ -2293,7 +2293,7 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter GridFutureAdapter<ByteBuffer> handFut = new GridFutureAdapter<>(); SSLEngine sslEngine = ignite.configuration().getSslContextFactory() - .createSslContext().createSSLEngine(); + .create().createSSLEngine(); sslEngine.setUseClientMode(true); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java index 106fe02..7d6ef2d 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java @@ -1622,12 +1622,12 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter implements DiscoverySpi, T if (isSslEnabled()) { try { - SSLContext sslCtx = ignite().configuration().getSslContextFactory().createSslContext(); + SSLContext sslCtx = ignite().configuration().getSslContextFactory().create(); sslSocketFactory = sslCtx.getSocketFactory(); sslSrvSocketFactory = sslCtx.getServerSocketFactory(); } - catch (SSLException e) { + catch (IgniteException e) { throw new IgniteSpiException("Failed to create SSL context. SSL factory: " + ignite.configuration().getSslContextFactory(), e); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java b/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java new file mode 100644 index 0000000..bf09541 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java @@ -0,0 +1,455 @@ +/* + * 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.ignite.ssl; + +import org.apache.ignite.*; +import org.apache.ignite.internal.util.typedef.internal.*; + +import javax.cache.configuration.*; +import javax.net.ssl.*; +import java.io.*; +import java.security.*; +import java.security.cert.*; +import java.util.*; + +/** + * This SSL context factory that provides ssl context configuration with specified key + * and trust stores. + * <p> + * In some cases it is useful to disable certificate validation of client side (e.g. when connecting + * to a server with self-signed certificate). This can be achieved by setting a disabled trust manager + * to this factory, which can be obtained by {@link #getDisabledTrustManager()} method: + * <pre> + * SslContextFactory factory = new SslContextFactory(); + * factory.setTrustManagers(SslContextFactory.getDisabledTrustManager()); + * // Rest of initialization. + * </pre> + */ +public class SslContextFactory implements Factory<SSLContext> { + /** Default key store type. */ + public static final String DFLT_STORE_TYPE = "JKS"; + + /** Default SSL protocol. */ + public static final String DFLT_SSL_PROTOCOL = "TLS"; + + /** Default key manager algorithm. */ + public static final String DFLT_KEY_ALGORITHM = "SunX509"; + + /** SSL protocol. */ + private String proto = DFLT_SSL_PROTOCOL; + + /** Key manager algorithm. */ + private String keyAlgorithm = DFLT_KEY_ALGORITHM; + + /** Key store type. */ + private String keyStoreType = DFLT_STORE_TYPE; + + /** Path to key store file */ + private String keyStoreFilePath; + + /** Key store password */ + private char[] keyStorePwd; + + /** Trust store type. */ + private String trustStoreType = DFLT_STORE_TYPE; + + /** Path to trust store. */ + private String trustStoreFilePath; + + /** Trust store password */ + private char[] trustStorePwd; + + /** Trust managers. */ + private TrustManager[] trustMgrs; + + /** + * Gets key store type used for context creation. + * + * @return Key store type. + */ + public String getKeyStoreType() { + return keyStoreType; + } + + /** + * Sets key store type used in context initialization. If not provided, {@link #DFLT_STORE_TYPE} will + * be used. + * + * @param keyStoreType Key store type. + */ + public void setKeyStoreType(String keyStoreType) { + A.notNull(keyStoreType, "keyStoreType"); + + this.keyStoreType = keyStoreType; + } + + /** + * Gets trust store type used for context creation. + * + * @return trust store type. + */ + public String getTrustStoreType() { + return trustStoreType; + } + + /** + * Sets trust store type used in context initialization. If not provided, {@link #DFLT_STORE_TYPE} will + * be used. + * + * @param trustStoreType Trust store type. + */ + public void setTrustStoreType(String trustStoreType) { + A.notNull(trustStoreType, "trustStoreType"); + + this.trustStoreType = trustStoreType; + } + + /** + * Gets protocol for secure transport. + * + * @return SSL protocol name. + */ + public String getProtocol() { + return proto; + } + + /** + * Sets protocol for secure transport. If not specified, {@link #DFLT_SSL_PROTOCOL} will be used. + * + * @param proto SSL protocol name. + */ + public void setProtocol(String proto) { + A.notNull(proto, "proto"); + + this.proto = proto; + } + + /** + * Gets algorithm that will be used to create a key manager. If not specified, {@link #DFLT_KEY_ALGORITHM} + * will be used. + * + * @return Key manager algorithm. + */ + public String getKeyAlgorithm() { + return keyAlgorithm; + } + + /** + * Sets key manager algorithm that will be used to create a key manager. Notice that in most cased default value + * suites well, however, on Android platform this value need to be set to <tt>X509<tt/>. + * + * @param keyAlgorithm Key algorithm name. + */ + public void setKeyAlgorithm(String keyAlgorithm) { + A.notNull(keyAlgorithm, "keyAlgorithm"); + + this.keyAlgorithm = keyAlgorithm; + } + + /** + * Gets path to the key store file. + * + * @return Path to key store file. + */ + public String getKeyStoreFilePath() { + return keyStoreFilePath; + } + + /** + * Sets path to the key store file. This is a mandatory parameter since + * ssl context could not be initialized without key manager. + * + * @param keyStoreFilePath Path to key store file. + */ + public void setKeyStoreFilePath(String keyStoreFilePath) { + A.notNull(keyStoreFilePath, "keyStoreFilePath"); + + this.keyStoreFilePath = keyStoreFilePath; + } + + /** + * Gets key store password. + * + * @return Key store password. + */ + public char[] getKeyStorePassword() { + return keyStorePwd; + } + + /** + * Sets key store password. + * + * @param keyStorePwd Key store password. + */ + public void setKeyStorePassword(char[] keyStorePwd) { + A.notNull(keyStorePwd, "keyStorePwd"); + + this.keyStorePwd = keyStorePwd; + } + + /** + * Gets path to the trust store file. + * + * @return Path to the trust store file. + */ + public String getTrustStoreFilePath() { + return trustStoreFilePath; + } + + /** + * Sets path to the trust store file. This is an optional parameter, + * however one of the {@code setTrustStoreFilePath(String)}, {@link #setTrustManagers(TrustManager[])} + * properties must be set. + * + * @param trustStoreFilePath Path to the trust store file. + */ + public void setTrustStoreFilePath(String trustStoreFilePath) { + this.trustStoreFilePath = trustStoreFilePath; + } + + /** + * Gets trust store password. + * + * @return Trust store password. + */ + public char[] getTrustStorePassword() { + return trustStorePwd; + } + + /** + * Sets trust store password. + * + * @param trustStorePwd Trust store password. + */ + public void setTrustStorePassword(char[] trustStorePwd) { + this.trustStorePwd = trustStorePwd; + } + + /** + * Gets pre-configured trust managers. + * + * @return Trust managers. + */ + public TrustManager[] getTrustManagers() { + return trustMgrs; + } + + /** + * Sets pre-configured trust managers. This is an optional parameter, + * however one of the {@link #setTrustStoreFilePath(String)}, {@code #setTrustManagers(TrustManager[])} + * + * @param trustMgrs Pre-configured trust managers. + */ + public void setTrustManagers(TrustManager... trustMgrs) { + this.trustMgrs = trustMgrs; + } + + /** + * Returns an instance of trust manager that will always succeed regardless of certificate provided. + * + * @return Trust manager instance. + */ + public static TrustManager getDisabledTrustManager() { + return new DisabledX509TrustManager(); + } + + /** + * Creates SSL context based on factory settings. + * + * @return Initialized SSL context. + * @throws SSLException If SSL context could not be created. + */ + private SSLContext createSslContext() throws SSLException { + checkParameters(); + + try { + KeyManagerFactory keyMgrFactory = KeyManagerFactory.getInstance(keyAlgorithm); + + KeyStore keyStore = loadKeyStore(keyStoreType, keyStoreFilePath, keyStorePwd); + + keyMgrFactory.init(keyStore, keyStorePwd); + + TrustManager[] mgrs = trustMgrs; + + if (mgrs == null) { + TrustManagerFactory trustMgrFactory = TrustManagerFactory.getInstance(keyAlgorithm); + + KeyStore trustStore = loadKeyStore(trustStoreType, trustStoreFilePath, trustStorePwd); + + trustMgrFactory.init(trustStore); + + mgrs = trustMgrFactory.getTrustManagers(); + } + + SSLContext ctx = SSLContext.getInstance(proto); + + ctx.init(keyMgrFactory.getKeyManagers(), mgrs, null); + + return ctx; + } + catch (GeneralSecurityException e) { + throw new SSLException("Failed to initialize SSL context " + parameters(), e); + } + } + + /** + * Builds human-readable string with factory parameters. + * + * @return Parameters string. + */ + private String parameters() { + StringBuilder buf = new StringBuilder("[keyStoreType=").append(keyStoreType); + + buf.append(", proto=").append(proto).append(", keyStoreFile=").append(keyStoreFilePath); + + if (trustMgrs != null) + buf.append(", trustMgrs=").append(Arrays.toString(trustMgrs)); + else + buf.append(", trustStoreFile=").append(trustStoreFilePath); + + buf.append(']'); + + return buf.toString(); + } + + /** + * Checks that all required parameters are set. + * + * @throws SSLException If any of required parameters is missing. + */ + private void checkParameters() throws SSLException { + assert keyStoreType != null; + assert proto != null; + + checkNullParameter(keyStoreFilePath, "keyStoreFilePath"); + checkNullParameter(keyStorePwd, "keyStorePwd"); + + if (trustMgrs == null) { + if (trustStoreFilePath == null) + throw new SSLException("Failed to initialize SSL context (either trustStoreFilePath or " + + "trustManagers must be provided)"); + else + checkNullParameter(trustStorePwd, "trustStorePwd"); + } + } + + /** + * @param param Value. + * @param name Name. + * @throws SSLException If {@code null}. + */ + private void checkNullParameter(Object param, String name) throws SSLException { + if (param == null) + throw new SSLException("Failed to initialize SSL context (parameter cannot be null): " + name); + } + + /** + * By default, this method simply opens a raw file input stream. Subclasses may override this method + * if some specific location should be handled (this may be a case for Android users). + * + * @param filePath Path to the file. + * @return Opened input stream. + * @throws IOException If stream could not be opened. + */ + protected InputStream openFileInputStream(String filePath) throws IOException { + return new FileInputStream(filePath); + } + + /** + * Loads key store with configured parameters. + * + * @param keyStoreType Type of key store. + * @param storeFilePath Path to key store file. + * @param keyStorePwd Store password. + * @return Initialized key store. + * @throws SSLException If key store could not be initialized. + */ + private KeyStore loadKeyStore(String keyStoreType, String storeFilePath, char[] keyStorePwd) throws SSLException { + InputStream input = null; + + try { + KeyStore keyStore = KeyStore.getInstance(keyStoreType); + + input = openFileInputStream(storeFilePath); + + keyStore.load(input, keyStorePwd); + + return keyStore; + } + catch (GeneralSecurityException e) { + throw new SSLException("Failed to initialize key store (security exception occurred) [type=" + + keyStoreType + ", keyStorePath=" + storeFilePath + ']', e); + } + catch (FileNotFoundException e) { + throw new SSLException("Failed to initialize key store (key store file was not found): [path=" + + storeFilePath + ", msg=" + e.getMessage() + ']'); + } + catch (IOException e) { + throw new SSLException("Failed to initialize key store (I/O error occurred): " + storeFilePath, e); + } + finally { + if (input != null) { + try { + input.close(); + } + catch (IOException ignored) { + } + } + } + } + + /** {@inheritDoc} */ + public String toString() { + return getClass().getSimpleName() + parameters(); + } + + /** + * Disabled trust manager, will skip all certificate checks. + */ + private static class DisabledX509TrustManager implements X509TrustManager { + /** Empty certificate array. */ + private static final X509Certificate[] CERTS = new X509Certificate[0]; + + /** {@inheritDoc} */ + @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) + throws CertificateException { + // No-op, all clients are trusted. + } + + /** {@inheritDoc} */ + @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) + throws CertificateException { + // No-op, all servers are trusted. + } + + /** {@inheritDoc} */ + @Override public X509Certificate[] getAcceptedIssuers() { + return CERTS; + } + } + + /** {@inheritDoc} */ + @Override public SSLContext create() { + try { + return createSslContext(); + } + catch (SSLException e) { + throw new IgniteException(e); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/main/java/org/apache/ignite/ssl/package-info.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/ssl/package-info.java b/modules/core/src/main/java/org/apache/ignite/ssl/package-info.java new file mode 100644 index 0000000..7be1910 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/ssl/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Contains classes for working with SSL. + */ +package org.apache.ignite.ssl; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/test/java/org/apache/ignite/spi/communication/GridAbstractCommunicationSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/spi/communication/GridAbstractCommunicationSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/communication/GridAbstractCommunicationSelfTest.java index 2271e3b..13ed880 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/communication/GridAbstractCommunicationSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/communication/GridAbstractCommunicationSelfTest.java @@ -307,7 +307,7 @@ public abstract class GridAbstractCommunicationSelfTest<T extends CommunicationS IgniteMock ignite = GridTestUtils.getFieldValue(spi, IgniteSpiAdapter.class, "ignite"); IgniteConfiguration cfg = ignite.configuration() - .setSslContextFactory(GridTestUtils.sslContextFactory()); + .setSslContextFactory(GridTestUtils.sslFactory()); ignite.setStaticCfg(cfg); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java index 373ca68..4bdcf0a 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/AbstractDiscoverySelfTest.java @@ -402,7 +402,7 @@ public abstract class AbstractDiscoverySelfTest<T extends IgniteSpi> extends Gri IgniteMock ignite = GridTestUtils.getFieldValue(spi, IgniteSpiAdapter.class, "ignite"); IgniteConfiguration cfg = ignite.configuration() - .setSslContextFactory(GridTestUtils.sslContextFactory()); + .setSslContextFactory(GridTestUtils.sslFactory()); ignite.setStaticCfg(cfg); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySslSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySslSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySslSelfTest.java index 13f1004..314ca01 100644 --- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySslSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySslSelfTest.java @@ -35,7 +35,7 @@ public class TcpDiscoverySslSelfTest extends TcpDiscoverySelfTest { @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(gridName); - cfg.setSslContextFactory(GridTestUtils.sslContextFactory()); + cfg.setSslContextFactory(GridTestUtils.sslFactory()); return cfg; } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java index d03d327..964f680 100644 --- a/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java +++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridTestUtils.java @@ -32,10 +32,12 @@ import org.apache.ignite.internal.util.lang.*; import org.apache.ignite.internal.util.typedef.*; import org.apache.ignite.internal.util.typedef.internal.*; import org.apache.ignite.lang.*; +import org.apache.ignite.ssl.*; import org.apache.ignite.testframework.config.*; import org.jetbrains.annotations.*; import javax.cache.*; +import javax.cache.configuration.*; import javax.net.ssl.*; import java.io.*; import java.lang.annotation.*; @@ -1338,6 +1340,24 @@ public final class GridTestUtils { return factory; } + + /** + * Creates test-purposed SSL context factory from test key store with disabled trust manager. + * + * @return SSL context factory used in test. + */ + public static Factory<SSLContext> sslFactory() { + SslContextFactory factory = new SslContextFactory(); + + factory.setKeyStoreFilePath( + U.resolveIgnitePath(GridTestProperties.getProperty("ssl.keystore.path")).getAbsolutePath()); + factory.setKeyStorePassword(GridTestProperties.getProperty("ssl.keystore.password").toCharArray()); + + factory.setTrustManagers(GridSslBasicContextFactory.getDisabledTrustManager()); + + return factory; + } + /** * @param o1 Object 1. * @param o2 Object 2. http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/26a038c8/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java index 5fdc76f..54dbebe 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiDiscoverySelfTestSuite.java @@ -63,7 +63,6 @@ public class IgniteSpiDiscoverySelfTestSuite extends TestSuite { // SSL. suite.addTest(new TestSuite(TcpDiscoverySslSelfTest.class)); - suite.addTest(new TestSuite(TcpDiscoverySpiSslSelfTest.class)); return suite; }