This is an automated email from the ASF dual-hosted git repository.

exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 76f33e4  NIFI-7198: Adding optional SSL Context Service to 
RedisConnectionPoolService
76f33e4 is described below

commit 76f33e42c675fe9ed7fdf716e8609b0aad11520b
Author: Joe Gresock <[email protected]>
AuthorDate: Wed Apr 7 14:15:56 2021 -0400

    NIFI-7198: Adding optional SSL Context Service to RedisConnectionPoolService
    
    This closes #4981
    
    Signed-off-by: David Handermann <[email protected]>
---
 .../nifi-redis-extensions/pom.xml                  |  5 ++
 .../org/apache/nifi/redis/util/RedisUtils.java     | 28 +++++++-
 .../service/TestRedisConnectionPoolService.java    | 83 ++++++++++++++++++++++
 3 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/pom.xml 
b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/pom.xml
index 67ea977..3bfe231 100644
--- a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/pom.xml
+++ b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/pom.xml
@@ -78,5 +78,10 @@
             <version>0.6</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-ssl-context-service-api</artifactId>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/main/java/org/apache/nifi/redis/util/RedisUtils.java
 
b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/main/java/org/apache/nifi/redis/util/RedisUtils.java
index 6489fcc..1b5bab8 100644
--- 
a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/main/java/org/apache/nifi/redis/util/RedisUtils.java
+++ 
b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/main/java/org/apache/nifi/redis/util/RedisUtils.java
@@ -25,6 +25,8 @@ import org.apache.nifi.expression.ExpressionLanguageScope;
 import org.apache.nifi.logging.ComponentLog;
 import org.apache.nifi.processor.util.StandardValidators;
 import org.apache.nifi.redis.RedisType;
+import org.apache.nifi.ssl.RestrictedSSLContextService;
+import org.apache.nifi.ssl.SSLContextService;
 import org.apache.nifi.util.StringUtils;
 import org.springframework.data.redis.connection.RedisClusterConfiguration;
 import org.springframework.data.redis.connection.RedisConfiguration;
@@ -35,6 +37,7 @@ import 
org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
 import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
 import redis.clients.jedis.JedisPoolConfig;
 
+import javax.net.ssl.SSLContext;
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -234,6 +237,15 @@ public class RedisUtils {
             .required(true)
             .build();
 
+    public static final PropertyDescriptor SSL_CONTEXT_SERVICE = new 
PropertyDescriptor.Builder()
+            .name("SSL Context Service")
+            .displayName("SSL Context Service")
+            .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)
+            .build();
+
     public static final List<PropertyDescriptor> 
