From ebb67c432a8f2fbb3ea0cbb466b0e73616e82748 Mon Sep 17 00:00:00 2001 From: Mark Bathori Date: Thu, 26 Oct 2023 16:51:57 +0200 Subject: [PATCH] NIFI-12277: Added SSLContextService to Slack Processors --- .../nifi-slack-bundle/nifi-slack-nar/pom.xml | 6 ++++ .../nifi-slack-processors/pom.xml | 1 - .../nifi/processors/slack/PostSlack.java | 34 +++++++++++++++---- .../nifi/processors/slack/PutSlack.java | 19 ++++++++++- .../nifi/processors/slack/PutSlackTest.java | 3 +- 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-nar/pom.xml b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-nar/pom.xml index 913b4328d4ec..593908a00924 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-nar/pom.xml +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-nar/pom.xml @@ -35,5 +35,11 @@ nifi-slack-processors 1.24.0-SNAPSHOT + + org.apache.nifi + nifi-standard-services-api-nar + 1.24.0-SNAPSHOT + nar + diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/pom.xml b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/pom.xml index 0636bad0b862..0b97f7d967d7 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/pom.xml +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/pom.xml @@ -83,7 +83,6 @@ org.apache.nifi nifi-ssl-context-service-api - test diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PostSlack.java b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PostSlack.java index f5817317640b..db534d12748b 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PostSlack.java +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PostSlack.java @@ -20,6 +20,11 @@ import org.apache.http.HttpHeaders; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; @@ -48,6 +53,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.ssl.SSLContextService; import javax.json.Json; import javax.json.JsonArrayBuilder; @@ -55,6 +61,7 @@ import javax.json.JsonObjectBuilder; import javax.json.JsonString; import javax.json.stream.JsonParsingException; +import javax.net.ssl.SSLContext; import java.io.IOException; import java.io.StringReader; import java.io.UnsupportedEncodingException; @@ -184,6 +191,12 @@ public class PostSlack extends AbstractProcessor { .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES) .build(); + public static final PropertyDescriptor SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder() + .name("SSL Context Service") + .description("Specifies an optional SSL Context Service that, if provided, will be used to create connections") + .identifiesControllerService(SSLContextService.class) + .build(); + public static final Relationship REL_SUCCESS = new Relationship.Builder() .name("success") .description("FlowFiles are routed to success after being successfully sent to Slack") @@ -195,7 +208,7 @@ public class PostSlack extends AbstractProcessor { .build(); public static final List properties = Collections.unmodifiableList( - Arrays.asList(POST_MESSAGE_URL, FILE_UPLOAD_URL, ACCESS_TOKEN, CHANNEL, TEXT, UPLOAD_FLOWFILE, FILE_TITLE, FILE_NAME, FILE_MIME_TYPE)); + Arrays.asList(POST_MESSAGE_URL, FILE_UPLOAD_URL, ACCESS_TOKEN, CHANNEL, TEXT, UPLOAD_FLOWFILE, FILE_TITLE, FILE_NAME, FILE_MIME_TYPE, SSL_CONTEXT_SERVICE)); public static final Set relationships = Collections.unmodifiableSet( new HashSet<>(Arrays.asList(REL_SUCCESS, REL_FAILURE))); @@ -232,18 +245,27 @@ public Set getRelationships() { } @OnScheduled - public void initDynamicProperties(ProcessContext context) { + public void onScheduled(ProcessContext context) { attachmentProperties.clear(); attachmentProperties.addAll( context.getProperties().keySet() .stream() .filter(PropertyDescriptor::isDynamic) .collect(Collectors.toList())); - } - @OnScheduled - public void initHttpResources() { - connManager = new PoolingHttpClientConnectionManager(); + final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class); + + if (sslService != null) { + final SSLContext sslContext = sslService.createContext(); + final Registry socketFactoryRegistry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", new SSLConnectionSocketFactory(sslContext)) + .build(); + + connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + } else { + connManager = new PoolingHttpClientConnectionManager(); + } client = HttpClientBuilder.create() .setConnectionManager(connManager) diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PutSlack.java b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PutSlack.java index d32a983e1f48..7395c7579bf0 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PutSlack.java +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/main/java/org/apache/nifi/processors/slack/PutSlack.java @@ -33,6 +33,7 @@ import org.apache.nifi.processor.ProcessSession; import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.util.StandardValidators; +import org.apache.nifi.ssl.SSLContextService; import javax.json.Json; import javax.json.JsonArrayBuilder; @@ -41,6 +42,8 @@ import javax.json.JsonReader; import javax.json.JsonWriter; import javax.json.stream.JsonParsingException; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; import java.io.DataOutputStream; import java.io.IOException; @@ -131,6 +134,12 @@ public class PutSlack extends AbstractProcessor { .addValidator(new EmojiValidator()) .build(); + public static final PropertyDescriptor SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder() + .name("SSL Context Service") + .description("Specifies an optional SSL Context Service that, if provided, will be used to create connections") + .identifiesControllerService(SSLContextService.class) + .build(); + public static final Relationship REL_SUCCESS = new Relationship.Builder() .name("success") .description("FlowFiles are routed to success after being successfully sent to Slack") @@ -144,7 +153,7 @@ public class PutSlack extends AbstractProcessor { private final SortedSet attachments = Collections.synchronizedSortedSet(new TreeSet()); public static final List descriptors = Collections.unmodifiableList( - Arrays.asList(WEBHOOK_URL, WEBHOOK_TEXT, CHANNEL, USERNAME, ICON_URL, ICON_EMOJI)); + Arrays.asList(WEBHOOK_URL, WEBHOOK_TEXT, CHANNEL, USERNAME, ICON_URL, ICON_EMOJI, SSL_CONTEXT_SERVICE)); public static final Set relationships = Collections.unmodifiableSet( new HashSet<>(Arrays.asList(REL_SUCCESS, REL_FAILURE))); @@ -237,6 +246,8 @@ public void onTrigger(final ProcessContext context, final ProcessSession session builder.add("icon_emoji", iconEmoji); } + final SSLContextService sslService = context.getProperty(SSL_CONTEXT_SERVICE).asControllerService(SSLContextService.class); + try { // Get Attachments Array if (!attachments.isEmpty()) { @@ -260,6 +271,12 @@ public void onTrigger(final ProcessContext context, final ProcessSession session HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); + + if (sslService != null) { + final SSLContext sslContext = sslService.createContext(); + ((HttpsURLConnection) conn).setSSLSocketFactory(sslContext.getSocketFactory()); + } + DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream()); String payload = "payload=" + URLEncoder.encode(stringWriter.getBuffer().toString(), "UTF-8"); outputStream.writeBytes(payload); diff --git a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/test/java/org/apache/nifi/processors/slack/PutSlackTest.java b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/test/java/org/apache/nifi/processors/slack/PutSlackTest.java index 5181f103c423..b2d92908314b 100644 --- a/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/test/java/org/apache/nifi/processors/slack/PutSlackTest.java +++ b/nifi-nar-bundles/nifi-slack-bundle/nifi-slack-processors/src/test/java/org/apache/nifi/processors/slack/PutSlackTest.java @@ -185,13 +185,14 @@ public void testInvalidDynamicPropertiesWithExpressionLanguage() { public void testGetPropertyDescriptors() { PutSlack processor = new PutSlack(); List pd = processor.getSupportedPropertyDescriptors(); - assertEquals(6, pd.size(), "size should be eq"); + assertEquals(7, pd.size(), "size should be eq"); assertTrue(pd.contains(PutSlack.WEBHOOK_TEXT)); assertTrue(pd.contains(PutSlack.WEBHOOK_URL)); assertTrue(pd.contains(PutSlack.CHANNEL)); assertTrue(pd.contains(PutSlack.USERNAME)); assertTrue(pd.contains(PutSlack.ICON_URL)); assertTrue(pd.contains(PutSlack.ICON_EMOJI)); + assertTrue(pd.contains(PutSlack.SSL_CONTEXT_SERVICE)); } @Test