exceptionfactory commented on code in PR #6553: URL: https://github.com/apache/nifi/pull/6553#discussion_r1001034186
########## nifi-nar-bundles/nifi-standard-services/nifi-key-service-bundle/nifi-key-service/src/main/java/org/apache/nifi/key/service/StandardPrivateKeyService.java: ########## @@ -0,0 +1,203 @@ +/* + * 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.key.service; + +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.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.components.ValidationContext; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.components.resource.ResourceCardinality; +import org.apache.nifi.components.resource.ResourceType; +import org.apache.nifi.context.PropertyContext; +import org.apache.nifi.controller.AbstractControllerService; +import org.apache.nifi.controller.ConfigurationContext; +import org.apache.nifi.key.service.api.PrivateKeyService; +import org.apache.nifi.key.service.reader.BouncyCastlePrivateKeyReader; +import org.apache.nifi.key.service.reader.PrivateKeyReader; +import org.apache.nifi.processor.util.StandardValidators; +import org.apache.nifi.reporting.InitializationException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Standard implementation of Private Key Service supporting encrypted or unencrypted sources + */ +@Tags({"PEM", "PKCS8"}) +@CapabilityDescription("Private Key Service provides access to a Private Key loaded from configured sources") +public class StandardPrivateKeyService extends AbstractControllerService implements PrivateKeyService { + public static final PropertyDescriptor KEY_FILE = new PropertyDescriptor.Builder() + .name("key-file") + .displayName("Key File") + .description("File path to Private Key structured using PKCS8 and encoded as PEM") + .required(false) + .identifiesExternalResource(ResourceCardinality.SINGLE, ResourceType.FILE) + .build(); + + public static final PropertyDescriptor KEY = new PropertyDescriptor.Builder() + .name("key") + .displayName("Key") + .description("Private Key structured using PKCS8 and encoded as PEM") + .required(false) + .sensitive(true) + .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) + .build(); + + public static final PropertyDescriptor KEY_PASSWORD = new PropertyDescriptor.Builder() + .name("key-password") + .displayName("Key Password") + .description("Password used for decrypting Private Keys") + .required(false) + .sensitive(true) + .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) + .build(); + + private static final List<PropertyDescriptor> DESCRIPTORS = Arrays.asList( + KEY_FILE, + KEY, + KEY_PASSWORD + ); + + private static final Charset KEY_CHARACTER_SET = StandardCharsets.US_ASCII; + + private static final PrivateKeyReader PRIVATE_KEY_READER = new BouncyCastlePrivateKeyReader(); + + private final AtomicReference<PrivateKey> keyReference = new AtomicReference<>(); + + @Override + public PrivateKey getPrivateKey() { + return keyReference.get(); + } + + /** + * On Enabled reads Private Keys using configured properties + * + * @param context Configuration Context with properties + * @throws InitializationException Thrown when unable to load + */ + @OnEnabled + public void onEnabled(final ConfigurationContext context) throws InitializationException { + try { + final PrivateKey readKey = readKey(context); + keyReference.set(readKey); + } catch (final RuntimeException e) { + throw new InitializationException("Reading Private Key Failed", e); + } + } + + /** + * On Disabled clears Private Keys + */ + @OnDisabled + public void onDisabled() { + keyReference.set(null); + } + + /** + * Get Supported Property Descriptors + * + * @return Supported Property Descriptors + */ + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + return DESCRIPTORS; + } + + /** + * Custom Validate reads key using configured password for encrypted keys + * + * @param context Validation Context + * @return Validation Results + */ + @Override + protected Collection<ValidationResult> customValidate(final ValidationContext context) { + final Collection<ValidationResult> results = new ArrayList<>(); + + + final PropertyValue keyFileProperty = context.getProperty(KEY_FILE); + final PropertyValue keyProperty = context.getProperty(KEY); + if (keyFileProperty.isSet() && keyProperty.isSet()) { + final String explanation = String.format("Both [%s] and [%s] properties configured", KEY_FILE.getDisplayName(), KEY.getDisplayName()); Review Comment: That's a good point. Given that other components follow a similar pattern, it seems like it would be better to change the general message prefix to improve the overall reading, as opposed to removing the capitalization in this explanation. Perhaps that could be address in a separate issue. -- 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]
