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:
exceptionfactory 2024-11-15 16:44:03 -06:00 committed by Pierre Villard
parent aa3a7c05ad
commit d07b363fb0
No known key found for this signature in database
GPG Key ID: F92A93B30C07C6D5
63 changed files with 628 additions and 803 deletions

View File

@ -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) {

View File

@ -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");
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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();

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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")

View File

@ -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 {

View File

@ -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()));

View File

@ -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());

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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();

View File

@ -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());

View File

@ -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());

View File

@ -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);
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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()) {

View File

@ -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();

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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() {

View File

@ -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");

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
/**

View File

@ -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)

View File

@ -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());

View File

@ -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");
}

View File

@ -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);
}
/**

View File

@ -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());
}

View File

@ -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")

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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();
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -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());
}
};
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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();