This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 24adc73862 NIFI-10012 Added XML and JSON FlowEncryptor implementations
24adc73862 is described below
commit 24adc73862466603eb08a526adcca065d0c71241
Author: Emilio Setiadarma <[email protected]>
AuthorDate: Thu May 12 17:59:44 2022 -0700
NIFI-10012 Added XML and JSON FlowEncryptor implementations
This closes #6054
Signed-off-by: David Handermann <[email protected]>
---
nifi-commons/nifi-flow-encryptor/pom.xml | 10 ++
.../nifi/flow/encryptor/AbstractFlowEncryptor.java | 35 +++++++
.../nifi/flow/encryptor/JsonFlowEncryptor.java | 102 ++++++++++++++++++
.../nifi/flow/encryptor/StandardFlowEncryptor.java | 55 +++-------
.../nifi/flow/encryptor/XmlFlowEncryptor.java | 80 +++++++++++++++
.../flow/encryptor/StandardFlowEncryptorTest.java | 114 +++++++++++++++++++--
.../properties/ConfigEncryptionToolTest.groovy | 14 +--
7 files changed, 350 insertions(+), 60 deletions(-)
diff --git a/nifi-commons/nifi-flow-encryptor/pom.xml
b/nifi-commons/nifi-flow-encryptor/pom.xml
index 527a2b570c..39ab59dfd2 100644
--- a/nifi-commons/nifi-flow-encryptor/pom.xml
+++ b/nifi-commons/nifi-flow-encryptor/pom.xml
@@ -34,5 +34,15 @@
</exclusion>
</exclusions>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-xml-processing</artifactId>
+ <version>1.17.0-SNAPSHOT</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git
a/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/AbstractFlowEncryptor.java
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/AbstractFlowEncryptor.java
new file mode 100644
index 0000000000..99e883042f
--- /dev/null
+++
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/AbstractFlowEncryptor.java
@@ -0,0 +1,35 @@
+/*
+ * 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.flow.encryptor;
+
+import org.apache.nifi.encrypt.PropertyEncryptor;
+
+import java.util.regex.Pattern;
+
+public abstract class AbstractFlowEncryptor implements FlowEncryptor {
+ protected static final Pattern ENCRYPTED_PATTERN =
Pattern.compile("^enc\\{([^}]+?)}$");
+
+ protected static final int FIRST_GROUP = 1;
+
+ protected static final String ENCRYPTED_FORMAT = "enc{%s}";
+
+ protected String getOutputEncrypted(final String inputEncrypted, final
PropertyEncryptor inputEncryptor, final PropertyEncryptor outputEncryptor) {
+ final String inputDecrypted = inputEncryptor.decrypt(inputEncrypted);
+ final String outputEncrypted = outputEncryptor.encrypt(inputDecrypted);
+ return String.format(ENCRYPTED_FORMAT, outputEncrypted);
+ }
+}
diff --git
a/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/JsonFlowEncryptor.java
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/JsonFlowEncryptor.java
new file mode 100644
index 0000000000..39062b81f4
--- /dev/null
+++
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/JsonFlowEncryptor.java
@@ -0,0 +1,102 @@
+/*
+ * 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.flow.encryptor;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.nifi.encrypt.PropertyEncryptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.util.regex.Matcher;
+
+public class JsonFlowEncryptor extends AbstractFlowEncryptor {
+ @Override
+ public void processFlow(final InputStream inputStream, final OutputStream
outputStream,
+ final PropertyEncryptor inputEncryptor, final
PropertyEncryptor outputEncryptor) {
+ final JsonFactory factory = new JsonFactory();
+ try (final JsonGenerator generator =
factory.createGenerator(outputStream)){
+ try (final JsonParser parser = factory.createParser(inputStream)) {
+ parser.setCodec(new ObjectMapper());
+ processJsonByTokens(parser, generator, inputEncryptor,
outputEncryptor);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException("Failed Processing Flow
Configuration", e);
+ }
+ }
+
+ private void processJsonByTokens(final JsonParser parser, final
JsonGenerator generator,
+ final PropertyEncryptor inputEncryptor,
final PropertyEncryptor outputEncryptor) throws IOException {
+ JsonToken token = parser.nextToken();
+ while (token != null) {
+ switch (token) {
+ case NOT_AVAILABLE:
+ break;
+ case START_OBJECT:
+ generator.writeStartObject();
+ break;
+ case END_OBJECT:
+ generator.writeEndObject();
+ break;
+ case START_ARRAY:
+ generator.writeStartArray();
+ break;
+ case END_ARRAY:
+ generator.writeEndArray();
+ break;
+ case FIELD_NAME:
+ generator.writeFieldName(parser.getValueAsString());
+ break;
+ case VALUE_EMBEDDED_OBJECT:
+ generator.writeEmbeddedObject(parser.getEmbeddedObject());
+ break;
+ case VALUE_STRING:
+ final String value = parser.getValueAsString();
+ final Matcher matcher = ENCRYPTED_PATTERN.matcher(value);
+ if (matcher.matches()) {
+
generator.writeString(getOutputEncrypted(matcher.group(FIRST_GROUP),
inputEncryptor, outputEncryptor));
+ } else {
+ generator.writeString(value);
+ }
+ break;
+ case VALUE_NUMBER_INT:
+ generator.writeNumber(parser.getIntValue());
+ break;
+ case VALUE_NUMBER_FLOAT:
+ generator.writeNumber(parser.getFloatValue());
+ break;
+ case VALUE_TRUE:
+ generator.writeBoolean(true);
+ break;
+ case VALUE_FALSE:
+ generator.writeBoolean(false);
+ break;
+ case VALUE_NULL:
+ generator.writeNull();
+ break;
+ default:
+ throw new IllegalStateException(String.format("Token
unrecognized [%s]", token));
+ }
+ token = parser.nextToken();
+ }
+ }
+}
diff --git
a/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptor.java
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptor.java
index 43e09012fb..2cbbfd2f09 100644
---
a/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptor.java
+++
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptor.java
@@ -18,26 +18,17 @@ package org.apache.nifi.flow.encryptor;
import org.apache.nifi.encrypt.PropertyEncryptor;
-import java.io.BufferedReader;
+import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
import java.io.UncheckedIOException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* Standard Flow Encryptor handles reading Input Steam and writing Output
Stream
*/
public class StandardFlowEncryptor implements FlowEncryptor {
- private static final Pattern ENCRYPTED_PATTERN =
Pattern.compile("enc\\{([^\\}]+?)\\}");
-
- private static final int FIRST_GROUP = 1;
-
- private static final String ENCRYPTED_FORMAT = "enc{%s}";
+ private static final int XML_DECLARATION = '<';
/**
* Process Flow Configuration Stream replacing existing encrypted
properties with new encrypted properties
@@ -48,39 +39,17 @@ public class StandardFlowEncryptor implements FlowEncryptor
{
* @param outputEncryptor Property Encryptor for Output Configuration
*/
@Override
- public void processFlow(final InputStream inputStream, final OutputStream
outputStream, final PropertyEncryptor inputEncryptor, final PropertyEncryptor
outputEncryptor) {
- try (final PrintWriter writer = new PrintWriter(new
OutputStreamWriter(outputStream))) {
- try (final BufferedReader reader = new BufferedReader(new
InputStreamReader(inputStream))) {
- reader.lines().forEach(line -> {
- final Matcher matcher = ENCRYPTED_PATTERN.matcher(line);
-
- final StringBuffer sb = new StringBuffer();
- boolean matched = false;
- while (matcher.find()) {
- final String outputEncrypted =
getOutputEncrypted(matcher.group(FIRST_GROUP), inputEncryptor, outputEncryptor);
- matcher.appendReplacement(sb, outputEncrypted);
- matched = true;
- }
-
- final String outputLine;
- if (matched) {
- matcher.appendTail(sb);
- outputLine = sb.toString();
- } else {
- outputLine = line;
- }
-
- writer.println(outputLine);
- });
- }
+ public void processFlow(final InputStream inputStream, final OutputStream
outputStream,
+ final PropertyEncryptor inputEncryptor, final
PropertyEncryptor outputEncryptor) {
+ final BufferedInputStream bufferedInputStream = new
BufferedInputStream(inputStream);
+ bufferedInputStream.mark(1);
+ try {
+ final int firstByte = bufferedInputStream.read();
+ bufferedInputStream.reset();
+ final FlowEncryptor flowEncryptor = (firstByte == XML_DECLARATION)
? new XmlFlowEncryptor() : new JsonFlowEncryptor();
+ flowEncryptor.processFlow(bufferedInputStream, outputStream,
inputEncryptor, outputEncryptor);
} catch (final IOException e) {
- throw new UncheckedIOException("Failed Processing Flow
Configuration", e);
+ throw new UncheckedIOException(e);
}
}
-
- private String getOutputEncrypted(final String inputEncrypted, final
PropertyEncryptor inputEncryptor, final PropertyEncryptor outputEncryptor) {
- final String inputDecrypted = inputEncryptor.decrypt(inputEncrypted);
- final String outputEncrypted = outputEncryptor.encrypt(inputDecrypted);
- return String.format(ENCRYPTED_FORMAT, outputEncrypted);
- }
}
diff --git
a/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/XmlFlowEncryptor.java
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/XmlFlowEncryptor.java
new file mode 100644
index 0000000000..db5b22bf24
--- /dev/null
+++
b/nifi-commons/nifi-flow-encryptor/src/main/java/org/apache/nifi/flow/encryptor/XmlFlowEncryptor.java
@@ -0,0 +1,80 @@
+/*
+ * 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.flow.encryptor;
+
+import org.apache.nifi.encrypt.PropertyEncryptor;
+import org.apache.nifi.xml.processing.stream.StandardXMLEventReaderProvider;
+import org.apache.nifi.xml.processing.stream.XMLEventReaderProvider;
+
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Characters;
+import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.stream.StreamSource;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+
+public class XmlFlowEncryptor extends AbstractFlowEncryptor {
+ private static final XMLEventReaderProvider eventReaderProvider = new
StandardXMLEventReaderProvider();
+
+ @Override
+ public void processFlow(final InputStream inputStream, final OutputStream
outputStream,
+ final PropertyEncryptor inputEncryptor, final
PropertyEncryptor outputEncryptor) {
+ final XMLOutputFactory xmlOutputFactory =
XMLOutputFactory.newInstance();
+ final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
+
+ try {
+ final XMLEventReader reader =
eventReaderProvider.getEventReader(new StreamSource(inputStream));
+ final XMLEventWriter writer =
xmlOutputFactory.createXMLEventWriter(outputStream,
StandardCharsets.UTF_8.name());
+ while (reader.hasNext()) {
+ final XMLEvent event = reader.nextEvent();
+ if (event.getEventType() == XMLEvent.CHARACTERS) {
+ final Characters characters = event.asCharacters();
+ final String value = characters.getData();
+ final Matcher matcher = ENCRYPTED_PATTERN.matcher(value);
+ if (matcher.matches()) {
+ final String processedValue =
getOutputEncrypted(matcher.group(FIRST_GROUP), inputEncryptor, outputEncryptor);
+
writer.add(eventFactory.createCharacters(processedValue));
+ } else {
+ writer.add(characters);
+ }
+ } else if (event.getEventType() == XMLEvent.START_DOCUMENT) {
+ writer.add(event);
+
writer.add(eventFactory.createSpace(System.lineSeparator()));
+ } else {
+ writer.add(event);
+ }
+ }
+ writer.flush();
+ writer.close();
+ reader.close();
+ outputStream.close();
+ inputStream.close();
+ } catch (final XMLStreamException e) {
+ throw new RuntimeException("Flow XML Processing Failed", e);
+ } catch (final IOException e) {
+ throw new UncheckedIOException("Failed Processing Flow
Configuration", e);
+ }
+ }
+}
diff --git
a/nifi-commons/nifi-flow-encryptor/src/test/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptorTest.java
b/nifi-commons/nifi-flow-encryptor/src/test/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptorTest.java
index 2494a953cc..45cea4ece6 100644
---
a/nifi-commons/nifi-flow-encryptor/src/test/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptorTest.java
+++
b/nifi-commons/nifi-flow-encryptor/src/test/java/org/apache/nifi/flow/encryptor/StandardFlowEncryptorTest.java
@@ -24,24 +24,27 @@ import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import java.util.Objects;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class StandardFlowEncryptorTest {
-
private static final String INPUT_KEY = UUID.randomUUID().toString();
private static final String OUTPUT_KEY = UUID.randomUUID().toString();
private static final String ENCRYPTED_FORMAT = "enc{%s}";
- private static final Pattern OUTPUT_PATTERN =
Pattern.compile("^enc\\{([^}]+?)}$");
+ private static final String PATTERN_REGEX = "enc\\{([^}]+?)}";
+
+ private static final Pattern PATTERN = Pattern.compile(PATTERN_REGEX);
private PropertyEncryptor inputEncryptor;
@@ -49,6 +52,7 @@ public class StandardFlowEncryptorTest {
private StandardFlowEncryptor flowEncryptor;
+
@BeforeEach
public void setEncryptors() {
inputEncryptor = getPropertyEncryptor(INPUT_KEY,
EncryptionMethod.MD5_256AES.getAlgorithm());
@@ -60,16 +64,17 @@ public class StandardFlowEncryptorTest {
public void testProcessEncrypted() {
final String property =
StandardFlowEncryptorTest.class.getSimpleName();
final String encryptedProperty = String.format(ENCRYPTED_FORMAT,
inputEncryptor.encrypt(property));
- final String encryptedRow = String.format("%s%n", encryptedProperty);
+ final String encryptedRow = String.format("<?xml version=\"1.0\"
encoding=\"UTF-8\" standalone=\"no\"?>%n" +
+ "<test>%s</test>", encryptedProperty);
final InputStream inputStream = new
ByteArrayInputStream(encryptedRow.getBytes(StandardCharsets.UTF_8));
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
flowEncryptor.processFlow(inputStream, outputStream, inputEncryptor,
outputEncryptor);
- final String outputEncrypted = new String(outputStream.toByteArray());
- final Matcher matcher = OUTPUT_PATTERN.matcher(outputEncrypted);
- assertTrue(String.format("Encrypted Pattern not found [%s]",
outputEncrypted), matcher.find());
+ final String outputEncrypted = outputStream.toString();
+ final Matcher matcher = PATTERN.matcher(outputEncrypted);
+ assertTrue(matcher.find(), String.format("Encrypted Pattern not found
[%s]", outputEncrypted));
final String outputEncryptedProperty = matcher.group(1);
final String outputDecrypted =
outputEncryptor.decrypt(outputEncryptedProperty);
@@ -78,18 +83,105 @@ public class StandardFlowEncryptorTest {
@Test
public void testProcessNoEncrypted() {
- final String property = String.format("%s%n",
StandardFlowEncryptorTest.class.getSimpleName());
+ final String property = String.format("<?xml version=\"1.0\"
encoding=\"UTF-8\" standalone=\"no\"?>%n" +
+ "<test>%s</test>",
StandardFlowEncryptorTest.class.getSimpleName());
final InputStream inputStream = new
ByteArrayInputStream(property.getBytes(StandardCharsets.UTF_8));
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
flowEncryptor.processFlow(inputStream, outputStream, inputEncryptor,
outputEncryptor);
- final String outputProperty = new String(outputStream.toByteArray());
- assertEquals(property, outputProperty);
+ final String outputProperty = outputStream.toString();
+ assertEquals(removeXmlDeclaration(property).trim(),
removeXmlDeclaration(outputProperty).trim());
+ }
+
+ @Test
+ public void testProcessJson() throws IOException {
+ final String password =
StandardFlowEncryptorTest.class.getSimpleName();
+ final String encryptedPassword = String.format(ENCRYPTED_FORMAT,
inputEncryptor.encrypt(password));
+
+ final String sampleFlowJson = getSampleFlowJson(encryptedPassword);
+
+ try (final InputStream inputStream = new
ByteArrayInputStream(sampleFlowJson.getBytes(StandardCharsets.UTF_8))) {
+ try (final ByteArrayOutputStream outputStream = new
ByteArrayOutputStream()) {
+ flowEncryptor.processFlow(inputStream, outputStream,
inputEncryptor, outputEncryptor);
+
+ final String outputFlowJson = outputStream.toString();
+
+ compareFlow(sampleFlowJson.trim(), outputFlowJson.trim());
+ }
+ }
+ }
+
+ @Test
+ public void testProcessXml() throws IOException {
+ final String password =
StandardFlowEncryptorTest.class.getSimpleName();
+ final String encryptedPassword = String.format(ENCRYPTED_FORMAT,
inputEncryptor.encrypt(password));
+ final String sampleFlowXml = getSampleFlowXml(encryptedPassword);
+ try (final InputStream inputStream = new
ByteArrayInputStream(sampleFlowXml.getBytes(StandardCharsets.UTF_8))) {
+ try (final ByteArrayOutputStream outputStream = new
ByteArrayOutputStream()) {
+ flowEncryptor.processFlow(inputStream, outputStream,
inputEncryptor, outputEncryptor);
+ final String outputXml = outputStream.toString();
+
+ compareFlow(removeXmlDeclaration(sampleFlowXml).trim(),
removeXmlDeclaration(outputXml).trim());
+ }
+ }
}
private PropertyEncryptor getPropertyEncryptor(final String propertiesKey,
final String propertiesAlgorithm) {
return new
PropertyEncryptorBuilder(propertiesKey).setAlgorithm(propertiesAlgorithm).build();
}
+
+ private void compareFlow(final String sampleFlow, final String outputFlow)
{
+ final Matcher inputMatcher = PATTERN.matcher(sampleFlow);
+ final Matcher outputMatcher = PATTERN.matcher(outputFlow);
+ assertTrue(inputMatcher.find() && outputMatcher.find());
+ assertEquals(inputEncryptor.decrypt(inputMatcher.group(1)),
outputEncryptor.decrypt(outputMatcher.group(1)));
+
+ assertEquals(sampleFlow.replaceAll(PATTERN_REGEX, ""),
outputFlow.replaceAll(PATTERN_REGEX, ""));
+ }
+
+ private String getSampleFlowJson(final String password) {
+ Objects.requireNonNull(password);
+ return
String.format("{\"properties\":{\"username\":\"sample_username\",\"password\":\"%s\"}}",
password);
+ }
+
+ private String getSampleFlowXml(final String password) {
+ Objects.requireNonNull(password);
+ final String flowXml = String.format("<?xml version=\"1.0\"
encoding=\"UTF-8\" standalone=\"no\"?>%n" +
+ "<processor>%n" +
+ "\t<property>%n" +
+ "\t\t<name>Username</name>%n" +
+ "\t\t<value>SAMPLE_USERNAME</value>%n" +
+ "\t</property>%n" +
+ "\t<property>%n" +
+ "\t\t<name>Password</name>%n" +
+ "\t\t<value>%s</value>%n" +
+ "\t</property>%n" +
+ "</processor>", password);
+
+ return getProcessedFlowXml(flowXml);
+ }
+
+ private String getProcessedFlowXml(final String flowXml) {
+ final PropertyEncryptor encryptor = new PropertyEncryptor() {
+ @Override
+ public String encrypt(String property) {
+ return property;
+ }
+
+ @Override
+ public String decrypt(String encryptedProperty) {
+ return encryptedProperty;
+ }
+ };
+ final InputStream inputStream = new
ByteArrayInputStream(flowXml.getBytes(StandardCharsets.UTF_8));
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ flowEncryptor.processFlow(inputStream, outputStream, encryptor,
encryptor);
+ return outputStream.toString();
+ }
+
+ private String removeXmlDeclaration(final String xmlFlow) {
+ return xmlFlow.replaceAll("<\\?xml.+\\?>", "");
+ }
}
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 987d1686e9..62c87d0a37 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
@@ -4057,8 +4057,8 @@ class ConfigEncryptionToolTest extends GroovyLogTestCase {
assert migratedCipherTexts.size() == cipherTextCount
// Ensure that everything else is identical
- assert flowXmlFile.text.replaceAll(WFXCTR, "") ==
- workingFile.text.replaceAll(WFXCTR, "")
+
assertEquals(removeXmlDeclarationAndComments(flowXmlFile.text).replaceAll(WFXCTR,
"").trim(),
+
removeXmlDeclarationAndComments(workingFile.text).replaceAll(WFXCTR, "").trim())
}
@@ -4109,8 +4109,8 @@ class ConfigEncryptionToolTest extends GroovyLogTestCase {
assert newCipherTexts.size() == ORIGINAL_CIPHER_TEXT_COUNT
// Ensure that everything else is identical
- assert new File(workingFile.path).text.replaceAll(WFXCTR, "")
==
- flowXmlFile.text.replaceAll(WFXCTR, "")
+ assertEquals(removeXmlDeclarationAndComments(new
File(workingFile.path).text).replaceAll(WFXCTR, "").trim(),
+
removeXmlDeclarationAndComments(flowXmlFile.text).replaceAll(WFXCTR, "").trim())
// Update the "source" XML content for the next iteration
currentXmlContent = tool.loadFlowXml(workingFile.path)
@@ -4234,7 +4234,7 @@ class ConfigEncryptionToolTest extends GroovyLogTestCase {
logger.info("Loaded flow.xml.gz: \n${readXmlContent}")
// Assert
- assert readXmlContent == xmlContent
+ assert readXmlContent.trim() == xmlContent.trim()
}
@Test
@@ -4700,5 +4700,7 @@ class ConfigEncryptionToolTest extends GroovyLogTestCase {
fieldsFound
}
-// TODO: Test with 128/256-bit available
+ private String removeXmlDeclarationAndComments(final String xmlFlow) {
+ return xmlFlow.replaceAll("<\\?xml.+\\?>",
"").replaceAll("(?s)<!--.*?-->", "")
+ }
}