This is an automated email from the ASF dual-hosted git repository.

joewitt pushed a commit to branch support/nifi-1.11.x
in repository https://gitbox.apache.org/repos/asf/nifi.git

commit 67db74148e2f73e27ce4a63308380bc7a0d50022
Author: Nathan Gough <[email protected]>
AuthorDate: Tue Mar 10 21:22:29 2020 +1100

    NIFI-7223 - Fixed a minor issue where the OkHttpReplicationClient class 
loaded blank properties as empty string instead of an expected null value. 
Added a isNotBlank check. Added unit tests for replication client and 
HTTPNotificationService.
    NIFI-7223 - Renamed some variables and methods.
    NIFI-7223 - Removed unused dependency. Corrected security properties in 
administration-guide.
---
 nifi-bootstrap/pom.xml                             |   5 +
 .../http/TestHttpNotificationServiceSSL.java       | 190 ++++++++++++++++++++-
 .../src/main/asciidoc/administration-guide.adoc    |   5 +-
 .../okhttp/OkHttpReplicationClient.java            |  11 +-
 .../okhttp/OkHttpReplicationClientTest.groovy      |  75 ++++++++
 .../src/test/resources/conf/keystore.jks           | Bin 0 -> 3088 bytes
 .../src/test/resources/conf/truststore.jks         | Bin 0 -> 911 bytes
 7 files changed, 273 insertions(+), 13 deletions(-)

diff --git a/nifi-bootstrap/pom.xml b/nifi-bootstrap/pom.xml
index 5d8dbdf..a1a9134 100644
--- a/nifi-bootstrap/pom.xml
+++ b/nifi-bootstrap/pom.xml
@@ -73,5 +73,10 @@ language governing permissions and limitations under the 
License. -->
             <artifactId>jna-platform</artifactId>
             <version>4.4.0</version>
         </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java
 
b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java
index 5ab8cab..2f54f1c 100644
--- 
a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java
+++ 
b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java
@@ -16,13 +16,21 @@
  */
 package org.apache.nifi.bootstrap.http;
 
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.read.ListAppender;
 import okhttp3.mockwebserver.MockWebServer;
+import org.apache.nifi.bootstrap.NotificationServiceManager;
 import org.apache.nifi.security.util.SslContextFactory;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.internal.util.io.IOUtil;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+import ch.qos.logback.classic.Logger;
 
 import javax.net.ssl.SSLContext;
+import javax.xml.parsers.ParserConfigurationException;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
@@ -32,9 +40,12 @@ import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateException;
+import java.util.List;
 
