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

markap14 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 ed8197eacb NIFI-10567 Corrected Sensitive Dynamic Property handling 
for flow.xml (#6524)
ed8197eacb is described below

commit ed8197eacb6b569568df711829fdf01b2f3b8729
Author: exceptionfactory <[email protected]>
AuthorDate: Thu Oct 13 18:38:17 2022 -0500

    NIFI-10567 Corrected Sensitive Dynamic Property handling for flow.xml 
(#6524)
    
    - Updated XmlFlowSynchronizer to filter parsed Sensitive Dynamic Property 
Names using dynamic status of component Property Descriptor
    - Lack of access to the Component Property Descriptor when parsing DOM 
elements required subsequent dynamic status filtering
---
 .../nifi/controller/XmlFlowSynchronizer.java       | 30 +++++----
 .../service/ControllerServiceLoader.java           | 73 ++++------------------
 2 files changed, 31 insertions(+), 72 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
index 8cd0b17b65..d331f9aaff 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/XmlFlowSynchronizer.java
@@ -33,7 +33,6 @@ import org.apache.nifi.connectable.Port;
 import org.apache.nifi.connectable.Position;
 import org.apache.nifi.connectable.Size;
 import org.apache.nifi.controller.flow.FlowManager;
-import 
org.apache.nifi.controller.flowrepository.FlowRepositoryClientInstantiationException;
 import org.apache.nifi.controller.inheritance.AuthorizerCheck;
 import org.apache.nifi.controller.inheritance.BundleCompatibilityCheck;
 import org.apache.nifi.controller.inheritance.ConnectionMissingCheck;
@@ -42,7 +41,6 @@ import 
org.apache.nifi.controller.inheritance.FlowInheritability;
 import org.apache.nifi.controller.inheritance.FlowInheritabilityCheck;
 import org.apache.nifi.controller.inheritance.MissingComponentsCheck;
 import org.apache.nifi.controller.label.Label;
-import 
org.apache.nifi.controller.parameter.ParameterProviderInstantiationException;
 import org.apache.nifi.controller.queue.LoadBalanceCompression;
 import org.apache.nifi.controller.queue.LoadBalanceStrategy;
 import 
org.apache.nifi.controller.reporting.ReportingTaskInstantiationException;
@@ -146,6 +144,7 @@ import java.util.stream.Collectors;
 import java.util.zip.GZIPInputStream;
 
 /**
+ * XML implementation of Flow Synchronizer for reading configuration using XML 
Document Object Model
  */
 public class XmlFlowSynchronizer implements FlowSynchronizer {
 
@@ -383,7 +382,7 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
     }
 
     private void updateFlow(final FlowController controller, final Document 
configuration, final DataFlow existingFlow, final boolean existingFlowEmpty)
-            throws ReportingTaskInstantiationException, 
ParameterProviderInstantiationException, 
FlowRepositoryClientInstantiationException {
+            throws ReportingTaskInstantiationException {
         final boolean flowAlreadySynchronized = 
controller.isFlowSynchronized();
         final FlowManager flowManager = controller.getFlowManager();
 
@@ -769,8 +768,7 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
     }
 
     private ParameterProviderNode getOrCreateParameterProvider(final 
FlowController controller, final ParameterProviderDTO dto,
-                                                               final boolean 
controllerInitialized, final boolean existingFlowEmpty)
-            throws ParameterProviderInstantiationException {
+                                                               final boolean 
controllerInitialized, final boolean existingFlowEmpty) {
         // create a new parameter provider node when the controller is not 
initialized or the flow is empty
         if (!controllerInitialized || existingFlowEmpty) {
             BundleCoordinate coordinate;
@@ -818,8 +816,8 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
             registryClient.setName(dto.getName());
             registryClient.setDescription(dto.getDescription());
             registryClient.setAnnotationData(dto.getAnnotationData());
-            final Set<String> sensitiveDynamicPropertyNames = 
dto.getSensitiveDynamicPropertyNames();
-            registryClient.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames == null ? Collections.emptySet() : 
sensitiveDynamicPropertyNames);
+            final Set<String> sensitiveDynamicPropertyNames = 
getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), 
registryClient);
+            registryClient.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames);
             return registryClient;
         } else {
             // otherwise return the existing flow registry client node
@@ -850,8 +848,8 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
             
reportingTask.setSchedulingStrategy(SchedulingStrategy.valueOf(dto.getSchedulingStrategy()));
 
             reportingTask.setAnnotationData(dto.getAnnotationData());
-            final Set<String> sensitiveDynamicPropertyNames = 
dto.getSensitiveDynamicPropertyNames();
-            reportingTask.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames == null ? Collections.emptySet() : 
sensitiveDynamicPropertyNames);
+            final Set<String> sensitiveDynamicPropertyNames = 
getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), 
reportingTask);
+            reportingTask.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames);
             return reportingTask;
         } else {
             // otherwise return the existing reporting task node
@@ -1396,8 +1394,8 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
                 procNode.setAutoTerminatedRelationships(relationships);
             }
 
