You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jo...@apache.org on 2021/02/25 05:57:13 UTC

[nifi] 04/24: NIFI-5623 Upgraded OkHttp3 to 4.9.1 and updated unit tests

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 <ex...@apache.org>
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 <pi...@gmail.com>
    
    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>