This is an automated email from the ASF dual-hosted git repository. joewitt pushed a commit to branch support/nifi-1.13 in repository https://gitbox.apache.org/repos/asf/nifi.git
commit 715133fce27936542cd97b04d31ced6ddeea4c7d Author: exceptionfactory <[email protected]> AuthorDate: Mon Feb 15 15:57:13 2021 -0600 NIFI-5623 Upgraded OkHttp3 to 4.9.1 and updated unit tests Signed-off-by: Pierre Villard <[email protected]> This closes #4826. --- nifi-bootstrap/pom.xml | 4 +- .../notification/http/HttpNotificationService.java | 25 +- .../http/HttpNotificationServiceTest.java | 242 ++++++++++++++++++++ .../http/TestHttpNotificationService.java | 61 ----- .../http/TestHttpNotificationServiceCommon.java | 128 ----------- .../http/TestHttpNotificationServiceSSL.java | 252 --------------------- nifi-bootstrap/src/test/resources/keystore.jks | Bin 3088 -> 0 bytes nifi-bootstrap/src/test/resources/truststore.jks | Bin 911 -> 0 bytes nifi-commons/nifi-web-utils/pom.xml | 2 +- .../nifi-elasticsearch-processors/pom.xml | 2 +- .../nifi-framework/nifi-framework-cluster/pom.xml | 2 +- .../okhttp/OkHttpReplicationClientTest.groovy | 4 - nifi-nar-bundles/nifi-standard-bundle/pom.xml | 2 +- .../nifi-lookup-services/pom.xml | 2 +- .../nifi-oauth2-provider-service/pom.xml | 2 +- nifi-toolkit/nifi-toolkit-api/pom.xml | 6 +- pom.xml | 1 + 17 files changed, 270 insertions(+), 465 deletions(-) diff --git a/nifi-bootstrap/pom.xml b/nifi-bootstrap/pom.xml index f471e99..dbfc890 100644 --- a/nifi-bootstrap/pom.xml +++ b/nifi-bootstrap/pom.xml @@ -53,12 +53,12 @@ language governing permissions and limitations under the License. --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.6.0</version> + <version>${okhttp.version}</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>mockwebserver</artifactId> - <version>3.6.0</version> + <version>${okhttp.version}</version> <scope>test</scope> </dependency> <!-- This needs to be here because it is relied upon by the nifi-runtime which starts NiFi. It uses this bootstrap module diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java index ee42a5b..2d7ac45 100644 --- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java +++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/http/HttpNotificationService.java @@ -21,7 +21,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import okhttp3.Call; import okhttp3.MediaType; @@ -189,15 +191,20 @@ public class HttpNotificationService extends AbstractNotificationService { // check if the keystore is set and add the factory if so if (url.toLowerCase().startsWith("https")) { try { - TlsConfiguration tlsConfiguration = createTlsConfigurationFromContext(context); - final SSLSocketFactory sslSocketFactory = SslContextFactory.createSSLSocketFactory(tlsConfiguration); + final TlsConfiguration tlsConfiguration = createTlsConfigurationFromContext(context); final X509TrustManager x509TrustManager = SslContextFactory.getX509TrustManager(tlsConfiguration); - if (sslSocketFactory != null && x509TrustManager != null) { - okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager); - } else { - // If the TLS config couldn't be parsed, throw an exception - throw new IllegalStateException("The HTTP notification service URL indicates HTTPS but the TLS properties are not valid"); + if (x509TrustManager == null) { + throw new IllegalStateException("Unable to get X.509 Trust Manager for HTTP Notification Service configured for TLS"); } + + final TrustManager[] trustManagers = new TrustManager[] { x509TrustManager }; + final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration, trustManagers); + if (sslContext == null) { + throw new IllegalStateException("Unable to get SSL Context for HTTP Notification Service configured for TLS"); + } + + final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager); } catch (Exception e) { throw new IllegalStateException(e); } @@ -214,13 +221,13 @@ public class HttpNotificationService extends AbstractNotificationService { String truststorePath = context.getProperty(HttpNotificationService.PROP_TRUSTSTORE).getValue(); String truststorePassword = context.getProperty(HttpNotificationService.PROP_TRUSTSTORE_PASSWORD).getValue(); String truststoreType = context.getProperty(HttpNotificationService.PROP_TRUSTSTORE_TYPE).getValue(); - return new StandardTlsConfiguration(keystorePath, keystorePassword, keyPassword, keystoreType, truststorePath, truststorePassword, truststoreType); + return new StandardTlsConfiguration(keystorePath, keystorePassword, keyPassword, keystoreType, truststorePath, truststorePassword, truststoreType, TlsConfiguration.TLS_PROTOCOL); } @Override public void notify(NotificationContext context, NotificationType notificationType, String subject, String message) throws NotificationFailedException { try { - final RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), message); + final RequestBody requestBody = RequestBody.create(message, MediaType.parse("text/plain")); Request.Builder requestBuilder = new Request.Builder() .post(requestBody) diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/HttpNotificationServiceTest.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/HttpNotificationServiceTest.java new file mode 100644 index 0000000..fa1108e --- /dev/null +++ b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/HttpNotificationServiceTest.java @@ -0,0 +1,242 @@ +/* + * 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.bootstrap.http; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import okio.Buffer; +import org.apache.nifi.attribute.expression.language.StandardPropertyValue; +import org.apache.nifi.bootstrap.notification.NotificationContext; +import org.apache.nifi.bootstrap.notification.NotificationFailedException; +import org.apache.nifi.bootstrap.notification.NotificationInitializationContext; +import org.apache.nifi.bootstrap.notification.NotificationType; +import org.apache.nifi.bootstrap.notification.http.HttpNotificationService; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.security.util.KeyStoreUtils; +import org.apache.nifi.security.util.SslContextFactory; +import org.apache.nifi.security.util.TlsConfiguration; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_URL; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_CONNECTION_TIMEOUT; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_WRITE_TIMEOUT; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_KEYSTORE; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_KEYSTORE_PASSWORD; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_KEYSTORE_TYPE; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_KEY_PASSWORD; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_TRUSTSTORE; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_TRUSTSTORE_PASSWORD; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.PROP_TRUSTSTORE_TYPE; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.NOTIFICATION_SUBJECT_KEY; +import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.NOTIFICATION_TYPE_KEY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; + +public class HttpNotificationServiceTest { + + private static final long REQUEST_TIMEOUT = 2; + + private static final String SUBJECT = "Subject"; + + private static final String MESSAGE = "Message"; + + private static final String LOCALHOST = "localhost"; + + private static final String BASE_PATH = "/"; + + private static final String TIMEOUT = "10s"; + + private MockWebServer mockWebServer; + + @Before + public void startServer() { + mockWebServer = new MockWebServer(); + } + + @After + public void shutdownServer() throws IOException { + mockWebServer.shutdown(); + } + + @Test + public void testStartNotification() throws InterruptedException, NotificationFailedException { + enqueueResponseCode(200); + + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + final HttpNotificationService service = getHttpNotificationService(properties); + service.notify(getNotificationContext(), NotificationType.NIFI_STARTED, SUBJECT, MESSAGE); + + assertRequestMatches(NotificationType.NIFI_STARTED); + } + + @Test + public void testStopNotification() throws InterruptedException, NotificationFailedException { + enqueueResponseCode(200); + + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + final HttpNotificationService service = getHttpNotificationService(properties); + service.notify(getNotificationContext(), NotificationType.NIFI_STOPPED, SUBJECT, MESSAGE); + + assertRequestMatches(NotificationType.NIFI_STOPPED); + } + + @Test + public void testDiedNotification() throws InterruptedException, NotificationFailedException { + enqueueResponseCode(200); + + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + final HttpNotificationService service = getHttpNotificationService(properties); + service.notify(getNotificationContext(), NotificationType.NIFI_DIED, SUBJECT, MESSAGE); + + assertRequestMatches(NotificationType.NIFI_DIED); + } + + @Test + public void testStartNotificationFailure() throws InterruptedException { + enqueueResponseCode(500); + + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + final HttpNotificationService service = getHttpNotificationService(properties); + assertThrows(NotificationFailedException.class, () -> service.notify(getNotificationContext(), NotificationType.NIFI_STARTED, SUBJECT, MESSAGE)); + + assertRequestMatches(NotificationType.NIFI_STARTED); + } + + @Test + public void testStartNotificationHttps() throws GeneralSecurityException, NotificationFailedException, InterruptedException, IOException { + final TlsConfiguration tlsConfiguration = KeyStoreUtils.createTlsConfigAndNewKeystoreTruststore(); + + try { + final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration); + final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + mockWebServer.useHttps(sslSocketFactory, false); + + enqueueResponseCode(200); + + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + + properties.put(PROP_KEYSTORE, createPropertyValue(tlsConfiguration.getKeystorePath())); + properties.put(PROP_KEYSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getKeystorePassword())); + properties.put(PROP_KEY_PASSWORD, createPropertyValue(tlsConfiguration.getKeyPassword())); + properties.put(PROP_KEYSTORE_TYPE, createPropertyValue(tlsConfiguration.getKeystoreType().getType())); + properties.put(PROP_TRUSTSTORE, createPropertyValue(tlsConfiguration.getTruststorePath())); + properties.put(PROP_TRUSTSTORE_PASSWORD, createPropertyValue(tlsConfiguration.getTruststorePassword())); + properties.put(PROP_TRUSTSTORE_TYPE, createPropertyValue(tlsConfiguration.getTruststoreType().getType())); + + final HttpNotificationService service = getHttpNotificationService(properties); + service.notify(getNotificationContext(), NotificationType.NIFI_STARTED, SUBJECT, MESSAGE); + + assertRequestMatches(NotificationType.NIFI_STARTED); + } finally { + Files.deleteIfExists(Paths.get(tlsConfiguration.getKeystorePath())); + Files.deleteIfExists(Paths.get(tlsConfiguration.getTruststorePath())); + } + } + + private void assertRequestMatches(final NotificationType notificationType) throws InterruptedException { + final RecordedRequest recordedRequest = mockWebServer.takeRequest(REQUEST_TIMEOUT, TimeUnit.SECONDS); + assertNotNull(recordedRequest); + assertEquals(notificationType.name(), recordedRequest.getHeader(NOTIFICATION_TYPE_KEY)); + assertEquals(SUBJECT, recordedRequest.getHeader(NOTIFICATION_SUBJECT_KEY)); + + final Buffer bodyBuffer = recordedRequest.getBody(); + final String bodyString = new String(bodyBuffer.readByteArray(), UTF_8); + assertEquals(MESSAGE, bodyString); + } + + private void enqueueResponseCode(final int responseCode) { + mockWebServer.enqueue(new MockResponse().setResponseCode(responseCode)); + } + + private HttpNotificationService getHttpNotificationService(final Map<PropertyDescriptor, PropertyValue> properties) { + final HttpNotificationService service = new HttpNotificationService(); + final NotificationInitializationContext context = new NotificationInitializationContext() { + @Override + public String getIdentifier() { + return NotificationInitializationContext.class.getName(); + } + + @Override + public PropertyValue getProperty(final PropertyDescriptor descriptor) { + return properties.get(descriptor); + } + + @Override + public Map<String, String> getAllProperties() { + final Map<String, String> allProperties = new HashMap<>(); + for (final Map.Entry<PropertyDescriptor, PropertyValue> entry : properties.entrySet()) { + allProperties.put(entry.getKey().getName(), entry.getValue().getValue()); + } + return allProperties; + } + }; + + service.initialize(context); + return service; + } + + private Map<PropertyDescriptor, PropertyValue> getProperties() { + final Map<PropertyDescriptor, PropertyValue> properties = new HashMap<>(); + + // Setting localhost is necessary to avoid hostname verification failures on Windows + final String url = mockWebServer.url(BASE_PATH).newBuilder().host(LOCALHOST).build().toString(); + properties.put(PROP_URL, createPropertyValue(url)); + properties.put(PROP_CONNECTION_TIMEOUT, createPropertyValue(TIMEOUT)); + properties.put(PROP_WRITE_TIMEOUT, createPropertyValue(TIMEOUT)); + + return properties; + } + + private PropertyValue createPropertyValue(final String value) { + return new StandardPropertyValue(value, null, null); + } + + private NotificationContext getNotificationContext() { + final Map<PropertyDescriptor, PropertyValue> properties = getProperties(); + return new NotificationContext() { + @Override + public PropertyValue getProperty(final PropertyDescriptor descriptor) { + return properties.get(descriptor); + } + + @Override + public Map<PropertyDescriptor, String> getProperties() { + final Map<PropertyDescriptor, String> propertyValues = new HashMap<>(); + for (final Map.Entry<PropertyDescriptor, PropertyValue> entry : properties.entrySet()) { + propertyValues.put(entry.getKey(), entry.getValue().getValue()); + } + return propertyValues; + } + }; + } +} diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationService.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationService.java deleted file mode 100644 index c7fdfd0..0000000 --- a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationService.java +++ /dev/null @@ -1,61 +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.bootstrap.http; - -import okhttp3.mockwebserver.MockWebServer; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.mockito.internal.util.io.IOUtil; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; - -public class TestHttpNotificationService extends TestHttpNotificationServiceCommon{ - - - static final String CONFIGURATION_FILE_TEXT = "\n"+ - "<services>\n"+ - " <service>\n"+ - " <id>http-notification</id>\n"+ - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n"+ - " <property name=\"URL\">${test.server}</property>\n"+ - " <property name=\"testProp\">${literal('testing')}</property>\n"+ - " </service>\n"+ - "</services>"; - - - @BeforeClass - public static void startServer() throws IOException { - tempConfigFilePath = "./target/TestHttpNotificationService-config.xml"; - - Files.deleteIfExists(Paths.get(tempConfigFilePath)); - - mockWebServer = new MockWebServer(); - - String configFileOutput = CONFIGURATION_FILE_TEXT.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - } - - @AfterClass - public static void shutdownServer() throws IOException { - Files.deleteIfExists(Paths.get(tempConfigFilePath)); - mockWebServer.shutdown(); - } - -} diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceCommon.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceCommon.java deleted file mode 100644 index c84c704..0000000 --- a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceCommon.java +++ /dev/null @@ -1,128 +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.bootstrap.http; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import okio.Buffer; -import org.apache.nifi.bootstrap.NotificationServiceManager; -import org.apache.nifi.bootstrap.notification.NotificationType; -import org.junit.Test; -import org.xml.sax.SAXException; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.NOTIFICATION_SUBJECT_KEY; -import static org.apache.nifi.bootstrap.notification.http.HttpNotificationService.NOTIFICATION_TYPE_KEY; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -public abstract class TestHttpNotificationServiceCommon { - - public static String tempConfigFilePath; - public static MockWebServer mockWebServer; - - @Test - public void testStartNotification() throws ParserConfigurationException, SAXException, IOException, InterruptedException { - mockWebServer.enqueue(new MockResponse().setResponseCode(200)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - notificationServiceManager.registerNotificationService(NotificationType.NIFI_STARTED, "http-notification"); - notificationServiceManager.notify(NotificationType.NIFI_STARTED, "Subject", "Message"); - - RecordedRequest recordedRequest = mockWebServer.takeRequest(2, TimeUnit.SECONDS); - assertNotNull(recordedRequest); - assertEquals(NotificationType.NIFI_STARTED.name(), recordedRequest.getHeader(NOTIFICATION_TYPE_KEY)); - assertEquals("Subject", recordedRequest.getHeader(NOTIFICATION_SUBJECT_KEY)); - assertEquals("testing", recordedRequest.getHeader("testProp")); - - Buffer bodyBuffer = recordedRequest.getBody(); - String bodyString =new String(bodyBuffer.readByteArray(), UTF_8); - assertEquals("Message", bodyString); - } - - @Test - public void testStopNotification() throws ParserConfigurationException, SAXException, IOException, InterruptedException { - mockWebServer.enqueue(new MockResponse().setResponseCode(200)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - notificationServiceManager.registerNotificationService(NotificationType.NIFI_STOPPED, "http-notification"); - notificationServiceManager.notify(NotificationType.NIFI_STOPPED, "Subject", "Message"); - - RecordedRequest recordedRequest = mockWebServer.takeRequest(2, TimeUnit.SECONDS); - assertNotNull(recordedRequest); - assertEquals(NotificationType.NIFI_STOPPED.name(), recordedRequest.getHeader(NOTIFICATION_TYPE_KEY)); - assertEquals("Subject", recordedRequest.getHeader(NOTIFICATION_SUBJECT_KEY)); - - Buffer bodyBuffer = recordedRequest.getBody(); - String bodyString =new String(bodyBuffer.readByteArray(), UTF_8); - assertEquals("Message", bodyString); - } - - @Test - public void testDiedNotification() throws ParserConfigurationException, SAXException, IOException, InterruptedException { - mockWebServer.enqueue(new MockResponse().setResponseCode(200)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - notificationServiceManager.registerNotificationService(NotificationType.NIFI_DIED, "http-notification"); - notificationServiceManager.notify(NotificationType.NIFI_DIED, "Subject", "Message"); - - RecordedRequest recordedRequest = mockWebServer.takeRequest(2, TimeUnit.SECONDS); - assertNotNull(recordedRequest); - - assertEquals(NotificationType.NIFI_DIED.name(), recordedRequest.getHeader(NOTIFICATION_TYPE_KEY)); - assertEquals("Subject", recordedRequest.getHeader(NOTIFICATION_SUBJECT_KEY)); - - Buffer bodyBuffer = recordedRequest.getBody(); - String bodyString =new String(bodyBuffer.readByteArray(), UTF_8); - assertEquals("Message", bodyString); - } - - @Test - public void testStartNotificationFailure() throws ParserConfigurationException, SAXException, IOException, InterruptedException { - // Web server will still get the request but will return an error. Observe that it is gracefully handled. - - mockWebServer.enqueue(new MockResponse().setResponseCode(500)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - notificationServiceManager.registerNotificationService(NotificationType.NIFI_STARTED, "http-notification"); - notificationServiceManager.notify(NotificationType.NIFI_STARTED, "Subject", "Message"); - - RecordedRequest recordedRequest = mockWebServer.takeRequest(2, TimeUnit.SECONDS); - assertNotNull(recordedRequest); - assertEquals(NotificationType.NIFI_STARTED.name(), recordedRequest.getHeader(NOTIFICATION_TYPE_KEY)); - assertEquals("Subject", recordedRequest.getHeader(NOTIFICATION_SUBJECT_KEY)); - - Buffer bodyBuffer = recordedRequest.getBody(); - String bodyString =new String(bodyBuffer.readByteArray(), UTF_8); - assertEquals("Message", bodyString); - } - -} diff --git a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java b/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java deleted file mode 100644 index 7e1687f..0000000 --- a/nifi-bootstrap/src/test/java/org/apache/nifi/bootstrap/http/TestHttpNotificationServiceSSL.java +++ /dev/null @@ -1,252 +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.bootstrap.http; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.read.ListAppender; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.List; -import javax.net.ssl.SSLContext; -import javax.xml.parsers.ParserConfigurationException; -import okhttp3.mockwebserver.MockWebServer; -import org.apache.nifi.bootstrap.NotificationServiceManager; -import org.apache.nifi.security.util.SslContextFactory; -import org.apache.nifi.security.util.StandardTlsConfiguration; -import org.apache.nifi.security.util.TlsConfiguration; -import org.apache.nifi.security.util.TlsException; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.mockito.internal.util.io.IOUtil; -import org.slf4j.LoggerFactory; -import org.xml.sax.SAXException; - -public class TestHttpNotificationServiceSSL extends TestHttpNotificationServiceCommon { - - static final String CONFIGURATION_FILE_TEXT = "\n" + - "<services>\n" + - " <service>\n" + - " <id>http-notification</id>\n" + - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n" + - " <property name=\"URL\">${test.server}</property>\n" + - " <property name=\"Truststore Filename\">./src/test/resources/truststore.jks</property>\n" + - " <property name=\"Truststore Type\">JKS</property>\n" + - " <property name=\"Truststore Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Filename\">./src/test/resources/keystore.jks</property>\n" + - " <property name=\"Keystore Type\">JKS</property>\n" + - " <property name=\"Key Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Password\">passwordpassword</property>\n" + - " <property name=\"testProp\">${literal('testing')}</property>\n" + - " </service>\n" + - "</services>"; - - static final String CONFIGURATION_FILE_TEXT_NO_KEYSTORE_PASSWORD = "\n" + - "<services>\n" + - " <service>\n" + - " <id>http-notification</id>\n" + - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n" + - " <property name=\"URL\">${test.server}</property>\n" + - " <property name=\"Truststore Filename\">./src/test/resources/truststore.jks</property>\n" + - " <property name=\"Truststore Type\">JKS</property>\n" + - " <property name=\"Truststore Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Filename\">./src/test/resources/keystore.jks</property>\n" + - " <property name=\"Keystore Type\">JKS</property>\n" + - " <property name=\"Key Password\">passwordpassword</property>\n" + - " <property name=\"testProp\">${literal('testing')}</property>\n" + - " </service>\n" + - "</services>"; - - static final String CONFIGURATION_FILE_TEXT_NO_KEY_PASSWORD = "\n" + - "<services>\n" + - " <service>\n" + - " <id>http-notification</id>\n" + - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n" + - " <property name=\"URL\">${test.server}</property>\n" + - " <property name=\"Truststore Filename\">./src/test/resources/truststore.jks</property>\n" + - " <property name=\"Truststore Type\">JKS</property>\n" + - " <property name=\"Truststore Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Filename\">./src/test/resources/keystore.jks</property>\n" + - " <property name=\"Keystore Type\">JKS</property>\n" + - " <property name=\"Keystore Password\">passwordpassword</property>\n" + - " <property name=\"testProp\">${literal('testing')}</property>\n" + - " </service>\n" + - "</services>"; - - static final String CONFIGURATION_FILE_TEXT_BLANK_KEY_PASSWORD = "\n" + - "<services>\n" + - " <service>\n" + - " <id>http-notification</id>\n" + - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n" + - " <property name=\"URL\">${test.server}</property>\n" + - " <property name=\"Truststore Filename\">./src/test/resources/truststore.jks</property>\n" + - " <property name=\"Truststore Type\">JKS</property>\n" + - " <property name=\"Truststore Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Filename\">./src/test/resources/keystore.jks</property>\n" + - " <property name=\"Keystore Type\">JKS</property>\n" + - " <property name=\"Keystore Password\">passwordpassword</property>\n" + - " <property name=\"Key Password\"></property>\n" + - " <property name=\"testProp\">${literal('testing')}</property>\n" + - " </service>\n" + - "</services>"; - - static final String CONFIGURATION_FILE_TEXT_BLANK_KEYSTORE_PASSWORD = "\n" + - "<services>\n" + - " <service>\n" + - " <id>http-notification</id>\n" + - " <class>org.apache.nifi.bootstrap.notification.http.HttpNotificationService</class>\n" + - " <property name=\"URL\">${test.server}</property>\n" + - " <property name=\"Truststore Filename\">./src/test/resources/truststore.jks</property>\n" + - " <property name=\"Truststore Type\">JKS</property>\n" + - " <property name=\"Truststore Password\">passwordpassword</property>\n" + - " <property name=\"Keystore Filename\">./src/test/resources/keystore.jks</property>\n" + - " <property name=\"Keystore Type\">JKS</property>\n" + - " <property name=\"Keystore Password\"></property>\n" + - " <property name=\"Key Password\">passwordpassword</property>\n" + - " <property name=\"testProp\">${literal('testing')}</property>\n" + - " </service>\n" + - "</services>"; - - @Before - public void startServer() throws IOException, TlsException { - tempConfigFilePath = "./target/TestHttpNotificationService-config.xml"; - - Files.deleteIfExists(Paths.get(tempConfigFilePath)); - - mockWebServer = new MockWebServer(); - - TlsConfiguration tlsConfiguration = new StandardTlsConfiguration("./src/test/resources/keystore.jks", "passwordpassword", null, "JKS", - "./src/test/resources/truststore.jks", "passwordpassword", "JKS", TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion()); - final SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration); - mockWebServer.useHttps(sslContext.getSocketFactory(), false); - - String configFileOutput = CONFIGURATION_FILE_TEXT.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - } - - @After - public void shutdownServer() throws IOException { - Files.deleteIfExists(Paths.get(tempConfigFilePath)); - mockWebServer.shutdown(); - } - - @Test - public void testStartNotificationSucceedsNoKeystorePasswd() throws ParserConfigurationException, SAXException, IOException { - Logger notificationServiceLogger = (Logger) LoggerFactory.getLogger(NotificationServiceManager.class); - ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); - listAppender.start(); - notificationServiceLogger.addAppender(listAppender); - - String configFileOutput = CONFIGURATION_FILE_TEXT_NO_KEYSTORE_PASSWORD.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - - List<ILoggingEvent> logsList = listAppender.list; - boolean notificationServiceFailed = false; - for (ILoggingEvent logMessage : logsList) { - if (logMessage.getFormattedMessage().contains("is not valid for the following reasons")) { - notificationServiceFailed = true; - } - } - - assertFalse(notificationServiceFailed); - } - - @Test - public void testStartNotificationSucceedsNoKeyPasswd() throws ParserConfigurationException, SAXException, IOException { - Logger notificationServiceLogger = (Logger) LoggerFactory.getLogger(NotificationServiceManager.class); - ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); - listAppender.start(); - notificationServiceLogger.addAppender(listAppender); - - String configFileOutput = CONFIGURATION_FILE_TEXT_NO_KEY_PASSWORD.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - - List<ILoggingEvent> logsList = listAppender.list; - boolean notificationServiceFailed = false; - for (ILoggingEvent logMessage : logsList) { - if (logMessage.getFormattedMessage().contains("is not valid for the following reasons")) { - notificationServiceFailed = true; - } - } - - assertFalse(notificationServiceFailed); - } - - @Test - public void testStartNotificationFailsBlankKeystorePasswdCorrectKeypasswd() throws ParserConfigurationException, SAXException, IOException { - Logger notificationServiceLogger = (Logger) LoggerFactory.getLogger(NotificationServiceManager.class); - ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); - listAppender.start(); - notificationServiceLogger.addAppender(listAppender); - - String configFileOutput = CONFIGURATION_FILE_TEXT_BLANK_KEYSTORE_PASSWORD.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - - List<ILoggingEvent> logsList = listAppender.list; - boolean notificationServiceFailed = false; - for (ILoggingEvent logMessage : logsList) { - if (logMessage.getFormattedMessage().contains("'Keystore Password' validated against '' is invalid because Keystore Password cannot be empty")) { - notificationServiceFailed = true; - } - } - - assertTrue(notificationServiceFailed); - } - - @Test - public void testStartNotificationFailsCorrectKeystorePasswdBlankKeypasswd() throws ParserConfigurationException, SAXException, IOException { - Logger notificationServiceLogger = (Logger) LoggerFactory.getLogger(NotificationServiceManager.class); - ListAppender<ILoggingEvent> listAppender = new ListAppender<>(); - listAppender.start(); - notificationServiceLogger.addAppender(listAppender); - - String configFileOutput = CONFIGURATION_FILE_TEXT_BLANK_KEY_PASSWORD.replace("${test.server}", String.valueOf(mockWebServer.url("/"))); - IOUtil.writeText(configFileOutput, new File(tempConfigFilePath)); - - NotificationServiceManager notificationServiceManager = new NotificationServiceManager(); - notificationServiceManager.setMaxNotificationAttempts(1); - notificationServiceManager.loadNotificationServices(new File(tempConfigFilePath)); - - List<ILoggingEvent> logsList = listAppender.list; - boolean notificationServiceFailed = false; - for (ILoggingEvent logMessage : logsList) { - if (logMessage.getFormattedMessage().contains("'Key Password' validated against '' is invalid because Key Password cannot be empty")) { - notificationServiceFailed = true; - } - } - - assertTrue(notificationServiceFailed); - } -} diff --git a/nifi-bootstrap/src/test/resources/keystore.jks b/nifi-bootstrap/src/test/resources/keystore.jks deleted file mode 100644 index 246fe88..0000000 Binary files a/nifi-bootstrap/src/test/resources/keystore.jks and /dev/null differ diff --git a/nifi-bootstrap/src/test/resources/truststore.jks b/nifi-bootstrap/src/test/resources/truststore.jks deleted file mode 100644 index 87f4be1..0000000 Binary files a/nifi-bootstrap/src/test/resources/truststore.jks and /dev/null differ diff --git a/nifi-commons/nifi-web-utils/pom.xml b/nifi-commons/nifi-web-utils/pom.xml index 832ce99..f40b530 100644 --- a/nifi-commons/nifi-web-utils/pom.xml +++ b/nifi-commons/nifi-web-utils/pom.xml @@ -94,7 +94,7 @@ <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.14.4</version> + <version>${okhttp.version}</version> </dependency> </dependencies> </project> diff --git a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml index 955efe1..0c2b4fb 100644 --- a/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml +++ b/nifi-nar-bundles/nifi-elasticsearch-bundle/nifi-elasticsearch-processors/pom.xml @@ -107,7 +107,7 @@ language governing permissions and limitations under the License. --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.14.4</version> + <version>4.9.1</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/pom.xml index 8a85256..6f38060 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/pom.xml +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/pom.xml @@ -128,7 +128,7 @@ <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.10.0</version> + <version>${okhttp.version}</version> </dependency> <!-- spring dependencies --> diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy index efd4813..d288aed 100644 --- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy +++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-cluster/src/test/groovy/org/apache/nifi/cluster/coordination/http/replication/okhttp/OkHttpReplicationClientTest.groovy @@ -158,8 +158,6 @@ class OkHttpReplicationClientTest extends GroovyTestCase { // Assert assert client.isTLSConfigured() - assert client.okHttpClient.sslSocketFactory - assert client.okHttpClient.sslSocketFactory.context.getX509KeyManager().credentialsMap["nifi-key"] } @Test @@ -183,8 +181,6 @@ class OkHttpReplicationClientTest extends GroovyTestCase { // Assert assert client.isTLSConfigured() - assert client.okHttpClient.sslSocketFactory - assert client.okHttpClient.sslSocketFactory.context.getX509KeyManager().credentialsMap["nifi-key"] } @Test diff --git a/nifi-nar-bundles/nifi-standard-bundle/pom.xml b/nifi-nar-bundles/nifi-standard-bundle/pom.xml index 8d78c18..be98240 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/pom.xml +++ b/nifi-nar-bundles/nifi-standard-bundle/pom.xml @@ -260,7 +260,7 @@ <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>4.9.0</version> + <version>4.9.1</version> </dependency> <dependency> <groupId>com.burgstaller</groupId> diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml index d304a25..568c5db 100644 --- a/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml +++ b/nifi-nar-bundles/nifi-standard-services/nifi-lookup-services-bundle/nifi-lookup-services/pom.xml @@ -79,7 +79,7 @@ <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.10.0</version> + <version>4.9.1</version> </dependency> <dependency> <groupId>org.apache.nifi</groupId> diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml index ac8fd2a..b33b22e 100644 --- a/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml +++ b/nifi-nar-bundles/nifi-standard-services/nifi-oauth2-provider-bundle/nifi-oauth2-provider-service/pom.xml @@ -74,7 +74,7 @@ <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> - <version>3.14.4</version> + <version>4.9.1</version> <scope>compile</scope> </dependency> <dependency> diff --git a/nifi-toolkit/nifi-toolkit-api/pom.xml b/nifi-toolkit/nifi-toolkit-api/pom.xml index b80e7a9..4cb456d 100644 --- a/nifi-toolkit/nifi-toolkit-api/pom.xml +++ b/nifi-toolkit/nifi-toolkit-api/pom.xml @@ -21,7 +21,7 @@ language governing permissions and limitations under the License. --> <artifactId>nifi-toolkit-api</artifactId> <properties> - <okhttp-version>2.7.5</okhttp-version> + <okhttp.version>2.7.5</okhttp.version> </properties> <dependencies> @@ -44,12 +44,12 @@ language governing permissions and limitations under the License. --> <dependency> <groupId>com.squareup.okhttp</groupId> <artifactId>okhttp</artifactId> - <version>${okhttp-version}</version> + <version>${okhttp.version}</version> </dependency> <dependency> <groupId>com.squareup.okhttp</groupId> <artifactId>logging-interceptor</artifactId> - <version>${okhttp-version}</version> + <version>${okhttp.version}</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> diff --git a/pom.xml b/pom.xml index c17f59e..f6eb233 100644 --- a/pom.xml +++ b/pom.xml @@ -88,6 +88,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <inceptionYear>2014</inceptionYear> + <okhttp.version>4.9.1</okhttp.version> <org.bouncycastle.version>1.68</org.bouncycastle.version> <org.slf4j.version>1.7.30</org.slf4j.version> <ranger.version>2.1.0</ranger.version>
