This is an automated email from the ASF dual-hosted git repository.
alopresto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push:
new 0de8945 NIFI-6927 Consolidate SSL context and trust managers for
OkHttp on JDK9. Fixes name conflicts.
0de8945 is described below
commit 0de89452f1975c5724e75e5f9d5865bb814cf4de
Author: Troy Melhase <[email protected]>
AuthorDate: Mon Feb 10 11:56:09 2020 -0900
NIFI-6927 Consolidate SSL context and trust managers for OkHttp on JDK9.
Fixes name conflicts.
This closes #4047.
Signed-off-by: Andy LoPresto <[email protected]>
---
.../notification/http/HttpNotificationService.java | 69 ++++------------
.../nifi/security/util/SslContextFactory.java | 71 +++++++++++++----
.../nifi-elasticsearch-processors/pom.xml | 2 +-
.../AbstractElasticsearchHttpProcessor.java | 31 +++++++-
.../TestQueryElasticsearchHttpNoHits.java | 2 +-
.../okhttp/OkHttpReplicationClient.java | 84 +++++++-------------
.../security/util/SslServerSocketFactory.java | 82 -------------------
.../framework/security/util/SslSocketFactory.java | 92 ----------------------
.../nifi/processors/standard/InvokeHTTP.java | 20 ++++-
.../org/apache/nifi/lookup/RestLookupService.java | 38 ++++++++-
10 files changed, 184 insertions(+), 307 deletions(-)
diff --git
a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java
b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java
index 1405625..2ab7c72 100644
---
a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java
+++
b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java
@@ -28,16 +28,13 @@ import
org.apache.nifi.bootstrap.notification.NotificationFailedException;
import
org.apache.nifi.bootstrap.notification.NotificationInitializationContext;
import org.apache.nifi.bootstrap.notification.NotificationType;
import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.expression.AttributeExpression;
import org.apache.nifi.expression.ExpressionLanguageScope;
-import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.util.Tuple;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.util.ArrayList;
@@ -196,12 +193,25 @@ public class HttpNotificationService extends
AbstractNotificationService {
// check if the keystore is set and add the factory if so
if (url.toLowerCase().startsWith("https")) {
try {
- Tuple<SSLSocketFactory, TrustManager[]>
sslSocketFactoryWithTrustManagers = getSslSocketFactory(context);
+ Tuple<SSLContext, TrustManager[]> sslContextTuple =
SslContextFactory.createTrustSslContextWithTrustManagers(
+
context.getProperty(HttpNotificationService.PROP_KEYSTORE).getValue(),
+
context.getProperty(HttpNotificationService.PROP_KEYSTORE_PASSWORD).isSet()
+ ?
context.getProperty(HttpNotificationService.PROP_KEYSTORE_PASSWORD).getValue().toCharArray()
: null,
+
context.getProperty(HttpNotificationService.PROP_KEY_PASSWORD).isSet()
+ ?
context.getProperty(HttpNotificationService.PROP_KEY_PASSWORD).getValue().toCharArray()
: null,
+
context.getProperty(HttpNotificationService.PROP_KEYSTORE_TYPE).getValue(),
+
context.getProperty(HttpNotificationService.PROP_TRUSTSTORE).getValue(),
+
context.getProperty(HttpNotificationService.PROP_TRUSTSTORE_PASSWORD).isSet()
+ ?
context.getProperty(HttpNotificationService.PROP_TRUSTSTORE_PASSWORD).getValue().toCharArray()
: null,
+
context.getProperty(HttpNotificationService.PROP_TRUSTSTORE_TYPE).getValue(),
+ SslContextFactory.ClientAuth.REQUIRED,
+
context.getProperty(HttpNotificationService.SSL_ALGORITHM).getValue()
+ );
// Find the first X509TrustManager
- List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslSocketFactoryWithTrustManagers.getValue())
+ List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslContextTuple.getValue())
.filter(trustManager -> trustManager instanceof
X509TrustManager)
.map(trustManager -> (X509TrustManager)
trustManager).collect(Collectors.toList());
-
okHttpClientBuilder.sslSocketFactory(sslSocketFactoryWithTrustManagers.getKey(),
x509TrustManagers.get(0));
+
okHttpClientBuilder.sslSocketFactory(sslContextTuple.getKey().getSocketFactory(),
x509TrustManagers.get(0));
} catch (Exception e) {
throw new IllegalStateException(e);
}
@@ -249,51 +259,4 @@ public class HttpNotificationService extends
AbstractNotificationService {
throw new NotificationFailedException("Failed to send Http
Notification", e);
}
}
-
- private static Tuple<SSLSocketFactory, TrustManager[]>
getSslSocketFactory(NotificationInitializationContext context) {
-
- final String protocol = context.getProperty(SSL_ALGORITHM).getValue();
- try {
- final PropertyValue keyPasswdProp =
context.getProperty(PROP_KEY_PASSWORD);
- final char[] keyPassword = keyPasswdProp.isSet() ?
keyPasswdProp.getValue().toCharArray() : null;
-
- final Tuple<SSLContext, TrustManager[]>
sslContextWithTrustManagers;
- final String truststoreFile =
context.getProperty(PROP_TRUSTSTORE).getValue();
- final String keystoreFile =
context.getProperty(PROP_KEYSTORE).getValue();
-
- if (keystoreFile == null) {
- // If keystore not specified, create SSL Context based only on
trust store.
- sslContextWithTrustManagers =
SslContextFactory.createTrustSslContextWithTrustManagers(
- context.getProperty(PROP_TRUSTSTORE).getValue(),
-
context.getProperty(PROP_TRUSTSTORE_PASSWORD).getValue().toCharArray(),
- context.getProperty(PROP_TRUSTSTORE_TYPE).getValue(),
- protocol);
-
- } else if (truststoreFile == null) {
- // If truststore not specified, create SSL Context based only
on key store.
- sslContextWithTrustManagers =
SslContextFactory.createSslContextWithTrustManagers(
- context.getProperty(PROP_KEYSTORE).getValue(),
-
context.getProperty(PROP_KEYSTORE_PASSWORD).getValue().toCharArray(),
- keyPassword,
- context.getProperty(PROP_KEYSTORE_TYPE).getValue(),
- protocol);
-
- } else {
- sslContextWithTrustManagers =
SslContextFactory.createSslContextWithTrustManagers(
- context.getProperty(PROP_KEYSTORE).getValue(),
-
context.getProperty(PROP_KEYSTORE_PASSWORD).getValue().toCharArray(),
- keyPassword,
- context.getProperty(PROP_KEYSTORE_TYPE).getValue(),
- context.getProperty(PROP_TRUSTSTORE).getValue(),
-
context.getProperty(PROP_TRUSTSTORE_PASSWORD).getValue().toCharArray(),
- context.getProperty(PROP_TRUSTSTORE_TYPE).getValue(),
- SslContextFactory.ClientAuth.REQUIRED,
- protocol);
- }
-
- return new
Tuple<>(sslContextWithTrustManagers.getKey().getSocketFactory(),
sslContextWithTrustManagers.getValue());
- } catch (final Exception e) {
- throw new ProcessException(e);
- }
- }
}
diff --git
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/SslContextFactory.java
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/SslContextFactory.java
index 8863260..3e8058f 100644
---
a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/SslContextFactory.java
+++
b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/SslContextFactory.java
@@ -50,7 +50,7 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance using the given information. The password
for the key is assumed to be the same
+ * Creates an SSLContext instance using the given information. The
password for the key is assumed to be the same
* as the password for the keystore. If this is not the case, the {@link
#createSslContext(String, char[], char[], String, String, char[], String,
ClientAuth, String)}
* method should be used instead
*
@@ -63,7 +63,7 @@ public final class SslContextFactory {
* @param clientAuth the type of client authentication
* @param protocol the protocol to use for the SSL connection
*
- * @return a SSLContext instance
+ * @return an SSLContext instance
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -83,10 +83,11 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance using the given information.
+ * Creates an SSLContext instance using the given information.
*
* @param keystore the full path to the keystore
* @param keystorePasswd the keystore password
+ * @param keyPasswd the password for the key within the keystore
* @param keystoreType the type of keystore (e.g., PKCS12, JKS)
* @param truststore the full path to the truststore
* @param truststorePasswd the truststore password
@@ -94,7 +95,7 @@ public final class SslContextFactory {
* @param clientAuth the type of client authentication
* @param protocol the protocol to use for the SSL connection
*
- * @return a SSLContext instance
+ * @return an SSLContext instance
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -113,10 +114,11 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance paired with its TrustManager instances
using the given information.
+ * Creates an SSLContext instance paired with its TrustManager instances
using the given information.
*
* @param keystore the full path to the keystore
* @param keystorePasswd the keystore password
+ * @param keyPasswd the password for the key within the keystore
* @param keystoreType the type of keystore (e.g., PKCS12, JKS)
* @param truststore the full path to the truststore
* @param truststorePasswd the truststore password
@@ -124,7 +126,7 @@ public final class SslContextFactory {
* @param clientAuth the type of client authentication
* @param protocol the protocol to use for the SSL connection
*
- * @return a {@link Tuple} pairing a SSLContext instance with its
TrustManagers
+ * @return a {@link Tuple} pairing an SSLContext instance with its
TrustManagers
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -174,7 +176,7 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance using the given information. This method
assumes that the key password is
+ * Creates an SSLContext instance using the given information. This method
assumes that the key password is
* the same as the keystore password. If this is not the case, use the
{@link #createSslContext(String, char[], char[], String, String)}
* method instead.
*
@@ -183,7 +185,7 @@ public final class SslContextFactory {
* @param keystoreType the type of keystore (e.g., PKCS12, JKS)
* @param protocol the protocol to use for the SSL connection
*
- * @return a SSLContext instance
+ * @return an SSLContext instance
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -201,14 +203,15 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance using the given information.
+ * Creates an SSLContext instance using the given information.
*
* @param keystore the full path to the keystore
* @param keystorePasswd the keystore password
+ * @param keyPasswd the password for the key within the keystore
* @param keystoreType the type of keystore (e.g., PKCS12, JKS)
* @param protocol the protocol to use for the SSL connection
*
- * @return a SSLContext instance
+ * @return an SSLContext instance
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -224,14 +227,15 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance paired with its TrustManager instances
using the given information.
+ * Creates an SSLContext instance paired with its TrustManager instances
using the given information.
*
* @param keystore the full path to the keystore
* @param keystorePasswd the keystore password
+ * @param keyPasswd the password for the key within the keystore
* @param keystoreType the type of keystore (e.g., PKCS12, JKS)
* @param protocol the protocol to use for the SSL connection
*
- * @return a {@link Tuple} pairing a SSLContext instance paired with its
TrustManager instances
+ * @return a {@link Tuple} pairing an SSLContext instance paired with its
TrustManager instances
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -265,14 +269,14 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance using the given information.
+ * Creates an SSLContext instance using the given information.
*
* @param truststore the full path to the truststore
* @param truststorePasswd the truststore password
* @param truststoreType the type of truststore (e.g., PKCS12, JKS)
* @param protocol the protocol to use for the SSL connection
*
- * @return a SSLContext instance
+ * @return an SSLContext instance
* @throws java.security.KeyStoreException if any issues accessing the
keystore
* @throws java.io.IOException for any problems loading the keystores
* @throws java.security.NoSuchAlgorithmException if an algorithm is found
to be used but is unknown
@@ -290,14 +294,14 @@ public final class SslContextFactory {
}
/**
- * Creates a SSLContext instance paired with its TrustManager instances
using the given information.
+ * Creates an SSLContext instance paired with its TrustManager instances
using the given information.
*
* @param truststore the full path to the truststore
* @param truststorePasswd the truststore password
* @param truststoreType the type of truststore (e.g., PKCS12, JKS)
* @param protocol the protocol to use for the SSL connection
*
- * @return a {@link Tuple} pairing a SSLContext instance paired with its
TrustManager instances
+ * @return a {@link Tuple} pairing an SSLContext instance paired with its
TrustManager instances
* @throws KeyStoreException if any issues accessing the keystore
* @throws IOException for any problems loading the keystores
* @throws NoSuchAlgorithmException if an algorithm is found to be used
but is unknown
@@ -324,4 +328,39 @@ public final class SslContextFactory {
return new Tuple<>(ctx, trustManagers);
}
+
+ /**
+ * Creates an SSLContext instance paired with its TrustManager instances
using the given information.
+ *
+ * @param keystore the full path to the keystore
+ * @param keystorePasswd the keystore password
+ * @param keyPasswd the password for the key within the keystore
+ * @param keystoreType the type of keystore (e.g., PKCS12, JKS)
+ * @param truststore the full path to the truststore
+ * @param truststorePasswd the truststore password
+ * @param truststoreType the type of truststore (e.g., PKCS12, JKS)
+ * @param clientAuth the type of client authentication
+ * @param protocol the protocol to use for the SSL connection
+ *
+ * @return a {@link Tuple} pairing an SSLSocketFactory instance with its
TrustManagers
+ *
+ */
+ public static Tuple<SSLContext, TrustManager[]>
createTrustSslContextWithTrustManagers(
+ final String keystore, final char[] keystorePasswd, final char[]
keyPasswd, final String keystoreType,
+ final String truststore, final char[] truststorePasswd, final
String truststoreType,
+ final ClientAuth clientAuth, final String protocol) throws
CertificateException, UnrecoverableKeyException,
+ NoSuchAlgorithmException, KeyStoreException,
KeyManagementException, IOException {
+
+ final Tuple<SSLContext, TrustManager[]>
sslContextWithTrustManagers;
+ if (keystore == null) {
+ sslContextWithTrustManagers =
createTrustSslContextWithTrustManagers(truststore, truststorePasswd,
truststoreType, protocol);
+ } else if (truststore == null) {
+ sslContextWithTrustManagers =
createSslContextWithTrustManagers(keystore, keystorePasswd, keyPasswd,
keystoreType, protocol);
+ } else {
+ sslContextWithTrustManagers =
createSslContextWithTrustManagers(keystore, keystorePasswd, keyPasswd,
keystoreType, truststore,
+ truststorePasswd, truststoreType, clientAuth,
protocol);
+ }
+ return new Tuple<>(sslContextWithTrustManagers.getKey(),
sslContextWithTrustManagers.getValue());
+
+ }
}
diff --git
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml
index e5a1def..9142a89 100644
---
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml
+++
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml
@@ -95,7 +95,7 @@ language governing permissions and limitations under the
License. -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
- <version>3.3.1</version>
+ <version>3.14.4</version>
</dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
diff --git
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/main/java/org/apache/nifi/processors/elasticsearch/AbstractElasticsearchHttpProcessor.java
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/main/java/org/apache/nifi/processors/elasticsearch/AbstractElasticsearchHttpProcessor.java
index 5787e59..49a1865 100644
---
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/main/java/org/apache/nifi/processors/elasticsearch/AbstractElasticsearchHttpProcessor.java
+++
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/main/java/org/apache/nifi/processors/elasticsearch/AbstractElasticsearchHttpProcessor.java
@@ -36,20 +36,31 @@ import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.proxy.ProxyConfiguration;
import org.apache.nifi.proxy.ProxySpec;
+import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.util.StringUtils;
+import org.apache.nifi.util.Tuple;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
/**
* A base class for Elasticsearch processors that use the HTTP API
@@ -212,7 +223,25 @@ public abstract class AbstractElasticsearchHttpProcessor
extends AbstractElastic
// check if the ssl context is set and add the factory if so
if (sslContext != null) {
- okHttpClient.sslSocketFactory(sslContext.getSocketFactory());
+ try {
+ Tuple<SSLContext, TrustManager[]> sslContextTuple =
SslContextFactory.createTrustSslContextWithTrustManagers(
+ sslService.getKeyStoreFile(),
+ sslService.getKeyStorePassword() != null ?
sslService.getKeyStorePassword().toCharArray() : null,
+ sslService.getKeyPassword() != null ?
sslService.getKeyPassword().toCharArray() : null,
+ sslService.getKeyStoreType(),
+ sslService.getTrustStoreFile(),
+ sslService.getTrustStorePassword() != null ?
sslService.getTrustStorePassword().toCharArray() : null,
+ sslService.getTrustStoreType(),
+ SslContextFactory.ClientAuth.WANT,
+ sslService.getSslAlgorithm()
+ );
+ List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslContextTuple.getValue())
+ .filter(trustManager -> trustManager instanceof
X509TrustManager)
+ .map(trustManager -> (X509TrustManager)
trustManager).collect(Collectors.toList());
+
okHttpClient.sslSocketFactory(sslContextTuple.getKey().getSocketFactory(),
x509TrustManagers.get(0));
+ } catch (CertificateException | UnrecoverableKeyException |
NoSuchAlgorithmException | KeyStoreException | KeyManagementException |
IOException e) {
+ throw new ProcessException(e);
+ }
}
okHttpClientAtomicReference.set(okHttpClient.build());
diff --git
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/test/java/org/apache/nifi/processors/elasticsearch/TestQueryElasticsearchHttpNoHits.java
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/test/java/org/apache/nifi/processors/elasticsearch/TestQueryElasticsearchHttpNoHits.java
index b648ec8..6b6d906 100644
---
a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/test/java/org/apache/nifi/processors/elasticsearch/TestQueryElasticsearchHttpNoHits.java
+++
b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/src/test/java/org/apache/nifi/processors/elasticsearch/TestQueryElasticsearchHttpNoHits.java
@@ -257,7 +257,7 @@ public class TestQueryElasticsearchHttpNoHits {
if (expectHitCountOnQueryInfo) {
out.assertAttributeEquals("es.query.hitcount",
String.valueOf(expectedHits));
}
-
Assert.assertTrue(out.getAttribute("es.query.url").startsWith("http://127.0.0.1:9200/doc/status/_search?q=source:Twitter%20AND%20identifier:%22%22&size=2"));
+
Assert.assertTrue(out.getAttribute("es.query.url").startsWith("http://127.0.0.1:9200/doc/status/_search?q=source%3ATwitter%20AND%20identifier%3A%22%22&size=2"));
}
}
}
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClient.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClient.java
index 81229de..2352026 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClient.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/main/java/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClient.java
@@ -23,12 +23,16 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
-import java.security.KeyStore;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -39,12 +43,9 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.GZIPInputStream;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MultivaluedHashMap;
@@ -70,6 +71,9 @@ import org.apache.nifi.util.Tuple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
+// Using static imports because of the name conflict:
+import static org.apache.nifi.security.util.SslContextFactory.ClientAuth.WANT;
+import static
org.apache.nifi.security.util.SslContextFactory.createTrustSslContextWithTrustManagers;
public class OkHttpReplicationClient implements HttpReplicationClient {
private static final Logger logger =
LoggerFactory.getLogger(OkHttpReplicationClient.class);
@@ -103,7 +107,8 @@ public class OkHttpReplicationClient implements
HttpReplicationClient {
/**
* Checks the content length header on DELETE requests to ensure it is set
to '0', avoiding request timeouts on replicated requests.
- * @param method the HTTP method of the request
+ *
+ * @param method the HTTP method of the request
* @param headers the header keys and values
*/
private void checkContentLengthHeader(String method, Map<String, String>
headers) {
@@ -327,57 +332,22 @@ public class OkHttpReplicationClient implements
HttpReplicationClient {
}
try {
- final KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- final TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance("X509");
-
- // initialize the KeyManager array to null and we will overwrite
later if a keystore is loaded
- KeyManager[] keyManagers = null;
-
- // we will only initialize the keystore if properties have been
supplied by the SSLContextService
- final String keystoreLocation =
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE);
- final String keystorePass =
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD);
- final String keystoreType =
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE);
-
- // prepare the keystore
- final KeyStore keyStore = KeyStore.getInstance(keystoreType);
-
- try (FileInputStream keyStoreStream = new
FileInputStream(keystoreLocation)) {
- keyStore.load(keyStoreStream, keystorePass.toCharArray());
- }
-
- keyManagerFactory.init(keyStore, keystorePass.toCharArray());
- keyManagers = keyManagerFactory.getKeyManagers();
-
- // we will only initialize the truststure if properties have been
supplied by the SSLContextService
- // load truststore
- final String truststoreLocation =
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE);
- final String truststorePass =
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD);
- final String truststoreType =
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE);
-
- KeyStore truststore = KeyStore.getInstance(truststoreType);
- truststore.load(new FileInputStream(truststoreLocation),
truststorePass.toCharArray());
- trustManagerFactory.init(truststore);
-
- // TrustManagerFactory.getTrustManagers returns a trust manager
for each type of trust material. Since we are getting a trust manager factory
that uses "X509"
- // as it's trust management algorithm, we are able to grab the
first (and thus the most preferred) and use it as our x509 Trust Manager
- //
- //
https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/TrustManagerFactory.html#getTrustManagers--
- final X509TrustManager x509TrustManager;
- TrustManager[] trustManagers =
trustManagerFactory.getTrustManagers();
- if (trustManagers[0] != null) {
- x509TrustManager = (X509TrustManager) trustManagers[0];
- } else {
- throw new IllegalStateException("List of trust managers is
null");
- }
-
- // if keystore properties were not supplied, the keyManagers array
will be null
- sslContext.init(keyManagers,
trustManagerFactory.getTrustManagers(), null);
-
- final SSLSocketFactory sslSocketFactory =
sslContext.getSocketFactory();
- return new Tuple<>(sslSocketFactory, x509TrustManager);
- } catch (final Exception e) {
- throw new RuntimeException("Failed to create SSL Socket Factory
for replicating requests across the cluster");
+ Tuple<SSLContext, TrustManager[]> sslContextTuple =
createTrustSslContextWithTrustManagers(
+ properties.getProperty(NiFiProperties.SECURITY_KEYSTORE),
+
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD) != null ?
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD).toCharArray() :
null,
+ properties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD)
!= null ?
properties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD).toCharArray() : null,
+
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_TYPE),
+ properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE),
+
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD) != null ?
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD).toCharArray()
: null,
+
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE),
+ WANT,
+ sslContext.getProtocol());
+ List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslContextTuple.getValue())
+ .filter(trustManager -> trustManager instanceof
X509TrustManager)
+ .map(trustManager -> (X509TrustManager)
trustManager).collect(Collectors.toList());
+ return new Tuple<>(sslContextTuple.getKey().getSocketFactory(),
x509TrustManagers.get(0));
+ } catch (CertificateException | UnrecoverableKeyException |
NoSuchAlgorithmException | KeyStoreException | KeyManagementException |
IOException e) {
+ return null;
}
}
-
}
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslServerSocketFactory.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslServerSocketFactory.java
deleted file mode 100644
index 458157c..0000000
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslServerSocketFactory.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.nifi.framework.security.util;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.security.NoSuchAlgorithmException;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLServerSocketFactory;
-import org.apache.nifi.util.NiFiProperties;
-
-/**
- * Implements a server socket factory for creating secure server sockets based
- * on the application's configuration properties. If the properties are
- * configured for SSL (one-way or two-way), then a SSLServerSocketFactory is
- * created and used based on those properties. Otherwise, Java's default
- * SSLServerSocketFactory is used. Specifically,
- * SSLContext.getDefault().getServerSocketFactory().
- */
-public class SslServerSocketFactory extends SSLServerSocketFactory {
-
- private SSLServerSocketFactory sslServerSocketFactory;
-
- public SslServerSocketFactory(final NiFiProperties nifiProperties) {
- final SSLContext sslCtx =
SslContextFactory.createSslContext(nifiProperties);
- if (sslCtx == null) {
- try {
- sslServerSocketFactory =
SSLContext.getDefault().getServerSocketFactory();
- } catch (final NoSuchAlgorithmException nsae) {
- throw new SslServerSocketFactoryCreationException(nsae);
- }
- } else {
- sslServerSocketFactory = sslCtx.getServerSocketFactory();
- }
- }
-
- @Override
- public ServerSocket createServerSocket(int i, int i1, InetAddress ia)
throws IOException {
- return sslServerSocketFactory.createServerSocket(i, i1, ia);
- }
-
- @Override
- public ServerSocket createServerSocket(int i, int i1) throws IOException {
- return sslServerSocketFactory.createServerSocket(i, i1);
- }
-
- @Override
- public ServerSocket createServerSocket(int i) throws IOException {
- return sslServerSocketFactory.createServerSocket(i);
- }
-
- @Override
- public ServerSocket createServerSocket() throws IOException {
- return sslServerSocketFactory.createServerSocket();
- }
-
- @Override
- public String[] getSupportedCipherSuites() {
- return sslServerSocketFactory.getSupportedCipherSuites();
- }
-
- @Override
- public String[] getDefaultCipherSuites() {
- return sslServerSocketFactory.getDefaultCipherSuites();
- }
-
-}
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslSocketFactory.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslSocketFactory.java
deleted file mode 100644
index fa6de56..0000000
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-security/src/main/java/org/apache/nifi/framework/security/util/SslSocketFactory.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.nifi.framework.security.util;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.UnknownHostException;
-import java.security.NoSuchAlgorithmException;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocketFactory;
-import org.apache.nifi.util.NiFiProperties;
-
-/**
- * Implements a socket factory for creating secure sockets based on the
- * application's configuration properties. If the properties are configured for
- * SSL (one-way or two-way), then a SSLSocketFactory is created and used based
- * on those properties. Otherwise, Java's default SSLSocketFactory is used.
- * Specifically, SSLContext.getDefault().getSocketFactory().
- */
-public class SslSocketFactory extends SSLSocketFactory {
-
- private final SSLSocketFactory sslSocketFactory;
-
- public SslSocketFactory(final NiFiProperties nifiProperties) {
- final SSLContext sslCtx =
SslContextFactory.createSslContext(nifiProperties);
- if (sslCtx == null) {
- try {
- sslSocketFactory = SSLContext.getDefault().getSocketFactory();
- } catch (final NoSuchAlgorithmException nsae) {
- throw new SslSocketFactoryCreationException(nsae);
- }
- } else {
- sslSocketFactory = sslCtx.getSocketFactory();
- }
- }
-
- @Override
- public String[] getSupportedCipherSuites() {
- return sslSocketFactory.getSupportedCipherSuites();
- }
-
- @Override
- public String[] getDefaultCipherSuites() {
- return sslSocketFactory.getDefaultCipherSuites();
- }
-
- @Override
- public Socket createSocket(Socket socket, String string, int i, boolean
bln) throws IOException {
- return sslSocketFactory.createSocket(socket, string, i, bln);
- }
-
- @Override
- public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1)
throws IOException {
- return sslSocketFactory.createSocket(ia, i, ia1, i1);
- }
-
- @Override
- public Socket createSocket(InetAddress ia, int i) throws IOException {
- return sslSocketFactory.createSocket(ia, i);
- }
-
- @Override
- public Socket createSocket(String string, int i, InetAddress ia, int i1)
throws IOException, UnknownHostException {
- return sslSocketFactory.createSocket(string, i, ia, i1);
- }
-
- @Override
- public Socket createSocket(String string, int i) throws IOException,
UnknownHostException {
- return sslSocketFactory.createSocket(string, i);
- }
-
- @Override
- public Socket createSocket() throws IOException {
- return sslSocketFactory.createSocket();
- }
-
-}
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
index c344410..78cadab 100644
---
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java
@@ -55,6 +55,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -104,9 +105,11 @@ import
org.apache.nifi.processors.standard.util.ProxyAuthenticator;
import
org.apache.nifi.processors.standard.util.SoftLimitBoundedByteArrayOutputStream;
import org.apache.nifi.proxy.ProxyConfiguration;
import org.apache.nifi.proxy.ProxySpec;
+import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.ssl.SSLContextService.ClientAuth;
import org.apache.nifi.stream.io.StreamUtils;
+import org.apache.nifi.util.Tuple;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
@@ -634,8 +637,21 @@ public final class InvokeHTTP extends AbstractProcessor {
// check if the ssl context is set and add the factory if so
if (sslContext != null) {
- setSslSocketFactory(okHttpClientBuilder, sslService, sslContext,
isHttpsProxy);
- }
+ Tuple<SSLContext, TrustManager[]> sslContextTuple
=SslContextFactory.createTrustSslContextWithTrustManagers(
+ sslService.getKeyStoreFile(),
+ sslService.getKeyStorePassword() != null ?
sslService.getKeyStorePassword().toCharArray() : null,
+ sslService.getKeyPassword() != null ?
sslService.getKeyPassword().toCharArray() : null,
+ sslService.getKeyStoreType(),
+ sslService.getTrustStoreFile(),
+ sslService.getTrustStorePassword() != null ?
sslService.getTrustStorePassword().toCharArray() : null,
+ sslService.getTrustStoreType(),
+ SslContextFactory.ClientAuth.NONE,
+ sslService.getSslAlgorithm());
+ List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslContextTuple.getValue())
+ .filter(trustManager -> trustManager instanceof
X509TrustManager)
+ .map(trustManager -> (X509TrustManager)
trustManager).collect(Collectors.toList());
+
okHttpClientBuilder.sslSocketFactory(sslContextTuple.getKey().getSocketFactory(),
x509TrustManagers.get(0));
+ }
setAuthenticator(okHttpClientBuilder, context);
diff --git
a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/main/java/org/apache/nifi/lookup/RestLookupService.java
b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/main/java/org/apache/nifi/lookup/RestLookupService.java
index 6ecc95d..882690d 100644
---
a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/main/java/org/apache/nifi/lookup/RestLookupService.java
+++
b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/src/main/java/org/apache/nifi/lookup/RestLookupService.java
@@ -40,6 +40,7 @@ import org.apache.nifi.components.Validator;
import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.proxy.ProxyConfiguration;
import org.apache.nifi.proxy.ProxyConfigurationService;
@@ -48,6 +49,7 @@ import org.apache.nifi.record.path.FieldValue;
import org.apache.nifi.record.path.RecordPath;
import org.apache.nifi.record.path.validation.RecordPathValidator;
import org.apache.nifi.schema.access.SchemaNotFoundException;
+import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.serialization.MalformedRecordException;
import org.apache.nifi.serialization.RecordReader;
import org.apache.nifi.serialization.RecordReaderFactory;
@@ -57,12 +59,20 @@ import org.apache.nifi.serialization.record.Record;
import org.apache.nifi.serialization.record.RecordSchema;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.util.StringUtils;
+import org.apache.nifi.util.Tuple;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -231,9 +241,33 @@ public class RestLookupService extends
AbstractControllerService implements Reco
}
final SSLContextService sslService =
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
- final SSLContext sslContext = sslService == null ? null :
sslService.createSSLContext(SSLContextService.ClientAuth.WANT);
if (sslService != null) {
- builder.sslSocketFactory(sslContext.getSocketFactory());
+ Tuple<SSLContext, TrustManager[]> sslContextTuple = null;
+ try {
+ sslContextTuple =
SslContextFactory.createTrustSslContextWithTrustManagers(
+ sslService.getKeyStoreFile(),
+ sslService.getKeyStorePassword() != null ?
sslService.getKeyStorePassword().toCharArray() : null,
+ sslService.getKeyPassword() != null ?
sslService.getKeyPassword().toCharArray() : null,
+ sslService.getKeyStoreType(),
+ sslService.getTrustStoreFile(),
+ sslService.getTrustStorePassword() != null ?
sslService.getTrustStorePassword().toCharArray() : null,
+ sslService.getTrustStoreType(),
+ SslContextFactory.ClientAuth.WANT,
+ sslService.getSslAlgorithm()
+ );
+ } catch (CertificateException | UnrecoverableKeyException |
NoSuchAlgorithmException | KeyStoreException | KeyManagementException |
IOException e) {
+ throw new ProcessException(e);
+ }
+ List<X509TrustManager> x509TrustManagers =
Arrays.stream(sslContextTuple.getValue())
+ .filter(trustManager -> trustManager instanceof
X509TrustManager)
+ .map(trustManager -> (X509TrustManager)
trustManager).collect(Collectors.toList());
+
builder.sslSocketFactory(sslContextTuple.getKey().getSocketFactory(),
x509TrustManagers.get(0));
+
+ if (sslContextTuple.getValue().length > 0) {
+
builder.sslSocketFactory(sslContextTuple.getKey().getSocketFactory(),
(X509TrustManager) sslContextTuple.getValue()[0]);
+ } else {
+ throw new ProcessException("Failed to create SSL socket
factory with trust manager.");
+ }
}
client = builder.build();