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 2016/11/18 09:10:47 UTC

nifi git commit: NIFI-3051 Fixed issue serializing commented or empty login-identity-providers.xml.

Repository: nifi
Updated Branches:
  refs/heads/master 7206318ec -> 8568d40cd


NIFI-3051 Fixed issue serializing commented or empty login-identity-providers.xml.

Cleaned up commented pom.xml contents. (+4 squashed commits)
Squashed commits:
[725860b] NIFI-3051 Switched CET test logging dependency from logback to log4j as Zookeeper migration has an explicit dependency on log4j as the logging provider and the two libraries were causing classpath collisions. Now the tests run in both Maven and Intellij, the tools all build successfully, and the tools all run (TLS Toolkit, CET, and ZK) without logging provider warnings and print the expected output to the console.
[0e604c7] NIFI-3051 Changed provider element selection in serialize method to be by class (org.apache.nifi.ldap.LdapProvider) rather than identifier in case it has been modified.
Added unit tests.
[300a23d] NIFI-3051 Changed provider element selection to be by class (org.apache.nifi.ldap.LdapProvider) rather than identifier in case it has been modified.
Added unit tests.
[a0cdd40] NIFI-3051 Fixed issue serializing commented or empty login-identity-providers.xml.
Updated and added unit tests. (+1 squashed commit)
Squashed commits:
[b187202] NIFI-3051 - checked in test demonstrating failure to serialize commented ldap-provider section.

This closes #1238.

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/8568d40c
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/8568d40c
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/8568d40c

Branch: refs/heads/master
Commit: 8568d40cd80ad12a258fbee498b733b78428a608
Parents: 7206318
Author: Andy LoPresto <al...@apache.org>
Authored: Wed Nov 16 22:38:59 2016 -0500
Committer: Andy LoPresto <al...@apache.org>
Committed: Fri Nov 18 01:12:00 2016 -0800

----------------------------------------------------------------------
 .../nifi-toolkit-encrypt-config/pom.xml         |  36 ---
 .../nifi/properties/ConfigEncryptionTool.groovy |  39 ++--
 .../src/main/resources/logback.xml              |  34 ---
 .../properties/ConfigEncryptionToolTest.groovy  | 230 +++++++++++++++----
 .../src/test/resources/log4j.properties         |   8 +-
 .../src/test/resources/logback-test.xml         |  34 ---
 ...gin-identity-providers-populated-renamed.xml | 105 +++++++++
 7 files changed, 325 insertions(+), 161 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/pom.xml b/nifi-toolkit/nifi-toolkit-encrypt-config/pom.xml
index 3b094c7..f2ef7e9 100644
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/pom.xml
+++ b/nifi-toolkit/nifi-toolkit-encrypt-config/pom.xml
@@ -52,16 +52,6 @@
             <groupId>commons-cli</groupId>
             <artifactId>commons-cli</artifactId>
         </dependency>
-        <!--<dependency>-->
-            <!--<groupId>org.codehaus.groovy</groupId>-->
-            <!--<artifactId>groovy-all</artifactId>-->
-            <!--<scope>compile</scope>-->
-        <!--</dependency>-->
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>com.github.stefanbirkner</groupId>
             <artifactId>system-rules</artifactId>
@@ -103,32 +93,6 @@
                     </dependency>
                 </dependencies>
             </plugin>
-            <!--<plugin>-->
-            <!--<groupId>org.codehaus.groovy</groupId>-->
-            <!--<artifactId>groovy-eclipse-compiler</artifactId>-->
-            <!--<version>2.9.2-01</version>-->
-            <!--<extensions>true</extensions>-->
-            <!--</plugin>-->
-            <!--<plugin>-->
-            <!--<groupId>org.apache.maven.plugins</groupId>-->
-            <!--<artifactId>maven-shade-plugin</artifactId>-->
-            <!--<version>2.1</version>-->
-            <!--<executions>-->
-            <!--<execution>-->
-            <!--<phase>package</phase>-->
-            <!--<goals>-->
-            <!--<goal>shade</goal>-->
-            <!--</goals>-->
-            <!--</execution>-->
-            <!--</executions>-->
-            <!--<configuration>-->
-            <!--<transformers>-->
-            <!--<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">-->
-            <!--<mainClass>ConfigEncryptionTool</mainClass>-->
-            <!--</transformer>-->
-            <!--</transformers>-->
-            <!--</configuration>-->
-            <!--</plugin>-->
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/groovy/org/apache/nifi/properties/ConfigEncryptionTool.groovy
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/groovy/org/apache/nifi/properties/ConfigEncryptionTool.groovy b/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/groovy/org/apache/nifi/properties/ConfigEncryptionTool.groovy
index dc11df4..0f69d1b 100644
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/groovy/org/apache/nifi/properties/ConfigEncryptionTool.groovy
+++ b/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/groovy/org/apache/nifi/properties/ConfigEncryptionTool.groovy
@@ -34,6 +34,7 @@ import org.bouncycastle.crypto.generators.SCrypt
 import org.bouncycastle.jce.provider.BouncyCastleProvider
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
+import org.xml.sax.SAXException
 
 import javax.crypto.Cipher
 import java.nio.charset.StandardCharsets