-            final Set<String> sensitiveDynamicPropertyNames = 
config.getSensitiveDynamicPropertyNames();
-            procNode.setProperties(config.getProperties(), false, 
sensitiveDynamicPropertyNames == null ? Collections.emptySet() : 
sensitiveDynamicPropertyNames);
+            final Set<String> sensitiveDynamicPropertyNames = 
getSensitiveDynamicPropertyNames(config.getSensitiveDynamicPropertyNames(), 
procNode);
+            procNode.setProperties(config.getProperties(), false, 
sensitiveDynamicPropertyNames);
 
             final ScheduledState scheduledState = 
ScheduledState.valueOf(processorDTO.getState());
             if (ScheduledState.RUNNING.equals(scheduledState)) {
@@ -1413,6 +1411,16 @@ public class XmlFlowSynchronizer implements 
FlowSynchronizer {
         }
     }
 
+    private Set<String> getSensitiveDynamicPropertyNames(final Set<String> 
parsedSensitivePropertyNames, final ComponentNode componentNode) {
+        final Set<String> sensitivePropertyNames = 
parsedSensitivePropertyNames == null ? Collections.emptySet() : 
parsedSensitivePropertyNames;
+        return sensitivePropertyNames.stream().filter(
+                propertyName -> {
+                    final PropertyDescriptor propertyDescriptor = 
componentNode.getPropertyDescriptor(propertyName);
+                    return propertyDescriptor.isDynamic();
+                }
+        ).collect(Collectors.toSet());
+    }
+
     private void updateNonFingerprintedProcessorSettings(final ProcessorNode 
procNode, final ProcessorDTO processorDTO) {
         procNode.setName(processorDTO.getName());
         procNode.setPosition(toPosition(processorDTO.getPosition()));
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
index 295d825cc3..e330f0fc6e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/service/ControllerServiceLoader.java
@@ -24,25 +24,14 @@ import 
org.apache.nifi.controller.serialization.FlowFromDOMFactory;
 import org.apache.nifi.encrypt.PropertyEncryptor;
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.logging.LogLevel;
-import org.apache.nifi.reporting.BulletinRepository;
 import org.apache.nifi.util.BundleUtils;
-import org.apache.nifi.util.DomUtils;
 import org.apache.nifi.web.api.dto.BundleDTO;
 import org.apache.nifi.web.api.dto.ControllerServiceDTO;
-import org.apache.nifi.xml.processing.ProcessingException;
-import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
 import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -51,59 +40,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 public class ControllerServiceLoader {
 
     private static final Logger logger = 
LoggerFactory.getLogger(ControllerServiceLoader.class);
 
-    public static List<ControllerServiceNode> loadControllerServices(final 
FlowController controller, final InputStream serializedStream, final 
ProcessGroup parentGroup,
-        final PropertyEncryptor encryptor, final BulletinRepository 
bulletinRepo, final boolean autoResumeState, final FlowEncodingVersion 
encodingVersion) throws IOException {
-
-        try (final InputStream in = new BufferedInputStream(serializedStream)) 
{
-            final StandardDocumentProvider documentProvider = new 
StandardDocumentProvider();
-
-            documentProvider.setErrorHandler(new org.xml.sax.ErrorHandler() {
-
-                @Override
-                public void fatalError(final SAXParseException err) throws 
SAXException {
-                    logger.error("Config file line " + err.getLineNumber() + 
", col " + err.getColumnNumber() + ", uri " + err.getSystemId() + " :message: " 
+ err.getMessage());
-                    if (logger.isDebugEnabled()) {
-                        logger.error("Error Stack Dump", err);
-                    }
-                    throw err;
-                }
-
-                @Override
-                public void error(final SAXParseException err) throws 
SAXParseException {
-                    logger.error("Config file line " + err.getLineNumber() + 
", col " + err.getColumnNumber() + ", uri " + err.getSystemId() + " :message: " 
+ err.getMessage());
-                    if (logger.isDebugEnabled()) {
-                        logger.error("Error Stack Dump", err);
-                    }
-                    throw err;
-                }
-
-                @Override
-                public void warning(final SAXParseException err) throws 
SAXParseException {
-                    logger.warn(" Config file line " + err.getLineNumber() + 
", uri " + err.getSystemId() + " : message : " + err.getMessage());
-                    if (logger.isDebugEnabled()) {
-                        logger.warn("Warning stack dump", err);
-                    }
-                    throw err;
-                }
-            });
-
-            final Document document = documentProvider.parse(in);
-            final Element controllerServices = document.getDocumentElement();
-            final List<Element> serviceElements = 
DomUtils.getChildElementsByTagName(controllerServices, "controllerService");
-
-            final Map<ControllerServiceNode, Element> controllerServiceMap = 
ControllerServiceLoader.loadControllerServices(serviceElements, controller, 
parentGroup, encryptor, encodingVersion);
-            enableControllerServices(controllerServiceMap, controller, 
encryptor, autoResumeState, encodingVersion);
-            return new ArrayList<>(controllerServiceMap.keySet());
-        } catch (final ProcessingException e) {
-            throw new IOException("Parsing Controller Services failed", e);
-        }
-    }
-
     public static Map<ControllerServiceNode, Element> 
loadControllerServices(final List<Element> serviceElements, final 
FlowController controller,
                                                                              
final ProcessGroup parentGroup, final PropertyEncryptor encryptor, final 
FlowEncodingVersion encodingVersion) {
 
@@ -227,11 +169,20 @@ public class ControllerServiceLoader {
         node.pauseValidationTrigger();
         try {
             node.setAnnotationData(dto.getAnnotationData());
-            final Set<String> sensitiveDynamicPropertyNames = 
dto.getSensitiveDynamicPropertyNames();
-            node.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames == null ? Collections.emptySet() : 
sensitiveDynamicPropertyNames);
+            final Set<String> sensitiveDynamicPropertyNames = 
getSensitiveDynamicPropertyNames(dto.getSensitiveDynamicPropertyNames(), node);
+            node.setProperties(dto.getProperties(), false, 
sensitiveDynamicPropertyNames);
         } finally {
             node.resumeValidationTrigger();
         }
     }
 
+    private static Set<String> getSensitiveDynamicPropertyNames(final 
Set<String> parsedSensitivePropertyNames, final ControllerServiceNode 
controllerServiceNode) {
+        final Set<String> sensitivePropertyNames = 
parsedSensitivePropertyNames == null ? Collections.emptySet() : 
parsedSensitivePropertyNames;
+        return sensitivePropertyNames.stream().filter(
+                propertyName -> {
+                    final PropertyDescriptor propertyDescriptor = 
controllerServiceNode.getPropertyDescriptor(propertyName);
+                    return propertyDescriptor.isDynamic();
+                }
+        ).collect(Collectors.toSet());
+    }
 }

Reply via email to