[nifi] branch main updated: NIFI-9538: Add C2 heartbeat capability to minifi-c2-service

2022-06-02 Thread kdoran
This is an automated email from the ASF dual-hosted git repository.

kdoran 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 b5e61109f6 NIFI-9538: Add C2 heartbeat capability to minifi-c2-service
b5e61109f6 is described below

commit b5e61109f6d5d7331d7cd0c7027ad9250c347852
Author: Matthew Burgess 
AuthorDate: Wed Feb 9 13:49:23 2022 -0500

NIFI-9538: Add C2 heartbeat capability to minifi-c2-service

- Added content hash code to avoid repeatedly updating with the same flow
- Gracefully handle agent classes and provide update URL to /config
- Fixed JDK 8 build issue with ConfigService

This closes #5755.

Signed-off-by: Kevin Doran 
---
 .../apache/nifi/minifi/c2/api/Configuration.java   |   8 +
 minifi/minifi-c2/minifi-c2-assembly/pom.xml|   2 +-
 .../src/main/resources/conf/authorizations.yaml|  28 
 .../FileSystemWritableConfiguration.java   |  11 ++
 .../c2/cache/s3/S3WritableConfiguration.java   |   8 +-
 .../minifi-c2-provider-nifi-rest/pom.xml   |   7 +-
 minifi/minifi-c2/minifi-c2-service/pom.xml |  22 ++-
 .../minifi/c2/configuration/C2ResourceConfig.java  |   3 +
 .../C2JsonProvider.java}   |  32 ++--
 .../C2JsonProviderFeature.java}|  23 ++-
 .../nifi/minifi/c2/service/C2ProtocolContext.java  |  96 +++
 .../C2ProtocolService.java}|  21 +--
 .../nifi/minifi/c2/service/ConfigService.java  | 182 +++--
 .../minifi/c2/service/SimpleC2ProtocolService.java | 127 ++
 minifi/pom.xml |   2 +-
 15 files changed, 513 insertions(+), 59 deletions(-)

diff --git 
a/minifi/minifi-c2/minifi-c2-api/src/main/java/org/apache/nifi/minifi/c2/api/Configuration.java
 
b/minifi/minifi-c2/minifi-c2-api/src/main/java/org/apache/nifi/minifi/c2/api/Configuration.java
index 90fbdba346..3f78b52269 100644
--- 
a/minifi/minifi-c2/minifi-c2-api/src/main/java/org/apache/nifi/minifi/c2/api/Configuration.java
+++ 
b/minifi/minifi-c2/minifi-c2-api/src/main/java/org/apache/nifi/minifi/c2/api/Configuration.java
@@ -18,6 +18,7 @@
 package org.apache.nifi.minifi.c2.api;
 
 import java.io.InputStream;
+import java.net.URL;
 
 /**
  * Represents a MiNiFi configuration of a given version, format matches the 
format of the ConfigurationProvider
@@ -44,4 +45,11 @@ public interface Configuration {
  * @return an input stream to read the configuration with
  */
 InputStream getInputStream() throws ConfigurationProviderException;
+
+/**
+ * Gets the URL of the resource
+ *
+ * @return the URL of the resource
+ */
+URL getURL() throws ConfigurationProviderException;
 }
diff --git a/minifi/minifi-c2/minifi-c2-assembly/pom.xml 
b/minifi/minifi-c2/minifi-c2-assembly/pom.xml
index ba2553e395..148a6efe7b 100644
--- a/minifi/minifi-c2/minifi-c2-assembly/pom.xml
+++ b/minifi/minifi-c2/minifi-c2-assembly/pom.xml
@@ -26,7 +26,7 @@ limitations under the License.
 pom
 This is the assembly of Apache MiNiFi's - Command And Control 
Server
 
-10080
+10090
 
 false
 
./conf/keystore.jks
diff --git 
a/minifi/minifi-c2/minifi-c2-assembly/src/main/resources/conf/authorizations.yaml
 