@@ -96,7 +97,8 @@ class ConfigEncryptionTool {
 
     private static
     final String DEFAULT_DESCRIPTION = "This tool reads from a nifi.properties and/or login-identity-providers.xml file with plain sensitive configuration values, prompts the user for a master key, and encrypts each value. It will replace the plain value with the protected value in the same file (or write to a new file if specified)."
-    static private final String LDAP_PROVIDER_REGEX = /<provider>\s*<identifier>\s*ldap-provider[\s\S]*?<\/provider>/
+    private static final String LDAP_PROVIDER_CLASS = "org.apache.nifi.ldap.LdapProvider"
+    static private final String LDAP_PROVIDER_REGEX = /<provider>[\s\S]*?<class>\s*org\.apache\.nifi\.ldap\.LdapProvider[\s\S]*?<\/provider>/
     static private final String XML_DECLARATION_REGEX = /<\?xml version="1.0" encoding="UTF-8"\?>/
 
     private static String buildHeader(String description = DEFAULT_DESCRIPTION) {
@@ -373,7 +375,6 @@ class ConfigEncryptionTool {
                 List<String> lines = loginIdentityProvidersFile.readLines()
                 logger.info("Loaded LoginIdentityProviders content (${lines.size()} lines)")
                 String decryptedXmlContent = decryptLoginIdentityProviders(xmlContent, existingKeyHex)
-//                String decryptedXmlContent = ConfigEncryptionUtility.decryptLoginIdentityProviders(xmlContent)
                 return decryptedXmlContent
             } catch (RuntimeException e) {
                 if (isVerbose) {
@@ -391,7 +392,8 @@ class ConfigEncryptionTool {
 
         try {
             def doc = new XmlSlurper().parseText(encryptedXml)
-            def passwords = doc.provider.find { it.identifier == 'ldap-provider' }.property.findAll {
+            // Find the provider element by class even if it has been renamed
+            def passwords = doc.provider.find { it.'class' as String == LDAP_PROVIDER_CLASS }.property.findAll {
                 it.@name =~ "Password" && it.@encryption =~ "aes/gcm/\\d{3}"
             }
 
@@ -427,9 +429,10 @@ class ConfigEncryptionTool {
         // TODO: Switch to XmlParser & XmlNodePrinter to maintain "empty" element structure
         try {
             def doc = new XmlSlurper().parseText(plainXml)
-            // Only operate on un-encrypted passwords
-            def passwords = doc.provider.find { it.identifier == 'ldap-provider' }
+            // Find the provider element by class even if it has been renamed
+            def passwords = doc.provider.find { it.'class' as String == LDAP_PROVIDER_CLASS }
                     .property.findAll {
+                // Only operate on un-encrypted passwords
                 it.@name =~ "Password" && (it.@encryption == "none" || it.@encryption == "") && it.text()
             }
 
@@ -687,19 +690,25 @@ class ConfigEncryptionTool {
         out.toString().split("\n")
     }
 
-
-    private
     static List<String> serializeLoginIdentityProvidersAndPreserveFormat(String xmlContent, File originalLoginIdentityProvidersFile) {
-       def parsedXml = new XmlSlurper().parseText(xmlContent)
-        def provider = parsedXml.provider.find { it.identifier == "ldap-provider" }
-        def serializedProvider = new XmlUtil().serialize(provider)
-        // Remove XML declaration from top
-        serializedProvider = serializedProvider.replaceFirst(XML_DECLARATION_REGEX, "")
-
         // Find the provider element of the new XML in the file contents
         String fileContents = originalLoginIdentityProvidersFile.text
-        fileContents = fileContents.replaceFirst(LDAP_PROVIDER_REGEX, serializedProvider)
-        fileContents.split("\n")
+        try {
+            def parsedXml = new XmlSlurper().parseText(xmlContent)
+            def provider = parsedXml.provider.find { it.'class' as String == LDAP_PROVIDER_CLASS }
+            if (provider) {
+                def serializedProvider = new XmlUtil().serialize(provider)
+                // Remove XML declaration from top
+                serializedProvider = serializedProvider.replaceFirst(XML_DECLARATION_REGEX, "")
+                fileContents = fileContents.replaceFirst(LDAP_PROVIDER_REGEX, serializedProvider)
+                return fileContents.split("\n")
+            } else {
+                throw new SAXException("No ldap-provider element found")
+            }
+        } catch (SAXException e) {
+            logger.error("No provider element with class org.apache.nifi.ldap.LdapProvider found in XML content; the file could be empty or the element may be missing or commented out")
+            return fileContents.split("\n")
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/resources/logback.xml
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/resources/logback.xml b/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/resources/logback.xml
deleted file mode 100644
index fb7e961..0000000
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/src/main/resources/logback.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-
-<configuration scan="true" scanPeriod="30 seconds">
-    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <pattern>%date %level [%thread] %logger{40} %msg%n</pattern>
-        </encoder>
-    </appender>
-
-    <!-- valid logging levels: TRACE, DEBUG, INFO, WARN, ERROR -->
-
-    <logger name="org.apache.nifi.util.config" level="INFO">
-        <appender-ref ref="CONSOLE"/>
-    </logger>
-
-    <root level="INFO">
-        <appender-ref ref="CONSOLE"/>
-    </root>
-
-</configuration>

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/groovy/org/apache/nifi/properties/ConfigEncryptionToolTest.groovy
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/groovy/org/apache/nifi/properties/ConfigEncryptionToolTest.groovy b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/groovy/org/apache/nifi/properties/ConfigEncryptionToolTest.groovy
index 1784748..32a1975 100644
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/groovy/org/apache/nifi/properties/ConfigEncryptionToolTest.groovy
+++ b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/groovy/org/apache/nifi/properties/ConfigEncryptionToolTest.groovy
@@ -16,9 +16,9 @@
  */
 package org.apache.nifi.properties
 
-import ch.qos.logback.classic.spi.LoggingEvent
-import ch.qos.logback.core.AppenderBase
 import org.apache.commons.lang3.SystemUtils
+import org.apache.log4j.AppenderSkeleton
+import org.apache.log4j.spi.LoggingEvent
 import org.apache.nifi.toolkit.tls.commandLine.CommandLineParseException
 import org.apache.nifi.util.NiFiProperties
 import org.apache.nifi.util.console.TextDevice
@@ -2050,7 +2050,7 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
         // Assert
         def passwordLines = encryptedLines.findAll { it =~ PASSWORD_PROP_REGEX }
         assert passwordLines.size() == LIP_PASSWORD_LINE_COUNT
-        def populatedPasswordLines = passwordLines.findAll { it.contains(">.*<") }
+        def populatedPasswordLines = passwordLines.findAll { it =~ />.+</ }
         assert populatedPasswordLines.every { !it.contains(">thisIsABadPassword<") }
         assert populatedPasswordLines.every { it.contains(encryptionScheme) }
         populatedPasswordLines.each {
@@ -2137,6 +2137,46 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
     }
 
     @Test
+    void testShouldEncryptLoginIdentityProvidersWithRenamedProvider() {
+        // Arrange
+        String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-populated-renamed.xml"
+        File loginIdentityProvidersFile = new File(loginIdentityProvidersPath)
+
+        File tmpDir = setupTmpDir()
+
+        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
+        workingFile.delete()
+        Files.copy(loginIdentityProvidersFile.toPath(), workingFile.toPath())
+        ConfigEncryptionTool tool = new ConfigEncryptionTool()
+        tool.isVerbose = true
+
+        tool.keyHex = KEY_HEX
+        String encryptionScheme = "encryption=\"aes/gcm/${getKeyLength(KEY_HEX)}\""
+
+        def lines = workingFile.readLines()
+        logger.info("Read lines: \n${lines.join("\n")}")
+        assert lines.findAll { it =~ "ldap-provider" }.empty
+
+        AESSensitivePropertyProvider spp = new AESSensitivePropertyProvider(KEY_HEX)
+
+        // Act
+        def encryptedLines = tool.encryptLoginIdentityProviders(lines.join("\n")).split("\n")
+        logger.info("Encrypted lines: \n${encryptedLines.join("\n")}")
+
+        // Assert
+        def passwordLines = encryptedLines.findAll { it =~ PASSWORD_PROP_REGEX }
+        assert passwordLines.size() == LIP_PASSWORD_LINE_COUNT
+        def populatedPasswordLines = passwordLines.findAll { it =~ />.+</ }
+        assert populatedPasswordLines.every { !it.contains(">thisIsABadPassword<") }
+        assert populatedPasswordLines.every { it.contains(encryptionScheme) }
+        populatedPasswordLines.each {
+            String ct = (it =~ ">(.*)</property>")[0][1]
+            logger.info("Cipher text: ${ct}")
+            assert spp.unprotect(ct) == PASSWORD
+        }
+    }
+
+    @Test
     void testEncryptLoginIdentityProvidersShouldHandleCommentedElements() {
         // Arrange
         String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-commented.xml"
@@ -2166,6 +2206,141 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
     }
 
     @Test
+    void testSerializeLoginIdentityProvidersAndPreserveFormatShouldRespectComments() {
+        // Arrange
+        String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-populated.xml"
+        File loginIdentityProvidersFile = new File(loginIdentityProvidersPath)
+
+        File tmpDir = setupTmpDir()
+
+        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
+        workingFile.delete()
+        Files.copy(loginIdentityProvidersFile.toPath(), workingFile.toPath())
+        ConfigEncryptionTool tool = new ConfigEncryptionTool()
+        tool.isVerbose = true
+
+        def lines = workingFile.readLines()
+        logger.info("Read lines: \n${lines.join("\n")}")
+
+        String plainXml = workingFile.text
+        String encryptedXml = tool.encryptLoginIdentityProviders(plainXml, KEY_HEX)
+        logger.info("Encrypted XML: \n${encryptedXml}")
+
+        // Act
+        def serializedLines = tool.serializeLoginIdentityProvidersAndPreserveFormat(encryptedXml, workingFile)
+        logger.info("Serialized lines: \n${serializedLines.join("\n")}")
+
+        // Assert
+
+        // Some empty lines will be removed
+        def trimmedLines = lines.collect { it.trim() }.findAll { it }
+        def trimmedSerializedLines = serializedLines.collect { it.trim() }.findAll { it }
+        assert trimmedLines.size() == trimmedSerializedLines.size()
+
+        // Ensure the replacement actually occurred
+        assert trimmedSerializedLines.findAll { it =~ "encryption=" }.size() == LIP_PASSWORD_LINE_COUNT
+    }
+
+    @Test
+    void testSerializeLoginIdentityProvidersAndPreserveFormatShouldHandleRenamedProvider() {
+        // Arrange
+        String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-populated-renamed.xml"
+        File loginIdentityProvidersFile = new File(loginIdentityProvidersPath)
+
+        File tmpDir = setupTmpDir()
+
+        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
+        workingFile.delete()
+        Files.copy(loginIdentityProvidersFile.toPath(), workingFile.toPath())
+        ConfigEncryptionTool tool = new ConfigEncryptionTool()
+        tool.isVerbose = true
+
+        def lines = workingFile.readLines()
+        logger.info("Read lines: \n${lines.join("\n")}")
+        assert lines.findAll { it =~ "ldap-provider" }.empty
+
+        String plainXml = workingFile.text
+        String encryptedXml = tool.encryptLoginIdentityProviders(plainXml, KEY_HEX)
+        logger.info("Encrypted XML: \n${encryptedXml}")
+
+        // Act
+        def serializedLines = tool.serializeLoginIdentityProvidersAndPreserveFormat(encryptedXml, workingFile)
+        logger.info("Serialized lines: \n${serializedLines.join("\n")}")
+
+        // Assert
+
+        // Some empty lines will be removed
+        def trimmedLines = lines.collect { it.trim() }.findAll { it }
+        def trimmedSerializedLines = serializedLines.collect { it.trim() }.findAll { it }
+        assert trimmedLines.size() == trimmedSerializedLines.size()
+
+        // Ensure the replacement actually occurred
+        assert trimmedSerializedLines.findAll { it =~ "encryption=" }.size() == LIP_PASSWORD_LINE_COUNT
+    }
+
+    @Test
+    void testSerializeLoginIdentityProvidersAndPreserveFormatShouldHandleCommentedFile() {
+        // Arrange
+        String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-commented.xml"
+        File loginIdentityProvidersFile = new File(loginIdentityProvidersPath)
+
+        File tmpDir = setupTmpDir()
+
+        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
+        workingFile.delete()
+        Files.copy(loginIdentityProvidersFile.toPath(), workingFile.toPath())
+        ConfigEncryptionTool tool = new ConfigEncryptionTool()
+        tool.isVerbose = true
+
+        tool.keyHex = KEY_HEX_128
+
+        def lines = workingFile.readLines()
+        logger.info("Read lines: \n${lines.join("\n")}")
+
+        // If no sensitive properties are found, the original input text is just returned (comments and formatting in tact)
+        def encryptedLines = tool.encryptLoginIdentityProviders(lines.join("\n")).split("\n")
+        logger.info("Encrypted lines: \n${encryptedLines.join("\n")}")
+        assert encryptedLines == lines
+
+        // Act
+        def serializedLines = ConfigEncryptionTool.serializeLoginIdentityProvidersAndPreserveFormat(encryptedLines.join("\n"), workingFile)
+        logger.info("Serialized lines: \n${serializedLines.join("\n")}")
+
+        // Assert
+        assert serializedLines == encryptedLines
+        assert TestAppender.events.any { it.renderedMessage =~ "No provider element with class org.apache.nifi.ldap.LdapProvider found in XML content; the file could be empty or the element may be missing or commented out" }
+    }
+
+    @Test
+    void testSerializeLoginIdentityProvidersAndPreserveFormatShouldHandleEmptyFile() {
+        // Arrange
+        File tmpDir = setupTmpDir()
+
+        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
+        workingFile.delete()
+        workingFile.createNewFile()
+        ConfigEncryptionTool tool = new ConfigEncryptionTool()
+        tool.isVerbose = true
+
+        tool.keyHex = KEY_HEX_128
+
+        def lines = workingFile.readLines()
+        logger.info("Read lines: \n${lines.join("\n")}")
+
+        // If no sensitive properties are found, the original input text is just returned (comments and formatting in tact)
+        def encryptedLines = lines
+        logger.info("Encrypted lines: \n${encryptedLines.join("\n")}")
+
+        // Act
+        def serializedLines = ConfigEncryptionTool.serializeLoginIdentityProvidersAndPreserveFormat(encryptedLines.join("\n"), workingFile)
+        logger.info("Serialized lines: \n${serializedLines.join("\n")}")
+
+        // Assert
+        assert serializedLines.findAll { it }.isEmpty()
+        assert TestAppender.events.any { it.renderedMessage =~ "No provider element with class org.apache.nifi.ldap.LdapProvider found in XML content; the file could be empty or the element may be missing or commented out" }
+    }
+
+    @Test
     void testShouldPerformFullOperationForLoginIdentityProviders() {
         // Arrange
         exit.expectSystemExitWithStatus(0)
@@ -2328,40 +2503,6 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
     }
 
     @Test
-    void testSerializeLoginIdentityProvidersAndPreserveFormatShouldRespectComments() {
-        // Arrange
-        String loginIdentityProvidersPath = "src/test/resources/login-identity-providers-populated.xml"
-        File loginIdentityProvidersFile = new File(loginIdentityProvidersPath)
-
-        File tmpDir = setupTmpDir()
-
-        File workingFile = new File("target/tmp/tmp-login-identity-providers.xml")
-        workingFile.delete()
-        Files.copy(loginIdentityProvidersFile.toPath(), workingFile.toPath())
-        ConfigEncryptionTool tool = new ConfigEncryptionTool()
-        tool.isVerbose = true
-
-        // Just need to read the lines from the original file, parse them to XML, serialize back, and compare output, as no transformation operation will occur
-        def lines = workingFile.readLines()
-        logger.info("Read lines: \n${lines.join("\n")}")
-
-        String plainXml = workingFile.text
-        String encryptedXml = tool.encryptLoginIdentityProviders(plainXml, KEY_HEX)
-        logger.info("Encrypted XML: \n${encryptedXml}")
-
-        // Act
-        def serializedLines = tool.serializeLoginIdentityProvidersAndPreserveFormat(encryptedXml, workingFile)
-        logger.info("Serialized lines: \n${serializedLines.join("\n")}")
-
-        // Assert
-
-        // Some empty lines will be removed
-        def trimmedLines = lines.collect {it.trim() }.findAll { it }
-        def trimmedSerializedLines = serializedLines.collect { it.trim() }.findAll { it }
-        assert trimmedLines.size() == trimmedSerializedLines.size()
-    }
-
-    @Test
     void testShouldPerformFullOperationForNiFiPropertiesAndLoginIdentityProviders() {
         // Arrange
         exit.expectSystemExitWithStatus(0)
@@ -2445,7 +2586,7 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
                 }
 
                 // Check that the comments are still there
-                def trimmedLines = inputLIPFile.readLines().collect {it.trim() }.findAll { it }
+                def trimmedLines = inputLIPFile.readLines().collect { it.trim() }.findAll { it }
                 def trimmedSerializedLines = updatedXmlContent.split("\n").collect { it.trim() }.findAll { it }
                 assert trimmedLines.size() == trimmedSerializedLines.size()
 
@@ -2477,8 +2618,8 @@ class ConfigEncryptionToolTest extends GroovyTestCase {
     }
 }
 
-public class TestAppender extends AppenderBase<LoggingEvent> {
-    static List<LoggingEvent> events = new ArrayList<>();
+public class TestAppender extends AppenderSkeleton {
+    static final List<LoggingEvent> events = new ArrayList<>();
 
     @Override
     protected void append(LoggingEvent e) {
@@ -2492,4 +2633,13 @@ public class TestAppender extends AppenderBase<LoggingEvent> {
             events.clear();
         }
     }
+
+    @Override
+    void close() {
+    }
+
+    @Override
+    boolean requiresLayout() {
+        return false
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/log4j.properties b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/log4j.properties
index 05cd375..aa42a32 100644
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/log4j.properties
+++ b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/log4j.properties
@@ -15,8 +15,12 @@
 # limitations under the License.
 #
 
-log4j.rootLogger=DEBUG,console
+log4j.rootLogger=DEBUG,console,test
 
 log4j.appender.console=org.apache.log4j.ConsoleAppender
 log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
\ No newline at end of file
+log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
+
+log4j.appender.test=org.apache.nifi.properties.TestAppender
+log4j.appender.test.layout=org.apache.log4j.PatternLayout
+log4j.appender.test.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/logback-test.xml b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/logback-test.xml
deleted file mode 100644
index af8074b..0000000
--- a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  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.
--->
-
-<configuration>
-    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
-        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <pattern>%-4r [%t] %-5p %c - %m%n</pattern>
-        </encoder>
-    </appender>
-    <appender name="TEST" class="org.apache.nifi.properties.TestAppender">
-        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
-            <pattern>%-4r [%t] %-5p %c - %m%n</pattern>
-        </encoder>
-    </appender>
-
-    <logger name="org.apache.nifi.properties" level="DEBUG"/>
-    <root level="DEBUG">
-        <appender-ref ref="CONSOLE"/>
-        <appender-ref ref="TEST"/>
-    </root>
-</configuration>

http://git-wip-us.apache.org/repos/asf/nifi/blob/8568d40c/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/login-identity-providers-populated-renamed.xml
----------------------------------------------------------------------
diff --git a/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/login-identity-providers-populated-renamed.xml b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/login-identity-providers-populated-renamed.xml
new file mode 100644
index 0000000..69290cb
--- /dev/null
+++ b/nifi-toolkit/nifi-toolkit-encrypt-config/src/test/resources/login-identity-providers-populated-renamed.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  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.
+-->
+<!--
+    This file lists the login identity providers to use when running securely. In order
+    to use a specific provider it must be configured here and it's identifier
+    must be specified in the nifi.properties file.
+-->
+<loginIdentityProviders>
+    <!--
+        Identity Provider for users logging in with username/password against an LDAP server.
+        
+        'Authentication Strategy' - How the connection to the LDAP server is authenticated. Possible
+            values are ANONYMOUS, SIMPLE, or START_TLS.
+        
+        'Manager DN' - The DN of the manager that is used to bind to the LDAP server to search for users.
+        'Manager Password' - The password of the manager that is used to bind to the LDAP server to
+            search for users.
+            
+        'TLS - Keystore' - Path to the Keystore that is used when connecting to LDAP using START_TLS.
+        'TLS - Keystore Password' - Password for the Keystore that is used when connecting to LDAP
+            using START_TLS.
+        'TLS - Keystore Type' - Type of the Keystore that is used when connecting to LDAP using
+            START_TLS (i.e. JKS or PKCS12).
+        'TLS - Truststore' - Path to the Truststore that is used when connecting to LDAP using START_TLS.
+        'TLS - Truststore Password' - Password for the Truststore that is used when connecting to
+            LDAP using START_TLS.
+        'TLS - Truststore Type' - Type of the Truststore that is used when connecting to LDAP using
+            START_TLS (i.e. JKS or PKCS12).
+        'TLS - Client Auth' - Client authentication policy when connecting to LDAP using START_TLS.
+            Possible values are REQUIRED, WANT, NONE.
+        'TLS - Protocol' - Protocol to use when connecting to LDAP using START_TLS. (i.e. TLS,
+            TLSv1.1, TLSv1.2, etc).
+        'TLS - Shutdown Gracefully' - Specifies whether the TLS should be shut down gracefully 
+            before the target context is closed. Defaults to false.
+            
+        'Referral Strategy' - Strategy for handling referrals. Possible values are FOLLOW, IGNORE, THROW.
+        'Connect Timeout' - Duration of connect timeout. (i.e. 10 secs).
+        'Read Timeout' - Duration of read timeout. (i.e. 10 secs).
+       
+        'Url' - Url of the LDAP servier (i.e. ldap://<hostname>:<port>).
+        'User Search Base' - Base DN for searching for users (i.e. CN=Users,DC=example,DC=com).
+        'User Search Filter' - Filter for searching for users against the 'User Search Base'.
+            (i.e. sAMAccountName={0}). The user specified name is inserted into '{0}'.
+            
+        'Authentication Expiration' - The duration of how long the user authentication is valid
+            for. If the user never logs out, they will be required to log back in following
+            this duration.
+    -->
+    <provider>
+        <identifier>definitely-not-dap-lay-provider</identifier>
+        <class>org.apache.nifi.ldap.LdapProvider</class>
+        <property name="Authentication Strategy">START_TLS</property>
+
+        <property name="Manager DN">someuser</property>
+        <property name="Manager Password">thisIsABadPassword</property>
+
+        <property name="TLS - Keystore"></property>
+        <property name="TLS - Keystore Password">thisIsABadPassword</property>
+        <property name="TLS - Keystore Type"></property>
+        <property name="TLS - Truststore"></property>
+        <property name="TLS - Truststore Password">thisIsABadPassword</property>
+        <property name="TLS - Truststore Type"></property>
+        <property name="TLS - Client Auth"></property>
+        <property name="TLS - Protocol"></property>
+        <property name="TLS - Shutdown Gracefully"></property>
+        
+        <property name="Referral Strategy">FOLLOW</property>
+        <property name="Connect Timeout">10 secs</property>
+        <property name="Read Timeout">10 secs</property>
+
+        <property name="Url"></property>
+        <property name="User Search Base"></property>
+        <property name="User Search Filter"></property>
+
+        <property name="Authentication Expiration">12 hours</property>
+    </provider>
+
+    <!--
+        Identity Provider for users logging in with username/password against a Kerberos KDC server.
+
+        'Default Realm' - Default realm to provide when user enters incomplete user principal (i.e. NIFI.APACHE.ORG).
+        'Authentication Expiration' - The duration of how long the user authentication is valid for. If the user never logs out, they will be required to log back in following this duration.
+    -->
+    <!-- To enable the kerberos-provider remove 2 lines. This is 1 of 2.
+    <provider>
+        <identifier>kerberos-provider</identifier>
+        <class>org.apache.nifi.kerberos.KerberosProvider</class>
+        <property name="Default Realm">NIFI.APACHE.ORG</property>
+        <property name="Authentication Expiration">12 hours</property>
+    </provider>
+    To enable the kerberos-provider remove 2 lines. This is 2 of 2. -->
+</loginIdentityProviders>
\ No newline at end of file