You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by al...@apache.org on 2017/08/31 03:17:16 UTC
nifi git commit: NIFI-2528 Added RestrictedSSLContextService
interface with implementation. Changed ListenHTTP to allow only new
StandardRestrictedSSLContextService.
Repository: nifi
Updated Branches:
refs/heads/master e62417ea6 -> d28e61c5d
NIFI-2528 Added RestrictedSSLContextService interface with implementation. Changed ListenHTTP to allow only new StandardRestrictedSSLContextService.
This closes #1986.
Signed-off-by: Andy LoPresto <al...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/d28e61c5
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/d28e61c5
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/d28e61c5
Branch: refs/heads/master
Commit: d28e61c5ddc7486747d431dfd82e17dc435ca817
Parents: e62417e
Author: m-hogue <ho...@gmail.com>
Authored: Thu Jul 6 11:42:46 2017 -0400
Committer: Andy LoPresto <al...@apache.org>
Committed: Wed Aug 30 20:17:01 2017 -0700
----------------------------------------------------------------------
.../nifi/processors/standard/ListenHTTP.java | 8 +-
.../processors/standard/TestListenHTTP.java | 100 ++++++++++++++++---
.../StandardRestrictedSSLContextService.java | 81 +++++++++++++++
.../nifi/ssl/StandardSSLContextService.java | 52 +++-------
...org.apache.nifi.controller.ControllerService | 3 +-
.../ssl/RestrictedSSLContextServiceTest.java | 44 ++++++++
.../apache/nifi/ssl/SSLContextServiceTest.java | 29 ++++++
.../nifi/ssl/RestrictedSSLContextService.java | 64 ++++++++++++
.../org/apache/nifi/ssl/SSLContextService.java | 44 ++++++++
9 files changed, 369 insertions(+), 56 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java
index d2bfa04..5d23370 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenHTTP.java
@@ -34,6 +34,7 @@ import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.util.StandardValidators;
import org.apache.nifi.processors.standard.servlets.ContentAcknowledgmentServlet;
import org.apache.nifi.processors.standard.servlets.ListenHTTPServlet;
+import org.apache.nifi.ssl.RestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.stream.io.LeakyBucketStreamThrottler;
import org.apache.nifi.stream.io.StreamThrottler;
@@ -118,7 +119,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
.name("SSL Context Service")
.description("The Controller Service to use in order to obtain an SSL Context")
.required(false)
- .identifiesControllerService(SSLContextService.class)
+ .identifiesControllerService(RestrictedSSLContextService.class)
.build();
public static final PropertyDescriptor HEADERS_AS_ATTRIBUTES_REGEX = new PropertyDescriptor.Builder()
.name("HTTP Headers to receive as Attributes (Regex)")
@@ -227,6 +228,10 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
contextFactory.setKeyStoreType(keyStoreType);
}
+ if (sslContextService != null) {
+ contextFactory.setProtocol(sslContextService.getSslAlgorithm());
+ }
+
// thread pool for the jetty instance
final QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName(String.format("%s (%s) Web Server", getClass().getSimpleName(), getIdentifier()));
@@ -249,6 +254,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
httpConfiguration.addCustomizer(new SecureRequestCustomizer());
// build the connector
+
connector = new ServerConnector(server, new SslConnectionFactory(contextFactory, "http/1.1"), new HttpConnectionFactory(httpConfiguration));
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java
index 9193f8e..c46d4cd 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java
@@ -20,11 +20,13 @@ import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.ssl.StandardRestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.ssl.StandardSSLContextService;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -35,10 +37,15 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.List;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+
import static org.apache.nifi.processors.standard.ListenHTTP.RELATIONSHIP_SUCCESS;
import static org.junit.Assert.fail;
+
public class TestListenHTTP {
+ private static final String SSL_CONTEXT_SERVICE_IDENTIFIER = "ssl-context";
private static final String HTTP_POST_METHOD = "POST";
private static final String HTTP_BASE_PATH = "basePath";
@@ -64,9 +71,13 @@ public class TestListenHTTP {
}
+ @After
+ public void teardown() {
+ proc.shutdownHttpServer();
+ }
+
@Test
public void testPOSTRequestsReceivedWithoutEL() throws Exception {
-
runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
@@ -75,30 +86,79 @@ public class TestListenHTTP {
@Test
public void testPOSTRequestsReceivedWithEL() throws Exception {
+ runner.setProperty(ListenHTTP.PORT, HTTP_SERVER_PORT_EL);
+ runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
+ runner.assertValid();
+
+ testPOSTRequestsReceived();
+ }
+
+ @Test
+ public void testSecurePOSTRequestsReceivedWithoutEL() throws Exception {
+ SSLContextService sslContextService = configureProcessorSslContextService();
+ runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
+ runner.enableControllerService(sslContextService);
+
+ runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
+ runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
+ runner.assertValid();
+
+ testPOSTRequestsReceived();
+ }
+
+ @Test
+ public void testSecurePOSTRequestsReceivedWithEL() throws Exception {
+ SSLContextService sslContextService = configureProcessorSslContextService();
+ runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
+ runner.enableControllerService(sslContextService);
runner.setProperty(ListenHTTP.PORT, HTTP_SERVER_PORT_EL);
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
+ runner.assertValid();
testPOSTRequestsReceived();
}
+ @Test
+ public void testSecureInvalidSSLConfiguration() throws Exception {
+ SSLContextService sslContextService = configureInvalidProcessorSslContextService();
+ runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, "TLSv1.2");
+ runner.enableControllerService(sslContextService);
+
+ runner.setProperty(ListenHTTP.PORT, HTTP_SERVER_PORT_EL);
+ runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
+ runner.assertNotValid();
+ }
+
private int executePOST(String message) throws Exception {
+ final SSLContextService sslContextService = runner.getControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, SSLContextService.class);
+ final boolean secure = (sslContextService != null);
+ final String scheme = secure ? "https" : "http";
+ final URL url = new URL(scheme + "://localhost:" + availablePort + "/" + HTTP_BASE_PATH);
+ HttpURLConnection connection;
+
+ if(secure) {
+ final HttpsURLConnection sslCon = (HttpsURLConnection) url.openConnection();
+ final SSLContext sslContext = sslContextService.createSSLContext(SSLContextService.ClientAuth.WANT);
+ sslCon.setSSLSocketFactory(sslContext.getSocketFactory());
+ connection = sslCon;
+
+ } else {
+ connection = (HttpURLConnection) url.openConnection();
+ }
+ connection.setRequestMethod(HTTP_POST_METHOD);
+ connection.setDoOutput(true);
- URL url= new URL("http://localhost:" + availablePort + "/" + HTTP_BASE_PATH);
- HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ final DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
- con.setRequestMethod(HTTP_POST_METHOD);
- con.setDoOutput(true);
- DataOutputStream wr = new DataOutputStream(con.getOutputStream());
if (message!=null) {
wr.writeBytes(message);
}
wr.flush();
wr.close();
-
- return con.getResponseCode();
-
+ return connection.getResponseCode();
}
+
private void testPOSTRequestsReceived() throws Exception {
final List<String> messages = new ArrayList<>();
messages.add("payload 1");
@@ -122,7 +182,7 @@ public class TestListenHTTP {
final ProcessSessionFactory processSessionFactory = runner.getProcessSessionFactory();
final ProcessContext context = runner.getProcessContext();
- proc.createHttpServer(context);
+ proc.createHttpServer(context);
Runnable sendMessagestoWebServer = () -> {
try {
@@ -151,18 +211,30 @@ public class TestListenHTTP {
}
private SSLContextService configureProcessorSslContextService() throws InitializationException {
- final SSLContextService sslContextService = new StandardSSLContextService();
- runner.addControllerService("ssl-context", sslContextService);
+ final SSLContextService sslContextService = new StandardRestrictedSSLContextService();
+ runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextService);
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, "src/test/resources/localhost-ts.jks");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, "localtest");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, "JKS");
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, "src/test/resources/localhost-ks.jks");
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, "localtest");
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, "JKS");
- runner.enableControllerService(sslContextService);
- runner.setProperty(ListenHTTP.SSL_CONTEXT_SERVICE, "ssl-context");
+ runner.setProperty(ListenHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_IDENTIFIER);
return sslContextService;
}
+ private SSLContextService configureInvalidProcessorSslContextService() throws InitializationException {
+ final SSLContextService sslContextService = new StandardSSLContextService();
+ runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextService);
+ runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, "src/test/resources/localhost-ts.jks");
+ runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, "localtest");
+ runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, "JKS");
+ runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, "src/test/resources/localhost-ks.jks");
+ runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, "localtest");
+ runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, "JKS");
+
+ runner.setProperty(ListenHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_IDENTIFIER);
+ return sslContextService;
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardRestrictedSSLContextService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardRestrictedSSLContextService.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardRestrictedSSLContextService.java
new file mode 100644
index 0000000..4ad7bbe
--- /dev/null
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardRestrictedSSLContextService.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ssl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.processor.util.StandardValidators;
+
+/**
+ * This class is functionally the same as {@link StandardSSLContextService}, but it restricts the allowable
+ * values that can be selected for TLS/SSL protocols.
+ */
+@Tags({"tls", "ssl", "secure", "certificate", "keystore", "truststore", "jks", "p12", "pkcs12", "pkcs"})
+@CapabilityDescription("Restricted implementation of the SSLContextService. Provides the ability to configure "
+ + "keystore and/or truststore properties once and reuse that configuration throughout the application, "
+ + "but only allows a restricted set of TLS/SSL protocols to be chosen (no SSL protocols are supported). The set of protocols selectable will "
+ + "evolve over time as new protocols emerge and older protocols are deprecated. This service is recommended "
+ + "over StandardSSLContextService if a component doesn't expect to communicate with legacy systems since it is "
+ + "unlikely that legacy systems will support these protocols.")
+public class StandardRestrictedSSLContextService extends StandardSSLContextService implements RestrictedSSLContextService {
+
+ public static final PropertyDescriptor RESTRICTED_SSL_ALGORITHM = new PropertyDescriptor.Builder()
+ .name("SSL Protocol")
+ .displayName("TLS Protocol")
+ .defaultValue("TLS")
+ .required(false)
+ .allowableValues(RestrictedSSLContextService.buildAlgorithmAllowableValues())
+ .description("The algorithm to use for this SSL context. By default, this will choose the highest supported TLS protocol version.")
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .sensitive(false)
+ .build();
+
+ private static final List<PropertyDescriptor> properties;
+
+ static {
+ List<PropertyDescriptor> props = new ArrayList<>();
+ props.add(KEYSTORE);
+ props.add(KEYSTORE_PASSWORD);
+ props.add(KEY_PASSWORD);
+ props.add(KEYSTORE_TYPE);
+ props.add(TRUSTSTORE);
+ props.add(TRUSTSTORE_PASSWORD);
+ props.add(TRUSTSTORE_TYPE);
+ props.add(RESTRICTED_SSL_ALGORITHM);
+ properties = Collections.unmodifiableList(props);
+ }
+
+ @Override
+ protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+ return properties;
+ }
+
+ @Override
+ public String getSslAlgorithm() {
+ return configContext.getProperty(RESTRICTED_SSL_ALGORITHM).getValue();
+ }
+
+ @Override
+ protected String getSSLProtocolForValidation(final ValidationContext validationContext) {
+ return validationContext.getProperty(RESTRICTED_SSL_ALGORITHM).getValue();
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardSSLContextService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardSSLContextService.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardSSLContextService.java
index 2570855..6b267ac 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardSSLContextService.java
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/java/org/apache/nifi/ssl/StandardSSLContextService.java
@@ -18,20 +18,15 @@ package org.apache.nifi.ssl;
import java.io.File;
import java.net.MalformedURLException;
-import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.net.ssl.SSLContext;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
-import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
import org.apache.nifi.components.ValidationContext;
@@ -48,7 +43,10 @@ import org.apache.nifi.security.util.SslContextFactory;
@Tags({"ssl", "secure", "certificate", "keystore", "truststore", "jks", "p12", "pkcs12", "pkcs", "tls"})
@CapabilityDescription("Standard implementation of the SSLContextService. Provides the ability to configure "
- + "keystore and/or truststore properties once and reuse that configuration throughout the application")
+ + "keystore and/or truststore properties once and reuse that configuration throughout the application. "
+ + "This service can be used to communicate with both legacy and modern systems. If you only need to "
+ + "communicate with non-legacy systems, then the StandardRestrictedSSLContextService is recommended as it only "
+ + "allows a specific set of SSL protocols to be chosen.")
public class StandardSSLContextService extends AbstractControllerService implements SSLContextService {
public static final String STORE_TYPE_JKS = "JKS";
@@ -110,14 +108,14 @@ public class StandardSSLContextService extends AbstractControllerService impleme
.displayName("TLS Protocol")
.defaultValue("TLS")
.required(false)
- .allowableValues(buildAlgorithmAllowableValues())
+ .allowableValues(SSLContextService.buildAlgorithmAllowableValues())
.description("The algorithm to use for this TLS/SSL context")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.sensitive(false)
.build();
private static final List<PropertyDescriptor> properties;
- private ConfigurationContext configContext;
+ protected ConfigurationContext configContext;
private boolean isValidated;
// TODO: This can be made configurable if necessary
@@ -252,8 +250,12 @@ public class StandardSSLContextService extends AbstractControllerService impleme
return VALIDATION_CACHE_EXPIRATION;
}
+ protected String getSSLProtocolForValidation(final ValidationContext validationContext) {
+ return validationContext.getProperty(SSL_ALGORITHM).getValue();
+ }
+
private void verifySslConfig(final ValidationContext validationContext) throws ProcessException {
- final String protocol = validationContext.getProperty(SSL_ALGORITHM).getValue();
+ final String protocol = getSSLProtocolForValidation(validationContext);
try {
final PropertyValue keyPasswdProp = validationContext.getProperty(KEY_PASSWORD);
final char[] keyPassword = keyPasswdProp.isSet() ? keyPasswdProp.getValue().toCharArray() : null;
@@ -295,7 +297,7 @@ public class StandardSSLContextService extends AbstractControllerService impleme
@Override
public SSLContext createSSLContext(final ClientAuth clientAuth) throws ProcessException {
- final String protocol = configContext.getProperty(SSL_ALGORITHM).getValue();
+ final String protocol = getSslAlgorithm();
try {
final PropertyValue keyPasswdProp = configContext.getProperty(KEY_PASSWORD);
final char[] keyPassword = keyPasswdProp.isSet() ? keyPasswdProp.getValue().toCharArray() : null;
@@ -458,36 +460,6 @@ public class StandardSSLContextService extends AbstractControllerService impleme
KEYSTORE, TRUSTSTORE
}
- private static AllowableValue[] buildAlgorithmAllowableValues() {
- final Set<String> supportedProtocols = new HashSet<>();
-
- /*
- * Prepopulate protocols with generic instance types commonly used
- * see: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
- */
- supportedProtocols.add("SSL");
- supportedProtocols.add("TLS");
-
- // Determine those provided by the JVM on the system
- try {
- supportedProtocols.addAll(Arrays.asList(SSLContext.getDefault().createSSLEngine().getSupportedProtocols()));
- } catch (NoSuchAlgorithmException e) {
- // ignored as default is used
- }
-
- final int numProtocols = supportedProtocols.size();
-
- // Sort for consistent presentation in configuration views
- final List<String> supportedProtocolList = new ArrayList<>(supportedProtocols);
- Collections.sort(supportedProtocolList);
-
- final List<AllowableValue> protocolAllowableValues = new ArrayList<>();
- for (final String protocol : supportedProtocolList) {
- protocolAllowableValues.add(new AllowableValue(protocol));
- }
- return protocolAllowableValues.toArray(new AllowableValue[numProtocols]);
- }
-
@Override
public String toString() {
return "SSLContextService[id=" + getIdentifier() + "]";
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
index b1b6124..115fe0d 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
@@ -12,4 +12,5 @@
# 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.
-org.apache.nifi.ssl.StandardSSLContextService
\ No newline at end of file
+org.apache.nifi.ssl.StandardSSLContextService
+org.apache.nifi.ssl.StandardRestrictedSSLContextService
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/RestrictedSSLContextServiceTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/RestrictedSSLContextServiceTest.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/RestrictedSSLContextServiceTest.java
new file mode 100644
index 0000000..3a44ef4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/RestrictedSSLContextServiceTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ssl;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.nifi.components.AllowableValue;
+import org.junit.Test;
+
+public class RestrictedSSLContextServiceTest {
+
+ @Test
+ public void testTLSAlgorithms() {
+ final Set<String> expected = new HashSet<>();
+ expected.add("TLS");
+ expected.add("TLSv1.2");
+
+ final AllowableValue[] allowableValues = RestrictedSSLContextService.buildAlgorithmAllowableValues();
+ assertThat(allowableValues, notNullValue());
+ assertThat(allowableValues.length, equalTo(expected.size()));
+ for(final AllowableValue value : allowableValues) {
+ assertTrue(expected.contains(value.getValue()));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
index 60b09bd..4c00bdc 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-bundle/nifi-ssl-context-service/src/test/java/org/apache/nifi/ssl/SSLContextServiceTest.java
@@ -16,6 +16,9 @@
*/
package org.apache.nifi.ssl;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -23,9 +26,17 @@ import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.components.ValidationContext;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.reporting.InitializationException;
@@ -311,4 +322,22 @@ public class SSLContextServiceTest {
Assert.fail("Should not have thrown a exception " + e.getMessage());
}
}
+
+ @Test
+ public void testSSLAlgorithms() throws NoSuchAlgorithmException {
+ final AllowableValue[] allowableValues = SSLContextService.buildAlgorithmAllowableValues();
+
+ // we expect TLS, SSL, and all available configured JVM protocols
+ final Set<String> expected = new HashSet<>();
+ expected.add("SSL");
+ expected.add("TLS");
+ final String[] supportedProtocols = SSLContext.getDefault().createSSLEngine().getSupportedProtocols();
+ expected.addAll(Arrays.asList(supportedProtocols));
+
+ assertThat(allowableValues, notNullValue());
+ assertThat(allowableValues.length, equalTo(expected.size()));
+ for(final AllowableValue value : allowableValues) {
+ assertTrue(expected.contains(value.getValue()));
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/RestrictedSSLContextService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/RestrictedSSLContextService.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/RestrictedSSLContextService.java
new file mode 100644
index 0000000..b76f31d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/RestrictedSSLContextService.java
@@ -0,0 +1,64 @@
+/*
+ * 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.ssl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.nifi.components.AllowableValue;
+
+/**
+ * Simple extension of the regular {@link SSLContextService} to allow for restricted implementations
+ * of that interface.
+ */
+public interface RestrictedSSLContextService extends SSLContextService {
+
+ /**
+ * Build a restricted set of allowable TLS protocol algorithms.
+ *
+ * @return the computed set of allowable values
+ */
+ static AllowableValue[] buildAlgorithmAllowableValues() {
+ final Set<String> supportedProtocols = new HashSet<>();
+
+ /*
+ * Prepopulate protocols with generic instance types commonly used
+ * see: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
+ */
+ supportedProtocols.add("TLS");
+
+ /*
+ * Add specifically supported TLS versions
+ */
+ supportedProtocols.add("TLSv1.2");
+
+ final int numProtocols = supportedProtocols.size();
+
+ // Sort for consistent presentation in configuration views
+ final List<String> supportedProtocolList = new ArrayList<>(supportedProtocols);
+ Collections.sort(supportedProtocolList);
+
+ final List<AllowableValue> protocolAllowableValues = new ArrayList<>();
+ for (final String protocol : supportedProtocolList) {
+ protocolAllowableValues.add(new AllowableValue(protocol));
+ }
+ return protocolAllowableValues.toArray(new AllowableValue[numProtocols]);
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/d28e61c5/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/SSLContextService.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/SSLContextService.java b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/SSLContextService.java
index 94f8bda..61f3b81 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/SSLContextService.java
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-ssl-context-service-api/src/main/java/org/apache/nifi/ssl/SSLContextService.java
@@ -16,10 +16,19 @@
*/
package org.apache.nifi.ssl;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import javax.net.ssl.SSLContext;
import org.apache.nifi.annotation.documentation.CapabilityDescription;
import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.AllowableValue;
import org.apache.nifi.controller.ControllerService;
import org.apache.nifi.processor.exception.ProcessException;
@@ -60,4 +69,39 @@ public interface SSLContextService extends ControllerService {
public boolean isKeyStoreConfigured();
String getSslAlgorithm();
+
+ /**
+ * Build a set of allowable TLS/SSL protocol algorithms based on JVM configuration.
+ *
+ * @return the computed set of allowable values
+ */
+ static AllowableValue[] buildAlgorithmAllowableValues() {
+ final Set<String> supportedProtocols = new HashSet<>();
+
+ /*
+ * Prepopulate protocols with generic instance types commonly used
+ * see: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext
+ */
+ supportedProtocols.add("TLS");
+ supportedProtocols.add("SSL");
+
+ // Determine those provided by the JVM on the system
+ try {
+ supportedProtocols.addAll(Arrays.asList(SSLContext.getDefault().createSSLEngine().getSupportedProtocols()));
+ } catch (NoSuchAlgorithmException e) {
+ // ignored as default is used
+ }
+
+ final int numProtocols = supportedProtocols.size();
+
+ // Sort for consistent presentation in configuration views
+ final List<String> supportedProtocolList = new ArrayList<>(supportedProtocols);
+ Collections.sort(supportedProtocolList);
+
+ final List<AllowableValue> protocolAllowableValues = new ArrayList<>();
+ for (final String protocol : supportedProtocolList) {
+ protocolAllowableValues.add(new AllowableValue(protocol));
+ }
+ return protocolAllowableValues.toArray(new AllowableValue[numProtocols]);
+ }
}