You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by GitBox <gi...@apache.org> on 2022/08/31 19:42:11 UTC

[GitHub] [nifi] exceptionfactory commented on a diff in pull request #6304: NIFI-9401: HashiCorpVaultParameterProvider

exceptionfactory commented on code in PR #6304:
URL: https://github.com/apache/nifi/pull/6304#discussion_r959775961


##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultClientService.java:
##########
@@ -0,0 +1,104 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.controller.VerifiableControllerService;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.ssl.SSLContextService;
+
+/**
+ *
+ */

Review Comment:
   A comment should be added, or the empty block should be removed.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultClientService.java:
##########
@@ -0,0 +1,215 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.behavior.DynamicProperties;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.controller.ControllerServiceInitializationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultConfiguration;
+import org.springframework.core.env.PropertySource;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+@Tags({"hashicorp", "vault", "client"})
+@CapabilityDescription("A controller service for interacting with HashiCorp Vault.")
+@DynamicProperties(
+        @DynamicProperty(name = "A HashiCorp Vault configuration property name",
+                value = "The property value",
+                description = "Allows any Spring Vault configuration properties to be specified, as described in " +
+                        "(https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration). " +
+                        "See Additional Details for more information.",
+                expressionLanguageScope = ExpressionLanguageScope.VARIABLE_REGISTRY
+        )
+)
+public class StandardHashiCorpVaultClientService extends AbstractControllerService implements HashiCorpVaultClientService {
+
+    private static final String SENSITIVE_PROPERTY_NAME_PATTERN = "vault\\.token|.*-password";

Review Comment:
   Should this be removed in favor of the `SupportsSensitiveDynamicProperties` annotation? This pattern provides some helpful defaults, but perhaps it is better to make the options user-selected?



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java:
##########
@@ -0,0 +1,155 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.PropertyValue;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterGroup;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TestHashiCorpVaultParameterProvider {
+
+    private HashiCorpVaultParameterProvider parameterProvider;
+    private HashiCorpVaultCommunicationService vaultCommunicationService;
+    private List<ParameterGroup> mockedGroups;
+
+    @Before
+    public void init() {
+        vaultCommunicationService = mock(HashiCorpVaultCommunicationService.class);

Review Comment:
   This could be switched to using the `Mock` annotation of the `vaultCommunicationService` member variable, in addition to adding `ExtendWith(MockitoExtension.class)` at the class level.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultClientService.java:
##########
@@ -0,0 +1,215 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.behavior.DynamicProperties;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.controller.ControllerServiceInitializationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultConfiguration;
+import org.springframework.core.env.PropertySource;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+@Tags({"hashicorp", "vault", "client"})
+@CapabilityDescription("A controller service for interacting with HashiCorp Vault.")
+@DynamicProperties(

Review Comment:
   This component should have the `SupportsSensitiveDynamicProperties` annotation as some of the dynamic properties might be sensitive.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultClientService.java:
##########
@@ -0,0 +1,104 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.controller.VerifiableControllerService;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.ssl.SSLContextService;
+
+/**
+ *
+ */
+public interface HashiCorpVaultClientService extends ControllerService, VerifiableControllerService {
+
+    PropertyDescriptor BOOTSTRAP_CONFIGURATION_FILE = new PropertyDescriptor.Builder()
+            .displayName("Bootstrap HashiCorp Vault Configuration File")
+            .name("vault-configuration-file")
+            .required(true)
+            .defaultValue("./conf/bootstrap-hashicorp-vault.conf")
+            .description("Location of the bootstrap-hashicorp-vault.conf file that configures the Vault connection.  Any properties in this configuration " +
+                    "file will be overridden by explicitly-configured properties in this service.")
+            .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+            .build();
+
+    PropertyDescriptor VAULT_URI = new PropertyDescriptor.Builder()
+            .name("vault.uri")
+            .displayName("Vault URI")
+            .description("The URI of the HashiCorp Vault server (e.g., http://localhost:8200).  Required if not specified in the " +
+                    "Bootstrap HashiCorp Vault Configuration File.")
+            .required(false)
+            .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
+            .addValidator(StandardValidators.URI_VALIDATOR)
+            .build();
+
+    PropertyDescriptor VAULT_AUTHENTICATION = new PropertyDescriptor.Builder()
+            .name("vault.authentication")
+            .displayName("Vault Authentication")
+            .description("Vault authentication method, as described in the Spring Vault Environment Configuration documentation " +
+                    "(https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration). " +
+                    "Defaults to 'TOKEN' if not specified in the Bootstrap HashiCorp Vault Configuration File or Authentication Properties File.")
+            .required(false)
+            .allowableValues(VaultAuthenticationMethod.values())
+            .defaultValue(VaultAuthenticationMethod.TOKEN.name())
+            .build();
+
+    PropertyDescriptor AUTHENTICATION_PROPERTIES_FILE = new PropertyDescriptor.Builder()
+            .name("vault.authentication.properties.file")
+            .displayName("Authentication Properties File")
+            .description("A file containing HashiCorp Vault authentication properties for the selected authentication method, as described in the Spring Vault " +
+                    "Environment Configuration documentation (https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration).")
+            .required(false)
+            .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+            .build();

Review Comment:
   Although having different properties for the Bootstrap configuration and Authentication configuration files, together with direct properties provides a great deal of flexibility, it seems to create a lot of complexity from a user experience point of view.
   
   Having some general `Configuration Strategy` property might be helpful as way to indicate dependent properties and simplify the potential configuration.
   
   I think it is also best to avoid direct reference to the bootstrap configuration. Although that might be the natural configuration option, it seems better to have the service reference more generalized. In that same light, having a separate authentication properties file may not make as much sense in the context of the Controller Service. One option might be a have a property name `Vault Properties Files`, which allows one or more files to be specified.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/pom.xml:
##########
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-hashicorp-vault-bundle</artifactId>
+        <version>1.18.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-hashicorp-vault-client-service</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-vault-utils</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-ssl-context-service-api</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-hashicorp-vault-client-service-api</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>

Review Comment:
   These API dependencies should be marked with the `provided` scope.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultClientService.java:
##########
@@ -0,0 +1,104 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.controller.VerifiableControllerService;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.ssl.SSLContextService;
+
+/**
+ *
+ */
+public interface HashiCorpVaultClientService extends ControllerService, VerifiableControllerService {
+
+    PropertyDescriptor BOOTSTRAP_CONFIGURATION_FILE = new PropertyDescriptor.Builder()
+            .displayName("Bootstrap HashiCorp Vault Configuration File")
+            .name("vault-configuration-file")
+            .required(true)
+            .defaultValue("./conf/bootstrap-hashicorp-vault.conf")
+            .description("Location of the bootstrap-hashicorp-vault.conf file that configures the Vault connection.  Any properties in this configuration " +
+                    "file will be overridden by explicitly-configured properties in this service.")
+            .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+            .build();
+
+    PropertyDescriptor VAULT_URI = new PropertyDescriptor.Builder()
+            .name("vault.uri")
+            .displayName("Vault URI")
+            .description("The URI of the HashiCorp Vault server (e.g., http://localhost:8200).  Required if not specified in the " +
+                    "Bootstrap HashiCorp Vault Configuration File.")
+            .required(false)
+            .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
+            .addValidator(StandardValidators.URI_VALIDATOR)
+            .build();
+
+    PropertyDescriptor VAULT_AUTHENTICATION = new PropertyDescriptor.Builder()
+            .name("vault.authentication")
+            .displayName("Vault Authentication")
+            .description("Vault authentication method, as described in the Spring Vault Environment Configuration documentation " +
+                    "(https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration). " +
+                    "Defaults to 'TOKEN' if not specified in the Bootstrap HashiCorp Vault Configuration File or Authentication Properties File.")
+            .required(false)
+            .allowableValues(VaultAuthenticationMethod.values())
+            .defaultValue(VaultAuthenticationMethod.TOKEN.name())
+            .build();
+
+    PropertyDescriptor AUTHENTICATION_PROPERTIES_FILE = new PropertyDescriptor.Builder()
+            .name("vault.authentication.properties.file")
+            .displayName("Authentication Properties File")
+            .description("A file containing HashiCorp Vault authentication properties for the selected authentication method, as described in the Spring Vault " +
+                    "Environment Configuration documentation (https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration).")
+            .required(false)
+            .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+            .build();
+
+    PropertyDescriptor SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder()
+            .name("vault.ssl.context.service")
+            .displayName("SSL Context Service")
+            .description("The SSL Context Service used to provide client certificate information for TLS/SSL connections to the " +
+                    "HashiCorp Vault server. This service is only relevant if the HashiCorp Vault endpoint has been secured with " +
+                    "TLS/SSL.")
+            .required(false)

Review Comment:
   Making this and other properties dependent on a general strategy property would clearly indicate when this property is considered.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/pom.xml:
##########
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-hashicorp-vault-bundle</artifactId>
+        <version>1.18.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-hashicorp-vault-client-service</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-vault-utils</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>

Review Comment:
   The `compile` scope can be omitted as it is the default setting.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultClientService.java:
##########
@@ -0,0 +1,215 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.behavior.DynamicProperties;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.controller.ControllerServiceInitializationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultConfiguration;
+import org.springframework.core.env.PropertySource;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+@Tags({"hashicorp", "vault", "client"})
+@CapabilityDescription("A controller service for interacting with HashiCorp Vault.")
+@DynamicProperties(
+        @DynamicProperty(name = "A HashiCorp Vault configuration property name",
+                value = "The property value",
+                description = "Allows any Spring Vault configuration properties to be specified, as described in " +
+                        "(https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration). " +
+                        "See Additional Details for more information.",
+                expressionLanguageScope = ExpressionLanguageScope.VARIABLE_REGISTRY
+        )
+)
+public class StandardHashiCorpVaultClientService extends AbstractControllerService implements HashiCorpVaultClientService {
+
+    private static final String SENSITIVE_PROPERTY_NAME_PATTERN = "vault\\.token|.*-password";
+
+    private List<PropertyDescriptor> properties;
+
+    private HashiCorpVaultCommunicationService communicationService;
+
+    @Override
+    protected void init(final ControllerServiceInitializationContext config) {
+        properties = Collections.unmodifiableList(Arrays.asList(
+                BOOTSTRAP_CONFIGURATION_FILE,
+                VAULT_URI,
+                VAULT_AUTHENTICATION,
+                AUTHENTICATION_PROPERTIES_FILE,
+                SSL_CONTEXT_SERVICE,
+                CONNECTION_TIMEOUT,
+                READ_TIMEOUT
+        ));
+    }
+
+    @Override
+    protected PropertyDescriptor getSupportedDynamicPropertyDescriptor(final String propertyDescriptorName) {
+        return new PropertyDescriptor.Builder()
+                .name(propertyDescriptorName)
+                .displayName(propertyDescriptorName)
+                .dynamic(true)
+                .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY)
+                .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+                .sensitive(propertyDescriptorName.matches(SENSITIVE_PROPERTY_NAME_PATTERN))
+                .build();
+    }
+
+    @Override
+    protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return properties;
+    }
+
+    @Override
+    public List<ConfigVerificationResult> verify(final ConfigurationContext context, final ComponentLog verificationLogger,
+                                                 final Map<String, String> variables) {
+        final List<ConfigVerificationResult> results = new ArrayList<>();
+        HashiCorpVaultCommunicationService service = null;
+        try {
+            service = createCommunicationService(context);
+            results.add(new ConfigVerificationResult.Builder()
+                    .outcome(ConfigVerificationResult.Outcome.SUCCESSFUL)
+                    .verificationStepName("Configure HashiCorp Vault Client")
+                    .explanation("Successfully configured HashiCorp Vault Client")
+                    .build());
+        } catch (final Exception e) {
+            verificationLogger.error("Failed to configure HashiCorp Vault Client", e);
+
+            results.add(new ConfigVerificationResult.Builder()
+                    .outcome(ConfigVerificationResult.Outcome.FAILED)
+                    .verificationStepName("Configure HashiCorp Vault Client")
+                    .explanation("Failed to configure HashiCorp Vault Client: " + e.getMessage())
+                    .build());
+        }
+        if (service != null) {
+            try {
+                service.testConnection();
+                results.add(new ConfigVerificationResult.Builder()
+                        .outcome(ConfigVerificationResult.Outcome.SUCCESSFUL)
+                        .verificationStepName("Connect to HashiCorp Vault Server")
+                        .explanation("Successfully connected to HashiCorp Vault Server")
+                        .build());
+            } catch (final Exception e) {
+                verificationLogger.error("Failed to connect to HashiCorp Vault Server", e);
+
+                results.add(new ConfigVerificationResult.Builder()
+                        .outcome(ConfigVerificationResult.Outcome.FAILED)
+                        .verificationStepName("Connect to HashiCorp Vault Server")
+                        .explanation("Failed to connect to HashiCorp Vault Server: " + e.getMessage())
+                        .build());
+            }
+        }
+
+        return results;
+    }
+
+    @OnEnabled
+    public void onEnabled(final ConfigurationContext context) throws InitializationException {
+        try {
+            communicationService = createCommunicationService(context);
+        } catch (final Exception e) {
+            getLogger().error("Could not initialize HashiCorp Vault client.", e);
+            throw new InitializationException(e);

Review Comment:
   It seems unnecessary to log an error and throw the exception, recommend removing the error log and adding a message to the exception.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-client-service/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultClientService.java:
##########
@@ -0,0 +1,215 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.behavior.DynamicProperties;
+import org.apache.nifi.annotation.behavior.DynamicProperty;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnDisabled;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.controller.ControllerServiceInitializationContext;
+import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.ssl.SSLContextService;
+import org.apache.nifi.vault.hashicorp.config.HashiCorpVaultConfiguration;
+import org.springframework.core.env.PropertySource;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+
+@Tags({"hashicorp", "vault", "client"})
+@CapabilityDescription("A controller service for interacting with HashiCorp Vault.")
+@DynamicProperties(
+        @DynamicProperty(name = "A HashiCorp Vault configuration property name",
+                value = "The property value",
+                description = "Allows any Spring Vault configuration properties to be specified, as described in " +
+                        "(https://docs.spring.io/spring-vault/docs/2.3.x/reference/html/#vault.core.environment-vault-configuration). " +
+                        "See Additional Details for more information.",
+                expressionLanguageScope = ExpressionLanguageScope.VARIABLE_REGISTRY
+        )
+)
+public class StandardHashiCorpVaultClientService extends AbstractControllerService implements HashiCorpVaultClientService {
+
+    private static final String SENSITIVE_PROPERTY_NAME_PATTERN = "vault\\.token|.*-password";
+
+    private List<PropertyDescriptor> properties;
+
+    private HashiCorpVaultCommunicationService communicationService;
+
+    @Override
+    protected void init(final ControllerServiceInitializationContext config) {
+        properties = Collections.unmodifiableList(Arrays.asList(
+                BOOTSTRAP_CONFIGURATION_FILE,
+                VAULT_URI,
+                VAULT_AUTHENTICATION,
+                AUTHENTICATION_PROPERTIES_FILE,
+                SSL_CONTEXT_SERVICE,
+                CONNECTION_TIMEOUT,
+                READ_TIMEOUT
+        ));
+    }

Review Comment:
   It looks like this should be move to a static initializer.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.parameter.AbstractParameterProvider;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterGroup;
+import org.apache.nifi.parameter.ParameterProvider;
+import org.apache.nifi.parameter.ParameterProviderInitializationContext;
+import org.apache.nifi.parameter.VerifiableParameterProvider;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@CapabilityDescription("Provides parameters from HashiCorp Vault Key/Value Secrets.  Each Secret represents a parameter group, " +
+        "which will map to a Parameter Context.  The keys and values in the Secret map to Parameters.")
+@Tags({"hashicorp", "vault", "secret"})
+public class HashiCorpVaultParameterProvider extends AbstractParameterProvider implements ParameterProvider, VerifiableParameterProvider {
+
+    public static final PropertyDescriptor VAULT_CLIENT_SERVICE = new PropertyDescriptor.Builder()
+            .name("vault-client-service")
+            .displayName("HashiCorp Vault Client Service")
+            .description("The service used to interact with HashiCorp Vault")
+            .identifiesControllerService(HashiCorpVaultClientService.class)
+            .addValidator(Validator.VALID)
+            .required(true)
+            .build();
+    public static final PropertyDescriptor KV_PATH = new PropertyDescriptor.Builder()
+            .name("kv-path")
+            .displayName("K/V Path")
+            .description("The HashiCorp Vault path to the K/V Secrets Engine")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .required(true)
+            .defaultValue("kv")
+            .build();
+    public static final PropertyDescriptor SECRET_NAME_REGEX = new PropertyDescriptor.Builder()
+            .name("secret-name-regex")
+            .displayName("Secret Name Regex")

Review Comment:
   Recommend naming this `Secret Name Pattern`, the description provides helpful details.
   ```suggestion
       public static final PropertyDescriptor SECRET_NAME_PATTERN = new PropertyDescriptor.Builder()
               .name("secret-name-pattern")
               .displayName("Secret Name Pattern")
   ```



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/pom.xml:
##########
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-hashicorp-vault-bundle</artifactId>
+        <version>1.18.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-hashicorp-vault-parameter-provider</artifactId>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-hashicorp-vault-client-service-api</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+            <version>1.18.0-SNAPSHOT</version>
+            <scope>compile</scope>

Review Comment:
   This scope should be to set `provided`.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.parameter.AbstractParameterProvider;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterGroup;
+import org.apache.nifi.parameter.ParameterProvider;
+import org.apache.nifi.parameter.ParameterProviderInitializationContext;
+import org.apache.nifi.parameter.VerifiableParameterProvider;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@CapabilityDescription("Provides parameters from HashiCorp Vault Key/Value Secrets.  Each Secret represents a parameter group, " +
+        "which will map to a Parameter Context.  The keys and values in the Secret map to Parameters.")
+@Tags({"hashicorp", "vault", "secret"})
+public class HashiCorpVaultParameterProvider extends AbstractParameterProvider implements ParameterProvider, VerifiableParameterProvider {
+
+    public static final PropertyDescriptor VAULT_CLIENT_SERVICE = new PropertyDescriptor.Builder()
+            .name("vault-client-service")
+            .displayName("HashiCorp Vault Client Service")
+            .description("The service used to interact with HashiCorp Vault")
+            .identifiesControllerService(HashiCorpVaultClientService.class)
+            .addValidator(Validator.VALID)
+            .required(true)
+            .build();
+    public static final PropertyDescriptor KV_PATH = new PropertyDescriptor.Builder()
+            .name("kv-path")
+            .displayName("K/V Path")

Review Comment:
   Recommend spelling out `Key/Value Path` for the display name:
   ```suggestion
               .displayName("Key/Value Path")
   ```



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java:
##########
@@ -0,0 +1,168 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.Validator;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.parameter.AbstractParameterProvider;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterGroup;
+import org.apache.nifi.parameter.ParameterProvider;
+import org.apache.nifi.parameter.ParameterProviderInitializationContext;
+import org.apache.nifi.parameter.VerifiableParameterProvider;
+import org.apache.nifi.processor.util.StandardValidators;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@CapabilityDescription("Provides parameters from HashiCorp Vault Key/Value Secrets.  Each Secret represents a parameter group, " +
+        "which will map to a Parameter Context.  The keys and values in the Secret map to Parameters.")
+@Tags({"hashicorp", "vault", "secret"})
+public class HashiCorpVaultParameterProvider extends AbstractParameterProvider implements ParameterProvider, VerifiableParameterProvider {
+
+    public static final PropertyDescriptor VAULT_CLIENT_SERVICE = new PropertyDescriptor.Builder()
+            .name("vault-client-service")
+            .displayName("HashiCorp Vault Client Service")
+            .description("The service used to interact with HashiCorp Vault")
+            .identifiesControllerService(HashiCorpVaultClientService.class)
+            .addValidator(Validator.VALID)
+            .required(true)
+            .build();
+    public static final PropertyDescriptor KV_PATH = new PropertyDescriptor.Builder()
+            .name("kv-path")
+            .displayName("K/V Path")
+            .description("The HashiCorp Vault path to the K/V Secrets Engine")
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .required(true)
+            .defaultValue("kv")
+            .build();
+    public static final PropertyDescriptor SECRET_NAME_REGEX = new PropertyDescriptor.Builder()
+            .name("secret-name-regex")
+            .displayName("Secret Name Regex")
+            .description("A Regular Expression indicating which Secrets to include as parameter groups to map to Parameter Contexts by name.")
+            .addValidator(StandardValidators.REGULAR_EXPRESSION_VALIDATOR)
+            .required(true)
+            .defaultValue(".*")
+            .build();
+
+    private List<PropertyDescriptor> supportedProperties;
+    private HashiCorpVaultCommunicationService vaultCommunicationService;
+
+    @Override
+    protected void init(final ParameterProviderInitializationContext config) {
+        supportedProperties = Collections.unmodifiableList(Arrays.asList(
+                VAULT_CLIENT_SERVICE,
+                KV_PATH,
+                SECRET_NAME_REGEX));
+    }
+
+    @Override
+    protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return supportedProperties;
+    }
+
+    @Override
+    public List<ParameterGroup> fetchParameters(final ConfigurationContext context) {
+        if (vaultCommunicationService == null) {
+            vaultCommunicationService = getVaultCommunicationService(context);
+        }
+
+        final List<ParameterGroup> parameterGroups = getParameterGroups(vaultCommunicationService, context);
+        return parameterGroups;
+    }
+
+    private List<ParameterGroup> getParameterGroups(final HashiCorpVaultCommunicationService vaultCommunicationService,
+                                                            final ConfigurationContext context) {
+        final String kvPath = context.getProperty(KV_PATH).getValue();
+        final String secretIncludeRegex = context.getProperty(SECRET_NAME_REGEX).getValue();
+        final List<String> allSecretNames = vaultCommunicationService.listKeyValueSecrets(kvPath);
+        final List<String> secretNames = allSecretNames.stream()
+                .filter(name -> name.matches(secretIncludeRegex))
+                .collect(Collectors.toList());
+
+        final List<ParameterGroup> parameterGroups = new ArrayList<>();
+        for (final String secretName : secretNames) {
+            final Map<String, String> keyValues = vaultCommunicationService.readKeyValueSecretMap(kvPath, secretName);
+            final List<Parameter> parameters = new ArrayList<>();
+            keyValues.forEach( (key, value) -> {
+                final ParameterDescriptor parameterDescriptor = new ParameterDescriptor.Builder().name(key).build();
+                parameters.add(new Parameter(parameterDescriptor, value, null, true));
+            });

Review Comment:
   It looks like this could be condensed to use `keyValues.map()` with a Collector to the List of Parameters.



##########
nifi-nar-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java:
##########
@@ -0,0 +1,155 @@
+/*
+ * 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.vault.hashicorp;
+
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.PropertyValue;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterGroup;
+import org.junit.Before;
+import org.junit.Test;

Review Comment:
   It would be helpful to update this test to use JUnit 5 Jupiter references.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: issues-unsubscribe@nifi.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org