exceptionfactory commented on code in PR #6304: URL: https://github.com/apache/nifi/pull/6304#discussion_r967364520
########## 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,149 @@ +/* + * 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.AllowableValue; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +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; + +import java.io.File; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Provides a HashiCorpVaultCommunicationService. + */ +public interface HashiCorpVaultClientService extends ControllerService, VerifiableControllerService { + + AllowableValue DIRECT_PROPERTIES = new AllowableValue("direct-properties", "Direct Properties", + "Use properties, including dynamic properties, configured directly in the Controller Service to configure the client"); + AllowableValue PROPERTIES_FILES = new AllowableValue("properties-files", "Properties Files", + "Use one or more '.properties' files to configure the client"); + + PropertyDescriptor CONFIGURATION_STRATEGY = new PropertyDescriptor.Builder() + .displayName("Configuration Strategy") + .name("configuration-strategy") + .required(true) + .allowableValues(DIRECT_PROPERTIES, PROPERTIES_FILES) + .defaultValue(DIRECT_PROPERTIES.getValue()) + .description("Specifies the source of the configuration properties.") + .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(true) + .expressionLanguageSupported(ExpressionLanguageScope.VARIABLE_REGISTRY) + .addValidator(StandardValidators.URI_VALIDATOR) + .dependsOn(CONFIGURATION_STRATEGY, DIRECT_PROPERTIES) + .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).") + .required(true) + .allowableValues(VaultAuthenticationMethod.values()) + .defaultValue(VaultAuthenticationMethod.TOKEN.name()) + .dependsOn(CONFIGURATION_STRATEGY, DIRECT_PROPERTIES) + .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.") + .required(false) + .identifiesControllerService(SSLContextService.class) + .dependsOn(CONFIGURATION_STRATEGY, DIRECT_PROPERTIES) + .build(); + + PropertyDescriptor VAULT_PROPERTIES_FILES = new PropertyDescriptor.Builder() + .name("vault.properties.files") + .displayName("Vault Properties Files") + .description("A comma-separated list of files containing HashiCorp Vault configuration properties, 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). " + + "All of the Spring property keys and authentication-specific property keys are supported.") + .required(true) + .addValidator(MultiFileExistsValidator.INSTANCE) Review Comment: This should be changed to use the `identifiesExternalResource(ResourceCardinality.MULTIPLE, ResourceType.FILE)` description to support framework-based resource handling. ########## 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,209 @@ +/* + * 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.behavior.SupportsSensitiveDynamicProperties; +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.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.") +@SupportsSensitiveDynamicProperties +@DynamicProperties( + @DynamicProperty(name = "A Spring Vault configuration property name", + value = "The property value", + description = "Allows any Spring Vault property keys 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 COMMA_SEPARATOR = ","; + private static List<PropertyDescriptor> PROPERTIES = Collections.unmodifiableList(Arrays.asList( + CONFIGURATION_STRATEGY, + VAULT_URI, + VAULT_AUTHENTICATION, + SSL_CONTEXT_SERVICE, + VAULT_PROPERTIES_FILES, + CONNECTION_TIMEOUT, + READ_TIMEOUT + )); + + private HashiCorpVaultCommunicationService communicationService; + + @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) + .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) { + throw new InitializationException("Failed to initialize HashiCorp Vault client", e); + } + } + + @OnDisabled + public void onDisabled() { + communicationService = null; + } + + @Override + public HashiCorpVaultCommunicationService getHashiCorpVaultCommunicationService() { + return communicationService; + } + + private HashiCorpVaultCommunicationService createCommunicationService(final ConfigurationContext context) throws IOException { + final List<PropertySource<?>> propertySources = new ArrayList<>(); + + final String configurationStrategy = context.getProperty(CONFIGURATION_STRATEGY).getValue(); + if (DIRECT_PROPERTIES.getValue().equals(configurationStrategy)) { + final PropertySource<?> configurationPropertySource = new DirectPropertySource("Direct Properties", context); + propertySources.add(configurationPropertySource); + } else { + final String propertiesFiles = context.getProperty(VAULT_PROPERTIES_FILES).getValue(); + for (final String propertiesFile : propertiesFiles.split(COMMA_SEPARATOR)) { Review Comment: This approach can be changed to use the `asResources()` and Resource References feature of Property Descriptors. -- 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: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
