mirror of https://github.com/apache/nifi.git
NIFI-14027 Added SSLContextProvider Controller Service Interface
- Updated SSLContextService to extend SSLContextProvider - Updated Processors and Controller Services to use SSLContextProvider where supported Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #9537.
This commit is contained in:
parent
aa3a7c05ad
commit
d07b363fb0
|
@ -43,7 +43,7 @@ import org.apache.nifi.processor.ProcessContext;
|
|||
import org.apache.nifi.processor.ProcessSession;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -127,7 +127,7 @@ abstract class AbstractAMQPProcessor<T extends AMQPWorker> extends AbstractProce
|
|||
.displayName("SSL Context Service")
|
||||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL connections.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor USE_CERT_AUTHENTICATION = new PropertyDescriptor.Builder()
|
||||
.name("cert-authentication")
|
||||
|
@ -314,11 +314,11 @@ abstract class AbstractAMQPProcessor<T extends AMQPWorker> extends AbstractProce
|
|||
}
|
||||
|
||||
// handles TLS/SSL aspects
|
||||
final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final Boolean useCertAuthentication = context.getProperty(USE_CERT_AUTHENTICATION).asBoolean();
|
||||
|
||||
if (sslService != null) {
|
||||
final SSLContext sslContext = sslService.createContext();
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
cf.useSslProtocol(sslContext);
|
||||
|
||||
if (useCertAuthentication) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.nifi.amqp.processors;
|
||||
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -90,10 +90,10 @@ public class AbstractAMQPProcessorTest {
|
|||
}
|
||||
|
||||
private void configureSSLContextService() throws InitializationException {
|
||||
SSLContextService sslService = mock(SSLContextService.class);
|
||||
when(sslService.getIdentifier()).thenReturn("ssl-context");
|
||||
testRunner.addControllerService("ssl-context", sslService);
|
||||
testRunner.enableControllerService(sslService);
|
||||
SSLContextProvider sslContextProvider = mock(SSLContextProvider.class);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn("ssl-context");
|
||||
testRunner.addControllerService("ssl-context", sslContextProvider);
|
||||
testRunner.enableControllerService(sslContextProvider);
|
||||
|
||||
testRunner.setProperty(AbstractAMQPProcessor.SSL_CONTEXT_SERVICE, "ssl-context");
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ import org.apache.nifi.processor.util.StandardValidators;
|
|||
import org.apache.nifi.processors.aws.credentials.provider.service.AWSCredentialsProviderService;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxySpec;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.net.Proxy;
|
||||
|
@ -98,7 +98,7 @@ public abstract class AbstractAWSCredentialsProviderProcessor<ClientType extends
|
|||
.name("SSL Context Service")
|
||||
.description("Specifies an optional SSL Context Service that, if provided, will be used to create connections")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor ENDPOINT_OVERRIDE = new PropertyDescriptor.Builder()
|
||||
|
@ -204,9 +204,9 @@ public abstract class AbstractAWSCredentialsProviderProcessor<ClientType extends
|
|||
config.setSocketTimeout(commsTimeout);
|
||||
|
||||
if (this.getSupportedPropertyDescriptors().contains(SSL_CONTEXT_SERVICE)) {
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
// NIFI-3788: Changed hostnameVerifier from null to DHV (BrowserCompatibleHostnameVerifier is deprecated)
|
||||
SdkTLSSocketFactory sdkTLSSocketFactory = new SdkTLSSocketFactory(sslContext, new DefaultHostnameVerifier());
|
||||
config.getApacheHttpClientConfig().setSslSocketFactory(sdkTLSSocketFactory);
|
||||
|
|
|
@ -39,26 +39,28 @@ import org.apache.nifi.processor.util.StandardValidators;
|
|||
import org.apache.nifi.processors.aws.credentials.provider.service.AWSCredentialsProviderService;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxySpec;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.awscore.client.builder.AwsClientBuilder;
|
||||
import software.amazon.awssdk.core.SdkClient;
|
||||
import software.amazon.awssdk.core.client.builder.SdkClientBuilder;
|
||||
import software.amazon.awssdk.core.client.config.SdkAdvancedClientOption;
|
||||
import software.amazon.awssdk.core.retry.RetryPolicy;
|
||||
import software.amazon.awssdk.http.FileStoreTlsKeyManagersProvider;
|
||||
import software.amazon.awssdk.http.TlsKeyManagersProvider;
|
||||
import software.amazon.awssdk.http.TlsTrustManagersProvider;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.net.Proxy;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -118,7 +120,7 @@ public abstract class AbstractAwsProcessor<T extends SdkClient> extends Abstract
|
|||
.name("SSL Context Service")
|
||||
.description("Specifies an optional SSL Context Service that, if provided, will be used to create connections")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor ENDPOINT_OVERRIDE = new PropertyDescriptor.Builder()
|
||||
|
@ -283,17 +285,22 @@ public abstract class AbstractAwsProcessor<T extends SdkClient> extends Abstract
|
|||
httpClientConfigurer.configureBasicSettings(Duration.ofMillis(communicationsTimeout), context.getMaxConcurrentTasks());
|
||||
|
||||
if (this.getSupportedPropertyDescriptors().contains(SSL_CONTEXT_SERVICE)) {
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
TlsTrustManagersProvider trustManagersProvider = null;
|
||||
TlsKeyManagersProvider keyManagersProvider = null;
|
||||
if (sslContextService.isTrustStoreConfigured()) {
|
||||
trustManagersProvider = () -> new TrustManager[]{sslContextService.createTrustManager()};
|
||||
}
|
||||
if (sslContextService.isKeyStoreConfigured()) {
|
||||
keyManagersProvider = FileStoreTlsKeyManagersProvider
|
||||
.create(Path.of(sslContextService.getKeyStoreFile()), sslContextService.getKeyStoreType(), sslContextService.getKeyStorePassword());
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
final TrustManager[] trustManagers = new TrustManager[]{trustManager};
|
||||
final TlsTrustManagersProvider trustManagersProvider = () -> trustManagers;
|
||||
|
||||
final TlsKeyManagersProvider keyManagersProvider;
|
||||
final Optional<X509ExtendedKeyManager> keyManagerFound = sslContextProvider.createKeyManager();
|
||||
if (keyManagerFound.isPresent()) {
|
||||
final X509ExtendedKeyManager keyManager = keyManagerFound.get();
|
||||
final KeyManager[] keyManagers = new KeyManager[]{keyManager};
|
||||
keyManagersProvider = () -> keyManagers;
|
||||
} else {
|
||||
keyManagersProvider = null;
|
||||
}
|
||||
|
||||
httpClientConfigurer.configureTls(trustManagersProvider, keyManagersProvider);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ import org.apache.nifi.parameter.ParameterGroup;
|
|||
import org.apache.nifi.parameter.VerifiableParameterProvider;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.processors.aws.credentials.provider.service.AWSCredentialsProviderService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.util.ArrayList;
|
||||
|
@ -160,7 +160,7 @@ public class AwsSecretsManagerParameterProvider extends AbstractParameterProvide
|
|||
.displayName("SSL Context Service")
|
||||
.description("Specifies an optional SSL Context Service that, if provided, will be used to create connections")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
private static final String DEFAULT_USER_AGENT = "NiFi";
|
||||
|
@ -311,9 +311,9 @@ public class AwsSecretsManagerParameterProvider extends AbstractParameterProvide
|
|||
config.setConnectionTimeout(commsTimeout);
|
||||
config.setSocketTimeout(commsTimeout);
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
SdkTLSSocketFactory sdkTLSSocketFactory = new SdkTLSSocketFactory(sslContext, new DefaultHostnameVerifier());
|
||||
config.getApacheHttpClientConfig().setSslSocketFactory(sdkTLSSocketFactory);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.apache.nifi.processors.aws.signer.AwsCustomSignerUtil;
|
|||
import org.apache.nifi.processors.aws.signer.AwsSignerType;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxyConfigurationService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.http.apache.ApacheHttpClient;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
@ -131,13 +131,13 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy {
|
|||
final String assumeRoleSTSRegion = propertyContext.getProperty(ASSUME_ROLE_STS_REGION).getValue();
|
||||
final String assumeRoleSTSEndpoint = propertyContext.getProperty(ASSUME_ROLE_STS_ENDPOINT).getValue();
|
||||
final String assumeRoleSTSSigner = propertyContext.getProperty(ASSUME_ROLE_STS_SIGNER_OVERRIDE).getValue();
|
||||
final SSLContextService sslContextService = propertyContext.getProperty(ASSUME_ROLE_SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = propertyContext.getProperty(ASSUME_ROLE_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final ProxyConfigurationService proxyConfigurationService = propertyContext.getProperty(ASSUME_ROLE_PROXY_CONFIGURATION_SERVICE).asControllerService(ProxyConfigurationService.class);
|
||||
|
||||
final ClientConfiguration config = new ClientConfiguration();
|
||||
|
||||
if (sslContextService != null) {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
config.getApacheHttpClientConfig().setSslSocketFactory(new SSLConnectionSocketFactory(sslContext));
|
||||
}
|
||||
|
||||
|
@ -199,15 +199,15 @@ public class AssumeRoleCredentialsStrategy extends AbstractCredentialsStrategy {
|
|||
final String assumeRoleExternalId = propertyContext.getProperty(ASSUME_ROLE_EXTERNAL_ID).getValue();
|
||||
final String assumeRoleSTSEndpoint = propertyContext.getProperty(ASSUME_ROLE_STS_ENDPOINT).getValue();
|
||||
final String stsRegion = propertyContext.getProperty(ASSUME_ROLE_STS_REGION).getValue();
|
||||
final SSLContextService sslContextService = propertyContext.getProperty(ASSUME_ROLE_SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = propertyContext.getProperty(ASSUME_ROLE_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final ProxyConfigurationService proxyConfigurationService = propertyContext.getProperty(ASSUME_ROLE_PROXY_CONFIGURATION_SERVICE).asControllerService(ProxyConfigurationService.class);
|
||||
|
||||
final StsAssumeRoleCredentialsProvider.Builder builder = StsAssumeRoleCredentialsProvider.builder();
|
||||
|
||||
final ApacheHttpClient.Builder httpClientBuilder = ApacheHttpClient.builder();
|
||||
|
||||
if (sslContextService != null) {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
httpClientBuilder.socketFactory(new SSLConnectionSocketFactory(sslContext));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.Fi
|
|||
import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.ImplicitDefaultCredentialsStrategy;
|
||||
import org.apache.nifi.processors.aws.credentials.provider.factory.strategies.NamedProfileCredentialsStrategy;
|
||||
import org.apache.nifi.proxy.ProxyConfigurationService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
|
@ -191,7 +191,7 @@ public class AWSCredentialsProviderControllerService extends AbstractControllerS
|
|||
.name("assume-role-ssl-context-service")
|
||||
.displayName("Assume Role SSL Context Service")
|
||||
.description("SSL Context Service used when connecting to the STS Endpoint.")
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.required(false)
|
||||
.dependsOn(ASSUME_ROLE_ARN)
|
||||
.build();
|
||||
|
|
|
@ -36,27 +36,28 @@ import org.apache.nifi.schema.access.SchemaNotFoundException;
|
|||
import org.apache.nifi.schemaregistry.services.SchemaRegistry;
|
||||
import org.apache.nifi.serialization.record.RecordSchema;
|
||||
import org.apache.nifi.serialization.record.SchemaIdentifier;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
|
||||
import software.amazon.awssdk.http.FileStoreTlsKeyManagersProvider;
|
||||
import software.amazon.awssdk.http.SdkHttpClient;
|
||||
import software.amazon.awssdk.http.TlsKeyManagersProvider;
|
||||
import software.amazon.awssdk.http.apache.ApacheHttpClient;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.glue.GlueClient;
|
||||
import software.amazon.awssdk.services.glue.GlueClientBuilder;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -129,7 +130,7 @@ public class AmazonGlueSchemaRegistry extends AbstractControllerService implemen
|
|||
.displayName("SSL Context Service")
|
||||
.description("Specifies an optional SSL Context Service that, if provided, will be used to create connections")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
private static final ProxySpec[] PROXY_SPECS = {ProxySpec.HTTP_AUTH};
|
||||
|
@ -218,16 +219,17 @@ public class AmazonGlueSchemaRegistry extends AbstractControllerService implemen
|
|||
builder.socketTimeout(Duration.ofMillis(communicationsTimeout));
|
||||
|
||||
if (this.getSupportedPropertyDescriptors().contains(SSL_CONTEXT_SERVICE)) {
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
if (sslContextService.isTrustStoreConfigured()) {
|
||||
final TrustManager[] trustManagers = new TrustManager[]{sslContextService.createTrustManager()};
|
||||
builder.tlsTrustManagersProvider(() -> trustManagers);
|
||||
}
|
||||
if (sslContextService.isKeyStoreConfigured()) {
|
||||
final TlsKeyManagersProvider keyManagersProvider = FileStoreTlsKeyManagersProvider
|
||||
.create(Paths.get(sslContextService.getKeyStoreFile()), sslContextService.getKeyStoreType(), sslContextService.getKeyStorePassword());
|
||||
builder.tlsKeyManagersProvider(keyManagersProvider);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
final TrustManager[] trustManagers = new TrustManager[]{trustManager};
|
||||
builder.tlsTrustManagersProvider(() -> trustManagers);
|
||||
|
||||
final Optional<X509ExtendedKeyManager> keyManagerFound = sslContextProvider.createKeyManager();
|
||||
if (keyManagerFound.isPresent()) {
|
||||
final X509ExtendedKeyManager keyManager = keyManagerFound.get();
|
||||
final KeyManager[] keyManagers = new KeyManager[]{keyManager};
|
||||
builder.tlsKeyManagersProvider(() -> keyManagers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ import org.apache.nifi.schema.access.SchemaNotFoundException;
|
|||
import org.apache.nifi.schemaregistry.services.SchemaRegistry;
|
||||
import org.apache.nifi.serialization.record.RecordSchema;
|
||||
import org.apache.nifi.serialization.record.SchemaIdentifier;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
@Tags({"schema", "registry", "confluent", "avro", "kafka"})
|
||||
@CapabilityDescription("Provides a Schema Registry that interacts with the Confluent Schema Registry so that those Schemas that are stored in the Confluent Schema "
|
||||
|
@ -86,7 +86,7 @@ public class ConfluentSchemaRegistry extends AbstractControllerService implement
|
|||
.name("ssl-context")
|
||||
.displayName("SSL Context Service")
|
||||
.description("Specifies the SSL Context Service to use for interacting with the Confluent Schema Registry")
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
|
@ -193,11 +193,11 @@ public class ConfluentSchemaRegistry extends AbstractControllerService implement
|
|||
final int timeoutMillis = context.getProperty(TIMEOUT).asTimePeriod(TimeUnit.MILLISECONDS).intValue();
|
||||
|
||||
final SSLContext sslContext;
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
if (sslContextService == null) {
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider == null) {
|
||||
sslContext = null;
|
||||
} else {
|
||||
sslContext = sslContextService.createContext();
|
||||
sslContext = sslContextProvider.createContext();
|
||||
}
|
||||
|
||||
final String username = context.getProperty(USERNAME).getValue();
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.nifi.expression.ExpressionLanguageScope;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxySpec;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -47,7 +47,7 @@ public interface ElasticSearchClientService extends ControllerService, Verifiabl
|
|||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL "
|
||||
+ "connections. This service only applies if the Elasticsearch endpoint(s) have been secured with TLS/SSL.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.addValidator(Validator.VALID)
|
||||
.build();
|
||||
PropertyDescriptor PROXY_CONFIGURATION_SERVICE = ProxyConfiguration.createProxyConfigPropertyDescriptor(ProxySpec.HTTP);
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.apache.nifi.processor.util.StandardValidators;
|
|||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxyConfigurationService;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.StopWatch;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.elasticsearch.client.Node;
|
||||
|
@ -143,9 +143,9 @@ public class ElasticSearchClientServiceImpl extends AbstractControllerService im
|
|||
final boolean apiKeyIdSet = validationContext.getProperty(API_KEY_ID).isSet();
|
||||
final boolean apiKeySet = validationContext.getProperty(API_KEY).isSet();
|
||||
|
||||
final SSLContextService sslService = validationContext.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = validationContext.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
|
||||
if (authorizationScheme == AuthorizationScheme.PKI && (sslService == null || !sslService.isKeyStoreConfigured())) {
|
||||
if (authorizationScheme == AuthorizationScheme.PKI && (sslContextProvider == null)) {
|
||||
results.add(new ValidationResult.Builder().subject(PROP_SSL_CONTEXT_SERVICE.getName()).valid(false)
|
||||
.explanation(String.format("if '%s' is '%s' then '%s' must be set and specify a Keystore for mutual TLS encryption.",
|
||||
AUTHORIZATION_SCHEME.getDisplayName(), authorizationScheme.getDisplayName(), PROP_SSL_CONTEXT_SERVICE.getDisplayName())
|
||||
|
@ -462,12 +462,10 @@ public class ElasticSearchClientServiceImpl extends AbstractControllerService im
|
|||
}
|
||||
|
||||
private SSLContext getSSLContext(final ConfigurationContext context) throws InitializationException {
|
||||
final SSLContextService sslService =
|
||||
context.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(PROP_SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
|
||||
try {
|
||||
return (sslService != null && (sslService.isKeyStoreConfigured() || sslService.isTrustStoreConfigured()))
|
||||
? sslService.createContext() : null;
|
||||
return sslContextProvider == null ? null : sslContextProvider.createContext();
|
||||
} catch (final Exception e) {
|
||||
getLogger().error("Error building up SSL Context from the supplied configuration.", e);
|
||||
throw new InitializationException(e);
|
||||
|
|
|
@ -36,9 +36,6 @@ import org.apache.nifi.elasticsearch.IndexOperationResponse;
|
|||
import org.apache.nifi.elasticsearch.MapBuilder;
|
||||
import org.apache.nifi.elasticsearch.SearchResponse;
|
||||
import org.apache.nifi.elasticsearch.UpdateOperationResponse;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.StandardRestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.StandardSSLContextService;
|
||||
import org.apache.nifi.util.MockConfigurationContext;
|
||||
import org.apache.nifi.util.MockControllerServiceLookup;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
|
@ -175,35 +172,6 @@ class ElasticSearchClientService_IT extends AbstractElasticsearch_IT {
|
|||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVerifyFailedSSL() throws Exception {
|
||||
runner.disableControllerService(service);
|
||||
final SSLContextService sslContextService = new StandardRestrictedSSLContextService();
|
||||
runner.addControllerService("SSL Context", sslContextService);
|
||||
runner.setProperty(service, ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE, "SSL Context");
|
||||
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, "not/a/file");
|
||||
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, "ignored");
|
||||
try {
|
||||
runner.enableControllerService(sslContextService);
|
||||
} catch (final Exception ignored) {
|
||||
// expected, ignore
|
||||
}
|
||||
|
||||
final List<ConfigVerificationResult> results = service.verify(
|
||||
new MockConfigurationContext(service, getClientServiceProperties(), runner.getProcessContext().getControllerServiceLookup(), null),
|
||||
runner.getLogger(),
|
||||
Collections.emptyMap()
|
||||
);
|
||||
assertEquals(4, results.size());
|
||||
assertEquals(3, results.stream().filter(result -> result.getOutcome() == ConfigVerificationResult.Outcome.SKIPPED).count(), results.toString());
|
||||
assertEquals(1, results.stream().filter(
|
||||
result -> Objects.equals(result.getVerificationStepName(), ElasticSearchClientServiceImpl.VERIFICATION_STEP_CLIENT_SETUP)
|
||||
&& Objects.equals(result.getExplanation(), "Incorrect/invalid " + ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE.getDisplayName())
|
||||
&& result.getOutcome() == ConfigVerificationResult.Outcome.FAILED).count(),
|
||||
results.toString()
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVerifyFailedAuth() {
|
||||
runner.disableControllerService(service);
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.apache.nifi.elasticsearch.ElasticSearchClientService;
|
|||
import org.apache.nifi.elasticsearch.ElasticSearchClientServiceImpl;
|
||||
import org.apache.nifi.elasticsearch.TestControllerServiceProcessor;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
@ -32,10 +32,7 @@ import org.opentest4j.AssertionFailedError;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.atMostOnce;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class ElasticSearchClientServiceImplTest {
|
||||
|
@ -107,24 +104,14 @@ class ElasticSearchClientServiceImplTest {
|
|||
void testValidatePkiAuth() throws InitializationException {
|
||||
runner.setProperty(service, ElasticSearchClientService.AUTHORIZATION_SCHEME, AuthorizationScheme.PKI);
|
||||
|
||||
final SSLContextService sslService = mock(SSLContextService.class);
|
||||
when(sslService.getIdentifier()).thenReturn("ssl-context");
|
||||
runner.addControllerService("ssl-context", sslService);
|
||||
final SSLContextProvider sslContextProvider = mock(SSLContextProvider.class);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn("ssl-context");
|
||||
runner.addControllerService("ssl-context", sslContextProvider);
|
||||
runner.setProperty(service, ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE, "ssl-context");
|
||||
when(sslService.isKeyStoreConfigured()).thenReturn(true);
|
||||
runner.assertValid(service);
|
||||
verify(sslService, atMostOnce()).isKeyStoreConfigured();
|
||||
reset(sslService);
|
||||
|
||||
when(sslService.isKeyStoreConfigured()).thenReturn(false);
|
||||
assertPKIAuthorizationValidationErrorMessage();
|
||||
verify(sslService, atMostOnce()).isKeyStoreConfigured();
|
||||
reset(sslService);
|
||||
|
||||
runner.removeProperty(service, ElasticSearchClientService.PROP_SSL_CONTEXT_SERVICE);
|
||||
assertPKIAuthorizationValidationErrorMessage();
|
||||
verify(sslService, atMostOnce()).isKeyStoreConfigured();
|
||||
reset(sslService);
|
||||
}
|
||||
|
||||
private void assertAuthorizationPropertyValidationErrorMessage(final PropertyDescriptor presentProperty, final PropertyDescriptor missingProperty) {
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.apache.nifi.processor.ProcessSession;
|
|||
import org.apache.nifi.processor.ProcessorInitializationContext;
|
||||
import org.apache.nifi.processor.Relationship;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
|
@ -155,7 +155,7 @@ public abstract class AbstractPutEventProcessor<T> extends AbstractSessionFactor
|
|||
.name("SSL Context Service")
|
||||
.description("Specifies the SSL Context Service to enable TLS socket communication")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final Relationship REL_SUCCESS = new Relationship.Builder()
|
||||
|
@ -265,8 +265,8 @@ public abstract class AbstractPutEventProcessor<T> extends AbstractSessionFactor
|
|||
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
if (sslContextServiceProperty.isSet()) {
|
||||
final SSLContextService sslContextService = sslContextServiceProperty.asControllerService(SSLContextService.class);
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = sslContextServiceProperty.asControllerService(SSLContextProvider.class);
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
factory.setSslContext(sslContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.nifi.registry.client.NiFiRegistryClientConfig;
|
|||
import org.apache.nifi.registry.client.NiFiRegistryException;
|
||||
import org.apache.nifi.registry.client.impl.JerseyNiFiRegistryClient;
|
||||
import org.apache.nifi.registry.client.impl.request.ProxiedEntityRequestConfig;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
|
@ -55,7 +55,7 @@ public class NifiRegistryFlowRegistryClient extends AbstractFlowRegistryClient {
|
|||
.displayName("SSL Context Service")
|
||||
.description("Specifies the SSL Context Service to use for communicating with NiFiRegistry")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
private volatile String registryUrl;
|
||||
|
@ -129,8 +129,8 @@ public class NifiRegistryFlowRegistryClient extends AbstractFlowRegistryClient {
|
|||
private SSLContext extractSSLContext(final FlowRegistryClientConfigurationContext context) {
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
if (sslContextServiceProperty.isSet()) {
|
||||
final SSLContextService sslContextService = sslContextServiceProperty.asControllerService(SSLContextService.class);
|
||||
return sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = sslContextServiceProperty.asControllerService(SSLContextProvider.class);
|
||||
return sslContextProvider.createContext();
|
||||
} else {
|
||||
return getSystemSslContext().orElse(null);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ import org.apache.nifi.graph.gremlin.SimpleEntry;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.apache.nifi.util.file.classloader.ClassLoaderUtils;
|
||||
import org.apache.tinkerpop.gremlin.driver.Client;
|
||||
|
@ -216,7 +216,7 @@ public class TinkerpopClientService extends AbstractControllerService implements
|
|||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL "
|
||||
+ "connections.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final List<PropertyDescriptor> DESCRIPTORS = Collections.unmodifiableList(Arrays.asList(
|
||||
|
@ -335,10 +335,10 @@ public class TinkerpopClientService extends AbstractControllerService implements
|
|||
|
||||
protected Cluster.Builder setupSSL(ConfigurationContext context, Cluster.Builder builder) {
|
||||
if (context.getProperty(SSL_CONTEXT_SERVICE).isSet()) {
|
||||
SSLContextService service = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
ApplicationProtocolConfig applicationProtocolConfig = new ApplicationProtocolConfig(ApplicationProtocolConfig.Protocol.NONE,
|
||||
ApplicationProtocolConfig.SelectorFailureBehavior.FATAL_ALERT, ApplicationProtocolConfig.SelectedListenerFailureBehavior.FATAL_ALERT);
|
||||
JdkSslContext jdkSslContext = new JdkSslContext(service.createContext(), true, null,
|
||||
JdkSslContext jdkSslContext = new JdkSslContext(sslContextProvider.createContext(), true, null,
|
||||
IdentityCipherSuiteFilter.INSTANCE, applicationProtocolConfig, ClientAuth.NONE, null, false);
|
||||
|
||||
builder
|
||||
|
|
|
@ -26,7 +26,7 @@ import org.apache.nifi.controller.VerifiableControllerService;
|
|||
import org.apache.nifi.expression.ExpressionLanguageScope;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.bson.Document;
|
||||
|
||||
public interface MongoDBClientService extends ControllerService, VerifiableControllerService {
|
||||
|
@ -101,7 +101,7 @@ public interface MongoDBClientService extends ControllerService, VerifiableContr
|
|||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL "
|
||||
+ "connections.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
PropertyDescriptor CLIENT_AUTH = new PropertyDescriptor.Builder()
|
||||
.name("ssl-client-auth")
|
||||
|
|
|
@ -41,7 +41,7 @@ import org.apache.nifi.components.PropertyDescriptor;
|
|||
import org.apache.nifi.controller.AbstractControllerService;
|
||||
import org.apache.nifi.controller.ConfigurationContext;
|
||||
import org.apache.nifi.logging.ComponentLog;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.bson.Document;
|
||||
|
||||
@Tags({"mongo", "mongodb", "service"})
|
||||
|
@ -83,13 +83,13 @@ public class MongoDBControllerService extends AbstractControllerService implemen
|
|||
writeConcernProperty = context.getProperty(WRITE_CONCERN).getValue();
|
||||
|
||||
// Set up the client for secure (SSL/TLS communications) if configured to do so
|
||||
final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final SSLContext sslContext;
|
||||
|
||||
if (sslService == null) {
|
||||
if (sslContextProvider == null) {
|
||||
sslContext = null;
|
||||
} else {
|
||||
sslContext = sslService.createContext();
|
||||
sslContext = sslContextProvider.createContext();
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -42,7 +42,7 @@ import org.apache.nifi.processor.Relationship;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.net.InetAddress;
|
||||
|
@ -96,7 +96,7 @@ public class ListenOTLP extends AbstractProcessor {
|
|||
.displayName("SSL Context Service")
|
||||
.description("SSL Context Service enables TLS communication for HTTPS")
|
||||
.required(true)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.expressionLanguageSupported(ExpressionLanguageScope.NONE)
|
||||
.build();
|
||||
|
||||
|
@ -224,8 +224,8 @@ public class ListenOTLP extends AbstractProcessor {
|
|||
final BlockingQueue<Message> messages = new LinkedBlockingQueue<>(queueCapacity);
|
||||
requestCallbackProvider = new RequestCallbackProvider(transitBaseUri, batchSize, messages);
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
|
||||
final NettyEventServerFactory eventServerFactory = new HttpServerFactory(getLogger(), messages, serverAddress, port, sslContext);
|
||||
eventServerFactory.setThreadNamePrefix(String.format("%s[%s]", getClass().getSimpleName(), getIdentifier()));
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
|||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.security.util.TlsPlatform;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
|
@ -106,7 +106,7 @@ class ListenOTLPTest {
|
|||
|
||||
private static final String HTTP_URL_FORMAT = "https://localhost:%d%s";
|
||||
|
||||
private static final String SERVICE_ID = SSLContextService.class.getSimpleName();
|
||||
private static final String SERVICE_ID = SSLContextProvider.class.getSimpleName();
|
||||
|
||||
private static final String PATH_NOT_FOUND = "/not-found";
|
||||
|
||||
|
@ -139,7 +139,7 @@ class ListenOTLPTest {
|
|||
private static StandardWebClientService webClientService;
|
||||
|
||||
@Mock
|
||||
private SSLContextService sslContextService;
|
||||
private SSLContextProvider sslContextProvider;
|
||||
|
||||
private TestRunner runner;
|
||||
|
||||
|
@ -506,7 +506,7 @@ class ListenOTLPTest {
|
|||
runner.setProperty(ListenOTLP.ADDRESS, LOCALHOST);
|
||||
runner.setProperty(ListenOTLP.PORT, RANDOM_PORT);
|
||||
setSslContextService();
|
||||
when(sslContextService.createContext()).thenReturn(sslContext);
|
||||
when(sslContextProvider.createContext()).thenReturn(sslContext);
|
||||
|
||||
runner.run(1, false, true);
|
||||
}
|
||||
|
@ -519,10 +519,10 @@ class ListenOTLPTest {
|
|||
}
|
||||
|
||||
private void setSslContextService() throws InitializationException {
|
||||
when(sslContextService.getIdentifier()).thenReturn(SERVICE_ID);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn(SERVICE_ID);
|
||||
|
||||
runner.addControllerService(SERVICE_ID, sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
runner.addControllerService(SERVICE_ID, sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
|
||||
runner.setProperty(ListenOTLP.SSL_CONTEXT_SERVICE, SERVICE_ID);
|
||||
runner.setProperty(ListenOTLP.CLIENT_AUTHENTICATION, ClientAuth.WANT.name());
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.nifi.controller.ConfigurationContext;
|
|||
import org.apache.nifi.redis.RedisConnectionPool;
|
||||
import org.apache.nifi.redis.RedisType;
|
||||
import org.apache.nifi.redis.util.RedisUtils;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
|
||||
|
@ -61,8 +61,8 @@ RedisConnectionPoolService extends AbstractControllerService implements RedisCon
|
|||
public void onEnabled(final ConfigurationContext context) {
|
||||
this.context = context;
|
||||
if (context.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).isSet()) {
|
||||
final SSLContextService sslContextService = context.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
this.sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
this.sslContext = sslContextProvider.createContext();
|
||||
}
|
||||
|
||||
final String redisMode = context.getProperty(RedisUtils.REDIS_MODE).getValue();
|
||||
|
|
|
@ -19,8 +19,7 @@ package org.apache.nifi.redis.service;
|
|||
import org.apache.nifi.redis.RedisConnectionPool;
|
||||
import org.apache.nifi.redis.util.RedisUtils;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.MockConfigurationContext;
|
||||
import org.apache.nifi.util.MockProcessContext;
|
||||
import org.apache.nifi.util.StandardProcessorTestRunner;
|
||||
|
@ -33,7 +32,6 @@ import org.mockito.Mockito;
|
|||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -49,7 +47,7 @@ public class TestRedisConnectionPoolService {
|
|||
private static SSLContext sslContext;
|
||||
|
||||
@BeforeAll
|
||||
public static void classSetup() throws IOException, GeneralSecurityException {
|
||||
public static void classSetup() throws GeneralSecurityException {
|
||||
sslContext = SSLContext.getDefault();
|
||||
}
|
||||
|
||||
|
@ -63,11 +61,11 @@ public class TestRedisConnectionPoolService {
|
|||
}
|
||||
|
||||
private void enableSslContextService() throws InitializationException {
|
||||
final RestrictedSSLContextService sslContextService = Mockito.mock(RestrictedSSLContextService.class);
|
||||
Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER);
|
||||
Mockito.when(sslContextService.createContext()).thenReturn(sslContext);
|
||||
testRunner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService);
|
||||
testRunner.enableControllerService(sslContextService);
|
||||
final SSLContextProvider sslContextProvider = Mockito.mock(SSLContextProvider.class);
|
||||
Mockito.when(sslContextProvider.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER);
|
||||
Mockito.when(sslContextProvider.createContext()).thenReturn(sslContext);
|
||||
testRunner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextProvider);
|
||||
testRunner.enableControllerService(sslContextProvider);
|
||||
testRunner.setProperty(redisService, RedisUtils.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER);
|
||||
}
|
||||
|
||||
|
@ -123,8 +121,8 @@ public class TestRedisConnectionPoolService {
|
|||
.get(redisService.getIdentifier()).getProperties(), processContext, null);
|
||||
SSLContext providedSslContext = null;
|
||||
if (configContext.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).isSet()) {
|
||||
final SSLContextService sslContextService = configContext.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
providedSslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = configContext.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
providedSslContext = sslContextProvider.createContext();
|
||||
}
|
||||
JedisConnectionFactory connectionFactory = RedisUtils.createConnectionFactory(configContext, providedSslContext);
|
||||
return connectionFactory;
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.nifi.expression.ExpressionLanguageScope;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.redis.RedisConnectionPool;
|
||||
import org.apache.nifi.redis.RedisType;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -295,7 +295,7 @@ public class RedisUtils {
|
|||
.description("If specified, this service will be used to create an SSL Context that will be used "
|
||||
+ "to secure communications; if not specified, communications will not be secure")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final List<PropertyDescriptor> REDIS_CONNECTION_PROPERTY_DESCRIPTORS;
|
||||
|
|
|
@ -37,8 +37,7 @@ import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
|
|||
import org.apache.nifi.remote.protocol.http.HttpProxy;
|
||||
import org.apache.nifi.remote.util.SiteToSiteRestApiClient;
|
||||
import org.apache.nifi.reporting.ReportingContext;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
public class SiteToSiteUtils {
|
||||
|
||||
|
@ -71,7 +70,7 @@ public class SiteToSiteUtils {
|
|||
.displayName("SSL Context Service")
|
||||
.description("The SSL Context Service to use when communicating with the destination. If not specified, communications will not be secure.")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor INSTANCE_URL = new PropertyDescriptor.Builder()
|
||||
.name("Instance URL")
|
||||
|
@ -128,8 +127,8 @@ public class SiteToSiteUtils {
|
|||
.build();
|
||||
|
||||
public static SiteToSiteClient getClient(PropertyContext reportContext, ComponentLog logger, StateManager stateManager) {
|
||||
final SSLContextService sslContextService = reportContext.getProperty(SiteToSiteUtils.SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
final SSLContext sslContext = sslContextService == null ? null : sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = reportContext.getProperty(SiteToSiteUtils.SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
final SSLContext sslContext = sslContextProvider == null ? null : sslContextProvider.createContext();
|
||||
final EventReporter eventReporter = (EventReporter) (severity, category, message) -> {
|
||||
switch (severity) {
|
||||
case WARNING:
|
||||
|
|
|
@ -52,7 +52,7 @@ import org.apache.nifi.processor.exception.ProcessException;
|
|||
import org.apache.nifi.processor.io.OutputStreamCallback;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.scheduling.SchedulingStrategy;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.IOException;
|
||||
|
@ -255,7 +255,7 @@ public class GetSplunk extends AbstractProcessor implements ClassloaderIsolation
|
|||
.name("SSL Context Service")
|
||||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL connections.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final Relationship REL_SUCCESS = new Relationship.Builder()
|
||||
|
@ -584,9 +584,9 @@ public class GetSplunk extends AbstractProcessor implements ClassloaderIsolation
|
|||
serviceArgs.setSSLSecurityProtocol(SSLSecurityProtocol.valueOf(secProtocol));
|
||||
}
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
Service.setSSLSocketFactory(sslContextService.createContext().getSocketFactory());
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
Service.setSSLSocketFactory(sslContextProvider.createContext().getSocketFactory());
|
||||
}
|
||||
|
||||
return Service.connect(serviceArgs);
|
||||
|
@ -625,11 +625,11 @@ public class GetSplunk extends AbstractProcessor implements ClassloaderIsolation
|
|||
|
||||
@Override
|
||||
public String getClassloaderIsolationKey(PropertyContext context) {
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
// Class loader isolation is only necessary when SSL is enabled, as Service.setSSLSocketFactory
|
||||
// changes the Socket Factory for all instances.
|
||||
return sslContextService.getIdentifier();
|
||||
return sslContextProvider.getIdentifier();
|
||||
} else {
|
||||
// This workaround ensures that instances don't unnecessarily use an isolated classloader.
|
||||
return getClass().getName();
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
|||
import org.apache.nifi.annotation.documentation.Tags;
|
||||
import org.apache.nifi.annotation.lifecycle.OnStopped;
|
||||
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.event.transport.EventException;
|
||||
|
@ -47,7 +48,6 @@ import org.apache.nifi.processor.ProcessSessionFactory;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.io.InputStreamCallback;
|
||||
import org.apache.nifi.processor.util.put.AbstractPutEventProcessor;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.stream.io.ByteCountingInputStream;
|
||||
import org.apache.nifi.stream.io.util.NonThreadSafeCircularBuffer;
|
||||
|
||||
|
@ -78,9 +78,9 @@ public class PutSplunk extends AbstractPutEventProcessor<byte[]> {
|
|||
final Collection<ValidationResult> results = new ArrayList<>();
|
||||
|
||||
final String protocol = context.getProperty(PROTOCOL).getValue();
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
|
||||
if (UDP_VALUE.getValue().equals(protocol) && sslContextService != null) {
|
||||
if (UDP_VALUE.getValue().equals(protocol) && sslContextServiceProperty.isSet()) {
|
||||
results.add(new ValidationResult.Builder()
|
||||
.explanation("SSL can not be used with UDP")
|
||||
.valid(false).subject("SSL Context").build());
|
||||
|
|
|
@ -57,7 +57,7 @@ import org.apache.nifi.processors.standard.http.HttpProtocolStrategy;
|
|||
import org.apache.nifi.processors.standard.util.HTTPUtils;
|
||||
import org.apache.nifi.scheduling.ExecutionNode;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.stream.io.StreamUtils;
|
||||
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.ee10.servlet.ServletContextRequest;
|
||||
|
@ -381,7 +381,7 @@ public class HandleHttpRequest extends AbstractProcessor {
|
|||
this.containerQueue = new LinkedBlockingQueue<>(context.getProperty(CONTAINER_QUEUE_SIZE).asInteger());
|
||||
final String host = context.getProperty(HOSTNAME).getValue();
|
||||
final int port = context.getProperty(PORT).evaluateAttributeExpressions().asInteger();
|
||||
final SSLContextService sslService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
final HttpContextMap httpContextMap = context.getProperty(HTTP_CONTEXT_MAP).asControllerService(HttpContextMap.class);
|
||||
final long requestTimeout = httpContextMap.getRequestTimeout(TimeUnit.MILLISECONDS);
|
||||
|
||||
|
@ -396,7 +396,7 @@ public class HandleHttpRequest extends AbstractProcessor {
|
|||
serverConnectorFactory.setNeedClientAuth(needClientAuth);
|
||||
final boolean wantClientAuth = CLIENT_WANT.getValue().equals(clientAuthValue);
|
||||
serverConnectorFactory.setWantClientAuth(wantClientAuth);
|
||||
final SSLContext sslContext = sslService == null ? null : sslService.createContext();
|
||||
final SSLContext sslContext = sslContextProvider == null ? null : sslContextProvider.createContext();
|
||||
serverConnectorFactory.setSslContext(sslContext);
|
||||
final HttpProtocolStrategy httpProtocolStrategy = context.getProperty(HTTP_PROTOCOL_STRATEGY).asAllowableValue(HttpProtocolStrategy.class);
|
||||
serverConnectorFactory.setApplicationLayerProtocols(httpProtocolStrategy.getApplicationLayerProtocols());
|
||||
|
|
|
@ -81,8 +81,7 @@ import org.apache.nifi.processors.standard.util.ProxyAuthenticator;
|
|||
import org.apache.nifi.processors.standard.util.SoftLimitBoundedByteArrayOutputStream;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxySpec;
|
||||
import org.apache.nifi.security.util.TlsException;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.stream.io.StreamUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -218,7 +217,7 @@ public class InvokeHTTP extends AbstractProcessor {
|
|||
.name("SSL Context Service")
|
||||
.description("SSL Context Service provides trusted certificates and client certificates for TLS communication.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor SOCKET_CONNECT_TIMEOUT = new PropertyDescriptor.Builder()
|
||||
|
@ -736,7 +735,7 @@ public class InvokeHTTP extends AbstractProcessor {
|
|||
}
|
||||
|
||||
@OnScheduled
|
||||
public void setUpClient(final ProcessContext context) throws TlsException, IOException {
|
||||
public void setUpClient(final ProcessContext context) throws IOException {
|
||||
okHttpClientAtomicReference.set(null);
|
||||
|
||||
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient().newBuilder();
|
||||
|
@ -774,11 +773,11 @@ public class InvokeHTTP extends AbstractProcessor {
|
|||
)
|
||||
);
|
||||
|
||||
final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslService != null) {
|
||||
final SSLContext sslContext = sslService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
final SSLSocketFactory socketFactory = sslContext.getSocketFactory();
|
||||
final X509TrustManager trustManager = sslService.createTrustManager();;
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
okHttpClientBuilder.sslSocketFactory(socketFactory, trustManager);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ import org.apache.nifi.processor.exception.ProcessException;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.processors.standard.ftp.FtpServer;
|
||||
import org.apache.nifi.processors.standard.ftp.NifiFtpServer;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -72,7 +72,7 @@ public class ListenFTP extends AbstractSessionFactoryProcessor {
|
|||
+ "preferred TLS Protocol, TLSv1.3 will be used (regardless of TLSv1.2 being selected) because Java 11 "
|
||||
+ "supports TLSv1.3.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor BIND_ADDRESS = new PropertyDescriptor.Builder()
|
||||
|
@ -155,7 +155,7 @@ public class ListenFTP extends AbstractSessionFactoryProcessor {
|
|||
String password = context.getProperty(PASSWORD).evaluateAttributeExpressions().getValue();
|
||||
String bindAddress = context.getProperty(BIND_ADDRESS).evaluateAttributeExpressions().getValue();
|
||||
int port = context.getProperty(PORT).evaluateAttributeExpressions().asInteger();
|
||||
SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
|
||||
try {
|
||||
sessionFactorySetSignal = new CountDownLatch(1);
|
||||
|
@ -167,7 +167,7 @@ public class ListenFTP extends AbstractSessionFactoryProcessor {
|
|||
.port(port)
|
||||
.username(username)
|
||||
.password(password)
|
||||
.sslContextService(sslContextService)
|
||||
.sslContextProvider(sslContextProvider)
|
||||
.build();
|
||||
ftpServer.start();
|
||||
} catch (ProcessException processException) {
|
||||
|
|
|
@ -52,8 +52,7 @@ import org.apache.nifi.scheduling.ExecutionNode;
|
|||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.serialization.RecordReaderFactory;
|
||||
import org.apache.nifi.serialization.RecordSetWriterFactory;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.stream.io.LeakyBucketStreamThrottler;
|
||||
import org.apache.nifi.stream.io.StreamThrottler;
|
||||
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
|
||||
|
@ -63,7 +62,12 @@ import org.eclipse.jetty.server.ServerConnector;
|
|||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -199,7 +203,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
.name("SSL Context Service")
|
||||
.description("SSL Context Service enables support for HTTPS")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor HTTP_PROTOCOL_STRATEGY = new PropertyDescriptor.Builder()
|
||||
.name("HTTP Protocols")
|
||||
|
@ -413,7 +417,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
}
|
||||
runOnPrimary.set(context.getExecutionNode().equals(ExecutionNode.PRIMARY));
|
||||
final String basePath = context.getProperty(BASE_PATH).evaluateAttributeExpressions().getValue();
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final Double maxBytesPerSecond = context.getProperty(MAX_DATA_RATE).asDataSize(DataUnit.B);
|
||||
final StreamThrottler streamThrottler = (maxBytesPerSecond == null) ? null : new LeakyBucketStreamThrottler(maxBytesPerSecond.intValue());
|
||||
final int returnCode = context.getProperty(RETURN_CODE).asInteger();
|
||||
|
@ -424,7 +428,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
throttlerRef.set(streamThrottler);
|
||||
|
||||
final PropertyValue clientAuthenticationProperty = context.getProperty(CLIENT_AUTHENTICATION);
|
||||
final ClientAuthentication clientAuthentication = getClientAuthentication(sslContextService, clientAuthenticationProperty);
|
||||
final ClientAuthentication clientAuthentication = getClientAuthentication(sslContextProvider, clientAuthenticationProperty);
|
||||
|
||||
// thread pool for the jetty instance
|
||||
final QueuedThreadPool threadPool = new QueuedThreadPool(maxThreadPoolSize);
|
||||
|
@ -439,7 +443,7 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
final ServerConnector connector = createServerConnector(server,
|
||||
port,
|
||||
requestHeaderSize,
|
||||
sslContextService,
|
||||
sslContextProvider,
|
||||
clientAuthentication,
|
||||
httpProtocolStrategy
|
||||
);
|
||||
|
@ -451,14 +455,14 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
final ServerConnector healthCheckConnector = createServerConnector(server,
|
||||
healthCheckPort,
|
||||
requestHeaderSize,
|
||||
sslContextService,
|
||||
sslContextProvider,
|
||||
ClientAuthentication.NONE,
|
||||
httpProtocolStrategy
|
||||
);
|
||||
server.addConnector(healthCheckConnector);
|
||||
}
|
||||
|
||||
final boolean securityEnabled = sslContextService != null;
|
||||
final boolean securityEnabled = sslContextProvider != null;
|
||||
final ServletContextHandler contextHandler = new ServletContextHandler("/", true, securityEnabled);
|
||||
for (final Class<? extends Servlet> cls : getServerClasses()) {
|
||||
final Path path = cls.getAnnotation(Path.class);
|
||||
|
@ -512,35 +516,57 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
|
|||
initialized.set(true);
|
||||
}
|
||||
|
||||
private ClientAuthentication getClientAuthentication(final SSLContextService sslContextService,
|
||||
private ClientAuthentication getClientAuthentication(final SSLContextProvider sslContextProvider,
|
||||
final PropertyValue clientAuthenticationProperty) {
|
||||
ClientAuthentication clientAuthentication = ClientAuthentication.NONE;
|
||||
if (clientAuthenticationProperty.isSet()) {
|
||||
clientAuthentication = ClientAuthentication.valueOf(clientAuthenticationProperty.getValue());
|
||||
final boolean trustStoreConfigured = sslContextService != null && sslContextService.isTrustStoreConfigured();
|
||||
|
||||
if (ClientAuthentication.AUTO.equals(clientAuthentication) && trustStoreConfigured) {
|
||||
clientAuthentication = ClientAuthentication.REQUIRED;
|
||||
getLogger().debug("Client Authentication REQUIRED from SSLContextService Trust Store configuration");
|
||||
if (ClientAuthentication.AUTO == clientAuthentication && sslContextProvider != null) {
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
if (isTrustManagerConfigured(trustManager)) {
|
||||
clientAuthentication = ClientAuthentication.REQUIRED;
|
||||
getLogger().debug("Client Authentication REQUIRED from SSLContextService Trust Manager configuration");
|
||||
}
|
||||
}
|
||||
}
|
||||
return clientAuthentication;
|
||||
}
|
||||
|
||||
private boolean isTrustManagerConfigured(final X509TrustManager configuredTrustManager) {
|
||||
boolean trustManagerConfigured = false;
|
||||
|
||||
try {
|
||||
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
final TrustManager trustManager = trustManagers[0];
|
||||
|
||||
if (trustManager instanceof X509TrustManager defaultTrustManager) {
|
||||
final X509Certificate[] defaultAcceptedIssuers = defaultTrustManager.getAcceptedIssuers();
|
||||
final X509Certificate[] acceptedIssuers = configuredTrustManager.getAcceptedIssuers();
|
||||
trustManagerConfigured = !Arrays.deepEquals(defaultAcceptedIssuers, acceptedIssuers);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
getLogger().warn("Loading default SSLContext for Client Authentication evaluation failed", e);
|
||||
}
|
||||
|
||||
return trustManagerConfigured;
|
||||
}
|
||||
|
||||
private ServerConnector createServerConnector(final Server server,
|
||||
final int port,
|
||||
final int requestMaxHeaderSize,
|
||||
final SSLContextService sslContextService,
|
||||
final SSLContextProvider sslContextProvider,
|
||||
final ClientAuthentication clientAuthentication,
|
||||
final HttpProtocolStrategy httpProtocolStrategy
|
||||
) {
|
||||
final StandardServerConnectorFactory serverConnectorFactory = new StandardServerConnectorFactory(server, port);
|
||||
serverConnectorFactory.setRequestHeaderSize(requestMaxHeaderSize);
|
||||
|
||||
final SSLContext sslContext = sslContextService == null ? null : sslContextService.createContext();
|
||||
final SSLContext sslContext = sslContextProvider == null ? null : sslContextProvider.createContext();
|
||||
serverConnectorFactory.setSslContext(sslContext);
|
||||
|
||||
final String[] enabledProtocols = sslContextService == null ? new String[0] : sslContextService.createTlsConfiguration().getEnabledProtocols();
|
||||
final String[] enabledProtocols = sslContext == null ? new String[0] : sslContext.getDefaultSSLParameters().getProtocols();
|
||||
serverConnectorFactory.setIncludeSecurityProtocols(enabledProtocols);
|
||||
|
||||
if (ClientAuthentication.REQUIRED == clientAuthentication) {
|
||||
|
|
|
@ -45,8 +45,7 @@ import org.apache.nifi.processor.Relationship;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.syslog.attributes.SyslogAttributes;
|
||||
import org.apache.nifi.syslog.events.SyslogEvent;
|
||||
import org.apache.nifi.syslog.parsers.SyslogParser;
|
||||
|
@ -170,7 +169,7 @@ public class ListenSyslog extends AbstractSyslogProcessor {
|
|||
.description("The Controller Service to use in order to obtain an SSL Context. If this property is set, syslog " +
|
||||
"messages will be received over a secure connection.")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.dependsOn(PROTOCOL, TCP_VALUE)
|
||||
.build();
|
||||
public static final PropertyDescriptor CLIENT_AUTH = new PropertyDescriptor.Builder()
|
||||
|
@ -290,9 +289,9 @@ public class ListenSyslog extends AbstractSyslogProcessor {
|
|||
final Boolean socketKeepAlive = context.getProperty(SOCKET_KEEP_ALIVE).asBoolean();
|
||||
factory.setSocketKeepAlive(socketKeepAlive);
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null && TCP_VALUE.getValue().equals(protocol)) {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null && TCP_VALUE.getValue().equals(protocol)) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
ClientAuth clientAuth = ClientAuth.REQUIRED;
|
||||
final PropertyValue clientAuthProperty = context.getProperty(CLIENT_AUTH);
|
||||
if (clientAuthProperty.isSet()) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
*/
|
||||
package org.apache.nifi.processors.standard;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.nifi.annotation.behavior.InputRequirement;
|
||||
import org.apache.nifi.annotation.behavior.SupportsBatching;
|
||||
import org.apache.nifi.annotation.behavior.WritesAttribute;
|
||||
|
@ -26,8 +25,6 @@ import org.apache.nifi.annotation.documentation.Tags;
|
|||
import org.apache.nifi.annotation.lifecycle.OnScheduled;
|
||||
import org.apache.nifi.annotation.lifecycle.OnStopped;
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.components.ValidationContext;
|
||||
import org.apache.nifi.components.ValidationResult;
|
||||
import org.apache.nifi.event.transport.EventException;
|
||||
import org.apache.nifi.event.transport.EventServer;
|
||||
import org.apache.nifi.event.transport.SslSessionStatus;
|
||||
|
@ -51,8 +48,7 @@ import org.apache.nifi.processor.util.listen.ListenerProperties;
|
|||
import org.apache.nifi.processor.util.listen.queue.TrackingLinkedBlockingQueue;
|
||||
import org.apache.nifi.remote.io.socket.NetworkUtils;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.IOException;
|
||||
|
@ -60,8 +56,6 @@ import java.net.InetAddress;
|
|||
import java.nio.charset.Charset;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -102,15 +96,16 @@ public class ListenTCP extends AbstractProcessor {
|
|||
.description("The Controller Service to use in order to obtain an SSL Context. If this property is set, " +
|
||||
"messages will be received over a secure connection.")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor CLIENT_AUTH = new PropertyDescriptor.Builder()
|
||||
.name("Client Auth")
|
||||
.description("The client authentication policy to use for the SSL Context. Only used if an SSL Context Service is provided.")
|
||||
.required(false)
|
||||
.required(true)
|
||||
.allowableValues(ClientAuth.values())
|
||||
.defaultValue(ClientAuth.REQUIRED.name())
|
||||
.dependsOn(SSL_CONTEXT_SERVICE)
|
||||
.build();
|
||||
|
||||
protected static final PropertyDescriptor POOL_RECV_BUFFERS = new PropertyDescriptor.Builder()
|
||||
|
@ -188,11 +183,11 @@ public class ListenTCP extends AbstractProcessor {
|
|||
messageDemarcatorBytes = msgDemarcator.getBytes(charset);
|
||||
final NettyEventServerFactory eventFactory = new ByteArrayMessageNettyEventServerFactory(getLogger(), address, port, TransportProtocol.TCP, messageDemarcatorBytes, bufferSize, events);
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslContextService != null) {
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final String clientAuthValue = context.getProperty(CLIENT_AUTH).getValue();
|
||||
ClientAuth clientAuth = ClientAuth.valueOf(clientAuthValue);
|
||||
SSLContext sslContext = sslContextService.createContext();
|
||||
SSLContext sslContext = sslContextProvider.createContext();
|
||||
eventFactory.setSslContext(sslContext);
|
||||
eventFactory.setClientAuth(clientAuth);
|
||||
}
|
||||
|
@ -256,22 +251,6 @@ public class ListenTCP extends AbstractProcessor {
|
|||
eventBatcher = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<ValidationResult> customValidate(final ValidationContext validationContext) {
|
||||
final List<ValidationResult> results = new ArrayList<>();
|
||||
|
||||
final String clientAuth = validationContext.getProperty(CLIENT_AUTH).getValue();
|
||||
final SSLContextService sslContextService = validationContext.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
|
||||
if (sslContextService != null && StringUtils.isBlank(clientAuth)) {
|
||||
results.add(new ValidationResult.Builder()
|
||||
.explanation("Client Auth must be provided when using TLS/SSL")
|
||||
.valid(false).subject("Client Auth").build());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
protected Map<String, String> getAttributes(final FlowFileEventBatch<ByteArrayMessage> batch) {
|
||||
final List<ByteArrayMessage> events = batch.getEvents();
|
||||
final String sender = events.getFirst().getSender();
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.apache.nifi.processor.ProcessSession;
|
|||
import org.apache.nifi.processor.Relationship;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.syslog.parsers.SyslogParser;
|
||||
import org.apache.nifi.util.StopWatch;
|
||||
|
||||
|
@ -145,7 +145,7 @@ public class PutSyslog extends AbstractSyslogProcessor {
|
|||
.description("The Controller Service to use in order to obtain an SSL Context. If this property is set, syslog " +
|
||||
"messages will be sent over a secure connection.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.dependsOn(PROTOCOL, TCP_VALUE)
|
||||
.build();
|
||||
|
||||
|
@ -203,12 +203,12 @@ public class PutSyslog extends AbstractSyslogProcessor {
|
|||
final Collection<ValidationResult> results = new ArrayList<>();
|
||||
|
||||
final String protocol = context.getProperty(PROTOCOL).getValue();
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
|
||||
if (UDP_VALUE.getValue().equals(protocol) && sslContextService != null) {
|
||||
if (UDP_VALUE.getValue().equals(protocol) && sslContextServiceProperty.isSet()) {
|
||||
results.add(new ValidationResult.Builder()
|
||||
.explanation("SSL can not be used with UDP")
|
||||
.valid(false).subject("SSL Context").build());
|
||||
.valid(false).subject(SSL_CONTEXT_SERVICE.getDisplayName()).build());
|
||||
}
|
||||
|
||||
return results;
|
||||
|
@ -279,8 +279,8 @@ public class PutSyslog extends AbstractSyslogProcessor {
|
|||
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
if (sslContextServiceProperty.isSet()) {
|
||||
final SSLContextService sslContextService = sslContextServiceProperty.asControllerService(SSLContextService.class);
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContextProvider sslContextProvider = sslContextServiceProperty.asControllerService(SSLContextProvider.class);
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
factory.setSslContext(sslContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ import org.apache.ftpserver.ftplet.FileSystemFactory;
|
|||
import org.apache.ftpserver.ftplet.User;
|
||||
import org.apache.ftpserver.listener.Listener;
|
||||
import org.apache.ftpserver.listener.ListenerFactory;
|
||||
import org.apache.ftpserver.ssl.ClientAuth;
|
||||
import org.apache.ftpserver.ssl.SslConfiguration;
|
||||
import org.apache.ftpserver.ssl.SslConfigurationFactory;
|
||||
import org.apache.ftpserver.usermanager.impl.BaseUser;
|
||||
import org.apache.ftpserver.usermanager.impl.WritePermission;
|
||||
import org.apache.nifi.processor.ProcessSessionFactory;
|
||||
|
@ -40,9 +40,11 @@ import org.apache.nifi.processor.Relationship;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processors.standard.ftp.commands.CommandMapFactory;
|
||||
import org.apache.nifi.processors.standard.ftp.filesystem.VirtualFileSystemFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.File;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
@ -105,7 +107,7 @@ public class NifiFtpServer implements org.apache.nifi.processors.standard.ftp.Ft
|
|||
private int port;
|
||||
private String username;
|
||||
private String password;
|
||||
private SSLContextService sslContextService;
|
||||
private SSLContextProvider sslContextProvider;
|
||||
|
||||
public Builder sessionFactory(AtomicReference<ProcessSessionFactory> sessionFactory) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
|
@ -146,8 +148,8 @@ public class NifiFtpServer implements org.apache.nifi.processors.standard.ftp.Ft
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder sslContextService(SSLContextService sslContextService) {
|
||||
this.sslContextService = sslContextService;
|
||||
public Builder sslContextProvider(SSLContextProvider sslContextProvider) {
|
||||
this.sslContextProvider = sslContextProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -159,7 +161,7 @@ public class NifiFtpServer implements org.apache.nifi.processors.standard.ftp.Ft
|
|||
CommandMapFactory commandMapFactory = new CommandMapFactory(sessionFactory, sessionFactorySetSignal, relationshipSuccess);
|
||||
Map<String, Command> commandMap = commandMapFactory.createCommandMap();
|
||||
ConnectionConfig connectionConfig = createConnectionConfig(anonymousLoginEnabled);
|
||||
Listener listener = createListener(bindAddress, port, sslContextService);
|
||||
Listener listener = createListener(bindAddress, port, sslContextProvider);
|
||||
User user = createUser(username, password, HOME_DIRECTORY);
|
||||
|
||||
return new NifiFtpServer(commandMap, fileSystemFactory, connectionConfig, listener, user);
|
||||
|
@ -174,26 +176,13 @@ public class NifiFtpServer implements org.apache.nifi.processors.standard.ftp.Ft
|
|||
return connectionConfigFactory.createConnectionConfig();
|
||||
}
|
||||
|
||||
private Listener createListener(String bindAddress, int port, SSLContextService sslContextService) throws FtpServerConfigurationException {
|
||||
private Listener createListener(String bindAddress, int port, SSLContextProvider sslContextProvider) throws FtpServerConfigurationException {
|
||||
ListenerFactory listenerFactory = new ListenerFactory();
|
||||
listenerFactory.setServerAddress(bindAddress);
|
||||
listenerFactory.setPort(port);
|
||||
if (sslContextService != null) {
|
||||
SslConfigurationFactory ssl = new SslConfigurationFactory();
|
||||
ssl.setKeystoreFile(new File(sslContextService.getKeyStoreFile()));
|
||||
ssl.setKeystorePassword(sslContextService.getKeyStorePassword());
|
||||
ssl.setKeyPassword(sslContextService.getKeyPassword());
|
||||
ssl.setKeystoreType(sslContextService.getKeyStoreType());
|
||||
ssl.setSslProtocol(sslContextService.getSslAlgorithm());
|
||||
|
||||
if (sslContextService.getTrustStoreFile() != null) {
|
||||
ssl.setClientAuthentication("NEED");
|
||||
ssl.setTruststoreFile(new File(sslContextService.getTrustStoreFile()));
|
||||
ssl.setTruststorePassword(sslContextService.getTrustStorePassword());
|
||||
ssl.setTruststoreType(sslContextService.getTrustStoreType());
|
||||
}
|
||||
|
||||
SslConfiguration sslConfiguration = ssl.createSslConfiguration();
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
SslConfiguration sslConfiguration = new StandardSslConfiguration(sslContext);
|
||||
|
||||
// Set implicit security for the control socket
|
||||
listenerFactory.setSslConfiguration(sslConfiguration);
|
||||
|
@ -235,4 +224,45 @@ public class NifiFtpServer implements org.apache.nifi.processors.standard.ftp.Ft
|
|||
return user;
|
||||
}
|
||||
}
|
||||
|
||||
private static class StandardSslConfiguration implements SslConfiguration {
|
||||
private final SSLContext sslContext;
|
||||
|
||||
private final SSLParameters sslParameters;
|
||||
|
||||
private StandardSslConfiguration(final SSLContext sslContext) {
|
||||
this.sslContext = sslContext;
|
||||
this.sslParameters = sslContext.getDefaultSSLParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSocketFactory getSocketFactory() {
|
||||
return sslContext.getSocketFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext getSSLContext() {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext getSSLContext(String enabledProtocol) {
|
||||
return sslContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getEnabledCipherSuites() {
|
||||
return sslParameters.getCipherSuites();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getEnabledProtocols() {
|
||||
return sslParameters.getProtocols();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientAuth getClientAuth() {
|
||||
return ClientAuth.WANT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
|||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.LogMessage;
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
|
@ -1034,22 +1034,22 @@ public class InvokeHTTPTest {
|
|||
private void setSslContextConfiguration(final SSLContext clientSslContext) throws InitializationException {
|
||||
setMockWebServerSslSocketFactory();
|
||||
|
||||
final SSLContextService sslContextService = setSslContextService();
|
||||
when(sslContextService.createContext()).thenReturn(clientSslContext);
|
||||
when(sslContextService.createTrustManager()).thenReturn(trustManager);
|
||||
final SSLContextProvider sslContextProvider = setSslContextProvider();
|
||||
when(sslContextProvider.createContext()).thenReturn(clientSslContext);
|
||||
when(sslContextProvider.createTrustManager()).thenReturn(trustManager);
|
||||
}
|
||||
|
||||
private SSLContextService setSslContextService() throws InitializationException {
|
||||
final String serviceIdentifier = SSLContextService.class.getName();
|
||||
final SSLContextService sslContextService = mock(SSLContextService.class);
|
||||
when(sslContextService.getIdentifier()).thenReturn(serviceIdentifier);
|
||||
private SSLContextProvider setSslContextProvider() throws InitializationException {
|
||||
final String serviceIdentifier = SSLContextProvider.class.getName();
|
||||
final SSLContextProvider sslContextProvider = mock(SSLContextProvider.class);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn(serviceIdentifier);
|
||||
|
||||
runner.addControllerService(serviceIdentifier, sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
runner.addControllerService(serviceIdentifier, sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
runner.setProperty(InvokeHTTP.SSL_CONTEXT_SERVICE, serviceIdentifier);
|
||||
runner.setProperty(InvokeHTTP.SOCKET_READ_TIMEOUT, TLS_CONNECTION_TIMEOUT);
|
||||
runner.setProperty(InvokeHTTP.SOCKET_CONNECT_TIMEOUT, TLS_CONNECTION_TIMEOUT);
|
||||
return sslContextService;
|
||||
return sslContextProvider;
|
||||
}
|
||||
|
||||
private void setMockWebServerSslSocketFactory() {
|
||||
|
|
|
@ -32,13 +32,11 @@ import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
|||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.security.util.TlsConfiguration;
|
||||
import org.apache.nifi.security.util.TlsPlatform;
|
||||
import org.apache.nifi.serialization.record.MockRecordParser;
|
||||
import org.apache.nifi.serialization.record.MockRecordWriter;
|
||||
import org.apache.nifi.serialization.record.RecordFieldType;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
|
@ -54,6 +52,8 @@ import javax.net.ssl.SSLContext;
|
|||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
|
@ -118,6 +118,7 @@ public class TestListenHTTP {
|
|||
private static SSLContext keyStoreSslContext;
|
||||
private static SSLContext trustStoreSslContext;
|
||||
private static X509TrustManager trustManager;
|
||||
private static X509TrustManager defaultTrustManager;
|
||||
|
||||
private ListenHTTP proc;
|
||||
private TestRunner runner;
|
||||
|
@ -130,7 +131,6 @@ public class TestListenHTTP {
|
|||
.addPrivateKeyEntry(new KeyStore.PrivateKeyEntry(keyPair.getPrivate(), new Certificate[]{certificate}))
|
||||
.build();
|
||||
final char[] protectionParameter = new char[]{};
|
||||
|
||||
trustManager = new StandardTrustManagerBuilder().trustStore(keyStore).build();
|
||||
serverKeyStoreNoTrustStoreSslContext = new StandardSslContextBuilder()
|
||||
.keyStore(keyStore)
|
||||
|
@ -145,6 +145,11 @@ public class TestListenHTTP {
|
|||
trustStoreSslContext = new StandardSslContextBuilder()
|
||||
.trustStore(keyStore)
|
||||
.build();
|
||||
|
||||
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
defaultTrustManager = (X509TrustManager) trustManagers[0];
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
|
@ -624,24 +629,22 @@ public class TestListenHTTP {
|
|||
}
|
||||
|
||||
private void configureProcessorSslContextService(final ListenHTTP.ClientAuthentication clientAuthentication) throws InitializationException {
|
||||
final RestrictedSSLContextService sslContextService = mock(RestrictedSSLContextService.class);
|
||||
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_IDENTIFIER);
|
||||
|
||||
final TlsConfiguration tlsConfiguration = mock(TlsConfiguration.class);
|
||||
when(tlsConfiguration.getEnabledProtocols()).thenReturn(TlsPlatform.getPreferredProtocols().toArray(new String[0]));
|
||||
when(sslContextService.createTlsConfiguration()).thenReturn(tlsConfiguration);
|
||||
final SSLContextProvider sslContextProvider = mock(SSLContextProvider.class);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_IDENTIFIER);
|
||||
|
||||
if (ListenHTTP.ClientAuthentication.REQUIRED.equals(clientAuthentication)) {
|
||||
when(sslContextService.createContext()).thenReturn(keyStoreSslContext);
|
||||
when(sslContextProvider.createContext()).thenReturn(keyStoreSslContext);
|
||||
when(sslContextProvider.createTrustManager()).thenReturn(trustManager);
|
||||
} else {
|
||||
when(sslContextService.createContext()).thenReturn(serverKeyStoreNoTrustStoreSslContext);
|
||||
when(sslContextProvider.createContext()).thenReturn(serverKeyStoreNoTrustStoreSslContext);
|
||||
when(sslContextProvider.createTrustManager()).thenReturn(defaultTrustManager);
|
||||
}
|
||||
runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextService);
|
||||
runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextProvider);
|
||||
|
||||
runner.setProperty(ListenHTTP.CLIENT_AUTHENTICATION, clientAuthentication.name());
|
||||
runner.setProperty(ListenHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_IDENTIFIER);
|
||||
|
||||
runner.enableControllerService(sslContextService);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -650,8 +653,8 @@ public class TestListenHTTP {
|
|||
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_OK));
|
||||
runner.setProperty(ListenHTTP.MULTIPART_READ_BUFFER_SIZE, "10 b");
|
||||
|
||||
final SSLContextService sslContextService = runner.getControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, SSLContextService.class);
|
||||
final boolean isSecure = (sslContextService != null);
|
||||
final SSLContextProvider sslContextProvider = runner.getControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, SSLContextProvider.class);
|
||||
final boolean isSecure = (sslContextProvider != null);
|
||||
final int port = startWebServer();
|
||||
|
||||
final File file1 = createTextFile("Hello", "World");
|
||||
|
|
|
@ -28,8 +28,7 @@ import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
|||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.util.ClientAuth;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
|
@ -53,7 +52,7 @@ import java.util.List;
|
|||
public class TestListenTCP {
|
||||
private static final String CLIENT_CERTIFICATE_SUBJECT_DN_ATTRIBUTE = "client.certificate.subject.dn";
|
||||
private static final String CLIENT_CERTIFICATE_ISSUER_DN_ATTRIBUTE = "client.certificate.issuer.dn";
|
||||
private static final String SSL_CONTEXT_IDENTIFIER = SSLContextService.class.getName();
|
||||
private static final String SSL_CONTEXT_IDENTIFIER = SSLContextProvider.class.getName();
|
||||
|
||||
private static final String LOCALHOST = "localhost";
|
||||
private static final Duration SENDER_TIMEOUT = Duration.ofSeconds(10);
|
||||
|
@ -202,11 +201,11 @@ public class TestListenTCP {
|
|||
}
|
||||
|
||||
private void enableSslContextService(final SSLContext sslContext) throws InitializationException {
|
||||
final RestrictedSSLContextService sslContextService = Mockito.mock(RestrictedSSLContextService.class);
|
||||
Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER);
|
||||
Mockito.when(sslContextService.createContext()).thenReturn(sslContext);
|
||||
runner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
final SSLContextProvider sslContextProvider = Mockito.mock(SSLContextProvider.class);
|
||||
Mockito.when(sslContextProvider.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER);
|
||||
Mockito.when(sslContextProvider.createContext()).thenReturn(sslContext);
|
||||
runner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
runner.setProperty(ListenTCP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ import org.apache.nifi.serialization.RecordSetWriterFactory;
|
|||
import org.apache.nifi.serialization.WriteResult;
|
||||
import org.apache.nifi.serialization.record.Record;
|
||||
import org.apache.nifi.serialization.record.RecordSet;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
|
@ -146,12 +146,12 @@ public class TestPutTCP {
|
|||
@Test
|
||||
public void testRunSuccessSslContextService() throws Exception {
|
||||
final SSLContext sslContext = getSslContext();
|
||||
final String identifier = SSLContextService.class.getName();
|
||||
final SSLContextService sslContextService = Mockito.mock(SSLContextService.class);
|
||||
Mockito.when(sslContextService.getIdentifier()).thenReturn(identifier);
|
||||
Mockito.when(sslContextService.createContext()).thenReturn(sslContext);
|
||||
runner.addControllerService(identifier, sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
final String identifier = SSLContextProvider.class.getName();
|
||||
final SSLContextProvider sslContextProvider = Mockito.mock(SSLContextProvider.class);
|
||||
Mockito.when(sslContextProvider.getIdentifier()).thenReturn(identifier);
|
||||
Mockito.when(sslContextProvider.createContext()).thenReturn(sslContext);
|
||||
runner.addControllerService(identifier, sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
runner.setProperty(PutTCP.SSL_CONTEXT_SERVICE, identifier);
|
||||
createTestServer(sslContext, OUTGOING_MESSAGE_DELIMITER);
|
||||
configureProperties(TCP_SERVER_ADDRESS, OUTGOING_MESSAGE_DELIMITER, false);
|
||||
|
|
|
@ -24,7 +24,7 @@ import io.netty.util.concurrent.DefaultThreadFactory;
|
|||
import org.apache.nifi.distributed.cache.client.adapter.InboundAdapter;
|
||||
import org.apache.nifi.distributed.cache.client.adapter.OutboundAdapter;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -45,24 +45,24 @@ public class CacheClient {
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextService the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextProvider the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
*/
|
||||
protected CacheClient(final String hostname,
|
||||
final int port,
|
||||
final int timeoutMillis,
|
||||
final SSLContextService sslContextService,
|
||||
final SSLContextProvider sslContextProvider,
|
||||
final VersionNegotiatorFactory factory,
|
||||
final String identifier) {
|
||||
final String poolName = String.format("%s[%s]", getClass().getSimpleName(), identifier);
|
||||
this.eventLoopGroup = new NioEventLoopGroup(new DefaultThreadFactory(poolName, DAEMON_THREAD_ENABLED));
|
||||
this.channelPool = new CacheClientChannelPoolFactory().createChannelPool(
|
||||
hostname, port, timeoutMillis, sslContextService, factory, eventLoopGroup);
|
||||
hostname, port, timeoutMillis, sslContextProvider, factory, eventLoopGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ import io.netty.channel.pool.FixedChannelPool;
|
|||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import org.apache.nifi.event.transport.netty.channel.pool.InitializingChannelPoolHandler;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.time.Duration;
|
||||
|
@ -53,22 +53,22 @@ class CacheClientChannelPoolFactory {
|
|||
/**
|
||||
* Instantiate a new netty pool of channels to be used for distributed cache communications
|
||||
*
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextService the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param eventLoopGroup Netty Event Loop Group providing threads for managing connections
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextProvider the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param eventLoopGroup Netty Event Loop Group providing threads for managing connections
|
||||
* @return a channel pool object from which {@link Channel} objects may be obtained
|
||||
*/
|
||||
public ChannelPool createChannelPool(final String hostname,
|
||||
final int port,
|
||||
final int timeoutMillis,
|
||||
final SSLContextService sslContextService,
|
||||
final SSLContextProvider sslContextProvider,
|
||||
final VersionNegotiatorFactory factory,
|
||||
final EventLoopGroup eventLoopGroup) {
|
||||
final SSLContext sslContext = (sslContextService == null) ? null : sslContextService.createContext();
|
||||
final SSLContext sslContext = (sslContextProvider == null) ? null : sslContextProvider.createContext();
|
||||
final Bootstrap bootstrap = new Bootstrap();
|
||||
final CacheClientChannelInitializer initializer = new CacheClientChannelInitializer(sslContext, factory, Duration.ofMillis(timeoutMillis), Duration.ofMillis(timeoutMillis));
|
||||
bootstrap.group(eventLoopGroup)
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.apache.nifi.distributed.cache.protocol.ProtocolVersion;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.remote.StandardVersionNegotiatorFactory;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -71,7 +71,7 @@ public class MapCacheClientService extends AbstractControllerService implements
|
|||
.description("If specified, indicates the SSL Context Service that is used to communicate with the "
|
||||
+ "remote server. If not specified, communications will not be encrypted")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor COMMUNICATIONS_TIMEOUT = new PropertyDescriptor.Builder()
|
||||
.name("Communications Timeout")
|
||||
|
@ -108,7 +108,7 @@ public class MapCacheClientService extends AbstractControllerService implements
|
|||
context.getProperty(HOSTNAME).getValue(),
|
||||
context.getProperty(PORT).asInteger(),
|
||||
context.getProperty(COMMUNICATIONS_TIMEOUT).asTimePeriod(TimeUnit.MILLISECONDS).intValue(),
|
||||
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class),
|
||||
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class),
|
||||
versionNegotiatorFactory,
|
||||
this.getIdentifier(),
|
||||
getLogger());
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.nifi.distributed.cache.operations.MapOperation;
|
|||
import org.apache.nifi.distributed.cache.protocol.ProtocolVersion;
|
||||
import org.apache.nifi.logging.ComponentLog;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
@ -45,25 +45,25 @@ public class NettyMapCacheClient extends CacheClient {
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextService the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
* @param log Component Log from instantiating Services
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextProvider the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
* @param log Component Log from instantiating Services
|
||||
*/
|
||||
public NettyMapCacheClient(
|
||||
final String hostname,
|
||||
final int port,
|
||||
final int timeoutMillis,
|
||||
final SSLContextService sslContextService,
|
||||
final SSLContextProvider sslContextProvider,
|
||||
final VersionNegotiatorFactory factory,
|
||||
final String identifier,
|
||||
final ComponentLog log
|
||||
) {
|
||||
super(hostname, port, timeoutMillis, sslContextService, factory, identifier);
|
||||
super(hostname, port, timeoutMillis, sslContextProvider, factory, identifier);
|
||||
this.log = Objects.requireNonNull(log, "Component Log required");
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import org.apache.nifi.distributed.cache.client.adapter.OutboundAdapter;
|
|||
import org.apache.nifi.distributed.cache.client.adapter.VoidInboundAdapter;
|
||||
import org.apache.nifi.distributed.cache.operations.SetOperation;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -34,23 +34,23 @@ public class NettySetCacheClient extends CacheClient {
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextService the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
* @param hostname the network name / IP address of the server running the distributed cache service
|
||||
* @param port the port on which the distributed cache service is running
|
||||
* @param timeoutMillis the network timeout associated with requests to the service
|
||||
* @param sslContextProvider the SSL context (if any) associated with requests to the service; if not specified,
|
||||
* communications will not be encrypted
|
||||
* @param factory creator of object used to broker the version of the distributed cache protocol with the service
|
||||
* @param identifier uniquely identifies this client
|
||||
*/
|
||||
public NettySetCacheClient(
|
||||
final String hostname,
|
||||
final int port,
|
||||
final int timeoutMillis,
|
||||
final SSLContextService sslContextService,
|
||||
final SSLContextProvider sslContextProvider,
|
||||
final VersionNegotiatorFactory factory,
|
||||
final String identifier
|
||||
) {
|
||||
super(hostname, port, timeoutMillis, sslContextService, factory, identifier);
|
||||
super(hostname, port, timeoutMillis, sslContextProvider, factory, identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.apache.nifi.distributed.cache.protocol.ProtocolVersion;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.remote.StandardVersionNegotiatorFactory;
|
||||
import org.apache.nifi.remote.VersionNegotiatorFactory;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -60,7 +60,7 @@ public class SetCacheClientService extends AbstractControllerService implements
|
|||
.description("If specified, indicates the SSL Context Service that is used to communicate with the "
|
||||
+ "remote server. If not specified, communications will not be encrypted")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor COMMUNICATIONS_TIMEOUT = new PropertyDescriptor.Builder()
|
||||
.name("Communications Timeout")
|
||||
|
@ -96,7 +96,7 @@ public class SetCacheClientService extends AbstractControllerService implements
|
|||
context.getProperty(HOSTNAME).getValue(),
|
||||
context.getProperty(PORT).asInteger(),
|
||||
context.getProperty(COMMUNICATIONS_TIMEOUT).asTimePeriod(TimeUnit.MILLISECONDS).intValue(),
|
||||
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class),
|
||||
context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class),
|
||||
versionNegotiatorFactory,
|
||||
this.getIdentifier());
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.nifi.components.PropertyDescriptor;
|
|||
import org.apache.nifi.controller.AbstractControllerService;
|
||||
import org.apache.nifi.controller.ConfigurationContext;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
public abstract class AbstractCacheServer extends AbstractControllerService {
|
||||
|
||||
|
@ -47,7 +47,7 @@ public abstract class AbstractCacheServer extends AbstractControllerService {
|
|||
.description("If specified, this service will be used to create an SSL Context that will be used "
|
||||
+ "to secure communications; if not specified, communications will not be secure")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
public static final PropertyDescriptor MAX_CACHE_ENTRIES = new PropertyDescriptor.Builder()
|
||||
.name("Maximum Cache Entries")
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.apache.nifi.annotation.documentation.Tags;
|
|||
import org.apache.nifi.controller.ConfigurationContext;
|
||||
import org.apache.nifi.distributed.cache.server.set.StandardSetCacheServer;
|
||||
import org.apache.nifi.processor.DataUnit;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
@Tags({"distributed", "set", "distinct", "cache", "server"})
|
||||
@CapabilityDescription("Provides a set (collection of unique values) cache that can be accessed over a socket. "
|
||||
|
@ -34,12 +34,12 @@ public class SetCacheServer extends AbstractCacheServer {
|
|||
protected CacheServer createCacheServer(final ConfigurationContext context) {
|
||||
final int port = context.getProperty(PORT).asInteger();
|
||||
final String persistencePath = context.getProperty(PERSISTENCE_PATH).getValue();
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final int maxSize = context.getProperty(MAX_CACHE_ENTRIES).asInteger();
|
||||
final String evictionPolicyName = context.getProperty(EVICTION_POLICY).getValue();
|
||||
final int maxReadSize = context.getProperty(MAX_READ_SIZE).asDataSize(DataUnit.B).intValue();
|
||||
|
||||
final SSLContext sslContext = sslContextService == null ? null : sslContextService.createContext();
|
||||
final SSLContext sslContext = sslContextProvider == null ? null : sslContextProvider.createContext();
|
||||
|
||||
final EvictionPolicy evictionPolicy;
|
||||
switch (evictionPolicyName) {
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.apache.nifi.distributed.cache.server.CacheServer;
|
|||
import org.apache.nifi.distributed.cache.server.AbstractCacheServer;
|
||||
import org.apache.nifi.distributed.cache.server.EvictionPolicy;
|
||||
import org.apache.nifi.processor.DataUnit;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
@Tags({"distributed", "cluster", "map", "cache", "server", "key/value"})
|
||||
@CapabilityDescription("Provides a map (key/value) cache that can be accessed over a socket. Interaction with this service"
|
||||
|
@ -39,16 +39,16 @@ public class MapCacheServer extends AbstractCacheServer {
|
|||
protected CacheServer createCacheServer(final ConfigurationContext context) {
|
||||
final int port = context.getProperty(PORT).asInteger();
|
||||
final String persistencePath = context.getProperty(PERSISTENCE_PATH).getValue();
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
final int maxSize = context.getProperty(MAX_CACHE_ENTRIES).asInteger();
|
||||
final String evictionPolicyName = context.getProperty(EVICTION_POLICY).getValue();
|
||||
final int maxReadSize = context.getProperty(MAX_READ_SIZE).asDataSize(DataUnit.B).intValue();
|
||||
|
||||
final SSLContext sslContext;
|
||||
if (sslContextService == null) {
|
||||
if (sslContextProvider == null) {
|
||||
sslContext = null;
|
||||
} else {
|
||||
sslContext = sslContextService.createContext();
|
||||
sslContext = sslContextProvider.createContext();
|
||||
}
|
||||
|
||||
final EvictionPolicy evictionPolicy;
|
||||
|
|
|
@ -25,7 +25,7 @@ import org.apache.nifi.processor.Processor;
|
|||
import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
||||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
|
@ -54,7 +54,7 @@ import static org.mockito.Mockito.when;
|
|||
public class MapCacheServiceTlsTest {
|
||||
|
||||
private static TestRunner runner = null;
|
||||
private static SSLContextService sslContextService = null;
|
||||
private static SSLContextProvider sslContextProvider = null;
|
||||
private static MapCacheServer server = null;
|
||||
private static MapCacheClientService client = null;
|
||||
private static final Serializer<String> serializer = new StringSerializer();
|
||||
|
@ -63,14 +63,14 @@ public class MapCacheServiceTlsTest {
|
|||
@BeforeAll
|
||||
public static void setServices() throws Exception {
|
||||
runner = TestRunners.newTestRunner(Mockito.mock(Processor.class));
|
||||
sslContextService = createSslContextService();
|
||||
runner.addControllerService(sslContextService.getIdentifier(), sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
sslContextProvider = createSslContextService();
|
||||
runner.addControllerService(sslContextProvider.getIdentifier(), sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
|
||||
server = new MapCacheServer();
|
||||
runner.addControllerService(server.getClass().getName(), server);
|
||||
runner.setProperty(server, MapCacheServer.PORT, "0");
|
||||
runner.setProperty(server, MapCacheServer.SSL_CONTEXT_SERVICE, sslContextService.getIdentifier());
|
||||
runner.setProperty(server, MapCacheServer.SSL_CONTEXT_SERVICE, sslContextProvider.getIdentifier());
|
||||
runner.enableControllerService(server);
|
||||
final int listeningPort = server.getPort();
|
||||
|
||||
|
@ -78,7 +78,7 @@ public class MapCacheServiceTlsTest {
|
|||
runner.addControllerService(client.getClass().getName(), client);
|
||||
runner.setProperty(client, MapCacheClientService.HOSTNAME, "localhost");
|
||||
runner.setProperty(client, MapCacheClientService.PORT, String.valueOf(listeningPort));
|
||||
runner.setProperty(client, MapCacheClientService.SSL_CONTEXT_SERVICE, sslContextService.getIdentifier());
|
||||
runner.setProperty(client, MapCacheClientService.SSL_CONTEXT_SERVICE, sslContextProvider.getIdentifier());
|
||||
runner.enableControllerService(client);
|
||||
}
|
||||
|
||||
|
@ -90,8 +90,8 @@ public class MapCacheServiceTlsTest {
|
|||
runner.disableControllerService(server);
|
||||
runner.removeControllerService(server);
|
||||
|
||||
runner.disableControllerService(sslContextService);
|
||||
runner.removeControllerService(sslContextService);
|
||||
runner.disableControllerService(sslContextProvider);
|
||||
runner.removeControllerService(sslContextProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -106,7 +106,7 @@ public class MapCacheServiceTlsTest {
|
|||
assertFalse(client.containsKey(key, serializer));
|
||||
}
|
||||
|
||||
private static SSLContextService createSslContextService() throws NoSuchAlgorithmException {
|
||||
private static SSLContextProvider createSslContextService() throws NoSuchAlgorithmException {
|
||||
final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
final X509Certificate certificate = new StandardCertificateBuilder(keyPair, new X500Principal("CN=localhost"), Duration.ofHours(1)).build();
|
||||
final KeyStore keyStore = new EphemeralKeyStoreBuilder()
|
||||
|
@ -118,7 +118,7 @@ public class MapCacheServiceTlsTest {
|
|||
.keyPassword(new char[]{})
|
||||
.build();
|
||||
|
||||
final SSLContextService sslContextService = Mockito.mock(SSLContextService.class);
|
||||
final SSLContextProvider sslContextService = Mockito.mock(SSLContextProvider.class);
|
||||
when(sslContextService.getIdentifier()).thenReturn(sslContextService.getClass().getName());
|
||||
when(sslContextService.createContext()).thenReturn(sslContext);
|
||||
return sslContextService;
|
||||
|
|
|
@ -58,7 +58,7 @@ import org.apache.nifi.serialization.SimpleRecordSchema;
|
|||
import org.apache.nifi.serialization.record.MapRecord;
|
||||
import org.apache.nifi.serialization.record.Record;
|
||||
import org.apache.nifi.serialization.record.RecordSchema;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
@ -124,7 +124,7 @@ public class RestLookupService extends AbstractControllerService implements Reco
|
|||
.description("The SSL Context Service used to provide client certificate information for TLS/SSL "
|
||||
+ "connections.")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
public static final PropertyDescriptor AUTHENTICATION_STRATEGY = new PropertyDescriptor.Builder()
|
||||
|
@ -280,10 +280,10 @@ public class RestLookupService extends AbstractControllerService implements Reco
|
|||
}
|
||||
|
||||
// Apply the TLS configuration if present
|
||||
final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
|
||||
if (sslService != null) {
|
||||
final SSLContext sslContext = sslService.createContext();
|
||||
final X509TrustManager trustManager = sslService.createTrustManager();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ import org.apache.nifi.processor.exception.ProcessException;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxySpec;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
@ -195,7 +195,7 @@ public class StandardOauth2AccessTokenProvider extends AbstractControllerService
|
|||
.name("ssl-context-service")
|
||||
.displayName("SSL Context Service")
|
||||
.addValidator(Validator.VALID)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.required(false)
|
||||
.build();
|
||||
|
||||
|
@ -316,10 +316,10 @@ public class StandardOauth2AccessTokenProvider extends AbstractControllerService
|
|||
protected OkHttpClient createHttpClient(ConfigurationContext context) {
|
||||
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
|
||||
|
||||
SSLContextService sslService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
if (sslService != null) {
|
||||
final X509TrustManager trustManager = sslService.createTrustManager();
|
||||
SSLContext sslContext = sslService.createContext();
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider != null) {
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,8 @@ import org.apache.nifi.expression.ExpressionLanguageScope;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.reporting.InitializationException;
|
||||
import org.apache.nifi.security.ssl.BuilderConfigurationException;
|
||||
import org.apache.nifi.security.ssl.StandardKeyManagerBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
|
@ -44,6 +46,9 @@ import org.apache.nifi.util.StringUtils;
|
|||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
@ -55,11 +60,13 @@ import java.nio.file.Paths;
|
|||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@Tags({"ssl", "secure", "certificate", "keystore", "truststore", "jks", "p12", "pkcs12", "pkcs", "tls"})
|
||||
@CapabilityDescription("Standard implementation of the SSLContextService. Provides the ability to configure "
|
||||
|
@ -258,10 +265,34 @@ public class StandardSSLContextService extends AbstractControllerService impleme
|
|||
sslContextBuilder.trustManager(trustManager);
|
||||
}
|
||||
|
||||
final String keyStoreFile = getKeyStoreFile();
|
||||
if (keyStoreFile == null || keyStoreFile.isBlank()) {
|
||||
getLogger().debug("Key Store File not configured");
|
||||
} else {
|
||||
final Optional<X509ExtendedKeyManager> keyManagerFound = createKeyManager();
|
||||
if (keyManagerFound.isPresent()) {
|
||||
final X509ExtendedKeyManager keyManager = keyManagerFound.get();
|
||||
sslContextBuilder.keyManager(keyManager);
|
||||
}
|
||||
|
||||
return sslContextBuilder.build();
|
||||
} catch (final Exception e) {
|
||||
throw new ProcessException("Unable to create SSLContext", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and initialize an X.509 Key Manager when configured with key and certificate properties
|
||||
*
|
||||
* @return X.509 Extended Key Manager or empty when not configured
|
||||
*/
|
||||
@Override
|
||||
public Optional<X509ExtendedKeyManager> createKeyManager() {
|
||||
final Optional<X509ExtendedKeyManager> keyManager;
|
||||
|
||||
final String keyStoreFile = getKeyStoreFile();
|
||||
if (keyStoreFile == null || keyStoreFile.isBlank()) {
|
||||
keyManager = Optional.empty();
|
||||
} else {
|
||||
try {
|
||||
final StandardKeyManagerBuilder keyManagerBuilder = new StandardKeyManagerBuilder();
|
||||
|
||||
final StandardKeyStoreBuilder keyStoreBuilder = new StandardKeyStoreBuilder();
|
||||
keyStoreBuilder.type(getKeyStoreType());
|
||||
keyStoreBuilder.password(getKeyStorePassword().toCharArray());
|
||||
|
@ -270,7 +301,7 @@ public class StandardSSLContextService extends AbstractControllerService impleme
|
|||
try (InputStream keyStoreInputStream = Files.newInputStream(keyStorePath)) {
|
||||
keyStoreBuilder.inputStream(keyStoreInputStream);
|
||||
final KeyStore keyStore = keyStoreBuilder.build();
|
||||
sslContextBuilder.keyStore(keyStore);
|
||||
keyManagerBuilder.keyStore(keyStore);
|
||||
}
|
||||
|
||||
final char[] keyProtectionPassword;
|
||||
|
@ -280,13 +311,16 @@ public class StandardSSLContextService extends AbstractControllerService impleme
|
|||
} else {
|
||||
keyProtectionPassword = keyPassword.toCharArray();
|
||||
}
|
||||
sslContextBuilder.keyPassword(keyProtectionPassword);
|
||||
}
|
||||
keyManagerBuilder.keyPassword(keyProtectionPassword);
|
||||
|
||||
return sslContextBuilder.build();
|
||||
} catch (final Exception e) {
|
||||
throw new ProcessException("Unable to create SSLContext", e);
|
||||
final X509ExtendedKeyManager extendedKeyManager = keyManagerBuilder.build();
|
||||
keyManager = Optional.of(extendedKeyManager);
|
||||
} catch (final Exception e) {
|
||||
throw new ProcessException("Unable to create X.509 Key Manager", e);
|
||||
}
|
||||
}
|
||||
|
||||
return keyManager;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,27 +331,40 @@ public class StandardSSLContextService extends AbstractControllerService impleme
|
|||
@Override
|
||||
public X509TrustManager createTrustManager() {
|
||||
try {
|
||||
final char[] password;
|
||||
final String trustStorePassword = getTrustStorePassword();
|
||||
if (trustStorePassword == null || trustStorePassword.isBlank()) {
|
||||
password = null;
|
||||
} else {
|
||||
password = trustStorePassword.toCharArray();
|
||||
}
|
||||
|
||||
final StandardKeyStoreBuilder builder = new StandardKeyStoreBuilder().type(getTrustStoreType()).password(password);
|
||||
final X509TrustManager trustManager;
|
||||
|
||||
final String trustStoreFile = getTrustStoreFile();
|
||||
if (trustStoreFile == null || trustStoreFile.isBlank()) {
|
||||
throw new ProcessException("Trust Store File not specified");
|
||||
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
trustManagerFactory.init((KeyStore) null);
|
||||
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
|
||||
|
||||
final Optional<X509ExtendedTrustManager> configuredTrustManager = Arrays.stream(trustManagers)
|
||||
.filter(manager -> manager instanceof X509ExtendedTrustManager)
|
||||
.map(manager -> (X509ExtendedTrustManager) manager)
|
||||
.findFirst();
|
||||
|
||||
trustManager = configuredTrustManager.orElseThrow(() -> new BuilderConfigurationException("X.509 Trust Manager not found"));
|
||||
} else {
|
||||
final char[] password;
|
||||
final String trustStorePassword = getTrustStorePassword();
|
||||
if (trustStorePassword == null || trustStorePassword.isBlank()) {
|
||||
password = null;
|
||||
} else {
|
||||
password = trustStorePassword.toCharArray();
|
||||
}
|
||||
|
||||
final StandardKeyStoreBuilder builder = new StandardKeyStoreBuilder().type(getTrustStoreType()).password(password);
|
||||
|
||||
final Path trustStorePath = Paths.get(trustStoreFile);
|
||||
try (InputStream trustStoreInputStream = Files.newInputStream(trustStorePath)) {
|
||||
builder.inputStream(trustStoreInputStream);
|
||||
final KeyStore trustStore = builder.build();
|
||||
trustManager = new StandardTrustManagerBuilder().trustStore(trustStore).build();
|
||||
}
|
||||
}
|
||||
|
||||
final Path trustStorePath = Paths.get(trustStoreFile);
|
||||
try (InputStream trustStoreInputStream = Files.newInputStream(trustStorePath)) {
|
||||
builder.inputStream(trustStoreInputStream);
|
||||
final KeyStore trustStore = builder.build();
|
||||
return new StandardTrustManagerBuilder().trustStore(trustStore).build();
|
||||
}
|
||||
return trustManager;
|
||||
} catch (final Exception e) {
|
||||
throw new ProcessException("Unable to create X.509 Trust Manager", e);
|
||||
}
|
||||
|
|
|
@ -23,15 +23,19 @@ import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
|||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.util.MockProcessContext;
|
||||
import org.apache.nifi.util.MockValidationContext;
|
||||
import org.apache.nifi.util.NoOpProcessor;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
@ -47,6 +51,7 @@ import java.time.Duration;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -76,6 +81,10 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
private static Path trustStorePath;
|
||||
|
||||
private TestRunner runner;
|
||||
|
||||
private StandardSSLContextService service;
|
||||
|
||||
@BeforeAll
|
||||
public static void setConfiguration() throws Exception {
|
||||
final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
|
@ -97,19 +106,20 @@ public class StandardSSLContextServiceTest {
|
|||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void setRunner() {
|
||||
runner = TestRunners.newTestRunner(NoOpProcessor.class);
|
||||
service = new StandardSSLContextService();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotValidMissingProperties() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
|
||||
runner.addControllerService(SERVICE_ID, service, Map.of());
|
||||
runner.assertNotValid(service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotValidMissingKeyStoreType() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
properties.put(StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
|
@ -120,8 +130,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testNotValidMissingTrustStoreType() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
properties.put(StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
|
@ -134,8 +142,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testNotValidIncorrectPassword() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
runner.addControllerService(SERVICE_ID, service, properties);
|
||||
|
@ -152,8 +158,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testShouldFailToAddControllerServiceWithNonExistentFiles() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
properties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/DOES-NOT-EXIST.jks");
|
||||
|
@ -169,9 +173,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testCreateContext() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEY_STORE_PASS);
|
||||
|
@ -189,10 +190,70 @@ public class StandardSSLContextServiceTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCreateContextExpressionLanguageProperties() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
public void testCreateTrustManager() throws InitializationException {
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE.getName(), trustStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), TRUST_STORE_PASS);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_TYPE.getName(), keyStoreType);
|
||||
runner.enableControllerService(service);
|
||||
|
||||
runner.setProperty(SERVICE_PROPERTY, SERVICE_ID);
|
||||
runner.assertValid(service);
|
||||
|
||||
final X509TrustManager trustManager = service.createTrustManager();
|
||||
assertNotNull(trustManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateTrustManagerKeyStoreConfigured() throws InitializationException {
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEY_STORE_PASS);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_TYPE.getName(), keyStoreType);
|
||||
runner.enableControllerService(service);
|
||||
|
||||
runner.setProperty(SERVICE_PROPERTY, SERVICE_ID);
|
||||
runner.assertValid(service);
|
||||
|
||||
final X509TrustManager trustManager = service.createTrustManager();
|
||||
assertNotNull(trustManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateKeyManager() throws InitializationException {
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEY_STORE_PASS);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_TYPE.getName(), keyStoreType);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE.getName(), trustStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), TRUST_STORE_PASS);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_TYPE.getName(), keyStoreType);
|
||||
runner.enableControllerService(service);
|
||||
|
||||
runner.setProperty(SERVICE_PROPERTY, SERVICE_ID);
|
||||
runner.assertValid(service);
|
||||
|
||||
final Optional<X509ExtendedKeyManager> keyManagerFound = service.createKeyManager();
|
||||
assertTrue(keyManagerFound.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateKeyManagerKeyStoreNotConfigured() throws InitializationException {
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE.getName(), trustStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), TRUST_STORE_PASS);
|
||||
runner.setProperty(service, StandardSSLContextService.TRUSTSTORE_TYPE.getName(), keyStoreType);
|
||||
runner.enableControllerService(service);
|
||||
|
||||
runner.setProperty(SERVICE_PROPERTY, SERVICE_ID);
|
||||
runner.assertValid(service);
|
||||
|
||||
final Optional<X509ExtendedKeyManager> keyManagerFound = service.createKeyManager();
|
||||
assertTrue(keyManagerFound.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateContextExpressionLanguageProperties() throws InitializationException {
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setEnvironmentVariableValue("keystore", keyStorePath.toString());
|
||||
runner.setEnvironmentVariableValue("truststore", trustStorePath.toString());
|
||||
|
@ -213,9 +274,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testValidPropertiesChanged() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE.getName(), keyStorePath.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.KEY_PASSWORD.getName(), KEY_STORE_PASS);
|
||||
|
@ -249,8 +307,6 @@ public class StandardSSLContextServiceTest {
|
|||
Files.copy(keyStorePath, tempKeyStore, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.copy(trustStorePath, tempTrustStore, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
runner.addControllerService(SERVICE_ID, service);
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE.getName(), tempKeyStore.toString());
|
||||
runner.setProperty(service, StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEY_STORE_PASS);
|
||||
|
@ -283,8 +339,6 @@ public class StandardSSLContextServiceTest {
|
|||
|
||||
@Test
|
||||
public void testCreateContextTrustStoreWithoutKeyStore() throws InitializationException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class);
|
||||
final StandardSSLContextService service = new StandardSSLContextService();
|
||||
final Map<String, String> properties = new HashMap<>();
|
||||
|
||||
properties.put(StandardSSLContextService.TRUSTSTORE.getName(), trustStorePath.toString());
|
||||
|
@ -293,9 +347,6 @@ public class StandardSSLContextServiceTest {
|
|||
runner.addControllerService(SERVICE_ID, service, properties);
|
||||
runner.enableControllerService(service);
|
||||
|
||||
runner.setProperty(SERVICE_PROPERTY, SERVICE_ID);
|
||||
runner.assertValid();
|
||||
|
||||
final SSLContext sslContext = service.createContext();
|
||||
assertNotNull(sslContext);
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* 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.ssl;
|
||||
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.processor.AbstractProcessor;
|
||||
import org.apache.nifi.processor.ProcessContext;
|
||||
import org.apache.nifi.processor.ProcessSession;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TestProcessor extends AbstractProcessor {
|
||||
|
||||
@Override
|
||||
public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
|
||||
List<PropertyDescriptor> propDescs = new ArrayList<>();
|
||||
propDescs.add(new PropertyDescriptor.Builder()
|
||||
.name("SSL Context Svc ID")
|
||||
.description("ID of SSL Context Svc")
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.required(true)
|
||||
.build());
|
||||
return propDescs;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.ssl;
|
||||
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Controller Service abstraction for creating instances of javax.net.ssl.SSLContext without access to supporting configuration properties
|
||||
*/
|
||||
public interface SSLContextProvider extends ControllerService {
|
||||
/**
|
||||
* Create and initialize an SSLContext with keys and certificates based on configuration
|
||||
*
|
||||
* @return SSLContext initialized using configured properties
|
||||
*/
|
||||
SSLContext createContext();
|
||||
|
||||
/**
|
||||
* Create and initialize an X.509 Key Manager when configured with key and certificate properties
|
||||
*
|
||||
* @return X.509 Extended Key Manager or empty when not configured
|
||||
*/
|
||||
Optional<X509ExtendedKeyManager> createKeyManager();
|
||||
|
||||
/**
|
||||
* Create and initialize an X.509 Trust Manager with certificates
|
||||
*
|
||||
* @return X509ExtendedTrustManager initialized using configured certificates
|
||||
*/
|
||||
X509TrustManager createTrustManager();
|
||||
}
|
|
@ -16,40 +16,20 @@
|
|||
*/
|
||||
package org.apache.nifi.ssl;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.nifi.annotation.documentation.CapabilityDescription;
|
||||
import org.apache.nifi.annotation.documentation.Tags;
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
import org.apache.nifi.security.util.TlsConfiguration;
|
||||
|
||||
/**
|
||||
* Definition for SSLContextService.
|
||||
*
|
||||
* Controller Service extension of SSLContextProvider with additional methods for retrieving configuration property values
|
||||
*/
|
||||
@Tags({"ssl", "secure", "certificate", "keystore", "truststore", "jks", "p12", "pkcs12", "pkcs"})
|
||||
@CapabilityDescription("Provides the ability to configure keystore and/or truststore properties once and reuse "
|
||||
+ "that configuration throughout the application")
|
||||
public interface SSLContextService extends ControllerService {
|
||||
public interface SSLContextService extends SSLContextProvider {
|
||||
|
||||
TlsConfiguration createTlsConfiguration();
|
||||
|
||||
/**
|
||||
* Create and initialize {@link SSLContext} using configured properties. This method is preferred over deprecated
|
||||
* create methods due to not requiring a client authentication policy.
|
||||
*
|
||||
* @return {@link SSLContext} initialized using configured properties
|
||||
*/
|
||||
SSLContext createContext();
|
||||
|
||||
/**
|
||||
* Create X.509 Trust Manager using configured properties
|
||||
*
|
||||
* @return {@link X509TrustManager} initialized using configured properties
|
||||
*/
|
||||
X509TrustManager createTrustManager();
|
||||
|
||||
String getTrustStoreFile();
|
||||
|
||||
String getTrustStoreType();
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* 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.web.client.provider.service;
|
||||
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Provider abstraction for loading a Key Manager
|
||||
*/
|
||||
interface KeyManagerProvider {
|
||||
/**
|
||||
* Get X.509 Key Manager
|
||||
*
|
||||
* @param sslContextService SSL Context Service
|
||||
* @return X.509 Key Manager or empty when not configured
|
||||
*/
|
||||
Optional<X509KeyManager> getKeyManager(SSLContextService sslContextService);
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* 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.web.client.provider.service;
|
||||
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Standard implementation of Key Manager Provider
|
||||
*/
|
||||
class StandardKeyManagerProvider implements KeyManagerProvider {
|
||||
/**
|
||||
* Get X.509 Key Manager using SSL Context Service configuration properties
|
||||
*
|
||||
* @param sslContextService SSL Context Service
|
||||
* @return X.509 Key Manager or empty when not configured
|
||||
*/
|
||||
@Override
|
||||
public Optional<X509KeyManager> getKeyManager(final SSLContextService sslContextService) {
|
||||
final X509KeyManager keyManager;
|
||||
|
||||
if (sslContextService.isKeyStoreConfigured()) {
|
||||
final KeyManagerFactory keyManagerFactory = getKeyManagerFactory();
|
||||
final KeyStore keyStore = getKeyStore(sslContextService);
|
||||
final char[] keyPassword = getKeyPassword(sslContextService);
|
||||
try {
|
||||
keyManagerFactory.init(keyStore, keyPassword);
|
||||
} catch (final KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
|
||||
throw new IllegalStateException("Key Manager Factory initialization failed", e);
|
||||
}
|
||||
|
||||
final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
|
||||
final Optional<KeyManager> firstKeyManager = Arrays.stream(keyManagers).findFirst();
|
||||
final KeyManager configuredKeyManager = firstKeyManager.orElse(null);
|
||||
keyManager = configuredKeyManager instanceof X509KeyManager ? (X509KeyManager) configuredKeyManager : null;
|
||||
} else {
|
||||
keyManager = null;
|
||||
}
|
||||
|
||||
return Optional.ofNullable(keyManager);
|
||||
}
|
||||
|
||||
private KeyStore getKeyStore(final SSLContextService sslContextService) {
|
||||
final String keyStoreType = sslContextService.getKeyStoreType();
|
||||
final KeyStore keyStore = getKeyStore(keyStoreType);
|
||||
final char[] keyStorePassword = sslContextService.getKeyStorePassword().toCharArray();
|
||||
final String keyStoreFile = sslContextService.getKeyStoreFile();
|
||||
try {
|
||||
try (final InputStream inputStream = new FileInputStream(keyStoreFile)) {
|
||||
keyStore.load(inputStream, keyStorePassword);
|
||||
}
|
||||
return keyStore;
|
||||
} catch (final IOException e) {
|
||||
throw new IllegalStateException(String.format("Key Store File [%s] reading failed", keyStoreFile), e);
|
||||
} catch (final NoSuchAlgorithmException | CertificateException e) {
|
||||
throw new IllegalStateException(String.format("Key Store File [%s] loading failed", keyStoreFile), e);
|
||||
}
|
||||
}
|
||||
|
||||
private KeyStore getKeyStore(final String keyStoreType) {
|
||||
try {
|
||||
return KeyStore.getInstance(keyStoreType);
|
||||
} catch (final KeyStoreException e) {
|
||||
throw new IllegalStateException(String.format("Key Store Type [%s] creation failed", keyStoreType), e);
|
||||
}
|
||||
}
|
||||
|
||||
private char[] getKeyPassword(final SSLContextService sslContextService) {
|
||||
final String keyPassword = sslContextService.getKeyPassword();
|
||||
final String keyStorePassword = sslContextService.getKeyStorePassword();
|
||||
final String password = keyPassword == null ? keyStorePassword : keyPassword;
|
||||
return password.toCharArray();
|
||||
}
|
||||
|
||||
private KeyManagerFactory getKeyManagerFactory() {
|
||||
try {
|
||||
return KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
} catch (final NoSuchAlgorithmException e) {
|
||||
throw new IllegalArgumentException("Key Manager Factory creation failed", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ import org.apache.nifi.controller.ConfigurationContext;
|
|||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.proxy.ProxyConfiguration;
|
||||
import org.apache.nifi.proxy.ProxyConfigurationService;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.web.client.StandardHttpUriBuilder;
|
||||
import org.apache.nifi.web.client.api.HttpUriBuilder;
|
||||
import org.apache.nifi.web.client.proxy.ProxyContext;
|
||||
|
@ -37,6 +37,8 @@ import org.apache.nifi.web.client.ssl.TlsContext;
|
|||
import org.apache.nifi.web.client.api.WebClientService;
|
||||
import org.apache.nifi.web.client.provider.api.WebClientServiceProvider;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.net.Proxy;
|
||||
|
@ -45,6 +47,7 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.apache.nifi.proxy.ProxyConfigurationService.PROXY_CONFIGURATION_SERVICE;
|
||||
|
||||
|
@ -93,7 +96,7 @@ public class StandardWebClientServiceProvider extends AbstractControllerService
|
|||
.displayName("SSL Context Service")
|
||||
.description("SSL Context Service overrides system default TLS settings for HTTPS communication")
|
||||
.required(false)
|
||||
.identifiesControllerService(SSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
static final List<PropertyDescriptor> PROPERTY_DESCRIPTORS = Arrays.asList(
|
||||
|
@ -105,8 +108,6 @@ public class StandardWebClientServiceProvider extends AbstractControllerService
|
|||
PROXY_CONFIGURATION_SERVICE
|
||||
);
|
||||
|
||||
private static final KeyManagerProvider keyManagerProvider = new StandardKeyManagerProvider();
|
||||
|
||||
private StandardWebClientService webClientService;
|
||||
|
||||
@OnEnabled
|
||||
|
@ -128,8 +129,8 @@ public class StandardWebClientServiceProvider extends AbstractControllerService
|
|||
|
||||
final PropertyValue sslContextServiceProperty = context.getProperty(SSL_CONTEXT_SERVICE);
|
||||
if (sslContextServiceProperty.isSet()) {
|
||||
final SSLContextService sslContextService = sslContextServiceProperty.asControllerService(SSLContextService.class);
|
||||
final TlsContext tlsContext = getTlsContext(sslContextService);
|
||||
final SSLContextProvider sslContextProvider = sslContextServiceProperty.asControllerService(SSLContextProvider.class);
|
||||
final TlsContext tlsContext = getTlsContext(sslContextProvider);
|
||||
standardWebClientService.setTlsContext(tlsContext);
|
||||
}
|
||||
|
||||
|
@ -169,14 +170,15 @@ public class StandardWebClientServiceProvider extends AbstractControllerService
|
|||
return Duration.ofMillis(millis);
|
||||
}
|
||||
|
||||
private TlsContext getTlsContext(final SSLContextService sslContextService) {
|
||||
final X509TrustManager trustManager = sslContextService.createTrustManager();
|
||||
final Optional<X509KeyManager> keyManager = keyManagerProvider.getKeyManager(sslContextService);
|
||||
private TlsContext getTlsContext(final SSLContextProvider sslContextProvider) {
|
||||
final X509TrustManager trustManager = sslContextProvider.createTrustManager();
|
||||
final Optional<X509ExtendedKeyManager> keyManager = sslContextProvider.createKeyManager();
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
|
||||
return new TlsContext() {
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return sslContextService.getSslAlgorithm();
|
||||
return sslContext.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -186,7 +188,7 @@ public class StandardWebClientServiceProvider extends AbstractControllerService
|
|||
|
||||
@Override
|
||||
public Optional<X509KeyManager> getKeyManager() {
|
||||
return keyManager;
|
||||
return keyManager.map(Function.identity());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* 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.web.client.provider.service;
|
||||
|
||||
import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
||||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.KeyStore;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class StandardKeyManagerProviderTest {
|
||||
@TempDir
|
||||
static Path keyStoreDirectory;
|
||||
|
||||
static Path keyStorePath;
|
||||
|
||||
static String keyStoreType;
|
||||
|
||||
static String keyStorePass;
|
||||
|
||||
private static final String KEY_STORE_EXTENSION = ".p12";
|
||||
|
||||
@Mock
|
||||
SSLContextService sslContextService;
|
||||
|
||||
StandardKeyManagerProvider provider;
|
||||
|
||||
@BeforeAll
|
||||
static void setKeyStore() throws Exception {
|
||||
final KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
||||
final X509Certificate certificate = new StandardCertificateBuilder(keyPair, new X500Principal("CN=localhost"), Duration.ofHours(1)).build();
|
||||
final KeyStore keyStore = new EphemeralKeyStoreBuilder()
|
||||
.addPrivateKeyEntry(new KeyStore.PrivateKeyEntry(keyPair.getPrivate(), new Certificate[]{certificate}))
|
||||
.build();
|
||||
final char[] protectionParameter = new char[]{};
|
||||
|
||||
keyStorePath = Files.createTempFile(keyStoreDirectory, StandardKeyManagerProviderTest.class.getSimpleName(), KEY_STORE_EXTENSION);
|
||||
try (OutputStream outputStream = Files.newOutputStream(keyStorePath)) {
|
||||
keyStore.store(outputStream, protectionParameter);
|
||||
}
|
||||
|
||||
keyStoreType = keyStore.getType();
|
||||
keyStorePass = new String(protectionParameter);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setProvider() {
|
||||
provider = new StandardKeyManagerProvider();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetKeyManagerNotConfigured() {
|
||||
when(sslContextService.isKeyStoreConfigured()).thenReturn(false);
|
||||
|
||||
final Optional<X509KeyManager> keyManager = provider.getKeyManager(sslContextService);
|
||||
|
||||
assertFalse(keyManager.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetKeyManager() {
|
||||
when(sslContextService.isKeyStoreConfigured()).thenReturn(true);
|
||||
when(sslContextService.getKeyStoreType()).thenReturn(keyStoreType);
|
||||
when(sslContextService.getKeyStoreFile()).thenReturn(keyStorePath.toString());
|
||||
when(sslContextService.getKeyStorePassword()).thenReturn(keyStorePass);
|
||||
|
||||
final Optional<X509KeyManager> keyManager = provider.getKeyManager(sslContextService);
|
||||
|
||||
assertTrue(keyManager.isPresent());
|
||||
}
|
||||
}
|
|
@ -28,8 +28,7 @@ import org.apache.nifi.security.cert.builder.StandardCertificateBuilder;
|
|||
import org.apache.nifi.security.ssl.EphemeralKeyStoreBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardSslContextBuilder;
|
||||
import org.apache.nifi.security.ssl.StandardTrustManagerBuilder;
|
||||
import org.apache.nifi.security.util.TlsPlatform;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.NoOpProcessor;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
import org.apache.nifi.util.TestRunners;
|
||||
|
@ -68,7 +67,7 @@ import static org.mockito.Mockito.when;
|
|||
class StandardWebClientServiceProviderTest {
|
||||
private static final String SERVICE_ID = StandardWebClientServiceProvider.class.getSimpleName();
|
||||
|
||||
private static final String SSL_CONTEXT_SERVICE_ID = SSLContextService.class.getSimpleName();
|
||||
private static final String SSL_CONTEXT_SERVICE_ID = SSLContextProvider.class.getSimpleName();
|
||||
|
||||
private static final String PROXY_SERVICE_ID = ProxyConfigurationService.class.getSimpleName();
|
||||
|
||||
|
@ -101,7 +100,7 @@ class StandardWebClientServiceProviderTest {
|
|||
static X509TrustManager trustManager;
|
||||
|
||||
@Mock
|
||||
SSLContextService sslContextService;
|
||||
SSLContextProvider sslContextProvider;
|
||||
|
||||
@Mock
|
||||
ProxyConfigurationService proxyConfigurationService;
|
||||
|
@ -179,12 +178,12 @@ class StandardWebClientServiceProviderTest {
|
|||
|
||||
@Test
|
||||
void testGetWebServiceClientSslContextServiceConfiguredGetUri() throws InitializationException, InterruptedException {
|
||||
when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
|
||||
when(sslContextService.getSslAlgorithm()).thenReturn(TlsPlatform.getLatestProtocol());
|
||||
when(sslContextService.createTrustManager()).thenReturn(trustManager);
|
||||
when(sslContextProvider.getIdentifier()).thenReturn(SSL_CONTEXT_SERVICE_ID);
|
||||
when(sslContextProvider.createTrustManager()).thenReturn(trustManager);
|
||||
when(sslContextProvider.createContext()).thenReturn(sslContext);
|
||||
|
||||
runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextService);
|
||||
runner.enableControllerService(sslContextService);
|
||||
runner.addControllerService(SSL_CONTEXT_SERVICE_ID, sslContextProvider);
|
||||
runner.enableControllerService(sslContextProvider);
|
||||
|
||||
runner.setProperty(provider, StandardWebClientServiceProvider.SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_ID);
|
||||
runner.enableControllerService(provider);
|
||||
|
|
|
@ -19,7 +19,7 @@ package org.apache.nifi.websocket;
|
|||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.controller.ControllerService;
|
||||
import org.apache.nifi.processor.Processor;
|
||||
import org.apache.nifi.ssl.RestrictedSSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public interface WebSocketService extends ControllerService {
|
|||
.description("The SSL Context Service to use in order to secure the server. If specified, the server will accept only WSS requests; "
|
||||
+ "otherwise, the server will accept only WS requests")
|
||||
.required(false)
|
||||
.identifiesControllerService(RestrictedSSLContextService.class)
|
||||
.identifiesControllerService(SSLContextProvider.class)
|
||||
.build();
|
||||
|
||||
void registerProcessor(final String endpointId, final Processor processor) throws WebSocketConfigurationException;
|
||||
|
|
|
@ -30,7 +30,7 @@ import org.apache.nifi.logging.ComponentLog;
|
|||
import org.apache.nifi.processor.DataUnit;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.util.StringUtils;
|
||||
import org.apache.nifi.websocket.WebSocketClientService;
|
||||
import org.apache.nifi.websocket.WebSocketConfigurationException;
|
||||
|
@ -235,12 +235,12 @@ public class JettyWebSocketClient extends AbstractJettyWebSocketService implemen
|
|||
connectCount = configurationContext.getProperty(CONNECTION_ATTEMPT_COUNT).evaluateAttributeExpressions().asInteger();
|
||||
|
||||
final HttpClient httpClient;
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
if (sslContextService == null) {
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider == null) {
|
||||
httpClient = new HttpClient();
|
||||
} else {
|
||||
final SslContextFactory.Client sslContextFactory = new SslContextFactory.Client();
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
sslContextFactory.setSslContext(sslContext);
|
||||
final ClientConnector clientConnector = new ClientConnector();
|
||||
clientConnector.setSslContextFactory(sslContextFactory);
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.apache.nifi.expression.ExpressionLanguageScope;
|
|||
import org.apache.nifi.jetty.configuration.connector.StandardServerConnectorFactory;
|
||||
import org.apache.nifi.processor.DataUnit;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.ssl.SSLContextService;
|
||||
import org.apache.nifi.ssl.SSLContextProvider;
|
||||
import org.apache.nifi.websocket.WebSocketConfigurationException;
|
||||
import org.apache.nifi.websocket.WebSocketMessageRouter;
|
||||
import org.apache.nifi.websocket.WebSocketServerService;
|
||||
|
@ -328,11 +328,11 @@ public class JettyWebSocketServer extends AbstractJettyWebSocketService implemen
|
|||
final StandardServerConnectorFactory serverConnectorFactory = new StandardServerConnectorFactory(server, listenPort);
|
||||
final ServerConnector serverConnector;
|
||||
|
||||
final SSLContextService sslContextService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
|
||||
if (sslContextService == null) {
|
||||
final SSLContextProvider sslContextProvider = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextProvider.class);
|
||||
if (sslContextProvider == null) {
|
||||
serverConnector = serverConnectorFactory.getServerConnector();
|
||||
} else {
|
||||
final SSLContext sslContext = sslContextService.createContext();
|
||||
final SSLContext sslContext = sslContextProvider.createContext();
|
||||
serverConnectorFactory.setSslContext(sslContext);
|
||||
|
||||
final String clientAuthValue = context.getProperty(CLIENT_AUTH).getValue();
|
||||
|
|
Loading…
Reference in New Issue