REDIS_CONNECTION_PROPERTY_DESCRIPTORS;
     static {
         final List<PropertyDescriptor> props = new ArrayList<>();
@@ -244,6 +256,7 @@ public class RedisUtils {
         props.add(RedisUtils.CLUSTER_MAX_REDIRECTS);
         props.add(RedisUtils.SENTINEL_MASTER);
         props.add(RedisUtils.PASSWORD);
+        props.add(RedisUtils.SSL_CONTEXT_SERVICE);
         props.add(RedisUtils.POOL_MAX_TOTAL);
         props.add(RedisUtils.POOL_MAX_IDLE);
         props.add(RedisUtils.POOL_MIN_IDLE);
@@ -268,12 +281,23 @@ public class RedisUtils {
         final Integer timeout = 
context.getProperty(RedisUtils.COMMUNICATION_TIMEOUT).asTimePeriod(TimeUnit.MILLISECONDS).intValue();
         final JedisPoolConfig poolConfig = createJedisPoolConfig(context);
 
-        final JedisClientConfiguration jedisClientConfiguration = 
JedisClientConfiguration.builder()
+        JedisClientConfiguration.JedisClientConfigurationBuilder builder = 
JedisClientConfiguration.builder()
                 .connectTimeout(Duration.ofMillis(timeout))
                 .readTimeout(Duration.ofMillis(timeout))
                 .usePooling()
                 .poolConfig(poolConfig)
-                .build();
+                .and();
+
+        if (context.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).isSet()) {
+            final SSLContextService sslContextService = 
context.getProperty(RedisUtils.SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class);
+            final SSLContext sslContext = sslContextService.createContext();
+            builder = builder.useSsl()
+                    .sslParameters(sslContext.getSupportedSSLParameters())
+                    .sslSocketFactory(sslContext.getSocketFactory())
+                    .and();
+        }
+
+        final JedisClientConfiguration jedisClientConfiguration = 
builder.build();
         JedisConnectionFactory connectionFactory;
 
         if (RedisUtils.REDIS_MODE_STANDALONE.getValue().equals(redisMode)) {
diff --git 
a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/test/java/org/apache/nifi/redis/service/TestRedisConnectionPoolService.java
 
b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/test/java/org/apache/nifi/redis/service/TestRedisConnectionPoolService.java
index 2017c3b..7223e65 100644
--- 
a/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/test/java/org/apache/nifi/redis/service/TestRedisConnectionPoolService.java
+++ 
b/nifi-nar-bundles/nifi-redis-bundle/nifi-redis-extensions/src/test/java/org/apache/nifi/redis/service/TestRedisConnectionPoolService.java
@@ -19,17 +19,37 @@ 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.util.MockConfigurationContext;
+import org.apache.nifi.util.MockProcessContext;
+import org.apache.nifi.util.StandardProcessorTestRunner;
 import org.apache.nifi.util.TestRunner;
 import org.apache.nifi.util.TestRunners;
+import org.junit.Assert;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
+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;
 
 public class TestRedisConnectionPoolService {
 
+    public static final String SSL_CONTEXT_IDENTIFIER = "ssl-context-service";
     private TestRunner testRunner;
     private FakeRedisProcessor proc;
     private RedisConnectionPool redisService;
 
+    private static SSLContext sslContext;
+
+    @BeforeClass
+    public static void classSetup() throws IOException, 
GeneralSecurityException {
+        sslContext = SSLContext.getDefault();
+    }
+
     @Before
     public void setup() throws InitializationException {
         proc = new FakeRedisProcessor();
@@ -39,6 +59,69 @@ public class TestRedisConnectionPoolService {
         testRunner.addControllerService("redis-service", redisService);
     }
 
+    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);
+        testRunner.setProperty(redisService, RedisUtils.SSL_CONTEXT_SERVICE, 
SSL_CONTEXT_IDENTIFIER);
+    }
+
+    @Test
+    public void testSSLContextService() throws InitializationException {
+        this.setDefaultRedisProperties();
+
+        this.enableSslContextService();
+
+        testRunner.assertValid(redisService);
+        testRunner.enableControllerService(redisService);
+
+        JedisConnectionFactory connectionFactory = 
getJedisConnectionFactory(); // Uses config from test runner
+
+        // Verify that the client configuration will be using an SSL socket 
factory and SSL parameters
+        
Assert.assertTrue(connectionFactory.getClientConfiguration().getSslSocketFactory().isPresent());
+        
Assert.assertTrue(connectionFactory.getClientConfiguration().getSslParameters().isPresent());
+
+        // Now remove the SSL context service
+        testRunner.disableControllerService(redisService);
+        testRunner.removeProperty(redisService, 
RedisUtils.SSL_CONTEXT_SERVICE);
+        testRunner.enableControllerService(redisService);
+        connectionFactory = getJedisConnectionFactory();
+
+        // Now the client configuration will not use SSL
+        
Assert.assertFalse(connectionFactory.getClientConfiguration().getSslSocketFactory().isPresent());
+        
Assert.assertFalse(connectionFactory.getClientConfiguration().getSslParameters().isPresent());
+    }
+
+    private void setDefaultRedisProperties() {
+        testRunner.setProperty(redisService, RedisUtils.REDIS_MODE, 
"Standalone");
+        testRunner.setProperty(redisService, RedisUtils.CONNECTION_STRING, 
"localhost:6379");
+        testRunner.setProperty(redisService, RedisUtils.DATABASE, "0");
+        testRunner.setProperty(redisService, RedisUtils.COMMUNICATION_TIMEOUT, 
"60s");
+        testRunner.setProperty(redisService, RedisUtils.CLUSTER_MAX_REDIRECTS, 
"5");
+        testRunner.setProperty(redisService, RedisUtils.POOL_MAX_TOTAL, "1");
+        testRunner.setProperty(redisService, RedisUtils.POOL_MAX_IDLE, "1");
+        testRunner.setProperty(redisService, RedisUtils.POOL_MIN_IDLE, "1");
+        testRunner.setProperty(redisService, 
RedisUtils.POOL_BLOCK_WHEN_EXHAUSTED, "true");
+        testRunner.setProperty(redisService, RedisUtils.POOL_MAX_WAIT_TIME, 
"1s");
+        testRunner.setProperty(redisService, 
RedisUtils.POOL_MIN_EVICTABLE_IDLE_TIME, "1s");
+        testRunner.setProperty(redisService, 
RedisUtils.POOL_TIME_BETWEEN_EVICTION_RUNS, "1s");
+        testRunner.setProperty(redisService, 
RedisUtils.POOL_NUM_TESTS_PER_EVICTION_RUN, "1");
+        testRunner.setProperty(redisService, RedisUtils.POOL_TEST_ON_CREATE, 
"false");
+        testRunner.setProperty(redisService, RedisUtils.POOL_TEST_ON_BORROW, 
"false");
+        testRunner.setProperty(redisService, RedisUtils.POOL_TEST_ON_RETURN, 
"false");
+        testRunner.setProperty(redisService, RedisUtils.POOL_TEST_WHILE_IDLE, 
"false");
+    }
+
+    private JedisConnectionFactory getJedisConnectionFactory() {
+        MockProcessContext processContext = ((StandardProcessorTestRunner) 
testRunner).getProcessContext();
+        MockConfigurationContext configContext = new 
MockConfigurationContext(processContext.getControllerServices()
+                .get(redisService.getIdentifier()).getProperties(), 
processContext);
+        JedisConnectionFactory connectionFactory = 
RedisUtils.createConnectionFactory(configContext, testRunner.getLogger());
+        return connectionFactory;
+    }
+
     @Test
     public void testValidateConnectionString() {
         testRunner.assertNotValid(redisService);

Reply via email to