b/minifi/minifi-c2/minifi-c2-assembly/src/main/resources/conf/authorizations.yaml
index 5669451940..14386e5c17 100644
--- 
a/minifi/minifi-c2/minifi-c2-assembly/src/main/resources/conf/authorizations.yaml
+++ 
b/minifi/minifi-c2/minifi-c2-assembly/src/main/resources/conf/authorizations.yaml
@@ -37,3 +37,31 @@ Paths:
 # Default authorization lets anonymous pull any config.  Remove below to 
change that.
 - Authorization: ROLE_ANONYMOUS
   Action: allow
+
+  /c2/config/heartbeat:
+Default Action: deny
+Actions:
+  - Authorization: CLASS_RASPI_3
+Query Parameters:
+  class: raspi3
+Action: allow
+  - Authorization: ROLE_SUPERUSER
+Action: allow
+
+  # Default authorization lets anonymous pull any config.  Remove below to 
change that.
+  - Authorization: ROLE_ANONYMOUS
+Action: allow
+
+  /c2/config/acknowledge:
+Default Action: deny
+Actions:
+  - Authorization: CLASS_RASPI_3
+Query Parameters:
+  class: raspi3
+Action: allow
+  - Authorization: ROLE_SUPERUSER
+Action: allow
+
+  # Default authorization lets anonymous pull any config.  Remove below to 
change that.
+  - Authorization: ROLE_ANONYMOUS
+Action: allow
diff --git 
a/minifi/minifi-c2/minifi-c2-cache/minifi-c2-cache-filesystem/src/main/java/org/apache/nifi/minifi/c2/cache/filesystem/FileSystemWritableConfiguration.java
 

