This is an automated email from the ASF dual-hosted git repository.
exceptionfactory 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 f828907df5 NIFI-12080 Added support for KV_2 in HashiCorp Parameter
Provider
f828907df5 is described below
commit f828907df50de98abdc73cb6d1c08cba4c4f8271
Author: Pierre Villard <[email protected]>
AuthorDate: Wed Aug 28 22:12:41 2024 +0200
NIFI-12080 Added support for KV_2 in HashiCorp Parameter Provider
This closes #9209
Signed-off-by: David Handermann <[email protected]>
---
.../HashiCorpVaultCommunicationService.java | 19 +++++++++++++++++
...StandardHashiCorpVaultCommunicationService.java | 18 ++++++++++------
.../hashicorp/HashiCorpVaultParameterProvider.java | 24 ++++++++++++++++++----
.../TestHashiCorpVaultParameterProvider.java | 18 ++++++++++------
4 files changed, 63 insertions(+), 16 deletions(-)
diff --git
a/nifi-commons/nifi-hashicorp-vault-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultCommunicationService.java
b/nifi-commons/nifi-hashicorp-vault-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultCommunicationService.java
index adbb4764b0..33ab496f66 100644
---
a/nifi-commons/nifi-hashicorp-vault-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultCommunicationService.java
+++
b/nifi-commons/nifi-hashicorp-vault-api/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultCommunicationService.java
@@ -89,10 +89,29 @@ public interface HashiCorpVaultCommunicationService {
*/
Map<String, String> readKeyValueSecretMap(String keyValuePath, String
secretKey);
+ /**
+ * Reads a secret with multiple key/value pairs from Vault's Key/Value
Secrets Engine.
+ *
+ * @see <a
href="https://www.vaultproject.io/api-docs/secret/kv">https://www.vaultproject.io/api-docs/secret/kv</a>
+ * @param keyValuePath The Vault path to use for the configured Key/Value
Secrets Engine
+ * @param secretKey The secret key
+ * @param version the Key/Vault Secrets engine version
+ * @return A map from key to value from the secret key/values, or an empty
map if not found
+ */
+ Map<String, String> readKeyValueSecretMap(String keyValuePath, String
secretKey, String version);
+
/**
* Lists the secrets at the given Key/Value Version 1 Secrets Engine path.
* @param keyValuePath The Vault path to list
* @return The list of secret names
*/
List<String> listKeyValueSecrets(String keyValuePath);
+
+ /**
+ * Lists the secrets at the given Key/Value Secrets Engine path.
+ * @param keyValuePath The Vault path to list
+ * @param version the Key/Vault Secrets engine version
+ * @return The list of secret names
+ */
+ List<String> listKeyValueSecrets(String keyValuePath, String version);
}
diff --git
a/nifi-commons/nifi-hashicorp-vault/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultCommunicationService.java
b/nifi-commons/nifi-hashicorp-vault/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultCommunicationService.java
index 38a6e5dfc6..533672af46 100644
---
a/nifi-commons/nifi-hashicorp-vault/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultCommunicationService.java
+++
b/nifi-commons/nifi-hashicorp-vault/src/main/java/org/apache/nifi/vault/hashicorp/StandardHashiCorpVaultCommunicationService.java
@@ -136,17 +136,23 @@ public class StandardHashiCorpVaultCommunicationService
implements HashiCorpVaul
@Override
public Map<String, String> readKeyValueSecretMap(final String
keyValuePath, final String key) {
- final VaultKeyValueOperations keyValueOperations =
keyValueOperationsMap
- .computeIfAbsent(keyValuePath, path ->
vaultTemplate.opsForKeyValue(path, keyValueBackend));
- final VaultResponseSupport<Map> response = keyValueOperations.get(key,
Map.class);
+ return readKeyValueSecretMap(keyValuePath, key,
keyValueBackend.name());
+ }
+
+ @Override
+ public Map<String, String> readKeyValueSecretMap(final String
keyValuePath, final String key, final String version) {
+ final VaultResponseSupport<Map> response =
vaultTemplate.opsForKeyValue(keyValuePath,
KeyValueBackend.valueOf(version)).get(key, Map.class);
return response == null ? Collections.emptyMap() : (Map<String,
String>) response.getRequiredData();
}
@Override
public List<String> listKeyValueSecrets(final String keyValuePath) {
- final VaultKeyValueOperations keyValueOperations =
keyValueOperationsMap
- .computeIfAbsent(keyValuePath, path ->
vaultTemplate.opsForKeyValue(path, KeyValueBackend.KV_1));
- return keyValueOperations.list("/");
+ return listKeyValueSecrets(keyValuePath, KeyValueBackend.KV_1.name());
+ }
+
+ @Override
+ public List<String> listKeyValueSecrets(final String keyValuePath, final
String version) {
+ return vaultTemplate.opsForKeyValue(keyValuePath,
KeyValueBackend.valueOf(version)).list("/");
}
private static class SecretData {
diff --git
a/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java
b/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java
index 624e976aef..26d71fbb55 100644
---
a/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java
+++
b/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/main/java/org/apache/nifi/vault/hashicorp/HashiCorpVaultParameterProvider.java
@@ -18,6 +18,7 @@ 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.AllowableValue;
import org.apache.nifi.components.ConfigVerificationResult;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.Validator;
@@ -37,11 +38,15 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-@CapabilityDescription("Provides parameters from HashiCorp Vault Key/Value
Version 1 Secrets. Each Secret represents a parameter group, " +
+@CapabilityDescription("Provides parameters from HashiCorp Vault Key/Value
Version 1 and Version 2 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 {
+ static final AllowableValue KV_1 = new AllowableValue("KV_1", "KV_1",
"Key/Value Secret Engine Version 1.");
+ static final AllowableValue KV_2 = new AllowableValue("KV_2", "KV_2",
"Key/Value Secret Engine Version 2. "
+ + "If multiple versions of the secret exist, latest will be
used.");
+
public static final PropertyDescriptor VAULT_CLIENT_SERVICE = new
PropertyDescriptor.Builder()
.name("vault-client-service")
.displayName("HashiCorp Vault Client Service")
@@ -53,11 +58,20 @@ public class HashiCorpVaultParameterProvider extends
AbstractParameterProvider i
public static final PropertyDescriptor KV_PATH = new
PropertyDescriptor.Builder()
.name("kv-path")
.displayName("Key/Value Path")
- .description("The HashiCorp Vault path to the Key/Value Version 1
Secrets Engine")
+ .description("The HashiCorp Vault path to the Key/Value Secrets
Engine")
.addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
.required(true)
.defaultValue("kv")
.build();
+ public static final PropertyDescriptor KV_VERSION = new
PropertyDescriptor.Builder()
+ .name("kv-version")
+ .displayName("Key/Value Version")
+ .description("The version of the Key/Value Secrets Engine")
+ .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+ .required(true)
+ .allowableValues(KV_1, KV_2)
+ .defaultValue(KV_1)
+ .build();
public static final PropertyDescriptor SECRET_NAME_PATTERN = new
PropertyDescriptor.Builder()
.name("secret-name-pattern")
.displayName("Secret Name Pattern")
@@ -70,6 +84,7 @@ public class HashiCorpVaultParameterProvider extends
AbstractParameterProvider i
private static final List<PropertyDescriptor> PROPERTIES =
Collections.unmodifiableList(Arrays.asList(
VAULT_CLIENT_SERVICE,
KV_PATH,
+ KV_VERSION,
SECRET_NAME_PATTERN));
private HashiCorpVaultCommunicationService vaultCommunicationService;
@@ -92,15 +107,16 @@ public class HashiCorpVaultParameterProvider extends
AbstractParameterProvider i
private List<ParameterGroup> getParameterGroups(final
HashiCorpVaultCommunicationService vaultCommunicationService,
final
ConfigurationContext context) {
final String kvPath = context.getProperty(KV_PATH).getValue();
+ final String kvVersion = context.getProperty(KV_VERSION).getValue();
final String secretIncludeRegex =
context.getProperty(SECRET_NAME_PATTERN).getValue();
- final List<String> allSecretNames =
vaultCommunicationService.listKeyValueSecrets(kvPath);
+ final List<String> allSecretNames =
vaultCommunicationService.listKeyValueSecrets(kvPath, kvVersion);
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 Map<String, String> keyValues =
vaultCommunicationService.readKeyValueSecretMap(kvPath, secretName, kvVersion);
final List<Parameter> parameters = new ArrayList<>();
keyValues.forEach( (key, value) -> {
parameters.add(new Parameter.Builder()
diff --git
a/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java
b/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java
index 5973da3928..023152a95c 100644
---
a/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java
+++
b/nifi-extension-bundles/nifi-hashicorp-vault-bundle/nifi-hashicorp-vault-parameter-provider/src/test/java/org/apache/nifi/vault/hashicorp/TestHashiCorpVaultParameterProvider.java
@@ -84,10 +84,12 @@ public class TestHashiCorpVaultParameterProvider {
@Test
public void testFetchParameters() {
- mockSecrets("kv2", mockedGroups);
+ final String kvVersion = "KV_1";
+ mockSecrets("kv2", kvVersion, mockedGroups);
final Map<PropertyDescriptor, String> properties = new HashMap<>();
properties.put(HashiCorpVaultParameterProvider.KV_PATH, "kv2");
+ properties.put(HashiCorpVaultParameterProvider.KV_VERSION, kvVersion);
properties.put(HashiCorpVaultParameterProvider.VAULT_CLIENT_SERVICE,
"service");
properties.put(HashiCorpVaultParameterProvider.SECRET_NAME_PATTERN,
".*");
final ConfigurationContext context = mockContext(properties);
@@ -101,10 +103,12 @@ public class TestHashiCorpVaultParameterProvider {
@Test
public void testFetchParametersSecretRegex() {
- mockSecrets("kv2", mockedGroups);
+ final String kvVersion = "KV_2";
+ mockSecrets("kv2", kvVersion, mockedGroups);
final Map<PropertyDescriptor, String> properties = new HashMap<>();
properties.put(HashiCorpVaultParameterProvider.KV_PATH, "kv2");
+ properties.put(HashiCorpVaultParameterProvider.KV_VERSION, kvVersion);
properties.put(HashiCorpVaultParameterProvider.VAULT_CLIENT_SERVICE,
"service");
properties.put(HashiCorpVaultParameterProvider.SECRET_NAME_PATTERN,
".*A");
final ConfigurationContext context = mockContext(properties);
@@ -118,10 +122,12 @@ public class TestHashiCorpVaultParameterProvider {
@Test
public void testVerifyParameters() {
- mockSecrets("kv2", mockedGroups);
+ final String kvVersion = "KV_1";
+ mockSecrets("kv2", kvVersion, mockedGroups);
final Map<PropertyDescriptor, String> properties = new HashMap<>();
properties.put(HashiCorpVaultParameterProvider.KV_PATH, "kv2");
+ properties.put(HashiCorpVaultParameterProvider.KV_VERSION, kvVersion);
properties.put(HashiCorpVaultParameterProvider.VAULT_CLIENT_SERVICE,
"service");
properties.put(HashiCorpVaultParameterProvider.SECRET_NAME_PATTERN,
".*");
final ConfigurationContext context = mockContext(properties);
@@ -145,13 +151,13 @@ public class TestHashiCorpVaultParameterProvider {
lenient().when(context.getProperty(descriptor)).thenReturn(propertyValue);
}
- private void mockSecrets(final String kvPath, final List<ParameterGroup>
parameterGroups) {
- when(vaultCommunicationService.listKeyValueSecrets(kvPath))
+ private void mockSecrets(final String kvPath, final String kvVersion,
final List<ParameterGroup> parameterGroups) {
+ when(vaultCommunicationService.listKeyValueSecrets(kvPath, kvVersion))
.thenReturn(parameterGroups.stream().map(group ->
group.getGroupName()).collect(Collectors.toList()));
for (final ParameterGroup parameterGroup : parameterGroups) {
final Map<String, String> keyValues =
parameterGroup.getParameters().stream()
.collect(Collectors.toMap(parameter ->
parameter.getDescriptor().getName(), parameter -> parameter.getValue()));
-
lenient().when(vaultCommunicationService.readKeyValueSecretMap(kvPath,
parameterGroup.getGroupName())).thenReturn(keyValues);
+
lenient().when(vaultCommunicationService.readKeyValueSecretMap(kvPath,
parameterGroup.getGroupName(), kvVersion)).thenReturn(keyValues);
}
}