exceptionfactory commented on a change in pull request #5008:
URL: https://github.com/apache/nifi/pull/5008#discussion_r616699567



##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
##########
@@ -1012,6 +1012,30 @@ protected static void 
configureSslContextFactory(SslContextFactory.Server contex
         
contextFactory.setIncludeProtocols(TlsConfiguration.getCurrentSupportedTlsProtocolVersions());
         contextFactory.setExcludeProtocols("TLS", "TLSv1", "TLSv1.1", "SSL", 
"SSLv2", "SSLv2Hello", "SSLv3");
 
+        // on configuration, replace default application cipher suites with 
those configured
+        final String includeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(includeCipherSuitesProps)) {
+            logger.info(String.format("NiFiProperties.%s = %s",
+                    NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES, 
includeCipherSuitesProps));

Review comment:
       In light of the following informational log message, this log message 
does not seem necessary.

##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
##########
@@ -1012,6 +1012,30 @@ protected static void 
configureSslContextFactory(SslContextFactory.Server contex
         
contextFactory.setIncludeProtocols(TlsConfiguration.getCurrentSupportedTlsProtocolVersions());
         contextFactory.setExcludeProtocols("TLS", "TLSv1", "TLSv1.1", "SSL", 
"SSLv2", "SSLv2Hello", "SSLv3");
 
+        // on configuration, replace default application cipher suites with 
those configured
+        final String includeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(includeCipherSuitesProps)) {
+            logger.info(String.format("NiFiProperties.%s = %s",
+                    NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES, 
includeCipherSuitesProps));
+            final String[] includeCipherSuitesRuntime = 
contextFactory.getIncludeCipherSuites();
+            final String[] includeCipherSuites = 
includeCipherSuitesProps.split(",\\s*");
+            logger.info(String.format("Replacing include cipher suites with 
configuration; FROM [%s] TO [%s].",
+                    ((includeCipherSuitesRuntime == null) ? null : 
Arrays.asList(includeCipherSuitesRuntime)),
+                    String.join(", ", Arrays.asList(includeCipherSuites))));

Review comment:
       Recommend restructuring this statement to use logging placeholders 
instead of String.format().  Using the configured property value seems more 
straightforward than reformatting the parsed string array.
   ```suggestion
               logger.info("Configuring TLS included cipher suites [{}] 
replacing default [{}]", includeCipherSuitesProps, 
Arrays.asList(includeCipherSuitesRuntime));
   ```

##########
File path: 
nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
##########
@@ -207,6 +207,8 @@
     public static final String WEB_HTTPS_PORT = "nifi.web.https.port";
     public static final String WEB_HTTPS_PORT_FORWARDING = 
"nifi.web.https.port.forwarding";
     public static final String WEB_HTTPS_HOST = "nifi.web.https.host";
+    public static final String WEB_HTTPS_INCLUDE_CIPHERSUITES = 
"nifi.web.https.includeciphersuites";
+    public static final String WEB_HTTPS_EXCLUDE_CIPHERSUITES = 
"nifi.web.https.excludeciphersuites";

Review comment:
       Given the multiple words included, and the parallel nature of the 
properties, what do you think about adjusting the naming to 
`nifi.web.https.ciphersuites.include` and `nifi.web.https.ciphersuites.exclude`?

##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
##########
@@ -1012,6 +1012,30 @@ protected static void 
configureSslContextFactory(SslContextFactory.Server contex
         
contextFactory.setIncludeProtocols(TlsConfiguration.getCurrentSupportedTlsProtocolVersions());
         contextFactory.setExcludeProtocols("TLS", "TLSv1", "TLSv1.1", "SSL", 
"SSLv2", "SSLv2Hello", "SSLv3");
 
+        // on configuration, replace default application cipher suites with 
those configured
+        final String includeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(includeCipherSuitesProps)) {

Review comment:
       This could be streamlined to `StringUtils.isNotEmpty()`
   ```suggestion
           if (StringUtils.isNotEmpty(includeCipherSuitesProps)) {
   ```

##########
File path: nifi-docs/src/main/asciidoc/administration-guide.adoc
##########
@@ -209,6 +209,28 @@ In order to facilitate the secure setup of NiFi, you can 
use the `tls-toolkit` c
 * <<toolkit-guide.adoc#tls_intermediate_ca,Using An Existing Intermediate 
Certificate Authority>>
 * <<toolkit-guide.adoc#additional_certificate_commands,Additional Certificate 
Commands>>
 
+[[tls_cipher_suites]]
+=== TLS Cipher Suites
+
+The Java Runtime Environment provides the ability to specify custom TLS cipher 
suites to be used by servers when accepting client connections.  See
+link:https://java.com/en/configure_crypto.html[here^] for more information.  
To use this feature for the NiFi web service, the following NiFi properties
+may be set:
+
+[options="header,footer"]
+|==================================================================================================================================================
+| Property Name | Description
+|`nifi.web.https.includeciphersuites` | Additional ciphers that may be used by 
incoming client connections.

Review comment:
       The description seems a little confusing on initial read.  The Jetty 
`SslContextFactory.selectCipherSuites` method appears to limit selected cipher 
suites based on included values, is that correct?  In other words, the list of 
included cipher suites would not be in addition to the default set, but limited 
to what is included.  If that is not the case, it would be helpful to indicate 
that this is in addition to system defaults.

##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/test/java/org/apache/nifi/web/server/JettyServerTest.java
##########
@@ -142,4 +146,64 @@ public void 
testConfigureSslContextFactoryWithPkcsTrustStore() {
         verify(mockSCF).setTrustStoreType(trustStoreType);
         
verify(mockSCF).setTrustStoreProvider(BouncyCastleProvider.PROVIDER_NAME);
     }
+
+    /**
+     * Verify correct processing of cipher suites with multiple elements.  
Verify call to override runtime ciphers.
+     */
+    @Test
+    public void testConfigureSslIncludeExcludeCiphers() {
+        final String[] includeCipherSuites = {"TLS_AES_256_GCM_SHA384", 
"TLS_AES_128_GCM_SHA256"};
+        final String includeCipherSuitesProp = String.join(", ", 
Arrays.asList(includeCipherSuites));
+        final String[] excludeCipherSuites = {".*DHE.*", ".*ECDH.*"};
+        final String excludeCipherSuitesProp = String.join(", ", 
Arrays.asList(excludeCipherSuites));
+        final Map<String, String> addProps = new HashMap<>();
+        addProps.put(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES, 
includeCipherSuitesProp);
+        addProps.put(NiFiProperties.WEB_HTTPS_EXCLUDE_CIPHERSUITES, 
excludeCipherSuitesProp);
+        final NiFiProperties nifiProperties = 
NiFiProperties.createBasicNiFiProperties(null, addProps);
+
+        final SslContextFactory.Server mockSCF = 
mock(SslContextFactory.Server.class);
+        JettyServer.configureSslContextFactory(mockSCF, nifiProperties);
+        verify(mockSCF, times(1)).getIncludeCipherSuites();
+        verify(mockSCF, times(1)).getExcludeCipherSuites();
+        verify(mockSCF, times(1)).setIncludeCipherSuites(includeCipherSuites);
+        verify(mockSCF, times(1)).setExcludeCipherSuites(excludeCipherSuites);
+    }
+
+    /**
+     * Verify skip cipher configuration when NiFiProperties are not specified.
+     */
+    @Test
+    public void testDoNotConfigureSslIncludeExcludeCiphers() {
+        final NiFiProperties nifiProperties = 
NiFiProperties.createBasicNiFiProperties(null);
+        final SslContextFactory.Server mockSCF = 
mock(SslContextFactory.Server.class);
+        JettyServer.configureSslContextFactory(mockSCF, nifiProperties);
+        verify(mockSCF, times(0)).getIncludeCipherSuites();
+        verify(mockSCF, times(0)).getExcludeCipherSuites();
+        verify(mockSCF, times(0)).setIncludeCipherSuites(any());
+        verify(mockSCF, times(0)).setExcludeCipherSuites(any());
+    }
+
+    /**
+     * Verify strategy for translating between String representation (in 
NiFiProperties)
+     * and String[] representation (hand off to JCE API).
+     */
+    @Test
+    public void testTransformStringToStringArray() {
+        final String[] strings = {
+                "ABC",
+                "ABC, DEF",
+                "ABC, DEF, GHI",  // single space is specified below in 
`String.join()` delimiter
+        };
+        final String[][] stringArrays = {
+                { "ABC" },
+                { "ABC", "DEF" },
+                { "ABC", "DEF", "GHI" },
+        };
+        for (int i = 0; (i < strings.length); ++i) {
+            final String string = strings[i];
+            final String[] stringArray = stringArrays[i];
+            Assert.assertEquals(string, String.join(", ", 
Arrays.asList(stringArray)));
+            Assert.assertArrayEquals(stringArray, string.split(",\\s*"));
+        }
+    }

Review comment:
       Is this test method necessary?  Since it does not exercise any of the 
JettyServer methods, it looks like it should be removed.

##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
##########
@@ -1012,6 +1012,30 @@ protected static void 
configureSslContextFactory(SslContextFactory.Server contex
         
contextFactory.setIncludeProtocols(TlsConfiguration.getCurrentSupportedTlsProtocolVersions());
         contextFactory.setExcludeProtocols("TLS", "TLSv1", "TLSv1.1", "SSL", 
"SSLv2", "SSLv2Hello", "SSLv3");
 
+        // on configuration, replace default application cipher suites with 
those configured
+        final String includeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(includeCipherSuitesProps)) {
+            logger.info(String.format("NiFiProperties.%s = %s",
+                    NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES, 
includeCipherSuitesProps));
+            final String[] includeCipherSuitesRuntime = 
contextFactory.getIncludeCipherSuites();
+            final String[] includeCipherSuites = 
includeCipherSuitesProps.split(",\\s*");
+            logger.info(String.format("Replacing include cipher suites with 
configuration; FROM [%s] TO [%s].",
+                    ((includeCipherSuitesRuntime == null) ? null : 
Arrays.asList(includeCipherSuitesRuntime)),
+                    String.join(", ", Arrays.asList(includeCipherSuites))));
+            contextFactory.setIncludeCipherSuites(includeCipherSuites);
+        }
+        final String excludeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_EXCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(excludeCipherSuitesProps)) {

Review comment:
       As mentioned above, this could be replaced with StringUtils.isNotEmpty().

##########
File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
##########
@@ -1012,6 +1012,30 @@ protected static void 
configureSslContextFactory(SslContextFactory.Server contex
         
contextFactory.setIncludeProtocols(TlsConfiguration.getCurrentSupportedTlsProtocolVersions());
         contextFactory.setExcludeProtocols("TLS", "TLSv1", "TLSv1.1", "SSL", 
"SSLv2", "SSLv2Hello", "SSLv3");
 
+        // on configuration, replace default application cipher suites with 
those configured
+        final String includeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(includeCipherSuitesProps)) {
+            logger.info(String.format("NiFiProperties.%s = %s",
+                    NiFiProperties.WEB_HTTPS_INCLUDE_CIPHERSUITES, 
includeCipherSuitesProps));
+            final String[] includeCipherSuitesRuntime = 
contextFactory.getIncludeCipherSuites();
+            final String[] includeCipherSuites = 
includeCipherSuitesProps.split(",\\s*");
+            logger.info(String.format("Replacing include cipher suites with 
configuration; FROM [%s] TO [%s].",
+                    ((includeCipherSuitesRuntime == null) ? null : 
Arrays.asList(includeCipherSuitesRuntime)),
+                    String.join(", ", Arrays.asList(includeCipherSuites))));
+            contextFactory.setIncludeCipherSuites(includeCipherSuites);
+        }
+        final String excludeCipherSuitesProps = 
props.getProperty(NiFiProperties.WEB_HTTPS_EXCLUDE_CIPHERSUITES);
+        if (!StringUtils.isEmpty(excludeCipherSuitesProps)) {
+            logger.info(String.format("NiFiProperties.%s = %s",
+                    NiFiProperties.WEB_HTTPS_EXCLUDE_CIPHERSUITES, 
excludeCipherSuitesProps));

Review comment:
       Recommend removing this log message in the light of the following 
informational message that includes the same configuration property.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to