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,

Reply via email to