This is an automated email from the ASF dual-hosted git repository.
mpetrov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 04bbcfec30f IGNITE-19975 Introduced abstract SSL Context Factory
(#10841)
04bbcfec30f is described below
commit 04bbcfec30fc05c87f8aec0cba30365b4a7bcfc9
Author: Mikhail Petrov <[email protected]>
AuthorDate: Sat Jul 15 16:17:01 2023 +0300
IGNITE-19975 Introduced abstract SSL Context Factory (#10841)
---
.../jdbc/thin/JdbcThinConnectionSSLTest.java | 2 +-
.../ignite/ssl/AbstractSslContextFactory.java | 199 +++++++++++++++++++++
.../org/apache/ignite/ssl/SslContextFactory.java | 198 +++-----------------
3 files changed, 224 insertions(+), 175 deletions(-)
diff --git
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSSLTest.java
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSSLTest.java
index a59e0e49a8c..ad422a3b93f 100644
---
a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSSLTest.java
+++
b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSSLTest.java
@@ -654,7 +654,7 @@ public class JdbcThinConnectionSSLTest extends
JdbcThinAbstractSelfTest {
return null;
}
- }, SQLException.class, "Unsupported keystore algorithm: INVALID");
+ }, SQLException.class, "Unsupported key algorithm: INVALID");
}
finally {
stopAllGrids();
diff --git
a/modules/core/src/main/java/org/apache/ignite/ssl/AbstractSslContextFactory.java
b/modules/core/src/main/java/org/apache/ignite/ssl/AbstractSslContextFactory.java
new file mode 100644
index 00000000000..77dedf84eba
--- /dev/null
+++
b/modules/core/src/main/java/org/apache/ignite/ssl/AbstractSslContextFactory.java
@@ -0,0 +1,199 @@
+/*
+ * 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 java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.cache.configuration.Factory;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.TrustManager;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.util.typedef.internal.A;
+
+/**
+ * Represents abstract implementation of SSL Context Factory that caches the
result of the first successful
+ * attempt to create an {@link SSLContext} and always returns it as a result
of further invocations of the
+ * {@link AbstractSslContextFactory#create()}} method.
+ */
+public abstract class AbstractSslContextFactory implements Factory<SSLContext>
{
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Default SSL protocol. */
+ public static final String DFLT_SSL_PROTOCOL = "TLS";
+
+ /** SSL protocol. */
+ protected String proto = DFLT_SSL_PROTOCOL;
+
+ /** Enabled cipher suites. */
+ protected String[] cipherSuites;
+
+ /** Enabled protocols. */
+ protected String[] protocols;
+
+ /** Cached instance of an {@link SSLContext}. */
+ protected final AtomicReference<SSLContext> sslCtx = new
AtomicReference<>();
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Sets enabled cipher suites.
+ *
+ * @param cipherSuites enabled cipher suites.
+ */
+ public void setCipherSuites(String... cipherSuites) {
+ this.cipherSuites = cipherSuites;
+ }
+
+ /**
+ * Gets enabled cipher suites.
+ *
+ * @return enabled cipher suites
+ */
+ public String[] getCipherSuites() {
+ return cipherSuites;
+ }
+
+ /**
+ * Gets enabled protocols.
+ *
+ * @return Enabled protocols.
+ */
+ public String[] getProtocols() {
+ return protocols;
+ }
+
+ /**
+ * Sets enabled protocols.
+ *
+ * @param protocols Enabled protocols.
+ */
+ public void setProtocols(String... protocols) {
+ this.protocols = protocols;
+ }
+
+ /**
+ * 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();
+
+ KeyManager[] keyMgrs = createKeyManagers();
+
+ TrustManager[] trustMgrs = createTrustManagers();
+
+ try {
+ SSLContext ctx = SSLContext.getInstance(proto);
+
+ if (cipherSuites != null || protocols != null) {
+ SSLParameters sslParameters = new SSLParameters();
+
+ if (cipherSuites != null)
+ sslParameters.setCipherSuites(cipherSuites);
+
+ if (protocols != null)
+ sslParameters.setProtocols(protocols);
+
+ ctx = new SSLContextWrapper(ctx, sslParameters);
+ }
+
+ ctx.init(keyMgrs, trustMgrs, null);
+
+ return ctx;
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new SSLException("Unsupported SSL protocol: " + proto, e);
+ }
+ catch (KeyManagementException e) {
+ throw new SSLException("Failed to initialized SSL context.", e);
+ }
+ }
+
+ /**
+ * @param param Value.
+ * @param name Name.
+ * @throws SSLException If {@code null}.
+ */
+ protected void checkNullParameter(Object param, String name) throws
SSLException {
+ if (param == null)
+ throw new SSLException("Failed to initialize SSL context
(parameter cannot be null): " + name);
+ }
+
+ /**
+ * Checks that all required parameters are set.
+ *
+ * @throws SSLException If any of required parameters is missing.
+ */
+ protected abstract void checkParameters() throws SSLException;
+
+ /**
+ * @return Created Key Managers.
+ * @throws SSLException If Key Managers could not be created.
+ */
+ protected abstract KeyManager[] createKeyManagers() throws SSLException;
+
+ /**
+ * @return Created Trust Managers.
+ * @throws SSLException If Trust Managers could not be created.
+ */
+ protected abstract TrustManager[] createTrustManagers() throws
SSLException;
+
+ /** {@inheritDoc} */
+ @Override public SSLContext create() {
+ SSLContext ctx = sslCtx.get();
+
+ if (ctx == null) {
+ try {
+ ctx = createSslContext();
+
+ if (!sslCtx.compareAndSet(null, ctx))
+ ctx = sslCtx.get();
+ }
+ catch (SSLException e) {
+ throw new IgniteException(e);
+ }
+ }
+
+ return ctx;
+ }
+}
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
index e8bc0de8ee3..af7d140b01f 100644
--- a/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/ssl/SslContextFactory.java
@@ -22,23 +22,18 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
-import java.util.concurrent.atomic.AtomicReference;
-import javax.cache.configuration.Factory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.util.typedef.internal.A;
/**
@@ -56,7 +51,7 @@ import org.apache.ignite.internal.util.typedef.internal.A;
* // Rest of initialization.
* </pre>
*/
-public class SslContextFactory implements Factory<SSLContext> {
+public class SslContextFactory extends AbstractSslContextFactory {
/** */
private static final long serialVersionUID = 0L;
@@ -64,24 +59,10 @@ public class SslContextFactory implements
Factory<SSLContext> {
public static final String DFLT_STORE_TYPE =
System.getProperty("javax.net.ssl.keyStoreType", "JKS");
/** Default SSL protocol. */
- public static final String DFLT_SSL_PROTOCOL = "TLS";
-
- /**
- * Property name to specify default key/trust manager algorithm.
- *
- * @deprecated Use {@code "ssl.KeyManagerFactory.algorithm"} instead as
per JSSE standard.
- *
- * Should be considered for deletion in 9.0.
- */
- @Deprecated
- public static final String IGNITE_KEY_ALGORITHM_PROPERTY =
"ssl.key.algorithm";
+ public static final String DFLT_SSL_PROTOCOL =
AbstractSslContextFactory.DFLT_SSL_PROTOCOL;
/** Default key manager / trust manager algorithm. Specifying different
trust manager algorithm is not supported. */
- public static final String DFLT_KEY_ALGORITHM =
System.getProperty("ssl.KeyManagerFactory.algorithm",
- System.getProperty(IGNITE_KEY_ALGORITHM_PROPERTY, "SunX509"));
-
- /** SSL protocol. */
- protected String proto = DFLT_SSL_PROTOCOL;
+ public static final String DFLT_KEY_ALGORITHM =
System.getProperty("ssl.KeyManagerFactory.algorithm", "SunX509");
/** Key manager algorithm. */
protected String keyAlgorithm = DFLT_KEY_ALGORITHM;
@@ -107,15 +88,6 @@ public class SslContextFactory implements
Factory<SSLContext> {
/** Trust managers. */
protected TrustManager[] trustMgrs;
- /** Enabled cipher suites. */
- protected String[] cipherSuites;
-
- /** Enabled protocols. */
- protected String[] protocols;
-
- /** Cached instance of an {@link SSLContext}. */
- protected final AtomicReference<SSLContext> sslCtx = new
AtomicReference<>();
-
/**
* Gets key store type used for context creation.
*
@@ -158,26 +130,6 @@ public class SslContextFactory implements
Factory<SSLContext> {
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.
@@ -306,53 +258,8 @@ public class SslContextFactory implements
Factory<SSLContext> {
return new DisabledX509TrustManager();
}
- /**
- * Sets enabled cipher suites.
- *
- * @param cipherSuites enabled cipher suites.
- */
- public void setCipherSuites(String... cipherSuites) {
- this.cipherSuites = cipherSuites;
- }
-
- /**
- * Gets enabled cipher suites.
- *
- * @return enabled cipher suites
- */
- public String[] getCipherSuites() {
- return cipherSuites;
- }
-
- /**
- * Gets enabled protocols.
- *
- * @return Enabled protocols.
- */
- public String[] getProtocols() {
- return protocols;
- }
-
- /**
- * Sets enabled protocols.
- *
- * @param protocols Enabled protocols.
- */
- public void setProtocols(String... protocols) {
- this.protocols = protocols;
- }
-
- /**
- * 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();
-
- final KeyManager[] keyMgrs;
-
+ /** {@inheritDoc} */
+ @Override protected final KeyManager[] createKeyManagers() throws
SSLException {
try {
KeyManagerFactory keyMgrFactory =
KeyManagerFactory.getInstance(keyAlgorithm);
@@ -360,61 +267,37 @@ public class SslContextFactory implements
Factory<SSLContext> {
keyMgrFactory.init(keyStore, keyStorePwd);
- keyMgrs = keyMgrFactory.getKeyManagers();
+ return keyMgrFactory.getKeyManagers();
}
catch (NoSuchAlgorithmException e) {
- throw new SSLException("Unsupported keystore algorithm: " +
keyAlgorithm, e);
+ throw new SSLException("Unsupported key algorithm: " +
keyAlgorithm, e);
}
catch (GeneralSecurityException e) {
- throw new SSLException("Failed to initialize key store (security
exception occurred) [type=" +
+ throw new SSLException("Failed to initialize Key Manager (security
exception occurred) [type=" +
keyStoreType + ", keyStorePath=" + keyStoreFilePath + ']', e);
}
+ }
- TrustManager[] trustMgrs = this.trustMgrs;
-
- if (trustMgrs == null) {
- try {
- TrustManagerFactory trustMgrFactory =
TrustManagerFactory.getInstance(keyAlgorithm);
-
- KeyStore trustStore = loadKeyStore(trustStoreType,
trustStoreFilePath, trustStorePwd);
-
- trustMgrFactory.init(trustStore);
+ /** {@inheritDoc} */
+ @Override protected final TrustManager[] createTrustManagers() throws
SSLException {
+ if (trustMgrs != null)
+ return trustMgrs;
- trustMgrs = trustMgrFactory.getTrustManagers();
- }
- catch (NoSuchAlgorithmException e) {
- throw new SSLException("Unsupported keystore algorithm: " +
keyAlgorithm, e);
- }
- catch (GeneralSecurityException e) {
- throw new SSLException("Failed to initialize key store
(security exception occurred) [type=" +
- keyStoreType + ", keyStorePath=" + keyStoreFilePath + ']',
e);
- }
- }
+ KeyStore trustStore = loadKeyStore(trustStoreType, trustStoreFilePath,
trustStorePwd);
try {
- SSLContext ctx = SSLContext.getInstance(proto);
-
- if (cipherSuites != null || protocols != null) {
- SSLParameters sslParameters = new SSLParameters();
-
- if (cipherSuites != null)
- sslParameters.setCipherSuites(cipherSuites);
+ TrustManagerFactory trustMgrFactory =
TrustManagerFactory.getInstance(keyAlgorithm);
- if (protocols != null)
- sslParameters.setProtocols(protocols);
-
- ctx = new SSLContextWrapper(ctx, sslParameters);
- }
+ trustMgrFactory.init(trustStore);
- ctx.init(keyMgrs, trustMgrs, null);
-
- return ctx;
+ return trustMgrFactory.getTrustManagers();
}
catch (NoSuchAlgorithmException e) {
- throw new SSLException("Unsupported SSL protocol: " + proto, e);
+ throw new SSLException("Unsupported key algorithm: " +
keyAlgorithm, e);
}
- catch (KeyManagementException e) {
- throw new SSLException("Failed to initialized SSL context.", e);
+ catch (GeneralSecurityException e) {
+ throw new SSLException("Failed to initialize Trust Manager
(security exception occurred) [type=" +
+ trustStoreType + ", trustStorePath=" + trustStoreFilePath +
']', e);
}
}
@@ -438,12 +321,8 @@ public class SslContextFactory implements
Factory<SSLContext> {
return buf.toString();
}
- /**
- * Checks that all required parameters are set.
- *
- * @throws SSLException If any of required parameters is missing.
- */
- protected void checkParameters() throws SSLException {
+ /** {@inheritDoc} */
+ @Override protected void checkParameters() throws SSLException {
assert keyStoreType != null;
assert proto != null;
@@ -459,16 +338,6 @@ public class SslContextFactory implements
Factory<SSLContext> {
}
}
- /**
- * @param param Value.
- * @param name Name.
- * @throws SSLException If {@code null}.
- */
- protected 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).
@@ -504,7 +373,7 @@ public class SslContextFactory implements
Factory<SSLContext> {
}
catch (GeneralSecurityException e) {
throw new SSLException("Failed to initialize key store (security
exception occurred) [type=" +
- keyStoreType + ", keyStorePath=" + keyStoreFilePath + ']', e);
+ keyStoreType + ", keyStorePath=" + storeFilePath + ']', e);
}
catch (FileNotFoundException e) {
throw new SSLException("Failed to initialize key store (key store
file was not found): [path=" +
@@ -544,23 +413,4 @@ public class SslContextFactory implements
Factory<SSLContext> {
return CERTS;
}
}
-
- /** {@inheritDoc} */
- @Override public SSLContext create() {
- SSLContext ctx = sslCtx.get();
-
- if (ctx == null) {
- try {
- ctx = createSslContext();
-
- if (!sslCtx.compareAndSet(null, ctx))
- ctx = sslCtx.get();
- }
- catch (SSLException e) {
- throw new IgniteException(e);
- }
- }
-
- return ctx;
- }
}