-public class TestHttpNotificationServiceSSL extends  
TestHttpNotificationServiceCommon{
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
+public class TestHttpNotificationServiceSSL extends 
TestHttpNotificationServiceCommon {
 
     static final String CONFIGURATION_FILE_TEXT = "\n"+
             "<services>\n"+
@@ -47,14 +58,80 @@ public class TestHttpNotificationServiceSSL extends  
TestHttpNotificationService
             "            <property name=\"Truststore 
Password\">passwordpassword</property>\n"+
             "            <property name=\"Keystore 
Filename\">./src/test/resources/keystore.jks</property>\n"+
             "            <property name=\"Keystore Type\">JKS</property>\n"+
+            "            <property name=\"Key 
Password\">passwordpassword</property>\n"+
             "            <property name=\"Keystore 
Password\">passwordpassword</property>\n"+
             "            <property 
name=\"testProp\">${literal('testing')}</property>\n"+
             "         </service>\n"+
             "</services>";
 
+    static final String CONFIGURATION_FILE_TEXT_NO_KEYSTORE_PASSWORD = "\n"+
+            "<services>\n"+
+            "         <service>\n"+
+            "            <id>http-notification</id>\n"+
+            "            
<class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n"+
+            "            <property name=\"URL\">${test.server}</property>\n"+
+            "            <property name=\"Truststore 
Filename\">./src/test/resources/truststore.jks</property>\n"+
+            "            <property name=\"Truststore Type\">JKS</property>\n"+
+            "            <property name=\"Truststore 
Password\">passwordpassword</property>\n"+
+            "            <property name=\"Keystore 
Filename\">./src/test/resources/keystore.jks</property>\n"+
+            "            <property name=\"Keystore Type\">JKS</property>\n"+
+            "            <property name=\"Key 
Password\">passwordpassword</property>\n"+
+            "            <property 
name=\"testProp\">${literal('testing')}</property>\n"+
+            "         </service>\n"+
+            "</services>";
+
+    static final String CONFIGURATION_FILE_TEXT_NO_KEY_PASSWORD = "\n"+
+            "<services>\n"+
+            "         <service>\n"+
+            "            <id>http-notification</id>\n"+
+            "            
<class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n"+
+            "            <property name=\"URL\">${test.server}</property>\n"+
+            "            <property name=\"Truststore 
Filename\">./src/test/resources/truststore.jks</property>\n"+
+            "            <property name=\"Truststore Type\">JKS</property>\n"+
+            "            <property name=\"Truststore 
Password\">passwordpassword</property>\n"+
+            "            <property name=\"Keystore 
Filename\">./src/test/resources/keystore.jks</property>\n"+
+            "            <property name=\"Keystore Type\">JKS</property>\n"+
+            "            <property name=\"Keystore 
Password\">passwordpassword</property>\n"+
+            "            <property 
name=\"testProp\">${literal('testing')}</property>\n"+
+            "         </service>\n"+
+            "</services>";
+
+    static final String CONFIGURATION_FILE_TEXT_BLANK_KEY_PASSWORD = "\n"+
+            "<services>\n"+
+            "         <service>\n"+
+            "            <id>http-notification</id>\n"+
+            "            
<class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n"+
+            "            <property name=\"URL\">${test.server}</property>\n"+
+            "            <property name=\"Truststore 
Filename\">./src/test/resources/truststore.jks</property>\n"+
+            "            <property name=\"Truststore Type\">JKS</property>\n"+
+            "            <property name=\"Truststore 
Password\">passwordpassword</property>\n"+
+            "            <property name=\"Keystore 
Filename\">./src/test/resources/keystore.jks</property>\n"+
+            "            <property name=\"Keystore Type\">JKS</property>\n"+
+            "            <property name=\"Keystore 
Password\">passwordpassword</property>\n"+
+            "            <property name=\"Key Password\"></property>\n"+
+            "            <property 
name=\"testProp\">${literal('testing')}</property>\n"+
+            "         </service>\n"+
+            "</services>";
 
-    @BeforeClass
-    public static void startServer() throws IOException, 
UnrecoverableKeyException, CertificateException, NoSuchAlgorithmException, 
KeyStoreException, KeyManagementException {
+    static final String CONFIGURATION_FILE_TEXT_BLANK_KEYSTORE_PASSWORD = "\n"+
+            "<services>\n"+
+            "         <service>\n"+
+            "            <id>http-notification</id>\n"+
+            "            
<class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n"+
+            "            <property name=\"URL\">${test.server}</property>\n"+
+            "            <property name=\"Truststore 
Filename\">./src/test/resources/truststore.jks</property>\n"+
+            "            <property name=\"Truststore Type\">JKS</property>\n"+
+            "            <property name=\"Truststore 
Password\">passwordpassword</property>\n"+
+            "            <property name=\"Keystore 
Filename\">./src/test/resources/keystore.jks</property>\n"+
+            "            <property name=\"Keystore Type\">JKS</property>\n"+
+            "            <property name=\"Keystore Password\"></property>\n"+
+            "            <property name=\"Key 
Password\">passwordpassword</property>\n"+
+            "            <property 
name=\"testProp\">${literal('testing')}</property>\n"+
+            "         </service>\n"+
+            "</services>";
+
+    @Before
+    public void startServer() throws IOException, UnrecoverableKeyException, 
CertificateException, NoSuchAlgorithmException, KeyStoreException, 
KeyManagementException {
         tempConfigFilePath = "./target/TestHttpNotificationService-config.xml";
 
         Files.deleteIfExists(Paths.get(tempConfigFilePath));
@@ -78,10 +155,109 @@ public class TestHttpNotificationServiceSSL extends  
TestHttpNotificationService
         IOUtil.writeText(configFileOutput, new File(tempConfigFilePath));
     }
 
-    @AfterClass
-    public static void shutdownServer() throws IOException {
+    @After
+    public void shutdownServer() throws IOException {
         Files.deleteIfExists(Paths.get(tempConfigFilePath));
         mockWebServer.shutdown();
     }
 
+    @Test
+    public void testStartNotificationSucceedsNoKeystorePasswd() throws 
ParserConfigurationException, SAXException, IOException {
+        Logger notificationServiceLogger = (Logger) 
LoggerFactory.getLogger(NotificationServiceManager.class);
+        ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
+        listAppender.start();
+        notificationServiceLogger.addAppender(listAppender);
+
+        String configFileOutput = 
CONFIGURATION_FILE_TEXT_NO_KEYSTORE_PASSWORD.replace("${test.server}", 
String.valueOf(mockWebServer.url("/")));
+        IOUtil.writeText(configFileOutput, new File(tempConfigFilePath));
+
+        NotificationServiceManager notificationServiceManager = new 
NotificationServiceManager();
+        notificationServiceManager.setMaxNotificationAttempts(1);
+        notificationServiceManager.loadNotificationServices(new 
File(tempConfigFilePath));
+
+        List<ILoggingEvent> logsList = listAppender.list;
+        boolean notificationServiceFailed = false;
+        for(ILoggingEvent logMessage : logsList) {
+            if(logMessage.getFormattedMessage().contains("is not valid for the 
following reasons")) {
+                    notificationServiceFailed = true;
+            }
+        }
+
+        assertFalse(notificationServiceFailed);
+    }
+
+    @Test
+    public void testStartNotificationSucceedsNoKeyPasswd() throws 
ParserConfigurationException, SAXException, IOException {
+        Logger notificationServiceLogger = (Logger) 
LoggerFactory.getLogger(NotificationServiceManager.class);
+        ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
+        listAppender.start();
+        notificationServiceLogger.addAppender(listAppender);
+
+        String configFileOutput = 
CONFIGURATION_FILE_TEXT_NO_KEY_PASSWORD.replace("${test.server}", 
String.valueOf(mockWebServer.url("/")));
+        IOUtil.writeText(configFileOutput, new File(tempConfigFilePath));
+
+        NotificationServiceManager notificationServiceManager = new 
NotificationServiceManager();
+        notificationServiceManager.setMaxNotificationAttempts(1);
+        notificationServiceManager.loadNotificationServices(new 
File(tempConfigFilePath));
+
+        List<ILoggingEvent> logsList = listAppender.list;
+        boolean notificationServiceFailed = false;
+        for(ILoggingEvent logMessage : logsList) {
+            if(logMessage.getFormattedMessage().contains("is not valid for the 
following reasons")) {
+                notificationServiceFailed = true;
+            }
+        }
+
+        assertFalse(notificationServiceFailed);
+    }
+
+    @Test
+    public void 
testStartNotificationFailsBlankKeystorePasswdCorrectKeypasswd() throws 
ParserConfigurationException, SAXException, IOException {
+        Logger notificationServiceLogger = (Logger) 
LoggerFactory.getLogger(NotificationServiceManager.class);
+        ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
+        listAppender.start();
+        notificationServiceLogger.addAppender(listAppender);
+
+        String configFileOutput = 
CONFIGURATION_FILE_TEXT_BLANK_KEYSTORE_PASSWORD.replace("${test.server}", 
String.valueOf(mockWebServer.url("/")));
+        IOUtil.writeText(configFileOutput, new File(tempConfigFilePath));
+
+        NotificationServiceManager notificationServiceManager = new 
NotificationServiceManager();
+        notificationServiceManager.setMaxNotificationAttempts(1);
+        notificationServiceManager.loadNotificationServices(new 
File(tempConfigFilePath));
+
+        List<ILoggingEvent> logsList = listAppender.list;
+        boolean notificationServiceFailed = false;
+        for(ILoggingEvent logMessage : logsList) {
+            if(logMessage.getFormattedMessage().contains("'Keystore Password' 
validated against '' is invalid because Keystore Password cannot be empty")) {
+                notificationServiceFailed = true;
+            }
+        }
+
+        assertTrue(notificationServiceFailed);
+    }
+
+    @Test
+    public void 
testStartNotificationFailsCorrectKeystorePasswdBlankKeypasswd() throws 
ParserConfigurationException, SAXException, IOException {
+        Logger notificationServiceLogger = (Logger) 
LoggerFactory.getLogger(NotificationServiceManager.class);
+        ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
+        listAppender.start();
+        notificationServiceLogger.addAppender(listAppender);
+
+        String configFileOutput = 
CONFIGURATION_FILE_TEXT_BLANK_KEY_PASSWORD.replace("${test.server}", 
String.valueOf(mockWebServer.url("/")));
+        IOUtil.writeText(configFileOutput, new File(tempConfigFilePath));
+
+        NotificationServiceManager notificationServiceManager = new 
NotificationServiceManager();
+        notificationServiceManager.setMaxNotificationAttempts(1);
+        notificationServiceManager.loadNotificationServices(new 
File(tempConfigFilePath));
+
+        List<ILoggingEvent> logsList = listAppender.list;
+        boolean notificationServiceFailed = false;
+        for(ILoggingEvent logMessage : logsList) {
+            if(logMessage.getFormattedMessage().contains("'Key Password' 
validated against '' is invalid because Key Password cannot be empty")) {
+                notificationServiceFailed = true;
+            }
+        }
+
+        assertTrue(notificationServiceFailed);
+    }
 }
diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc 
b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index 5c90725..c97aa89 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -2252,8 +2252,9 @@ It has the following properties available:
 |`Truststore Type`||The Type of the Truststore. Either `JKS` or `PKCS12`
 |`Truststore Password`||The password for the Truststore
 |`Keystore Filename`||The fully-qualified filename of the Keystore
-|`Keystore Type`||The password for the Keystore
-|`Keystore Password`||The password for the key. If this is not specified, but 
the Keystore Filename, Password, and Type are specified, then the Keystore 
Password will be assumed to be the same as the Key Password.
+|`Keystore Type`||The Type of the Keystore. Either `JKS` or `PKCS12`
+|`Keystore Password`||The password for the Keystore
+|`Key Password`||The password for the key. If this is not specified, but the 
Keystore Filename, Password, and Type are specified, then the Key Password will 
be assumed to be the same as the Keystore Password.
 |`SSL Protocol`||The algorithm to use for this SSL context. This can either be 
`SSL` or `TLS`.
 |====
 
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 2352026..ff63836 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
@@ -334,11 +334,11 @@ public class OkHttpReplicationClient implements 
HttpReplicationClient {
         try {
             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,
+                    
StringUtils.isNotBlank(properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD))
 ? 
properties.getProperty(NiFiProperties.SECURITY_KEYSTORE_PASSWD).toCharArray() : 
null,
+                    
StringUtils.isNotBlank(properties.getProperty(NiFiProperties.SECURITY_KEY_PASSWD))
 ? 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,
+                    
StringUtils.isNotBlank(properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD))
 ? 
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_PASSWD).toCharArray() 
: null,
                     
properties.getProperty(NiFiProperties.SECURITY_TRUSTSTORE_TYPE),
                     WANT,
                     sslContext.getProtocol());
@@ -346,7 +346,10 @@ public class OkHttpReplicationClient implements 
HttpReplicationClient {
                     .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) {
+        } catch(UnrecoverableKeyException e) {
+            logger.error("Key password may be incorrect or not set. Check your 
keystore passwords." + e.getMessage());
+            return null;
+        } catch (CertificateException | NoSuchAlgorithmException | 
KeyStoreException | KeyManagementException | IOException e) {
             return null;
         }
     }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy
index cad27f1..712f80a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy
@@ -26,6 +26,8 @@ import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
+import sun.security.ssl.DummyX509KeyManager
+import sun.security.ssl.SunX509KeyManagerImpl
 
 @RunWith(JUnit4.class)
 class OkHttpReplicationClientTest extends GroovyTestCase {
@@ -135,4 +137,77 @@ class OkHttpReplicationClientTest extends GroovyTestCase {
             assert headers."Content-Length" == "123"
         }
     }
+
+    @Test
+    void testShouldUseKeystorePasswdIfKeypasswdIsBlank() {
+        // Arrange
+        Map flowfileEncryptionProps = [
+                (NiFiProperties.SECURITY_TRUSTSTORE): 
"./src/test/resources/conf/truststore.jks",
+                (NiFiProperties.SECURITY_TRUSTSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): 
"passwordpassword",
+                (NiFiProperties.SECURITY_KEYSTORE): 
"./src/test/resources/conf/keystore.jks",
+                (NiFiProperties.SECURITY_KEYSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_KEYSTORE_PASSWD): "passwordpassword",
+                (NiFiProperties.SECURITY_KEY_PASSWD): "",
+                (NiFiProperties.WEB_HTTPS_HOST): "localhost",
+                (NiFiProperties.WEB_HTTPS_PORT): "51552",
+        ]
+        NiFiProperties mockNiFiProperties = new StandardNiFiProperties(new 
Properties(flowfileEncryptionProps))
+
+        // Act
+        OkHttpReplicationClient client = new 
OkHttpReplicationClient(mockNiFiProperties)
+
+        // Assert
+        assertNotNull(client.okHttpClient.sslSocketFactory)
+        assertEquals(SunX509KeyManagerImpl.class, 
client.okHttpClient.sslSocketFactory.context.getX509KeyManager().getClass())
+        
assertNotNull(client.okHttpClient.sslSocketFactory.context.getX509KeyManager().credentialsMap["nifi-key"])
+    }
+
+    @Test
+    void testShouldFailIfKeyPasswdIsSetButKeystorePasswdIsBlank() {
+        // Arrange
+        Map flowfileEncryptionProps = [
+                (NiFiProperties.SECURITY_TRUSTSTORE): 
"./src/test/resources/conf/truststore.jks",
+                (NiFiProperties.SECURITY_TRUSTSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): 
"passwordpassword",
+                (NiFiProperties.SECURITY_KEYSTORE): 
"./src/test/resources/conf/keystore.jks",
+                (NiFiProperties.SECURITY_KEYSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_KEYSTORE_PASSWD): "",
+                (NiFiProperties.SECURITY_KEY_PASSWD): "passwordpassword",
+                (NiFiProperties.WEB_HTTPS_HOST): "localhost",
+                (NiFiProperties.WEB_HTTPS_PORT): "51552",
+        ]
+        NiFiProperties mockNiFiProperties = new StandardNiFiProperties(new 
Properties(flowfileEncryptionProps))
+
+        // Act
+        OkHttpReplicationClient client = new 
OkHttpReplicationClient(mockNiFiProperties)
+
+        // Assert
+        // The replication client will fail to initialize if the keystore 
password is missing, and will use
+        // a default empty DummyX509KeyManager instead. This is considered a 
failure to start the service.
+        assertSame(DummyX509KeyManager.class, 
client.okHttpClient.sslSocketFactory.context.getX509KeyManager().getClass())
+    }
+
+    @Test
+    void testShouldFailIfKeyPasswdIsBlankAndKeystorePasswd() {
+        // Arrange
+        Map flowfileEncryptionProps = [
+                (NiFiProperties.SECURITY_TRUSTSTORE): 
"./src/test/resources/conf/truststore.jks",
+                (NiFiProperties.SECURITY_TRUSTSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): 
"passwordpassword",
+                (NiFiProperties.SECURITY_KEYSTORE): 
"./src/test/resources/conf/keystore.jks",
+                (NiFiProperties.SECURITY_KEYSTORE_TYPE): "JKS",
+                (NiFiProperties.SECURITY_KEYSTORE_PASSWD): "",
+                (NiFiProperties.SECURITY_KEY_PASSWD): "",
+                (NiFiProperties.WEB_HTTPS_HOST): "localhost",
+                (NiFiProperties.WEB_HTTPS_PORT): "51552",
+        ]
+        NiFiProperties mockNiFiProperties = new StandardNiFiProperties(new 
Properties(flowfileEncryptionProps))
+
+        // Act
+        OkHttpReplicationClient client = new 
OkHttpReplicationClient(mockNiFiProperties)
+
+        // Assert
+        assertEquals(DummyX509KeyManager.class, 
client.okHttpClient.sslSocketFactory.context.getX509KeyManager().getClass())
+    }
 }
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/keystore.jks
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/keystore.jks
new file mode 100644
index 0000000..246fe88
Binary files /dev/null and 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/keystore.jks
 differ
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/truststore.jks
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/truststore.jks
new file mode 100644
index 0000000..87f4be1
Binary files /dev/null and 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/resources/conf/truststore.jks
 differ

Reply via email to