This is an automated email from the ASF dual-hosted git repository.
pvillard31 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 d3781c09346 NIFI-16354 Switched MiNiFi C2 to Property Encryption
Provider (#11689)
d3781c09346 is described below
commit d3781c0934603c6648f2fb765293af31497db830
Author: David Handermann <[email protected]>
AuthorDate: Thu Sep 17 08:32:07 2026 -0500
NIFI-16354 Switched MiNiFi C2 to Property Encryption Provider (#11689)
---
.../minifi-commons-framework/pom.xml | 10 ++---
.../service/StandardFlowPropertyEncryptor.java | 48 +++++++++++++---------
.../service/StandardFlowPropertyEncryptorTest.java | 28 +++++++++----
.../minifi-framework/minifi-framework-core/pom.xml | 5 ---
.../apache/nifi/minifi/c2/C2NifiClientService.java | 6 +--
5 files changed, 55 insertions(+), 42 deletions(-)
diff --git a/minifi/minifi-commons/minifi-commons-framework/pom.xml
b/minifi/minifi-commons/minifi-commons-framework/pom.xml
index b2fe4437108..376f76b7a6c 100644
--- a/minifi/minifi-commons/minifi-commons-framework/pom.xml
+++ b/minifi/minifi-commons/minifi-commons-framework/pom.xml
@@ -40,6 +40,11 @@ limitations under the License.
<artifactId>nifi-property-utils</artifactId>
<version>2.13.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-framework-api</artifactId>
+ <version>2.13.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-framework-core-api</artifactId>
@@ -74,11 +79,6 @@ limitations under the License.
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
- <dependency>
- <groupId>org.apache.nifi</groupId>
- <artifactId>nifi-property-encryptor</artifactId>
- <version>2.13.0-SNAPSHOT</version>
- </dependency>
</dependencies>
<build>
<plugins>
diff --git
a/minifi/minifi-commons/minifi-commons-framework/src/main/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptor.java
b/minifi/minifi-commons/minifi-commons-framework/src/main/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptor.java
index a058f442d96..1c6a8c524d4 100644
---
a/minifi/minifi-commons/minifi-commons-framework/src/main/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptor.java
+++
b/minifi/minifi-commons/minifi-commons-framework/src/main/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptor.java
@@ -21,16 +21,20 @@ import
org.apache.nifi.c2.protocol.component.api.DefinedType;
import org.apache.nifi.c2.protocol.component.api.PropertyDescriptor;
import org.apache.nifi.c2.protocol.component.api.RuntimeManifest;
import org.apache.nifi.controller.flow.VersionedDataflow;
-import org.apache.nifi.encrypt.PropertyEncryptor;
import org.apache.nifi.flow.VersionedConfigurableExtension;
import org.apache.nifi.flow.VersionedParameter;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedPropertyDescriptor;
import org.apache.nifi.security.encryption.PropertyEncryptionEncoder;
+import org.apache.nifi.security.encryption.PropertyEncryptionProvider;
+import org.apache.nifi.security.encryption.SensitivePropertyCodec;
+import org.apache.nifi.security.encryption.SensitivePropertyContext;
+import org.apache.nifi.security.encryption.SensitivePropertyContextFactory;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
@@ -44,36 +48,39 @@ import static java.util.stream.Stream.concat;
public class StandardFlowPropertyEncryptor implements FlowPropertyEncryptor {
- private final PropertyEncryptor propertyEncryptor;
+ private final PropertyEncryptionProvider propertyEncryptionProvider;
private final RuntimeManifest runTimeManifest;
- public StandardFlowPropertyEncryptor(PropertyEncryptor propertyEncryptor,
RuntimeManifest runTimeManifest) {
- this.propertyEncryptor = propertyEncryptor;
+ public StandardFlowPropertyEncryptor(final PropertyEncryptionProvider
propertyEncryptionProvider, final RuntimeManifest runTimeManifest) {
+ this.propertyEncryptionProvider =
Objects.requireNonNull(propertyEncryptionProvider, "Property Encryption
Provider required");
this.runTimeManifest = runTimeManifest;
}
@Override
- public void encryptSensitiveProperties(VersionedDataflow flow) {
+ public void encryptSensitiveProperties(final VersionedDataflow flow) {
encryptParameterContextsProperties(flow);
- Map<String, Set<String>> sensitivePropertiesByComponentType =
Optional.of(flowProvidedSensitiveProperties(flow))
+ final Map<String, Set<String>> sensitivePropertiesByComponentType =
Optional.of(flowProvidedSensitiveProperties(flow))
.filter(not(Map::isEmpty))
.orElseGet(this::runtimeManifestSensitiveProperties);
encryptFlowComponentsProperties(flow,
sensitivePropertiesByComponentType);
}
- private void encryptParameterContextsProperties(VersionedDataflow flow) {
+ private void encryptParameterContextsProperties(final VersionedDataflow
flow) {
ofNullable(flow.getParameterContexts())
.orElse(List.of())
.forEach(parameterContext ->
ofNullable(parameterContext.getParameters()).orElse(Set.of())
.stream()
.filter(VersionedParameter::isSensitive)
.filter(not(parameter ->
PropertyEncryptionEncoder.isEncrypted(parameter.getValue())))
- .forEach(parameter ->
parameter.setValue(encrypt(parameter.getValue()))));
+ .forEach(parameter -> {
+ final SensitivePropertyContext context =
SensitivePropertyContextFactory.forParameter(parameterContext.getName(),
parameter.getName());
+ parameter.setValue(encrypt(parameter.getValue(), context));
+ }));
}
- private Map<String, Set<String>>
flowProvidedSensitiveProperties(VersionedDataflow flow) {
+ private Map<String, Set<String>> flowProvidedSensitiveProperties(final
VersionedDataflow flow) {
return fetchFlowComponents(flow)
.map(extension -> Map.entry(
extension.getType(),
@@ -110,26 +117,26 @@ public class StandardFlowPropertyEncryptor implements
FlowPropertyEncryptor {
));
}
- private void encryptFlowComponentsProperties(VersionedDataflow flow,
Map<String, Set<String>> sensitivePropertiesByComponentType) {
+ private void encryptFlowComponentsProperties(final VersionedDataflow flow,
final Map<String, Set<String>> sensitivePropertiesByComponentType) {
fetchFlowComponents(flow)
.forEach(extension -> {
- Set<String> sensitivePropertyNames =
sensitivePropertiesByComponentType.getOrDefault(extension.getType(), Set.of());
- Map<String, String> encryptedProperties =
ofNullable(extension.getProperties()).orElse(Map.of())
+ final Set<String> sensitivePropertyNames =
sensitivePropertiesByComponentType.getOrDefault(extension.getType(), Set.of());
+ final Map<String, String> encryptedProperties =
ofNullable(extension.getProperties()).orElse(Map.of())
.entrySet()
.stream()
- .collect(toMap(Entry::getKey,
encryptPropertyIfNeeded(sensitivePropertyNames)));
+ .collect(toMap(Entry::getKey,
encryptPropertyIfNeeded(extension, sensitivePropertyNames)));
extension.setProperties(encryptedProperties);
});
}
- private Stream<? extends VersionedConfigurableExtension>
fetchFlowComponents(VersionedDataflow flow) {
+ private Stream<? extends VersionedConfigurableExtension>
fetchFlowComponents(final VersionedDataflow flow) {
return concat(
ofNullable(flow.getControllerServices()).orElse(List.of()).stream(),
fetchComponentsRecursively(flow.getRootGroup())
);
}
- private Stream<? extends VersionedConfigurableExtension>
fetchComponentsRecursively(VersionedProcessGroup processGroup) {
+ private Stream<? extends VersionedConfigurableExtension>
fetchComponentsRecursively(final VersionedProcessGroup processGroup) {
return concat(
Stream.of(
ofNullable(processGroup.getProcessors()).orElse(Set.of()),
@@ -140,20 +147,21 @@ public class StandardFlowPropertyEncryptor implements
FlowPropertyEncryptor {
);
}
- private Set<String> mergeSets(Set<String> first, Set<String> second) {
+ private Set<String> mergeSets(final Set<String> first, final Set<String>
second) {
first.addAll(second);
return first;
}
- private Function<Entry<String, String>, String>
encryptPropertyIfNeeded(Set<String> sensitivePropertyNames) {
+ private Function<Entry<String, String>, String>
encryptPropertyIfNeeded(final VersionedConfigurableExtension extension, final
Set<String> sensitivePropertyNames) {
return entry ->
sensitivePropertyNames.contains(entry.getKey()) &&
!PropertyEncryptionEncoder.isEncrypted(entry.getValue())
- ? encrypt(entry.getValue())
+ ? encrypt(entry.getValue(),
SensitivePropertyContextFactory.forComponent(extension.getInstanceIdentifier(),
extension.getType(), entry.getKey()))
: entry.getValue();
}
- private String encrypt(String parameter) {
- return
PropertyEncryptionEncoder.getEncoded(propertyEncryptor.encrypt(parameter));
+ private String encrypt(final String value, final SensitivePropertyContext
context) {
+ final String encrypted =
SensitivePropertyCodec.encrypt(propertyEncryptionProvider, value, context);
+ return PropertyEncryptionEncoder.getEncoded(encrypted);
}
}
diff --git
a/minifi/minifi-commons/minifi-commons-framework/src/test/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptorTest.java
b/minifi/minifi-commons/minifi-commons-framework/src/test/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptorTest.java
index 326f6782214..6b907f64a89 100644
---
a/minifi/minifi-commons/minifi-commons-framework/src/test/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptorTest.java
+++
b/minifi/minifi-commons/minifi-commons-framework/src/test/java/org/apache/nifi/minifi/commons/service/StandardFlowPropertyEncryptorTest.java
@@ -17,7 +17,6 @@
package org.apache.nifi.minifi.commons.service;
-import org.apache.commons.lang3.RandomStringUtils;
import org.apache.nifi.c2.protocol.component.api.Bundle;
import org.apache.nifi.c2.protocol.component.api.ComponentManifest;
import org.apache.nifi.c2.protocol.component.api.ControllerServiceDefinition;
@@ -25,7 +24,6 @@ import
org.apache.nifi.c2.protocol.component.api.ProcessorDefinition;
import org.apache.nifi.c2.protocol.component.api.PropertyDescriptor;
import org.apache.nifi.c2.protocol.component.api.RuntimeManifest;
import org.apache.nifi.controller.flow.VersionedDataflow;
-import org.apache.nifi.encrypt.PropertyEncryptor;
import org.apache.nifi.flow.VersionedConfigurableExtension;
import org.apache.nifi.flow.VersionedControllerService;
import org.apache.nifi.flow.VersionedParameter;
@@ -33,6 +31,7 @@ import org.apache.nifi.flow.VersionedParameterContext;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedProcessor;
import org.apache.nifi.flow.VersionedPropertyDescriptor;
+import
org.apache.nifi.security.encryption.InternalPassThroughPropertyEncryptionProvider;
import org.apache.nifi.security.encryption.PropertyEncryptionEncoder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -40,6 +39,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -50,9 +50,9 @@ import java.util.stream.Stream;
import static java.util.Map.entry;
import static java.util.UUID.randomUUID;
import static java.util.stream.Collectors.toMap;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -96,8 +96,6 @@ public class StandardFlowPropertyEncryptorTest {
SENSITIVE_3, versionedPropertyDescriptor(SENSITIVE_3, true)
);
- @Mock
- private PropertyEncryptor mockPropertyEncryptor;
@Mock
private RuntimeManifest mockRunTimeManifest;
@@ -112,8 +110,7 @@ public class StandardFlowPropertyEncryptorTest {
@BeforeEach
public void setup() {
-
when(mockPropertyEncryptor.encrypt(anyString())).thenReturn(RandomStringUtils.secure().nextAlphabetic(5));
- testEncryptor = new
StandardFlowPropertyEncryptor(mockPropertyEncryptor, mockRunTimeManifest);
+ testEncryptor = new StandardFlowPropertyEncryptor(new
InternalPassThroughPropertyEncryptionProvider(), mockRunTimeManifest);
}
@Test
@@ -143,6 +140,23 @@ public class StandardFlowPropertyEncryptorTest {
assertSensitiveFlowComponentPropertiesAreEncoded(testFlow);
}
+ @Test
+ public void shouldRetainAlreadyEncodedSensitiveProperties() {
+ final VersionedDataflow testFlow = flowWithPropertyDescriptors();
+ final VersionedProcessor processor =
testFlow.getRootGroup().getProcessors().stream()
+ .filter(candidate -> PROCESSOR_TYPE_1.equals(candidate.getType()))
+ .findFirst()
+ .orElseThrow();
+ final String alreadyEncrypted =
PropertyEncryptionEncoder.getEncoded("already-encrypted");
+ final Map<String, String> properties = new
HashMap<>(processor.getProperties());
+ properties.put(SENSITIVE_1, alreadyEncrypted);
+ processor.setProperties(properties);
+
+ testEncryptor.encryptSensitiveProperties(testFlow);
+
+ assertEquals(alreadyEncrypted,
processor.getProperties().get(SENSITIVE_1));
+ }
+
@Test
public void shouldEncryptPropertiesUsingDescriptorsFromRuntimeManifest() {
VersionedDataflow testFlow = flowWithoutPropertyDescriptors();
diff --git
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/pom.xml
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/pom.xml
index 3d1cd5d6ea3..49f71adbec3 100644
---
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/pom.xml
+++
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/pom.xml
@@ -53,11 +53,6 @@ limitations under the License.
<artifactId>c2-client-http</artifactId>
<version>2.13.0-SNAPSHOT</version>
</dependency>
- <dependency>
- <groupId>org.apache.nifi</groupId>
- <artifactId>nifi-property-encryptor</artifactId>
- <version>2.13.0-SNAPSHOT</version>
- </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>c2-protocol-api</artifactId>
diff --git
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/C2NifiClientService.java
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/C2NifiClientService.java
index 56cf077d403..3c51b3997c7 100644
---
a/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/C2NifiClientService.java
+++
b/minifi/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-framework-core/src/main/java/org/apache/nifi/minifi/c2/C2NifiClientService.java
@@ -57,7 +57,6 @@ import org.apache.nifi.c2.serializer.C2Serializer;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.Triggerable;
import org.apache.nifi.diagnostics.SystemDiagnostics;
-import org.apache.nifi.encrypt.PropertyEncryptorBuilder;
import
org.apache.nifi.extension.manifest.parser.jaxb.JAXBExtensionManifestParser;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.RemoteProcessGroup;
@@ -141,8 +140,6 @@ import static
org.apache.nifi.minifi.commons.api.MiNiFiProperties.C2_SECURITY_TR
import static
org.apache.nifi.minifi.commons.api.MiNiFiProperties.C2_SECURITY_TRUSTSTORE_TYPE;
import static org.apache.nifi.util.FormatUtils.getPreciseTimeDuration;
import static org.apache.nifi.util.NiFiProperties.FLOW_CONFIGURATION_FILE;
-import static org.apache.nifi.util.NiFiProperties.SENSITIVE_PROPS_ALGORITHM;
-import static org.apache.nifi.util.NiFiProperties.SENSITIVE_PROPS_KEY;
public class C2NifiClientService {
@@ -259,8 +256,7 @@ public class C2NifiClientService {
FlowPropertyAssetReferenceResolver flowPropertyAssetReferenceResolver
= new
StandardFlowPropertyAssetReferenceResolverService(resourceRepository::getAbsolutePath);
FlowPropertyEncryptor flowPropertyEncryptor = new
StandardFlowPropertyEncryptor(
- new
PropertyEncryptorBuilder(niFiProperties.getProperty(SENSITIVE_PROPS_KEY))
-
.setAlgorithm(niFiProperties.getProperty(SENSITIVE_PROPS_ALGORITHM)).build(),
+ flowController.getPropertyEncryptionProvider(),
runtimeManifestService.getManifest());
UpdateConfigurationStrategy updateConfigurationStrategy = new
DefaultUpdateConfigurationStrategy(
flowController,