[nifi] branch main updated: NIFI-9960 Add documentation for Sensitive Dynamic Properties (#6089)

2022-06-02 Thread andrewmlim
This is an automated email from the ASF dual-hosted git repository.

andrewmlim 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 5a2992c243 NIFI-9960 Add documentation for Sensitive Dynamic 
Properties (#6089)
5a2992c243 is described below

commit 5a2992c243e81724ce13033a9818df28d4c3af95
Author: exceptionfactory 
AuthorDate: Thu Jun 2 07:12:22 2022 -0500

NIFI-9960 Add documentation for Sensitive Dynamic Properties (#6089)

* NIFI-9960 Added documentation for Sensitive Dynamic Properties

- Updated User Guide with Add Property details
- Updated Developer Guide with annotation configuration details
- Updated Document Writer to indicate Supports Sensitive Dynamic Properties 
status

* NIFI-9960 Adjusted User Guide wording based on feedback
---
 nifi-docs/src/main/asciidoc/developer-guide.adoc   |  34 ++---
 .../images/add-property-sensitive-value-dialog.png | Bin 0 -> 15549 bytes
 nifi-docs/src/main/asciidoc/user-guide.adoc|  15 +++--
 .../html/HtmlDocumentationWriter.java  |  16 ++
 .../html/ProcessorDocumentationWriterTest.java |   2 ++
 5 files changed, 61 insertions(+), 6 deletions(-)

diff --git a/nifi-docs/src/main/asciidoc/developer-guide.adoc 
b/nifi-docs/src/main/asciidoc/developer-guide.adoc
index a136e149a5..d654a7a77a 100644
--- a/nifi-docs/src/main/asciidoc/developer-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/developer-guide.adoc
@@ -326,21 +326,47 @@ instance of the `PropertyDescriptor.Builder` object,
 calling the appropriate methods on the builder, and finally calling
 the `build` method.
 
-While this method covers most of the use cases, it is sometimes
+= Dynamic Processor Properties
+
+In addition to standard properties, it is sometimes
 desirable to allow users to configure
-additional properties whose name are not known. This can be achieved
-by overriding the
+additional properties whose names are not predefined.
+This can be achieved by overriding the
 `getSupportedDynamicPropertyDescriptor` method. This method takes a
 `String` as its only argument, which
 indicates the name of the property. The method returns a
 `PropertyDescriptor` object that can be used to validate
 both the name of the property, as well as the value. Any
 PropertyDescriptor that is returned from this method
-should be built setting the value of `isDynamic` to true in the
+should be built setting the value of `isDynamic` to `true` in the
 `PropertyDescriptor.Builder` class. The default
 behavior of AbstractProcessor is to not allow any dynamically created
 properties.
 
+= Sensitive Dynamic Properties
+
+The default implementation for dynamic properties does not treat the
+property values as sensitive. This approach is sufficient when configuring
+features such as FlowFile attributes or custom expressions, but it does
+not provide protection for values such as passwords or keys.
+
+NiFi 1.17.0 introduced framework support for sensitive dynamic properties
+through a new behavior annotation named `SupportsSensitiveDynamicProperties`.
+The annotation can be applied to a Processor, Controller Service, or
+Reporting Task that supports dynamic properties through the
+`getSupportedDynamicPropertyDescriptor` method. The annotation indicates
+that the component allows individual dynamic properties to be marked as
+sensitive for the purpose of persistence and framework processing.
+
+The `getSupportedDynamicPropertyDescriptor` must return a `PropertyDescriptor`
+with the `sensitive` field set to `false` to allow customization of sensitive
+status. Setting the `sensitive` field to `true` in this method forces all
+dynamic properties to be handled as sensitive. This approach allows sensitive
+status to be upgraded in supported components, but not downgraded.
+
+Secure handling of sensitive property values is the responsibility of the
+annotated class. Components that support sensitive dynamic properties must
+not log property values or provide property values as FlowFile attributes.
 
  Validating Processor Properties
 
diff --git 
a/nifi-docs/src/main/asciidoc/images/add-property-sensitive-value-dialog.png 
b/nifi-docs/src/main/asciidoc/images/add-property-sensitive-value-dialog.png
new file mode 100644
index 00..6bdf906064
Binary files /dev/null and 
b/nifi-docs/src/main/asciidoc/images/add-property-sensitive-value-dialog.png 
differ
diff --git a/nifi-docs/src/main/asciidoc/user-guide.adoc 
b/nifi-docs/src/main/asciidoc/user-guide.adoc
index 9b6286b40f..2dbc063db6 100644
--- a/nifi-docs/src/main/asciidoc/user-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/user-guide.adoc
@@ -690,8 +690,19 @@ image::edit-property-dropdown.png["Edit Property with 
Dropdown"]
 
 In the top-right corner of the tab is a button for adding a New Property. 
Clicking this button will provide the DFM with a dialog to
 enter 

[nifi] branch main updated: NIFI-10054: Improve SendTrapSNMP error handling

2022-06-02 Thread pvillard
This is an automated email from the ASF dual-hosted git repository.

pvillard 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 04aa32cd57 NIFI-10054: Improve SendTrapSNMP error handling
04aa32cd57 is described below

commit 04aa32cd576ef47a7ec1b7a2df4f5f60b8b9a6bd
Author: Lehel 
AuthorDate: Thu May 26 18:35:14 2022 +0200

NIFI-10054: Improve SendTrapSNMP error handling

Signed-off-by: Pierre Villard 

This closes #6081.
---
 .../nifi/snmp/operations/SendTrapSNMPHandler.java  | 10 +-
 .../snmp/operations/SendTrapSNMPHandlerTest.java   | 41 +-
 2 files changed, 49 insertions(+), 2 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java
 
b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java
index f9f608d670..6b2a3bfc2a 100644
--- 
a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java
+++ 
b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/main/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandler.java
@@ -25,6 +25,8 @@ import org.apache.nifi.snmp.utils.SNMPUtils;
 import org.snmp4j.PDU;
 import org.snmp4j.Snmp;
 import org.snmp4j.Target;
+import org.snmp4j.event.ResponseEvent;
+import org.snmp4j.smi.TransportIpAddress;
 
 import java.io.IOException;
 import java.time.Instant;
@@ -62,7 +64,13 @@ public class SendTrapSNMPHandler {
 logger.debug("No optional SNMP specific variables found in 
flowfile.");
 }
 
-snmpManager.send(pdu, target);
+final ResponseEvent response = snmpManager.send(pdu, target);
+if (response == null) {
+final int port = ((TransportIpAddress) 
target.getAddress()).getPort();
+throw new IOException(String.format("The sent PDU has not been 
confirmed, the target port [%d] may be unavailable.", port));
+} else if (response.getError() != null) {
+throw new IOException("An error occurred while sending trap.", 
response.getError());
+}
 }
 
 V1TrapPDUFactory createV1TrapPduFactory(final Instant startTime) {
diff --git 
a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java
 
b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java
index 6a202055f4..b7bed1d682 100644
--- 
a/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java
+++ 
b/nifi-nar-bundles/nifi-snmp-bundle/nifi-snmp-processors/src/test/java/org/apache/nifi/snmp/operations/SendTrapSNMPHandlerTest.java
@@ -18,6 +18,7 @@ package org.apache.nifi.snmp.operations;
 
 import org.apache.nifi.snmp.configuration.V1TrapConfiguration;
 import org.apache.nifi.snmp.configuration.V2TrapConfiguration;
+import org.apache.nifi.snmp.exception.SNMPException;
 import org.apache.nifi.snmp.factory.trap.V1TrapPDUFactory;
 import org.apache.nifi.snmp.factory.trap.V2TrapPDUFactory;
 import org.apache.nifi.util.MockComponentLog;
@@ -27,12 +28,16 @@ import org.junit.Test;
 import org.snmp4j.PDU;
 import org.snmp4j.Snmp;
 import org.snmp4j.Target;
+import org.snmp4j.event.ResponseEvent;
+import org.snmp4j.smi.TransportIpAddress;
 
 import java.io.IOException;
 import java.time.Instant;
 import java.util.Collections;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -42,6 +47,7 @@ public class SendTrapSNMPHandlerTest {
 private Target mockTarget;
 private Snmp mockSnmpManager;
 private PDU mockPdu;
+private ResponseEvent mockResponseEvent;
 private MockComponentLog mockComponentLog;
 private V1TrapConfiguration mockV1TrapConfiguration;
 private V2TrapConfiguration mockV2TrapConfiguration;
@@ -49,10 +55,11 @@ public class SendTrapSNMPHandlerTest {
 private SendTrapSNMPHandler sendTrapSNMPHandler;
 
 @Before
-public void init() {
+public void init() throws IOException {
 mockTarget = mock(Target.class);
 mockSnmpManager = mock(Snmp.class);
 mockPdu = mock(PDU.class);
+mockResponseEvent = mock(ResponseEvent.class);
 mockComponentLog = new MockComponentLog("id", new Object());
 mockV1TrapConfiguration = mock(V1TrapConfiguration.class);
 mockV2TrapConfiguration = mock(V2TrapConfiguration.class);
@@ -61,6 +68,8 @@ public class SendTrapSNMPHandlerTest {
 V2TrapPDUFactory mockV2TrapPDUFactory = 

[nifi] branch main updated: NIFI-6943 Set DataDogReportingTask API Key Property as Sensitive

2022-06-02 Thread pvillard
This is an automated email from the ASF dual-hosted git repository.

pvillard 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 7f93cb4c91 NIFI-6943 Set DataDogReportingTask API Key Property as 
Sensitive
7f93cb4c91 is described below

commit 7f93cb4c91914d7e5cf4b2933deafa99d52893ee
Author: exceptionfactory 
AuthorDate: Wed Jun 1 13:04:28 2022 -0500

NIFI-6943 Set DataDogReportingTask API Key Property as Sensitive

- Corrected Logger handling and improved unit tests

Signed-off-by: Pierre Villard 

This closes #6090.
---
 .../reporting/datadog/DataDogReportingTask.java| 18 ++--
 .../datadog/TestDataDogReportingTask.java  | 95 ++
 2 files changed, 48 insertions(+), 65 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/java/org/apache/nifi/reporting/datadog/DataDogReportingTask.java
 
b/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/java/org/apache/nifi/reporting/datadog/DataDogReportingTask.java
index 7026a2d416..9ac94bcd4c 100644
--- 
a/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/java/org/apache/nifi/reporting/datadog/DataDogReportingTask.java
+++ 
b/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/java/org/apache/nifi/reporting/datadog/DataDogReportingTask.java
@@ -35,8 +35,6 @@ import org.apache.nifi.reporting.AbstractReportingTask;
 import org.apache.nifi.reporting.ReportingContext;
 import org.apache.nifi.reporting.datadog.metrics.MetricsService;
 import org.coursera.metrics.datadog.DynamicTagsCallback;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Map;
@@ -69,6 +67,7 @@ public class DataDogReportingTask extends 
AbstractReportingTask {
 .name("API key")
 .description("Datadog API key. If specified value is 'agent', 
local Datadog agent will be used.")
 .required(false)
+.sensitive(true)
 .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
 .build();
 
@@ -96,11 +95,9 @@ public class DataDogReportingTask extends 
AbstractReportingTask {
 private MetricRegistry metricRegistry;
 private String metricsPrefix;
 private String environment;
-private String statusId;
 private ConcurrentHashMap metricsMap;
 private Map defaultTags;
 private volatile JmxJvmMetrics virtualMachineMetrics;
-private Logger logger = LoggerFactory.getLogger(getClass().getName());
 
 @OnScheduled
 public void setup(final ConfigurationContext context) {
@@ -130,15 +127,14 @@ public class DataDogReportingTask extends 
AbstractReportingTask {
 
 metricsPrefix = 
context.getProperty(METRICS_PREFIX).evaluateAttributeExpressions().getValue();
 environment = 
context.getProperty(ENVIRONMENT).evaluateAttributeExpressions().getValue();
-statusId = status.getId();
 final Map tags = new HashMap<>();
 tags.put("env", environment);
-tags.put("dataflow_id", statusId);
+tags.put("dataflow_id", status.getId());
 defaultTags = Collections.unmodifiableMap(tags);
 try {
 updateDataDogTransport(context);
 } catch (IOException e) {
-logger.warn("Unable to update data dog transport", e);
+getLogger().warn("Unable to update data dog transport", e);
 }
 updateAllMetricGroups(status);
 ddMetricRegistryBuilder.getDatadogReporter().report();
@@ -147,7 +143,7 @@ public class DataDogReportingTask extends 
AbstractReportingTask {
 protected void updateMetrics(Map metrics, Map tags) {
 for (Map.Entry entry : metrics.entrySet()) {
 final String metricName = buildMetricName(entry.getKey());
-logger.debug(metricName + ": " + entry.getValue());
+getLogger().debug("Metric [{}] Value [{}]", metricName, 
entry.getValue());
 //if metric is not registered yet - register it
 if (!metricsMap.containsKey(metricName)) {
 metricsMap.put(metricName, entry.getValue());
@@ -189,9 +185,9 @@ public class DataDogReportingTask extends 
AbstractReportingTask {
 updateMetrics(metricsService.getDataFlowMetrics(processGroupStatus), 
defaultTags);
 }
 
-private class MetricGauge implements Gauge, DynamicTagsCallback {
-private Map tags;
-private String metricName;
+private class MetricGauge implements Gauge, DynamicTagsCallback {
+private final Map tags;
+private final String metricName;
 
 public MetricGauge(String metricName, Map tagsMap) {
 this.tags = tagsMap;
diff --git 

[nifi] branch main updated: NIFI-10075 Improved TestListSFTP configuration verification

2022-06-02 Thread pvillard
This is an automated email from the ASF dual-hosted git repository.

pvillard 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 1f9672c18b NIFI-10075 Improved TestListSFTP configuration verification
1f9672c18b is described below

commit 1f9672c18bd6ccac4386bae8083793d8e74dd9df
Author: exceptionfactory 
AuthorDate: Wed Jun 1 16:28:54 2022 -0500

NIFI-10075 Improved TestListSFTP configuration verification

- Changed assertVerificationSuccess() to separate 
testVerificationSuccessful() method
- Upgraded TestListSFTP to JUnit 5

Signed-off-by: Pierre Villard 

This closes #6092.
---
 .../nifi/processors/standard/TestListSFTP.java | 46 ++
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListSFTP.java
 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListSFTP.java
index 6dd969d8cc..f9077f8fbd 100644
--- 
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListSFTP.java
+++ 
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListSFTP.java
@@ -22,7 +22,6 @@ import java.io.UncheckedIOException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
@@ -43,29 +42,28 @@ import 
org.apache.nifi.serialization.record.MockRecordWriter;
 import org.apache.nifi.util.MockFlowFile;
 import org.apache.nifi.util.TestRunner;
 import org.apache.nifi.util.TestRunners;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class TestListSFTP {
 private static final String REMOTE_DIRECTORY = "/";
 
+private static final int TEMPORARY_FILES = 3;
+
 private static final byte[] FILE_CONTENTS = 
String.class.getName().getBytes(StandardCharsets.UTF_8);
 
 private TestRunner runner;
 
 private SSHTestServer sshServer;
 
-private List testFileNames;
-
-@Before
-public void setUp() throws Exception {
+@BeforeEach
+public void startServer() throws Exception {
 sshServer = new SSHTestServer();
 sshServer.startServer();
-testFileNames = new ArrayList();
-writeTempFile(3);
+writeTempFile();
 runner = TestRunners.newTestRunner(ListSFTP.class);
 runner.setProperty(ListSFTP.HOSTNAME, sshServer.getHost());
 runner.setProperty(ListSFTP.USERNAME, sshServer.getUsername());
@@ -74,17 +72,16 @@ public class TestListSFTP {
 runner.setProperty(ListSFTP.REMOTE_PATH, REMOTE_DIRECTORY);
 runner.setProperty(ListFile.TARGET_SYSTEM_TIMESTAMP_PRECISION, 
ListFile.PRECISION_MILLIS);
 runner.assertValid();
-assertVerificationSuccess();
 }
 
-@After
-public void tearDown() throws Exception {
+@AfterEach
+public void stopServer() throws Exception {
 sshServer.stopServer();
 Files.deleteIfExists(Paths.get(sshServer.getVirtualFileSystemPath()));
 }
 
 @Test
-public void testRunFileFound() throws InterruptedException {
+public void testRunFileFound() {
 runner.run(1);
 runner.assertTransferCount(ListSFTP.REL_SUCCESS, 3);
 runner.assertAllFlowFilesContainAttribute("sftp.remote.host");
@@ -102,7 +99,7 @@ public class TestListSFTP {
 }
 
 @Test
-public void testRunWithRecordWriter() throws InitializationException, 
InterruptedException {
+public void testRunWithRecordWriter() throws InitializationException {
 RecordSetWriterFactory recordWriter = getCsvRecordWriter();
 runner.addControllerService("csv-record-writer", recordWriter);
 runner.setProperty(AbstractListProcessor.RECORD_WRITER, 
"csv-record-writer");
@@ -114,7 +111,7 @@ public class TestListSFTP {
 }
 
 @Test
-public void testRunWithRecordWriterNoTracking() throws 
InitializationException, InterruptedException {
+public void testRunWithRecordWriterNoTracking() throws 
InitializationException {
 RecordSetWriterFactory recordWriter = getCsvRecordWriter();
 runner.addControllerService("csv-record-writer", recordWriter);
 runner.setProperty(AbstractListProcessor.RECORD_WRITER, 
"csv-record-writer");
@@ -126,7 +123,7 @@ public class TestListSFTP {
 }
 
 @Test
-public void