You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jg...@apache.org on 2023/02/23 15:34:03 UTC

[nifi] branch main updated: NIFI-11195 Refactored Identity Mapping to nifi-security-identity

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

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


The following commit(s) were added to refs/heads/main by this push:
     new 48689a2567 NIFI-11195 Refactored Identity Mapping to nifi-security-identity
48689a2567 is described below

commit 48689a2567dadfd478e967f2f565b15b5cf24a1b
Author: exceptionfactory <ex...@apache.org>
AuthorDate: Thu Feb 16 20:51:25 2023 -0600

    NIFI-11195 Refactored Identity Mapping to nifi-security-identity
    
    - Moved StringUtils from nifi-properties to nifi-property-utils
    - Moved Peer Identity methods from CertificateUtils to specific Site-to-Site classes
    
    Signed-off-by: Joe Gresock <jg...@gmail.com>
    This closes #6977.
---
 nifi-commons/nifi-properties/pom.xml               |  12 +-
 .../java/org/apache/nifi/util/StringUtils.java     |   0
 .../java/org/apache/nifi/util/StringUtilsTest.java |   0
 nifi-commons/nifi-security-identity/pom.xml        |  35 ++
 .../nifi/authorization/util/IdentityMapping.java   |   0
 .../authorization/util/IdentityMappingUtil.java    |   0
 .../nifi/security/util/CertificateUtils.java       | 140 -----
 .../nifi/security/util/CertificateUtilsTest.groovy | 654 ---------------------
 nifi-commons/nifi-site-to-site-client/pom.xml      |  10 -
 .../client/socket/EndpointConnectionPool.java      |  16 +-
 .../client/socket/SocketPeerIdentityProvider.java  |  33 ++
 .../socket/StandardSocketPeerIdentityProvider.java |  74 +++
 .../nifi/remote/util/SiteToSiteRestApiClient.java  |   6 +-
 .../nifi/remote/client/PeerSelectorTest.groovy     |  23 -
 .../nifi/remote/client/http/TestHttpClient.java    | 174 +-----
 .../StandardSocketPeerIdentityProviderTest.java    | 103 ++++
 nifi-commons/nifi-utils/pom.xml                    |   6 +
 nifi-commons/pom.xml                               |   1 +
 .../nifi-email-processors/pom.xml                  |   6 +
 .../nifi-event-transport/pom.xml                   |  10 +
 .../nifi-standard-record-utils/pom.xml             |   4 +
 .../nifi-reporting-utils/pom.xml                   |   4 +
 .../nifi-framework/nifi-documentation/pom.xml      |   1 -
 .../nifi-framework/nifi-file-authorizer/pom.xml    |   3 +-
 .../nifi-framework/nifi-framework-core/pom.xml     |   5 +
 .../nifi-framework/nifi-site-to-site/pom.xml       |   9 +
 .../nifi/remote/SocketRemoteSiteListener.java      |  43 +-
 .../remote/SocketRemoteSiteListenerTest.groovy     | 127 ----
 .../src/test/resources/localhost-ks.jks            | Bin 3076 -> 0 bytes
 .../src/test/resources/localhost-ts.jks            | Bin 911 -> 0 bytes
 .../nifi-framework/nifi-web/nifi-web-api/pom.xml   |   6 +
 .../nifi-web/nifi-web-security/pom.xml             |   5 +
 .../nifi-gcp-parameter-providers/pom.xml           |   1 -
 .../nifi-ldap-iaa-providers/pom.xml                |   5 +
 .../nifi-record-sink-service/pom.xml               |   5 +
 .../nifi-web-client-provider-service/pom.xml       |   6 +
 36 files changed, 380 insertions(+), 1147 deletions(-)

diff --git a/nifi-commons/nifi-properties/pom.xml b/nifi-commons/nifi-properties/pom.xml
index 8cbcc37e3b..cf4a935a3e 100644
--- a/nifi-commons/nifi-properties/pom.xml
+++ b/nifi-commons/nifi-properties/pom.xml
@@ -15,6 +15,12 @@
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-commons</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>nifi-properties</artifactId>
     <dependencies>
         <dependency>
             <groupId>org.apache.nifi</groupId>
@@ -23,10 +29,4 @@
             <scope>compile</scope>
         </dependency>
     </dependencies>
-    <parent>
-        <groupId>org.apache.nifi</groupId>
-        <artifactId>nifi-commons</artifactId>
-        <version>2.0.0-SNAPSHOT</version>
-    </parent>
-    <artifactId>nifi-properties</artifactId>
 </project>
diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/StringUtils.java b/nifi-commons/nifi-property-utils/src/main/java/org/apache/nifi/util/StringUtils.java
similarity index 100%
rename from nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/StringUtils.java
rename to nifi-commons/nifi-property-utils/src/main/java/org/apache/nifi/util/StringUtils.java
diff --git a/nifi-commons/nifi-properties/src/test/java/org/apache/nifi/util/StringUtilsTest.java b/nifi-commons/nifi-property-utils/src/test/java/org/apache/nifi/util/StringUtilsTest.java
similarity index 100%
rename from nifi-commons/nifi-properties/src/test/java/org/apache/nifi/util/StringUtilsTest.java
rename to nifi-commons/nifi-property-utils/src/test/java/org/apache/nifi/util/StringUtilsTest.java
diff --git a/nifi-commons/nifi-security-identity/pom.xml b/nifi-commons/nifi-security-identity/pom.xml
new file mode 100644
index 0000000000..b6c3fd397f
--- /dev/null
+++ b/nifi-commons/nifi-security-identity/pom.xml
@@ -0,0 +1,35 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <!--
+      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.
+    -->
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-commons</artifactId>
+        <version>2.0.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>nifi-security-identity</artifactId>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-properties</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+    </dependencies>
+</project>
+
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/authorization/util/IdentityMapping.java b/nifi-commons/nifi-security-identity/src/main/java/org/apache/nifi/authorization/util/IdentityMapping.java
similarity index 100%
rename from nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/authorization/util/IdentityMapping.java
rename to nifi-commons/nifi-security-identity/src/main/java/org/apache/nifi/authorization/util/IdentityMapping.java
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/authorization/util/IdentityMappingUtil.java b/nifi-commons/nifi-security-identity/src/main/java/org/apache/nifi/authorization/util/IdentityMappingUtil.java
similarity index 100%
rename from nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/authorization/util/IdentityMappingUtil.java
rename to nifi-commons/nifi-security-identity/src/main/java/org/apache/nifi/authorization/util/IdentityMappingUtil.java
diff --git a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
index d386e0f0fc..c00ea50262 100644
--- a/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
+++ b/nifi-commons/nifi-security-utils/src/main/java/org/apache/nifi/security/util/CertificateUtils.java
@@ -18,12 +18,10 @@ package org.apache.nifi.security.util;
 
 import java.io.ByteArrayInputStream;
 import java.math.BigInteger;
-import java.net.Socket;
 import java.security.KeyPair;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
 import java.security.Security;
-import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.CertificateParsingException;
@@ -42,8 +40,6 @@ import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSocket;
 import org.apache.commons.lang3.StringUtils;
 import org.bouncycastle.asn1.ASN1Encodable;
 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -81,14 +77,8 @@ import org.slf4j.LoggerFactory;
 
 public final class CertificateUtils {
     private static final Logger logger = LoggerFactory.getLogger(CertificateUtils.class);
-    private static final String PEER_NOT_AUTHENTICATED_MSG = "peer not authenticated";
     private static final Map<ASN1ObjectIdentifier, Integer> dnOrderMap = createDnOrderMap();
 
-    public static final String JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = "TLSv1.2";
-    public static final String JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = "TLSv1.3";
-    public static final String[] JAVA_8_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION};
-    public static final String[] JAVA_11_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION, JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION};
-
     static {
         Security.addProvider(new BouncyCastleProvider());
     }
@@ -206,136 +196,6 @@ public final class CertificateUtils {
         return result;
     }
 
-    /**
-     * Returns the DN extracted from the peer certificate (the server DN if run on the client; the client DN (if available) if run on the server).
-     * <p>
-     * If the client auth setting is WANT or NONE and a client certificate is not present, this method will return {@code null}.
-     * If the client auth is NEED, it will throw a {@link CertificateException}.
-     *
-     * @param socket the SSL Socket
-     * @return the extracted DN
-     * @throws CertificateException if there is a problem parsing the certificate
-     */
-    public static String extractPeerDNFromSSLSocket(Socket socket) throws CertificateException {
-        String dn = null;
-        if (socket instanceof SSLSocket) {
-            final SSLSocket sslSocket = (SSLSocket) socket;
-
-            boolean clientMode = sslSocket.getUseClientMode();
-            logger.debug("SSL Socket in {} mode", clientMode ? "client" : "server");
-            ClientAuth clientAuth = getClientAuthStatus(sslSocket);
-            logger.debug("SSL Socket client auth status: {}", clientAuth);
-
-            if (clientMode) {
-                logger.debug("This socket is in client mode, so attempting to extract certificate from remote 'server' socket");
-                dn = extractPeerDNFromServerSSLSocket(sslSocket);
-            } else {
-                logger.debug("This socket is in server mode, so attempting to extract certificate from remote 'client' socket");
-                dn = extractPeerDNFromClientSSLSocket(sslSocket);
-            }
-        }
-
-        return dn;
-    }
-
-    /**
-     * Returns the DN extracted from the client certificate.
-     * <p>
-     * If the client auth setting is WANT or NONE and a certificate is not present (and {@code respectClientAuth} is {@code true}), this method will return {@code null}.
-     * If the client auth is NEED, it will throw a {@link CertificateException}.
-     *
-     * @param sslSocket the SSL Socket
-     * @return the extracted DN
-     * @throws CertificateException if there is a problem parsing the certificate
-     */
-    private static String extractPeerDNFromClientSSLSocket(SSLSocket sslSocket) throws CertificateException {
-        String dn = null;
-
-        /** The clientAuth value can be "need", "want", or "none"
-         * A client must send client certificates for need, should for want, and will not for none.
-         * This method should throw an exception if none are provided for need, return null if none are provided for want, and return null (without checking) for none.
-         */
-
-        ClientAuth clientAuth = getClientAuthStatus(sslSocket);
-        logger.debug("SSL Socket client auth status: {}", clientAuth);
-
-        if (clientAuth != ClientAuth.NONE) {
-            try {
-                final Certificate[] certChains = sslSocket.getSession().getPeerCertificates();
-                if (certChains != null && certChains.length > 0) {
-                    X509Certificate x509Certificate = convertAbstractX509Certificate(certChains[0]);
-                    dn = x509Certificate.getSubjectDN().getName().trim();
-                    logger.debug("Extracted DN={} from client certificate", dn);
-                }
-            } catch (SSLPeerUnverifiedException e) {
-                if (e.getMessage().equals(PEER_NOT_AUTHENTICATED_MSG)) {
-                    logger.error("The incoming request did not contain client certificates and thus the DN cannot" +
-                            " be extracted. Check that the other endpoint is providing a complete client certificate chain");
-                }
-                if (clientAuth == ClientAuth.WANT) {
-                    logger.warn("Suppressing missing client certificate exception because client auth is set to 'want'");
-                    return null;
-                }
-                throw new CertificateException(e);
-            }
-        }
-        return dn;
-    }
-
-    /**
-     * Returns the DN extracted from the server certificate.
-     *
-     * @param socket the SSL Socket
-     * @return the extracted DN
-     * @throws CertificateException if there is a problem parsing the certificate
-     */
-    private static String extractPeerDNFromServerSSLSocket(Socket socket) throws CertificateException {
-        String dn = null;
-        if (socket instanceof SSLSocket) {
-            final SSLSocket sslSocket = (SSLSocket) socket;
-            try {
-                final Certificate[] certChains = sslSocket.getSession().getPeerCertificates();
-                if (certChains != null && certChains.length > 0) {
-                    X509Certificate x509Certificate = convertAbstractX509Certificate(certChains[0]);
-                    dn = x509Certificate.getSubjectDN().getName().trim();
-                    logger.debug("Extracted DN={} from server certificate", dn);
-                }
-            } catch (SSLPeerUnverifiedException e) {
-                if (e.getMessage().equals(PEER_NOT_AUTHENTICATED_MSG)) {
-                    logger.error("The server did not present a certificate and thus the DN cannot" +
-                            " be extracted. Check that the other endpoint is providing a complete certificate chain");
-                }
-                throw new CertificateException(e);
-            }
-        }
-        return dn;
-    }
-
-    private static ClientAuth getClientAuthStatus(SSLSocket sslSocket) {
-        return sslSocket.getNeedClientAuth() ? ClientAuth.REQUIRED : sslSocket.getWantClientAuth() ? ClientAuth.WANT : ClientAuth.NONE;
-    }
-
-    /**
-     * Accepts a legacy {@link javax.security.cert.X509Certificate} and returns an {@link X509Certificate}. The {@code javax.*} package certificate classes are for legacy compatibility and should
-     * not be used for new development.
-     *
-     * @param legacyCertificate the {@code javax.security.cert.X509Certificate}
-     * @return a new {@code java.security.cert.X509Certificate}
-     * @throws CertificateException if there is an error generating the new certificate
-     */
-    @SuppressWarnings("deprecation")
-    public static X509Certificate convertLegacyX509Certificate(javax.security.cert.X509Certificate legacyCertificate) throws CertificateException {
-        if (legacyCertificate == null) {
-            throw new IllegalArgumentException("The X.509 certificate cannot be null");
-        }
-
-        try {
-            return formX509Certificate(legacyCertificate.getEncoded());
-        } catch (javax.security.cert.CertificateEncodingException e) {
-            throw new CertificateException(e);
-        }
-    }
-
     /**
      * Accepts an abstract {@link java.security.cert.Certificate} and returns an {@link X509Certificate}. Because {@code sslSocket.getSession().getPeerCertificates()} returns an array of the
      * abstract certificates, they must be translated to X.509 to replace the functionality of {@code sslSocket.getSession().getPeerCertificateChain()}.
diff --git a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy b/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
deleted file mode 100644
index c910cbebd3..0000000000
--- a/nifi-commons/nifi-security-utils/src/test/groovy/org/apache/nifi/security/util/CertificateUtilsTest.groovy
+++ /dev/null
@@ -1,654 +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.security.util
-
-import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers
-import org.bouncycastle.asn1.x500.X500Name
-import org.bouncycastle.asn1.x500.style.BCStyle
-import org.bouncycastle.asn1.x500.style.IETFUtils
-import org.bouncycastle.asn1.x509.Extension
-import org.bouncycastle.asn1.x509.Extensions
-import org.bouncycastle.asn1.x509.ExtensionsGenerator
-import org.bouncycastle.asn1.x509.GeneralName
-import org.bouncycastle.asn1.x509.GeneralNames
-import org.bouncycastle.operator.OperatorCreationException
-import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
-import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
-import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder
-import org.bouncycastle.util.IPAddress
-import org.junit.jupiter.api.BeforeAll
-import org.junit.jupiter.api.Test
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-
-import javax.net.ssl.SSLException
-import javax.net.ssl.SSLPeerUnverifiedException
-import javax.net.ssl.SSLSession
-import javax.net.ssl.SSLSocket
-import java.security.InvalidKeyException
-import java.security.KeyPair
-import java.security.KeyPairGenerator
-import java.security.NoSuchAlgorithmException
-import java.security.NoSuchProviderException
-import java.security.SignatureException
-import java.security.cert.Certificate
-import java.security.cert.CertificateException
-import java.security.cert.X509Certificate
-import java.util.concurrent.Callable
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.ExecutionException
-import java.util.concurrent.Executors
-import java.util.concurrent.Future
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.atomic.AtomicBoolean
-
-import static org.junit.jupiter.api.Assertions.assertEquals
-import static org.junit.jupiter.api.Assertions.assertFalse
-import static org.junit.jupiter.api.Assertions.assertInstanceOf
-import static org.junit.jupiter.api.Assertions.assertNull
-import static org.junit.jupiter.api.Assertions.assertThrows
-import static org.junit.jupiter.api.Assertions.assertTrue
-
-class CertificateUtilsTest  {
-    private static final Logger logger = LoggerFactory.getLogger(CertificateUtilsTest.class)
-
-    private static final int KEY_SIZE = 2048
-
-    private static final int DAYS_IN_YEAR = 365
-    private static final long YESTERDAY = System.currentTimeMillis() - 24 * 60 * 60 * 1000
-    private static final long ONE_YEAR_FROM_NOW = System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000
-    private static final String SIGNATURE_ALGORITHM = "SHA256withRSA"
-    private static final String PROVIDER = "BC"
-
-    private static final String SUBJECT_DN = "CN=NiFi Test Server,OU=Security,O=Apache,ST=CA,C=US"
-    private static final String SUBJECT_DN_LEGACY_EMAIL_ATTR_RFC2985 = "CN=NiFi Test Server/emailAddress=test@apache.org,OU=Security,O=Apache,ST=CA,C=US"
-    private static final String ISSUER_DN = "CN=NiFi Test CA,OU=Security,O=Apache,ST=CA,C=US"
-    private static final List<String> SUBJECT_ALT_NAMES = ["127.0.0.1", "nifi.nifi.apache.org"]
-
-    @BeforeAll
-    static void setUpOnce() {
-        logger.metaClass.methodMissing = { String name, args ->
-            logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
-        }
-    }
-
-    /**
-     * Generates a public/private RSA keypair using the default key size.
-     *
-     * @return the keypair
-     * @throws java.security.NoSuchAlgorithmException if the RSA algorithm is not available
-     */
-    private static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
-        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA")
-        keyPairGenerator.initialize(KEY_SIZE)
-        return keyPairGenerator.generateKeyPair()
-    }
-
-    /**
-     * Generates a signed certificate using an on-demand keypair.
-     *
-     * @param dn the DN
-     * @return the certificate
-     * @throws IOException* @throws NoSuchAlgorithmException
-     * @throws java.security.cert.CertificateException*
-     * @throws java.security.NoSuchProviderException
-     * @throws java.security.SignatureException
-     * @throws OperatorCreationException
-     */
-    private
-    static X509Certificate generateCertificate(String dn) throws IOException, NoSuchAlgorithmException, CertificateException,
-            NoSuchProviderException, SignatureException, InvalidKeyException, OperatorCreationException {
-        KeyPair keyPair = generateKeyPair()
-        return CertificateUtils.generateSelfSignedX509Certificate(keyPair, dn, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
-    }
-
-    /**
-     * Generates a certificate signed by the issuer key.
-     *
-     * @param dn the subject DN
-     * @param issuerDn the issuer DN
-     * @param issuerKey the issuer private key
-     * @return the certificate
-     * @throws IOException
-     * @throws NoSuchAlgorithmException
-     * @throws CertificateException
-     * @throws NoSuchProviderException*
-     * @throws SignatureException* @throws InvalidKeyException
-     * @throws OperatorCreationException
-     */
-    private
-    static X509Certificate generateIssuedCertificate(String dn, X509Certificate issuer, KeyPair issuerKey) throws IOException,
-            NoSuchAlgorithmException, CertificateException, NoSuchProviderException, SignatureException, InvalidKeyException, OperatorCreationException {
-        KeyPair keyPair = generateKeyPair()
-        return CertificateUtils.generateIssuedCertificate(dn, keyPair.getPublic(), issuer, issuerKey, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
-    }
-
-    private static X509Certificate[] generateCertificateChain(String dn = SUBJECT_DN, String issuerDn = ISSUER_DN) {
-        final KeyPair issuerKeyPair = generateKeyPair()
-
-        final X509Certificate issuerCertificate = CertificateUtils.generateSelfSignedX509Certificate(issuerKeyPair, issuerDn, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
-        final X509Certificate certificate = generateIssuedCertificate(dn, issuerCertificate, issuerKeyPair)
-        [certificate, issuerCertificate] as X509Certificate[]
-    }
-
-    @SuppressWarnings("deprecation")
-    private static javax.security.cert.X509Certificate generateLegacyCertificate(X509Certificate x509Certificate) {
-        return javax.security.cert.X509Certificate.getInstance(x509Certificate.getEncoded())
-    }
-
-    private static Certificate generateAbstractCertificate(X509Certificate x509Certificate) {
-        return x509Certificate as Certificate
-    }
-
-    private static Date inFuture(int days) {
-        return new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(days))
-    }
-
-    @Test
-    void testShouldConvertAbstractX509Certificate() {
-        // Arrange
-        final X509Certificate EXPECTED_NEW_CERTIFICATE = generateCertificate(SUBJECT_DN)
-        logger.info("Expected certificate: ${EXPECTED_NEW_CERTIFICATE.class.canonicalName} ${EXPECTED_NEW_CERTIFICATE.subjectDN.toString()} (${EXPECTED_NEW_CERTIFICATE.getSerialNumber()})")
-
-        // Form the abstract certificate
-        final Certificate ABSTRACT_CERTIFICATE = generateAbstractCertificate(EXPECTED_NEW_CERTIFICATE)
-        logger.info("Abstract certificate: ${ABSTRACT_CERTIFICATE.class.canonicalName} (?)")
-
-        // Act
-        X509Certificate convertedCertificate = CertificateUtils.convertAbstractX509Certificate(ABSTRACT_CERTIFICATE)
-        logger.info("Converted certificate: ${convertedCertificate.class.canonicalName} ${convertedCertificate.subjectDN.toString()} (${convertedCertificate.getSerialNumber()})")
-
-        // Assert
-        assertEquals(EXPECTED_NEW_CERTIFICATE, convertedCertificate)
-    }
-
-    @Test
-    void testShouldDetermineClientAuthStatusFromSocket() {
-        // Arrange
-        SSLSocket needSocket = [getNeedClientAuth: { -> true }] as SSLSocket
-        SSLSocket wantSocket = [getNeedClientAuth: { -> false }, getWantClientAuth: { -> true }] as SSLSocket
-        SSLSocket noneSocket = [getNeedClientAuth: { -> false }, getWantClientAuth: { -> false }] as SSLSocket
-
-        // Act
-        ClientAuth needClientAuthStatus = CertificateUtils.getClientAuthStatus(needSocket)
-        logger.info("Client auth (needSocket): ${needClientAuthStatus}")
-        ClientAuth wantClientAuthStatus = CertificateUtils.getClientAuthStatus(wantSocket)
-        logger.info("Client auth (wantSocket): ${wantClientAuthStatus}")
-        ClientAuth noneClientAuthStatus = CertificateUtils.getClientAuthStatus(noneSocket)
-        logger.info("Client auth (noneSocket): ${noneClientAuthStatus}")
-
-        // Assert
-        assertEquals(ClientAuth.REQUIRED, needClientAuthStatus)
-        assertEquals(ClientAuth.WANT, wantClientAuthStatus)
-        assertEquals(ClientAuth.NONE, noneClientAuthStatus)
-    }
-
-    @Test
-    void testShouldExtractClientCertificatesFromSSLServerSocketWithAnyClientAuth() {
-        final String EXPECTED_DN = "CN=ncm.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
-        Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN)
-        logger.info("Expected DN: ${EXPECTED_DN}")
-        logger.info("Expected certificate chain: ${certificateChain.collect { (it as X509Certificate).getSubjectDN().name }.join(" issued by ")}")
-
-        SSLSession mockSession = [getPeerCertificates: { -> certificateChain }] as SSLSession
-
-        // This socket is in client mode, so the peer ("target") is a server
-
-        // Create mock sockets for each possible value of ClientAuth
-        SSLSocket mockNoneSocket = [
-                getUseClientMode : { -> true },
-                getNeedClientAuth: { -> false },
-                getWantClientAuth: { -> false },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        SSLSocket mockNeedSocket = [
-                getUseClientMode : { -> true },
-                getNeedClientAuth: { -> true },
-                getWantClientAuth: { -> false },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        SSLSocket mockWantSocket = [
-                getUseClientMode : { -> true },
-                getNeedClientAuth: { -> false },
-                getWantClientAuth: { -> true },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        // Act
-        def resolvedServerDNs = [mockNeedSocket, mockWantSocket, mockNoneSocket].collect { SSLSocket mockSocket ->
-            logger.info("Running test with socket ClientAuth setting: ${CertificateUtils.getClientAuthStatus(mockSocket)}")
-            String serverDN = CertificateUtils.extractPeerDNFromSSLSocket(mockNoneSocket)
-            logger.info("Extracted server DN: ${serverDN}")
-            serverDN
-        }
-
-        // Assert
-        resolvedServerDNs.stream().forEach(serverDN -> assertTrue(CertificateUtils.compareDNs(serverDN, EXPECTED_DN)))
-    }
-
-    @Test
-    void testShouldNotExtractClientCertificatesFromSSLClientSocketWithClientAuthNone() {
-        // Arrange
-
-        // This socket is in server mode, so the peer ("target") is a client
-        SSLSocket mockSocket = [
-                getUseClientMode : { -> false },
-                getNeedClientAuth: { -> false },
-                getWantClientAuth: { -> false }
-        ] as SSLSocket
-
-        // Act
-        String clientDN = CertificateUtils.extractPeerDNFromSSLSocket(mockSocket)
-        logger.info("Extracted client DN: ${clientDN}")
-
-        // Assert
-        assertNull(clientDN)
-    }
-
-    @Test
-    void testShouldExtractClientCertificatesFromSSLClientSocketWithClientAuthWant() {
-        // Arrange
-        final String EXPECTED_DN = "CN=client.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
-        Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN)
-        logger.info("Expected DN: ${EXPECTED_DN}")
-        logger.info("Expected certificate chain: ${certificateChain.collect { (it as X509Certificate).getSubjectDN().name }.join(" issued by ")}")
-
-        SSLSession mockSession = [getPeerCertificates: { -> certificateChain }] as SSLSession
-
-        // This socket is in server mode, so the peer ("target") is a client
-        SSLSocket mockSocket = [
-                getUseClientMode : { -> false },
-                getNeedClientAuth: { -> false },
-                getWantClientAuth: { -> true },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        // Act
-        String clientDN = CertificateUtils.extractPeerDNFromSSLSocket(mockSocket)
-        logger.info("Extracted client DN: ${clientDN}")
-
-        // Assert
-        assertTrue(CertificateUtils.compareDNs(clientDN, EXPECTED_DN))
-    }
-
-    @Test
-    void testShouldHandleFailureToExtractClientCertificatesFromSSLClientSocketWithClientAuthWant() {
-        // Arrange
-        SSLSession mockSession = [getPeerCertificates: { ->
-            throw new SSLPeerUnverifiedException("peer not authenticated")
-        }] as SSLSession
-
-        // This socket is in server mode, so the peer ("target") is a client
-        SSLSocket mockSocket = [
-                getUseClientMode : { -> false },
-                getNeedClientAuth: { -> false },
-                getWantClientAuth: { -> true },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        // Act
-        String clientDN = CertificateUtils.extractPeerDNFromSSLSocket(mockSocket)
-        logger.info("Extracted client DN: ${clientDN}")
-
-        // Assert
-        assertTrue(CertificateUtils.compareDNs(clientDN, null))
-    }
-
-
-    @Test
-    void testShouldExtractClientCertificatesFromSSLClientSocketWithClientAuthNeed() {
-        // Arrange
-        final String EXPECTED_DN = "CN=client.nifi.apache.org,OU=Security,O=Apache,ST=CA,C=US"
-        Certificate[] certificateChain = generateCertificateChain(EXPECTED_DN)
-        logger.info("Expected DN: ${EXPECTED_DN}")
-        logger.info("Expected certificate chain: ${certificateChain.collect { (it as X509Certificate).getSubjectDN().name }.join(" issued by ")}")
-
-        SSLSession mockSession = [getPeerCertificates: { -> certificateChain }] as SSLSession
-
-        // This socket is in server mode, so the peer ("target") is a client
-        SSLSocket mockSocket = [
-                getUseClientMode : { -> false },
-                getNeedClientAuth: { -> true },
-                getWantClientAuth: { -> false },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        // Act
-        String clientDN = CertificateUtils.extractPeerDNFromSSLSocket(mockSocket)
-        logger.info("Extracted client DN: ${clientDN}")
-
-        // Assert
-        assertTrue(CertificateUtils.compareDNs(clientDN, EXPECTED_DN))
-    }
-
-    @Test
-    void testShouldHandleFailureToExtractClientCertificatesFromSSLClientSocketWithClientAuthNeed() {
-        // Arrange
-        SSLSession mockSession = [getPeerCertificates: { ->
-            throw new SSLPeerUnverifiedException("peer not authenticated")
-        }] as SSLSession
-
-        // This socket is in server mode, so the peer ("target") is a client
-        SSLSocket mockSocket = [
-                getUseClientMode : { -> false },
-                getNeedClientAuth: { -> true },
-                getWantClientAuth: { -> false },
-                getSession       : { -> mockSession }
-        ] as SSLSocket
-
-        // Act
-        CertificateException ce = assertThrows(CertificateException.class,
-                () -> CertificateUtils.extractPeerDNFromSSLSocket(mockSocket))
-
-        // Assert
-        assertTrue(ce.getMessage().contains("peer not authenticated"))
-    }
-
-    @Test
-    void testShouldCompareDNs() {
-        // Arrange
-        final String DN_1_ORDERED = "CN=test1.nifi.apache.org, OU=Apache NiFi, O=Apache, ST=California, C=US"
-        logger.info("DN 1 Ordered : ${DN_1_ORDERED}")
-        final String DN_1_REVERSED = DN_1_ORDERED.split(", ").reverse().join(", ")
-        logger.info("DN 1 Reversed: ${DN_1_REVERSED}")
-
-        final String DN_2_ORDERED = "CN=test2.nifi.apache.org, OU=Apache NiFi, O=Apache, ST=California, C=US"
-        logger.info("DN 2 Ordered : ${DN_2_ORDERED}")
-        final String DN_2_REVERSED = DN_2_ORDERED.split(", ").reverse().join(", ")
-        logger.info("DN 2 Reversed: ${DN_2_REVERSED}")
-
-        // Act
-
-        // True
-        boolean dn1MatchesSelf = CertificateUtils.compareDNs(DN_1_ORDERED, DN_1_ORDERED)
-        logger.matches("DN 1, DN 1: ${dn1MatchesSelf}")
-
-        boolean dn1MatchesReversed = CertificateUtils.compareDNs(DN_1_ORDERED, DN_1_REVERSED)
-        logger.matches("DN 1, DN 1 (R): ${dn1MatchesReversed}")
-
-        boolean emptyMatchesEmpty = CertificateUtils.compareDNs("", "")
-        logger.matches("empty, empty: ${emptyMatchesEmpty}")
-
-        boolean nullMatchesNull = CertificateUtils.compareDNs(null, null)
-        logger.matches("null, null: ${nullMatchesNull}")
-
-        // False
-        boolean dn1MatchesDn2 = CertificateUtils.compareDNs(DN_1_ORDERED, DN_2_ORDERED)
-        logger.matches("DN 1, DN 2: ${dn1MatchesDn2}")
-
-        boolean dn1MatchesDn2Reversed = CertificateUtils.compareDNs(DN_1_ORDERED, DN_2_REVERSED)
-        logger.matches("DN 1, DN 2 (R): ${dn1MatchesDn2Reversed}")
-
-        boolean dn1MatchesEmpty = CertificateUtils.compareDNs(DN_1_ORDERED, "")
-        logger.matches("DN 1, empty: ${dn1MatchesEmpty}")
-
-        // Assert
-        assertTrue(dn1MatchesReversed)
-        assertTrue(emptyMatchesEmpty)
-        assertTrue(nullMatchesNull)
-
-        assertFalse(dn1MatchesDn2)
-        assertFalse(dn1MatchesDn2Reversed)
-        assertFalse(dn1MatchesEmpty)
-    }
-
-    @Test
-    void testGetCommonName(){
-        String dn1 = "CN=testDN,O=testOrg"
-        String dn2 = "O=testDN,O=testOrg"
-
-        assertEquals("testDN", CertificateUtils.getCommonName(dn1))
-        assertNull(CertificateUtils.getCommonName(dn2))
-    }
-
-    @Test
-    void testShouldGenerateSelfSignedCert() throws Exception {
-        String dn = "CN=testDN,O=testOrg"
-
-        int days = 365
-        X509Certificate x509Certificate = CertificateUtils.generateSelfSignedX509Certificate(generateKeyPair(), dn, SIGNATURE_ALGORITHM, days)
-
-        Date notAfter = x509Certificate.getNotAfter()
-        assertTrue(notAfter.after(inFuture(days - 1)))
-        assertTrue(notAfter.before(inFuture(days + 1)))
-
-        Date notBefore = x509Certificate.getNotBefore()
-        assertTrue(notBefore.after(inFuture(-1)))
-        assertTrue(notBefore.before(inFuture(1)))
-
-        assertEquals(dn, x509Certificate.getIssuerX500Principal().getName())
-        assertEquals(SIGNATURE_ALGORITHM.toUpperCase(), x509Certificate.getSigAlgName().toUpperCase())
-        assertEquals("RSA", x509Certificate.getPublicKey().getAlgorithm())
-
-        assertEquals(1, x509Certificate.getSubjectAlternativeNames().size())
-
-        GeneralName gn = x509Certificate.getSubjectAlternativeNames().iterator().next()
-        assertEquals(GeneralName.dNSName, gn.getTagNo())
-        assertEquals("testDN", gn.getName().toString())
-
-        x509Certificate.checkValidity()
-    }
-
-    @Test
-    void testIssueCert() throws Exception {
-        int days = 365
-        KeyPair issuerKeyPair = generateKeyPair()
-        X509Certificate issuer = CertificateUtils.generateSelfSignedX509Certificate(issuerKeyPair, "CN=testCa,O=testOrg", SIGNATURE_ALGORITHM, days)
-
-        String dn = "CN=testIssued, O=testOrg"
-
-        KeyPair keyPair = generateKeyPair()
-        X509Certificate x509Certificate = CertificateUtils.generateIssuedCertificate(dn, keyPair.getPublic(), issuer, issuerKeyPair, SIGNATURE_ALGORITHM, days)
-        assertEquals(dn, x509Certificate.getSubjectX500Principal().toString())
-        assertEquals(issuer.getSubjectX500Principal().toString(), x509Certificate.getIssuerX500Principal().toString())
-        assertEquals(keyPair.getPublic(), x509Certificate.getPublicKey())
-
-        Date notAfter = x509Certificate.getNotAfter()
-        assertTrue(notAfter.after(inFuture(days - 1)))
-        assertTrue(notAfter.before(inFuture(days + 1)))
-
-        Date notBefore = x509Certificate.getNotBefore()
-        assertTrue(notBefore.after(inFuture(-1)))
-        assertTrue(notBefore.before(inFuture(1)))
-
-        assertEquals(SIGNATURE_ALGORITHM.toUpperCase(), x509Certificate.getSigAlgName().toUpperCase())
-        assertEquals("RSA", x509Certificate.getPublicKey().getAlgorithm())
-
-        x509Certificate.verify(issuerKeyPair.getPublic())
-    }
-
-    @Test
-    void reorderShouldPutElementsInCorrectOrder() {
-        String cn = "CN=testcn"
-        String l = "L=testl"
-        String st = "ST=testst"
-        String o = "O=testo"
-        String ou = "OU=testou"
-        String c = "C=testc"
-        String street = "STREET=teststreet"
-        String dc = "DC=testdc"
-        String uid = "UID=testuid"
-        String surname = "SURNAME=testsurname"
-        String initials = "INITIALS=testinitials"
-        String givenName = "GIVENNAME=testgivenname"
-        assertEquals("$cn,$l,$st,$o,$ou,$c,$street,$dc,$uid,$surname,$givenName,$initials".toString(),
-                CertificateUtils.reorderDn("$surname,$st,$o,$initials,$givenName,$uid,$street,$c,$cn,$ou,$l,$dc"))
-    }
-
-    @Test
-    void testUniqueSerialNumbers() {
-        def running = new AtomicBoolean(true)
-        def executorService = Executors.newCachedThreadPool()
-        def serialNumbers = Collections.newSetFromMap(new ConcurrentHashMap())
-        try {
-            def futures = new ArrayList<Future>()
-            for (int i = 0; i < 8; i++) {
-                futures.add(executorService.submit(new Callable<Integer>() {
-                    @Override
-                    Integer call() throws Exception {
-                        int count = 0
-                        while (running.get()) {
-                            def before = System.currentTimeMillis()
-                            def serialNumber = CertificateUtils.getUniqueSerialNumber()
-                            def after = System.currentTimeMillis()
-                            def serialNumberMillis = serialNumber.shiftRight(32)
-                            assertTrue(serialNumberMillis >= before)
-                            assertTrue(serialNumberMillis <= after)
-                            assertTrue(serialNumbers.add(serialNumber))
-                            count++
-                        }
-                        return count
-                    }
-                }))
-            }
-
-            Thread.sleep(1000)
-
-            running.set(false)
-
-            def totalRuns = 0
-            for (int i = 0; i < futures.size(); i++) {
-                try {
-                    def numTimes = futures.get(i).get()
-                    logger.info("future $i executed $numTimes times")
-                    totalRuns += numTimes
-                } catch (ExecutionException e) {
-                    throw e.getCause()
-                }
-            }
-            logger.info("Generated ${serialNumbers.size()} unique serial numbers")
-            assertEquals(totalRuns, serialNumbers.size())
-        } finally {
-            executorService.shutdown()
-        }
-    }
-
-    @Test
-    void testShouldGenerateIssuedCertificateWithSans() {
-        // Arrange
-        final String SUBJECT_DN = "CN=localhost"
-        final List<String> SANS = ["127.0.0.1", "nifi.nifi.apache.org"]
-        logger.info("Creating a certificate with subject: ${SUBJECT_DN} and SAN: ${SANS}")
-
-        final KeyPair subjectKeyPair = generateKeyPair()
-        final KeyPair issuerKeyPair = generateKeyPair()
-
-        final X509Certificate issuerCertificate = CertificateUtils.generateSelfSignedX509Certificate(issuerKeyPair, ISSUER_DN, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
-
-        // Form the SANS into GeneralName instances and populate the container with the array
-        def gns = SANS.collect { String san ->
-            new GeneralName(GeneralName.dNSName, san)
-        }
-        def generalNames = new GeneralNames(gns as GeneralName[])
-        logger.info("Created GeneralNames object: ${generalNames.names*.toString()}")
-
-        // Form the Extensions object
-        ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator()
-        extensionsGenerator.addExtension(Extension.subjectAlternativeName, false, generalNames)
-        Extensions extensions = extensionsGenerator.generate()
-        logger.info("Generated extensions object: ${extensions.oids()*.toString()}")
-
-        // Act
-        X509Certificate certificate = CertificateUtils.generateIssuedCertificate(SUBJECT_DN, subjectKeyPair.public, extensions, issuerCertificate, issuerKeyPair, SIGNATURE_ALGORITHM, DAYS_IN_YEAR)
-        logger.info("Issued certificate with subject: ${certificate.getSubjectDN().name} and SAN: ${certificate.getSubjectAlternativeNames().join(",")}")
-
-        // Assert
-        assertEquals(SUBJECT_DN, certificate.getSubjectDN().name)
-        assertEquals(SANS.size(), certificate.getSubjectAlternativeNames().size())
-        assertTrue(certificate.getSubjectAlternativeNames()*.last().containsAll(SANS))
-    }
-
-    @Test
-    void testShouldDetectTlsErrors() {
-        // Arrange
-        final String msg = "Test exception"
-
-        // SSLPeerUnverifiedException isn't specifically defined in the method, but is a subclass of SSLException so it should be caught
-        List<Throwable> directErrors = [new TlsException(msg), new SSLPeerUnverifiedException(msg), new CertificateException(msg), new SSLException(msg)]
-        List<Throwable> causedErrors = directErrors.collect { Throwable cause -> new Exception(msg, cause) } + [
-                new Exception(msg,
-                        new Exception("Nested $msg",
-                                new Exception("Double nested $msg",
-                                        new TlsException("Triple nested $msg"))))]
-        List<Throwable> unrelatedErrors = [new Exception(msg), new IllegalArgumentException(msg), new NullPointerException(msg)]
-
-        // Act
-        def directResults = directErrors.collect { Throwable e -> CertificateUtils.isTlsError(e) }
-        def causedResults = causedErrors.collect { Throwable e -> CertificateUtils.isTlsError(e) }
-        def unrelatedResults = unrelatedErrors.collect { Throwable e -> CertificateUtils.isTlsError(e) }
-
-        logger.info("Direct results: ${directResults}")
-        logger.info("Caused results: ${causedResults}")
-        logger.info("Unrelated results: ${unrelatedResults}")
-
-        // Assert
-        assertTrue(directResults.every())
-        assertTrue(causedResults.every())
-        assertFalse(unrelatedResults.any())
-    }
-
-    @Test
-    void testGetExtensionsFromCSR() {
-        // Arrange
-        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA")
-        KeyPair keyPair = generator.generateKeyPair()
-        Extensions sanExtensions = createDomainAlternativeNamesExtensions(SUBJECT_ALT_NAMES, SUBJECT_DN)
-
-        JcaPKCS10CertificationRequestBuilder jcaPKCS10CertificationRequestBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(SUBJECT_DN), keyPair.getPublic())
-        jcaPKCS10CertificationRequestBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, sanExtensions)
-        JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder("SHA256WITHRSA")
-        JcaPKCS10CertificationRequest jcaPKCS10CertificationRequest = new JcaPKCS10CertificationRequest(jcaPKCS10CertificationRequestBuilder.build(jcaContentSignerBuilder.build(keyPair.getPrivate())))
-
-        // Act
-        Extensions extensions = CertificateUtils.getExtensionsFromCSR(jcaPKCS10CertificationRequest)
-
-        // Assert
-        assert(extensions.equivalent(sanExtensions))
-    }
-
-    @Test
-    void testExtractUserNameFromDN() {
-        String expected = "NiFi Test Server"
-        assertEquals(CertificateUtils.extractUsername(SUBJECT_DN), expected)
-        assertEquals(CertificateUtils.extractUsername(SUBJECT_DN_LEGACY_EMAIL_ATTR_RFC2985), expected)
-    }
-
-    // Using this directly from tls-toolkit results in a dependency loop, so it's added here for testing purposes.
-    private static Extensions createDomainAlternativeNamesExtensions(List<String> domainAlternativeNames, String requestedDn) throws IOException {
-        List<GeneralName> namesList = new ArrayList<>()
-
-        try {
-            final String cn = IETFUtils.valueToString(new X500Name(requestedDn).getRDNs(BCStyle.CN)[0].getFirst().getValue())
-            namesList.add(new GeneralName(GeneralName.dNSName, cn))
-        } catch (Exception e) {
-            throw new IOException("Failed to extract CN from request DN: " + requestedDn, e)
-        }
-
-        if (domainAlternativeNames != null) {
-            for (String alternativeName : domainAlternativeNames) {
-                namesList.add(new GeneralName(IPAddress.isValid(alternativeName) ? GeneralName.iPAddress : GeneralName.dNSName, alternativeName))
-            }
-        }
-
-        GeneralNames subjectAltNames = new GeneralNames(namesList.toArray([] as GeneralName[]))
-        ExtensionsGenerator extGen = new ExtensionsGenerator()
-        extGen.addExtension(Extension.subjectAlternativeName, false, subjectAltNames)
-        return extGen.generate()
-    }
-}
diff --git a/nifi-commons/nifi-site-to-site-client/pom.xml b/nifi-commons/nifi-site-to-site-client/pom.xml
index 4b70a883d2..69d80f324a 100644
--- a/nifi-commons/nifi-site-to-site-client/pom.xml
+++ b/nifi-commons/nifi-site-to-site-client/pom.xml
@@ -46,16 +46,6 @@
             <artifactId>nifi-utils</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
-        <dependency>
-            <groupId>org.apache.nifi</groupId>
-            <artifactId>nifi-security-utils</artifactId>
-            <version>2.0.0-SNAPSHOT</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.nifi</groupId>
-            <artifactId>nifi-security-utils-api</artifactId>
-            <version>2.0.0-SNAPSHOT</version>
-        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-security-ssl</artifactId>
diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/EndpointConnectionPool.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/EndpointConnectionPool.java
index 83fce50b97..878d16b1e3 100644
--- a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/EndpointConnectionPool.java
+++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/EndpointConnectionPool.java
@@ -26,12 +26,12 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.URI;
-import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentHashMap;
@@ -64,7 +64,6 @@ import org.apache.nifi.remote.io.socket.SocketCommunicationsSession;
 import org.apache.nifi.remote.protocol.CommunicationsSession;
 import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
 import org.apache.nifi.remote.protocol.socket.SocketClientProtocol;
-import org.apache.nifi.security.util.CertificateUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,6 +71,8 @@ public class EndpointConnectionPool implements PeerStatusProvider {
 
     private static final Logger logger = LoggerFactory.getLogger(EndpointConnectionPool.class);
 
+    private static final SocketPeerIdentityProvider socketPeerIdentityProvider = new StandardSocketPeerIdentityProvider();
+
     private final ConcurrentMap<PeerDescription, BlockingQueue<EndpointConnection>> connectionQueueMap = new ConcurrentHashMap<>();
 
     private final Set<EndpointConnection> activeConnections = Collections.synchronizedSet(new HashSet<>());
@@ -449,11 +450,12 @@ public class EndpointConnectionPool implements PeerStatusProvider {
                 socket.setSoTimeout(commsTimeout);
                 commsSession = new SocketCommunicationsSession(socket);
 
-                try {
-                    final String dn = CertificateUtils.extractPeerDNFromSSLSocket(socket);
-                    commsSession.setUserDn(dn);
-                } catch (final CertificateException ex) {
-                    throw new IOException(ex);
+                final Optional<String> peerIdentity = socketPeerIdentityProvider.getPeerIdentity(socket);
+                if (peerIdentity.isPresent()) {
+                    final String userDn = peerIdentity.get();
+                    commsSession.setUserDn(userDn);
+                } else {
+                    throw new IOException(String.format("Site-to-Site Peer [%s] Identity not found", socket.getRemoteSocketAddress()));
                 }
             } else {
 
diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/SocketPeerIdentityProvider.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/SocketPeerIdentityProvider.java
new file mode 100644
index 0000000000..6d1a1c4297
--- /dev/null
+++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/SocketPeerIdentityProvider.java
@@ -0,0 +1,33 @@
+/*
+ * 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.remote.client.socket;
+
+import java.net.Socket;
+import java.util.Optional;
+
+/**
+ * Abstraction for reading identity information from socket connections
+ */
+public interface SocketPeerIdentityProvider {
+    /**
+     * Get Peer Identity from Socket
+     *
+     * @param socket Socket
+     * @return Peer Identity or empty when not found
+     */
+    Optional<String> getPeerIdentity(Socket socket);
+}
diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProvider.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProvider.java
new file mode 100644
index 0000000000..45a64f1820
--- /dev/null
+++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProvider.java
@@ -0,0 +1,74 @@
+/*
+ * 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.remote.client.socket;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.net.Socket;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Optional;
+
+/**
+ * Standard implementation attempts to read X.509 certificates from an SSLSocket
+ */
+public class StandardSocketPeerIdentityProvider implements SocketPeerIdentityProvider {
+    private static final Logger logger = LoggerFactory.getLogger(StandardSocketPeerIdentityProvider.class);
+
+    @Override
+    public Optional<String> getPeerIdentity(final Socket socket) {
+        final Optional<String> peerIdentity;
+
+        if (socket instanceof SSLSocket) {
+            final SSLSocket sslSocket = (SSLSocket) socket;
+            final SSLSession sslSession = sslSocket.getSession();
+            peerIdentity = getPeerIdentity(sslSession);
+        } else {
+            peerIdentity = Optional.empty();
+        }
+
+        return peerIdentity;
+    }
+
+    private Optional<String> getPeerIdentity(final SSLSession sslSession) {
+        String peerIdentity = null;
+
+        final String peerHost = sslSession.getPeerHost();
+        final int peerPort = sslSession.getPeerPort();
+
+        try {
+            final Certificate[] peerCertificates = sslSession.getPeerCertificates();
+            if (peerCertificates == null || peerCertificates.length == 0) {
+                logger.warn("Peer Identity not found: Peer Certificates not provided [{}:{}]", peerHost, peerPort);
+            } else {
+                final X509Certificate peerCertificate = (X509Certificate) peerCertificates[0];
+                final Principal subjectDistinguishedName = peerCertificate.getSubjectDN();
+                peerIdentity = subjectDistinguishedName.getName();
+            }
+        } catch (final SSLPeerUnverifiedException e) {
+            logger.warn("Peer Identity not found: Peer Unverified [{}:{}]", peerHost, peerPort);
+            logger.debug("TLS Protocol [{}] Peer Unverified [{}:{}]", sslSession.getProtocol(), peerHost, peerPort, e);
+        }
+
+        return Optional.ofNullable(peerIdentity);
+    }
+}
diff --git a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java
index 8726c49ce5..cd34cbccf3 100644
--- a/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java
+++ b/nifi-commons/nifi-site-to-site-client/src/main/java/org/apache/nifi/remote/util/SiteToSiteRestApiClient.java
@@ -47,7 +47,6 @@ import java.nio.channels.Channels;
 import java.nio.channels.ReadableByteChannel;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collection;
@@ -128,7 +127,6 @@ import org.apache.nifi.remote.protocol.ResponseCode;
 import org.apache.nifi.remote.protocol.http.HttpHeaders;
 import org.apache.nifi.remote.protocol.http.HttpProxy;
 import org.apache.nifi.reporting.Severity;
-import org.apache.nifi.security.util.CertificateUtils;
 import org.apache.nifi.stream.io.StreamUtils;
 import org.apache.nifi.web.api.dto.ControllerDTO;
 import org.apache.nifi.web.api.dto.remote.PeerDTO;
@@ -319,9 +317,9 @@ public class SiteToSiteRestApiClient implements Closeable {
                 }
 
                 try {
-                    final X509Certificate cert = CertificateUtils.convertAbstractX509Certificate(certChain[0]);
+                    final X509Certificate cert = (X509Certificate) certChain[0];
                     trustedPeerDn = cert.getSubjectDN().getName().trim();
-                } catch (final CertificateException e) {
+                } catch (final RuntimeException e) {
                     final String msg = "Could not extract subject DN from SSL session peer certificate";
                     logger.warn(msg);
                     eventReporter.reportEvent(Severity.WARNING, EVENT_CATEGORY, msg);
diff --git a/nifi-commons/nifi-site-to-site-client/src/test/groovy/org/apache/nifi/remote/client/PeerSelectorTest.groovy b/nifi-commons/nifi-site-to-site-client/src/test/groovy/org/apache/nifi/remote/client/PeerSelectorTest.groovy
index d644f8e5d1..fc1c76535a 100644
--- a/nifi-commons/nifi-site-to-site-client/src/test/groovy/org/apache/nifi/remote/client/PeerSelectorTest.groovy
+++ b/nifi-commons/nifi-site-to-site-client/src/test/groovy/org/apache/nifi/remote/client/PeerSelectorTest.groovy
@@ -16,21 +16,16 @@
  */
 package org.apache.nifi.remote.client
 
-
 import org.apache.nifi.remote.PeerDescription
 import org.apache.nifi.remote.PeerStatus
 import org.apache.nifi.remote.TransferDirection
 import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol
 import org.apache.nifi.remote.util.PeerStatusCache
-import org.bouncycastle.jce.provider.BouncyCastleProvider
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.BeforeAll
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 
-import java.security.Security
 import java.util.concurrent.ArrayBlockingQueue
 
 import static org.junit.jupiter.api.Assertions.assertEquals
@@ -52,16 +47,6 @@ class PeerSelectorTest {
     private static mockPSP
     private static mockPP
 
-
-    @BeforeAll
-    static void setUpOnce() throws Exception {
-        Security.addProvider(new BouncyCastleProvider())
-
-        logger.metaClass.methodMissing = { String name, args ->
-            logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
-        }
-    }
-
     @BeforeEach
     void setUp() {
         // Mock collaborators
@@ -69,11 +54,6 @@ class PeerSelectorTest {
         mockPP = mockPeerPersistence()
     }
 
-    @AfterEach
-    void tearDown() {
-
-    }
-
     private static String buildRemoteInstanceUris(List<String> nodes = DEFAULT_NODES) {
         String remoteInstanceUris = "http://" + nodes.join(":8443/nifi-api,http://") + ":8443/nifi-api";
         remoteInstanceUris
@@ -206,7 +186,6 @@ class PeerSelectorTest {
             new PeerStatusCache(peerStatuses, System.currentTimeMillis(), remoteInstanceUris, SiteToSiteTransportProtocol.HTTP)
         },
          save   : { PeerStatusCache psc ->
-             logger.mock("Persisting PeerStatusCache: ${psc}")
          }] as PeerPersistence
     }
 
@@ -985,8 +964,6 @@ class PeerSelectorTest {
                     bootstrapDescription
                 },
                 fetchRemotePeerStatuses    : { PeerDescription pd ->
-                    // Depending on the scenario, return given peer statuses
-                    logger.mock("Scenario ${currentAttempt} fetchRemotePeerStatus for ${pd}")
                     switch (currentAttempt) {
                         case 1:
                             return [bootstrapStatus, node2Status] as Set<PeerStatus>
diff --git a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java
index 93a1fe8def..892388708b 100644
--- a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java
+++ b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/http/TestHttpClient.java
@@ -22,10 +22,8 @@ import org.apache.nifi.events.EventReporter;
 import org.apache.nifi.remote.Peer;
 import org.apache.nifi.remote.Transaction;
 import org.apache.nifi.remote.TransferDirection;
-import org.apache.nifi.remote.client.KeystoreType;
 import org.apache.nifi.remote.client.SiteToSiteClient;
 import org.apache.nifi.remote.codec.StandardFlowFileCodec;
-import org.apache.nifi.remote.exception.HandshakeException;
 import org.apache.nifi.remote.io.CompressionInputStream;
 import org.apache.nifi.remote.io.CompressionOutputStream;
 import org.apache.nifi.remote.protocol.DataPacket;
@@ -34,8 +32,6 @@ import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
 import org.apache.nifi.remote.protocol.http.HttpHeaders;
 import org.apache.nifi.remote.protocol.http.HttpProxy;
 import org.apache.nifi.remote.util.StandardDataPacket;
-import org.apache.nifi.security.util.TemporaryKeyStoreBuilder;
-import org.apache.nifi.security.util.TlsConfiguration;
 import org.apache.nifi.stream.io.StreamUtils;
 import org.apache.nifi.web.api.dto.ControllerDTO;
 import org.apache.nifi.web.api.dto.PortDTO;
@@ -45,16 +41,11 @@ import org.apache.nifi.web.api.entity.PeersEntity;
 import org.apache.nifi.web.api.entity.TransactionResultEntity;
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.HttpConfiguration;
-import org.eclipse.jetty.server.HttpConnectionFactory;
-import org.eclipse.jetty.server.SecureRequestCustomizer;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
@@ -117,7 +108,6 @@ public class TestHttpClient {
 
     private static Server server;
     private static ServerConnector httpConnector;
-    private static ServerConnector sslConnector;
     private static CountDownLatch testCaseFinished;
 
     private static HttpProxyServer proxyServer;
@@ -126,11 +116,8 @@ public class TestHttpClient {
     private static Set<PortDTO> inputPorts;
     private static Set<PortDTO> outputPorts;
     private static Set<PeerDTO> peers;
-    private static Set<PeerDTO> peersSecure;
     private static String serverChecksum;
 
-    private static TlsConfiguration tlsConfiguration;
-
     private static final int INITIAL_TRANSACTIONS = 0;
 
     private static final AtomicInteger outputExtendTransactions = new AtomicInteger(INITIAL_TRANSACTIONS);
@@ -141,16 +128,13 @@ public class TestHttpClient {
     public static class SiteInfoServlet extends HttpServlet {
 
         @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
 
             final ControllerDTO controller = new ControllerDTO();
 
             if (req.getLocalPort() == httpConnector.getLocalPort()) {
                 controller.setRemoteSiteHttpListeningPort(httpConnector.getLocalPort());
                 controller.setSiteToSiteSecure(false);
-            } else {
-                controller.setRemoteSiteHttpListeningPort(sslConnector.getLocalPort());
-                controller.setSiteToSiteSecure(true);
             }
 
             controller.setId("remote-controller-id");
@@ -175,7 +159,7 @@ public class TestHttpClient {
     public static class WrongSiteInfoServlet extends HttpServlet {
 
         @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
             // This response simulates when a Site-to-Site is given a URL which has wrong path.
             respondWithText(resp, "<p class=\"message-pane-content\">You may have mistyped...</p>", 200);
         }
@@ -184,16 +168,13 @@ public class TestHttpClient {
     public static class PeersServlet extends HttpServlet {
 
         @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
 
             final PeersEntity peersEntity = new PeersEntity();
 
             if (req.getLocalPort() == httpConnector.getLocalPort()) {
                 assertNotNull(peers, "Test case should set <peers> depending on the test scenario.");
                 peersEntity.setPeers(peers);
-            } else {
-                assertNotNull(peersSecure, "Test case should set <peersSecure> depending on the test scenario.");
-                peersEntity.setPeers(peersSecure);
             }
 
             respondWithJson(resp, peersEntity);
@@ -368,7 +349,7 @@ public class TestHttpClient {
         }
 
         @Override
-        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
 
             final int reqProtocolVersion = getReqProtocolVersion(req);
 
@@ -477,24 +458,10 @@ public class TestHttpClient {
         final ServletHandler wrongPathServletHandler = new ServletHandler();
         wrongPathContextHandler.insertHandler(wrongPathServletHandler);
 
-        final SslContextFactory sslContextFactory = new SslContextFactory.Server();
-
-        setTlsConfiguration();
-        sslContextFactory.setKeyStorePath(tlsConfiguration.getKeystorePath());
-        sslContextFactory.setKeyStorePassword(tlsConfiguration.getKeystorePassword());
-        sslContextFactory.setKeyStoreType(tlsConfiguration.getKeystoreType().getType());
-        sslContextFactory.setProtocol(TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion());
 
         httpConnector = new ServerConnector(server);
 
-        final HttpConfiguration https = new HttpConfiguration();
-        https.addCustomizer(new SecureRequestCustomizer());
-        sslConnector = new ServerConnector(server,
-                new SslConnectionFactory(sslContextFactory, "http/1.1"),
-                new HttpConnectionFactory(https));
-        logger.info("SSL Connector: " + sslConnector.dump());
-
-        server.setConnectors(new Connector[] { httpConnector, sslConnector });
+        server.setConnectors(new Connector[] { httpConnector });
 
         wrongPathServletHandler.addServletWithMapping(WrongSiteInfoServlet.class, "/site-to-site");
 
@@ -528,8 +495,6 @@ public class TestHttpClient {
 
         server.start();
 
-        logger.info("Starting server on port {} for HTTP, and {} for HTTPS", httpConnector.getLocalPort(), sslConnector.getLocalPort());
-
         startProxyServer();
         startProxyServerWithAuth();
     }
@@ -634,15 +599,6 @@ public class TestHttpClient {
         peers = new HashSet<>();
         peers.add(peer);
 
-        final PeerDTO peerSecure = new PeerDTO();
-        peerSecure.setHostname("localhost");
-        peerSecure.setPort(sslConnector.getLocalPort());
-        peerSecure.setFlowFileCount(10);
-        peerSecure.setSecure(true);
-
-        peersSecure = new HashSet<>();
-        peersSecure.add(peerSecure);
-
         inputPorts = new HashSet<>();
 
         final PortDTO runningInputPort = new PortDTO();
@@ -711,18 +667,6 @@ public class TestHttpClient {
                 ;
     }
 
-    private SiteToSiteClient.Builder getDefaultBuilderHTTPS() {
-        return new SiteToSiteClient.Builder().transportProtocol(SiteToSiteTransportProtocol.HTTP)
-                .url("https://localhost:" + sslConnector.getLocalPort() + "/nifi")
-                .timeout(3, TimeUnit.MINUTES)
-                .keystoreFilename(tlsConfiguration.getKeystorePath())
-                .keystorePass(tlsConfiguration.getKeystorePassword())
-                .keystoreType(KeystoreType.valueOf(tlsConfiguration.getKeystoreType().getType()))
-                .truststoreFilename(tlsConfiguration.getTruststorePath())
-                .truststorePass(tlsConfiguration.getTruststorePassword())
-                .truststoreType(KeystoreType.valueOf(tlsConfiguration.getTruststoreType().getType()));
-    }
-
     private static void consumeDataPacket(DataPacket packet) throws IOException {
         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
         StreamUtils.copy(packet.getData(), bos);
@@ -893,31 +837,6 @@ public class TestHttpClient {
 
     }
 
-    @Test
-    public void testSendAccessDeniedHTTPS() throws Exception {
-
-        try (
-                final SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("input-access-denied")
-                        .build()
-        ) {
-           assertThrows(HandshakeException.class, () -> client.createTransaction(TransferDirection.SEND));
-        }
-    }
-
-    @Test
-    public void testSendSuccessHTTPS() throws Exception {
-
-        try (
-                final SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("input-running")
-                        .build()
-        ) {
-            testSend(client);
-        }
-
-    }
-
     private interface SendData {
         void apply(final Transaction transaction) throws IOException;
     }
@@ -1013,47 +932,6 @@ public class TestHttpClient {
 
     }
 
-    @Test
-    public void testSendLargeFileHTTPS() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("input-running")
-                        .build()
-        ) {
-            testSendLargeFile(client);
-        }
-
-    }
-
-    @Test
-    public void testSendLargeFileHTTPSWithProxy() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("input-running")
-                        .httpProxy(new HttpProxy("localhost", proxyServer.getListenAddress().getPort(), null, null))
-                        .build()
-        ) {
-            testSendLargeFile(client);
-        }
-
-    }
-
-    @Test
-    public void testSendLargeFileHTTPSWithProxyAuth() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("input-running")
-                        .httpProxy(new HttpProxy("localhost", proxyServerWithAuth.getListenAddress().getPort(), PROXY_USER, PROXY_PASSWORD))
-                        .build()
-        ) {
-            testSendLargeFile(client);
-        }
-
-    }
-
     @Test
     public void testSendSuccessCompressed() throws Exception {
 
@@ -1264,44 +1142,6 @@ public class TestHttpClient {
         }
     }
 
-    @Test
-    public void testReceiveSuccessHTTPS() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("output-running")
-                        .build()
-        ) {
-            testReceive(client);
-        }
-    }
-
-    @Test
-    public void testReceiveSuccessHTTPSWithProxy() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("output-running")
-                        .httpProxy(new HttpProxy("localhost", proxyServer.getListenAddress().getPort(), null, null))
-                        .build()
-        ) {
-            testReceive(client);
-        }
-    }
-
-    @Test
-    public void testReceiveSuccessHTTPSWithProxyAuth() throws Exception {
-
-        try (
-                SiteToSiteClient client = getDefaultBuilderHTTPS()
-                        .portName("output-running")
-                        .httpProxy(new HttpProxy("localhost", proxyServerWithAuth.getListenAddress().getPort(), PROXY_USER, PROXY_PASSWORD))
-                        .build()
-        ) {
-            testReceive(client);
-        }
-    }
-
     @Test
     public void testReceiveSuccessCompressed() throws Exception {
 
@@ -1375,8 +1215,4 @@ public class TestHttpClient {
             assertNotSame(INITIAL_TRANSACTIONS, outputExtendTransactions.get());
         }
     }
-
-    private static void setTlsConfiguration() {
-        tlsConfiguration = new TemporaryKeyStoreBuilder().trustStoreType(KeystoreType.JKS.name()).build();
-    }
 }
diff --git a/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProviderTest.java b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProviderTest.java
new file mode 100644
index 0000000000..9fa921050b
--- /dev/null
+++ b/nifi-commons/nifi-site-to-site-client/src/test/java/org/apache/nifi/remote/client/socket/StandardSocketPeerIdentityProviderTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.remote.client.socket;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.security.auth.x500.X500Principal;
+import java.io.IOException;
+import java.net.Socket;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class StandardSocketPeerIdentityProviderTest {
+    private static final String DISTINGUISHED_NAME = "CN=Common Name,OU=Organizational Unit,O=Organization";
+
+    @Mock
+    SSLSocket sslSocket;
+
+    @Mock
+    SSLSession sslSession;
+
+    @Mock
+    X509Certificate peerCertificate;
+
+    StandardSocketPeerIdentityProvider provider;
+
+    @BeforeEach
+    void setProvider() {
+        provider = new StandardSocketPeerIdentityProvider();
+    }
+
+    @Test
+    void testGetPeerIdentityStandardSocket() throws IOException {
+        try (Socket socket = new Socket()) {
+            final Optional<String> peerIdentity = provider.getPeerIdentity(socket);
+
+            assertFalse(peerIdentity.isPresent());
+        }
+    }
+
+    @Test
+    void testGetPeerIdentitySSLSocketPeerUnverifiedException() throws SSLPeerUnverifiedException {
+        when(sslSocket.getSession()).thenReturn(sslSession);
+        when(sslSession.getPeerCertificates()).thenThrow(new SSLPeerUnverifiedException(SSLPeerUnverifiedException.class.getSimpleName()));
+
+        final Optional<String> peerIdentity = provider.getPeerIdentity(sslSocket);
+
+        assertFalse(peerIdentity.isPresent());
+    }
+
+    @Test
+    void testGetPeerIdentitySSLSocketPeerCertificatesNotFound() throws SSLPeerUnverifiedException {
+        when(sslSocket.getSession()).thenReturn(sslSession);
+        when(sslSession.getPeerCertificates()).thenReturn(new Certificate[]{});
+
+        final Optional<String> peerIdentity = provider.getPeerIdentity(sslSocket);
+
+        assertFalse(peerIdentity.isPresent());
+    }
+
+    @Test
+    void testGetPeerIdentityFound() throws SSLPeerUnverifiedException {
+        when(sslSocket.getSession()).thenReturn(sslSession);
+        when(sslSession.getPeerCertificates()).thenReturn(new X509Certificate[]{peerCertificate});
+
+        final X500Principal subjectDistinguishedName = new X500Principal(DISTINGUISHED_NAME);
+        when(peerCertificate.getSubjectDN()).thenReturn(subjectDistinguishedName);
+
+        final Optional<String> peerIdentity = provider.getPeerIdentity(sslSocket);
+
+        assertTrue(peerIdentity.isPresent());
+        final String identity = peerIdentity.get();
+        assertEquals(DISTINGUISHED_NAME, identity);
+    }
+}
diff --git a/nifi-commons/nifi-utils/pom.xml b/nifi-commons/nifi-utils/pom.xml
index 963cfb3463..13adbc70bb 100644
--- a/nifi-commons/nifi-utils/pom.xml
+++ b/nifi-commons/nifi-utils/pom.xml
@@ -39,6 +39,12 @@
             <artifactId>nifi-api</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <!-- Included for StringUtils -->
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-property-utils</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>jakarta.xml.bind</groupId>
             <artifactId>jakarta.xml.bind-api</artifactId>
diff --git a/nifi-commons/pom.xml b/nifi-commons/pom.xml
index 439bc17c9e..c37cd33664 100644
--- a/nifi-commons/pom.xml
+++ b/nifi-commons/pom.xml
@@ -54,6 +54,7 @@
         <module>nifi-repository-encryption</module>
         <module>nifi-schema-utils</module>
         <module>nifi-security-crypto-key</module>
+        <module>nifi-security-identity</module>
         <module>nifi-security-kerberos-api</module>
         <module>nifi-security-kerberos</module>
         <module>nifi-security-kms</module>
diff --git a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/pom.xml b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/pom.xml
index 304b7de3d9..b6fd7fa36a 100644
--- a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/pom.xml
@@ -136,6 +136,12 @@
             <version>2.0.0-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.icegreen</groupId>
             <artifactId>greenmail</artifactId>
diff --git a/nifi-nar-bundles/nifi-extension-utils/nifi-event-transport/pom.xml b/nifi-nar-bundles/nifi-extension-utils/nifi-event-transport/pom.xml
index 58595ba026..89e5cc10f1 100644
--- a/nifi-nar-bundles/nifi-extension-utils/nifi-event-transport/pom.xml
+++ b/nifi-nar-bundles/nifi-extension-utils/nifi-event-transport/pom.xml
@@ -32,6 +32,16 @@
             <artifactId>nifi-api</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-mock</artifactId>
diff --git a/nifi-nar-bundles/nifi-extension-utils/nifi-record-utils/nifi-standard-record-utils/pom.xml b/nifi-nar-bundles/nifi-extension-utils/nifi-record-utils/nifi-standard-record-utils/pom.xml
index 043948ed1f..e7211fe4d3 100644
--- a/nifi-nar-bundles/nifi-extension-utils/nifi-record-utils/nifi-standard-record-utils/pom.xml
+++ b/nifi-nar-bundles/nifi-extension-utils/nifi-record-utils/nifi-standard-record-utils/pom.xml
@@ -38,6 +38,10 @@
             <artifactId>nifi-security-socket-ssl</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils-api</artifactId>
+        </dependency>
         <!-- Other modules using nifi-standard-record-utils are expected to have these APIs available, typically through a NAR dependency -->
         <dependency>
             <groupId>org.apache.nifi</groupId>
diff --git a/nifi-nar-bundles/nifi-extension-utils/nifi-reporting-utils/pom.xml b/nifi-nar-bundles/nifi-extension-utils/nifi-reporting-utils/pom.xml
index 4fa2f3ec7b..3d45b23162 100644
--- a/nifi-nar-bundles/nifi-extension-utils/nifi-reporting-utils/pom.xml
+++ b/nifi-nar-bundles/nifi-extension-utils/nifi-reporting-utils/pom.xml
@@ -34,6 +34,10 @@
             <artifactId>nifi-utils</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.glassfish</groupId>
             <artifactId>javax.json</artifactId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/pom.xml
index d65a94ba62..9f9bdc60e3 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-documentation/pom.xml
@@ -45,7 +45,6 @@
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-utils</artifactId>
-            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
index bfe1947261..75f7dc7b88 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-file-authorizer/pom.xml
@@ -100,7 +100,8 @@
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
-            <artifactId>nifi-security-utils</artifactId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
index 6495e49b87..e02e27c18e 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/pom.xml
@@ -77,6 +77,11 @@
             <artifactId>nifi-security-kms</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-repository-encryption</artifactId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/pom.xml
index f0fa6dfe8c..2a7e8b0a7a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/pom.xml
@@ -38,6 +38,15 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-framework-core-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-mock</artifactId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/SocketRemoteSiteListener.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/SocketRemoteSiteListener.java
index 5f0284addc..d25edbcf2a 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/SocketRemoteSiteListener.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/main/java/org/apache/nifi/remote/SocketRemoteSiteListener.java
@@ -26,6 +26,10 @@ import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -33,7 +37,12 @@ import java.util.Optional;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.remote.cluster.ClusterNodeInformation;
 import org.apache.nifi.remote.cluster.NodeInformant;
@@ -46,7 +55,6 @@ import org.apache.nifi.remote.io.socket.SocketCommunicationsSession;
 import org.apache.nifi.remote.protocol.CommunicationsSession;
 import org.apache.nifi.remote.protocol.RequestType;
 import org.apache.nifi.remote.protocol.ServerProtocol;
-import org.apache.nifi.security.util.CertificateUtils;
 import org.apache.nifi.security.util.TlsConfiguration;
 import org.apache.nifi.util.NiFiProperties;
 import org.slf4j.Logger;
@@ -160,7 +168,8 @@ public class SocketRemoteSiteListener implements RemoteSiteListener {
                         try {
                             if (secure) {
                                 LOG.trace("{} Connection is secure", this);
-                                dn = CertificateUtils.extractPeerDNFromSSLSocket(socket);
+                                final SSLSocket sslSocket = (SSLSocket) socket;
+                                dn = getPeerIdentity(sslSocket);
 
                                 commsSession = new SocketCommunicationsSession(socket);
                                 commsSession.setUserDn(dn);
@@ -174,7 +183,7 @@ public class SocketRemoteSiteListener implements RemoteSiteListener {
                             // TODO: Add SocketProtocolListener#handleTlsError logic here
                             String msg = String.format("RemoteSiteListener Unable to accept connection from %s due to %s", socket, e.getLocalizedMessage());
                             // Suppress repeated TLS errors
-                            if (CertificateUtils.isTlsError(e)) {
+                            if (isTlsError(e)) {
                                 boolean printedAsWarning = handleTlsError(msg);
 
                                 // TODO: Move into handleTlsError and refactor shared behavior
@@ -320,6 +329,32 @@ public class SocketRemoteSiteListener implements RemoteSiteListener {
         listenerThread.start();
     }
 
+    private boolean isTlsError(final Throwable e) {
+        final boolean tlsError;
+
+        if (e instanceof SSLException || e instanceof GeneralSecurityException) {
+            tlsError = true;
+        } else if (e.getCause() == null) {
+            tlsError = false;
+        } else {
+            tlsError = isTlsError(e.getCause());
+        }
+
+        return tlsError;
+    }
+
+    private String getPeerIdentity(final SSLSocket sslSocket) throws SSLPeerUnverifiedException {
+        final SSLSession sslSession = sslSocket.getSession();
+        final Certificate[] peerCertificates = sslSession.getPeerCertificates();
+        if (peerCertificates == null || peerCertificates.length == 0) {
+            throw new SSLPeerUnverifiedException(String.format("Peer [%s] certificates not found", sslSocket.getRemoteSocketAddress()));
+        }
+
+        final X509Certificate peerCertificate = (X509Certificate) peerCertificates[0];
+        final Principal subjectDistinguishedName = peerCertificate.getSubjectDN();
+        return subjectDistinguishedName.getName();
+    }
+
     private boolean handleTlsError(String msg) {
         if (tlsErrorRecentlySeen()) {
             LOG.debug(msg);
@@ -331,7 +366,7 @@ public class SocketRemoteSiteListener implements RemoteSiteListener {
     }
 
     /**
-     * Returns {@code true} if any related exception (determined by {@link CertificateUtils#isTlsError(Throwable)}) has occurred within the last
+     * Returns {@code true} if any related exception has occurred within the last
      * {@link #EXCEPTION_THRESHOLD_MILLIS} milliseconds. Does not evaluate the error locally,
      * simply checks the last time the timestamp was updated.
      *
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/groovy/org/apache/nifi/remote/SocketRemoteSiteListenerTest.groovy b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/groovy/org/apache/nifi/remote/SocketRemoteSiteListenerTest.groovy
deleted file mode 100644
index 0a28a0aebd..0000000000
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/groovy/org/apache/nifi/remote/SocketRemoteSiteListenerTest.groovy
+++ /dev/null
@@ -1,127 +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.remote
-
-import org.apache.nifi.security.util.KeyStoreUtils
-import org.apache.nifi.security.util.KeystoreType
-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.util.NiFiProperties
-import org.bouncycastle.jce.provider.BouncyCastleProvider
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.BeforeAll
-import org.junit.jupiter.api.Test
-import org.slf4j.Logger
-import org.slf4j.LoggerFactory
-
-import javax.net.ssl.SSLContext
-import javax.net.ssl.SSLServerSocket
-import java.security.Security
-
-import static org.junit.jupiter.api.Assertions.assertArrayEquals
-import static org.junit.jupiter.api.Assertions.assertEquals
-import static org.junit.jupiter.api.Assertions.assertTrue
-
-class SocketRemoteSiteListenerTest {
-    private static final Logger logger = LoggerFactory.getLogger(SocketRemoteSiteListenerTest.class)
-
-    private static final String KEYSTORE_PATH = "src/test/resources/localhost-ks.jks"
-    private static final String KEYSTORE_PASSWORD = "OI7kMpWzzVNVx/JGhTL/0uO4+PWpGJ46uZ/pfepbkwI"
-    private static final KeystoreType KEYSTORE_TYPE = KeystoreType.JKS
-
-    private static final String TRUSTSTORE_PATH = "src/test/resources/localhost-ts.jks"
-    private static final String TRUSTSTORE_PASSWORD = "wAOR0nQJ2EXvOP0JZ2EaqA/n7W69ILS4sWAHghmIWCc"
-    private static final KeystoreType TRUSTSTORE_TYPE = KeystoreType.JKS
-
-    private static final String HOSTNAME = "localhost"
-    private static final int PORT = 0
-
-    // The nifi.properties in src/test/resources has 0.x properties and should be removed or updated
-    private static final Map<String, String> DEFAULT_PROPS = [
-            (NiFiProperties.SECURITY_KEYSTORE)         : KEYSTORE_PATH,
-            (NiFiProperties.SECURITY_KEYSTORE_PASSWD)  : KEYSTORE_PASSWORD,
-            (NiFiProperties.SECURITY_KEYSTORE_TYPE)    : KEYSTORE_TYPE.getType(),
-            (NiFiProperties.SECURITY_TRUSTSTORE)       : TRUSTSTORE_PATH,
-            (NiFiProperties.SECURITY_TRUSTSTORE_PASSWD): TRUSTSTORE_PASSWORD,
-            (NiFiProperties.SECURITY_TRUSTSTORE_TYPE)  : TRUSTSTORE_TYPE.getType(),
-            (NiFiProperties.REMOTE_INPUT_HOST): HOSTNAME,
-            (NiFiProperties.REMOTE_INPUT_PORT): PORT as String,
-            "nifi.remote.input.secure": "true"
-    ]
-
-    private NiFiProperties mockNiFiProperties = NiFiProperties.createBasicNiFiProperties("", DEFAULT_PROPS)
-
-    private static TlsConfiguration tlsConfiguration
-    private static SSLContext sslContext
-
-    private SocketRemoteSiteListener srsListener
-
-    @BeforeAll
-    static void setUpOnce() throws Exception {
-        Security.addProvider(new BouncyCastleProvider())
-
-        logger.metaClass.methodMissing = { String name, args ->
-            logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}")
-        }
-
-        tlsConfiguration = new StandardTlsConfiguration(KEYSTORE_PATH, KEYSTORE_PASSWORD, KEYSTORE_TYPE, TRUSTSTORE_PATH, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE)
-        sslContext = SslContextFactory.createSslContext(tlsConfiguration)
-    }
-
-    @AfterEach
-    void tearDown() {
-        if (srsListener) {
-            srsListener.stop()
-        }
-    }
-
-    /**
-     * Asserts that the protocol versions in the parameters object are correct. In recent versions of Java, this enforces order as well, but in older versions, it just enforces presence.
-     *
-     * @param enabledProtocols the actual protocols, either in {@code String[]} or {@code Collection<String>} form
-     * @param expectedProtocols the specific protocol versions to be present (ordered as desired)
-     */
-    static void assertProtocolVersions(def enabledProtocols, def expectedProtocols) {
-        if (TlsConfiguration.getJavaVersion() > 8) {
-            assertArrayEquals(expectedProtocols as String[], enabledProtocols)
-        } else {
-            assertEquals(expectedProtocols as Set, enabledProtocols as Set)
-        }
-    }
-
-    @Test
-    void testShouldCreateSecureServer() {
-        // Arrange
-        logger.info("Creating SSL Context from TLS Configuration: ${tlsConfiguration}")
-        SSLContext sslContext = SslContextFactory.createSslContext(tlsConfiguration)
-        logger.info("Created SSL Context: ${KeyStoreUtils.sslContextToString(sslContext)}")
-
-        srsListener = new SocketRemoteSiteListener(PORT, sslContext, mockNiFiProperties)
-
-        // Act
-        srsListener.start()
-
-        // Assert
-
-        // serverSocket isn't instance field like CLBS so have to use private method invocation to verify
-        SSLServerSocket sslServerSocket = srsListener.createServerSocket() as SSLServerSocket
-        logger.info("Created SSL server socket: ${KeyStoreUtils.sslServerSocketToString(sslServerSocket)}" as String)
-        assertProtocolVersions(sslServerSocket.enabledProtocols, TlsConfiguration.getCurrentSupportedTlsProtocolVersions())
-        assertTrue(sslServerSocket.needClientAuth)
-    }
-}
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ks.jks b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ks.jks
deleted file mode 100755
index 6db775d765..0000000000
Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ks.jks and /dev/null differ
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ts.jks b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ts.jks
deleted file mode 100755
index 5a4fd2d292..0000000000
Binary files a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/localhost-ts.jks and /dev/null differ
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/pom.xml
index 95100028eb..08966d6632 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/pom.xml
@@ -187,6 +187,12 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-xml-processing</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-web-security</artifactId>
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
index e6f00df2d6..9ae1be82bd 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/pom.xml
@@ -101,6 +101,11 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-security-utils</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-framework-core</artifactId>
diff --git a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-parameter-providers/pom.xml b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-parameter-providers/pom.xml
index 6cfbf230ce..65aafb4b4d 100644
--- a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-parameter-providers/pom.xml
+++ b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-parameter-providers/pom.xml
@@ -32,7 +32,6 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-utils</artifactId>
             <version>2.0.0-SNAPSHOT</version>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
diff --git a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml
index f6ca193b4e..9b40a352d3 100644
--- a/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml
+++ b/nifi-nar-bundles/nifi-ldap-iaa-providers-bundle/nifi-ldap-iaa-providers/pom.xml
@@ -41,6 +41,11 @@
             <artifactId>nifi-security-utils</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-identity</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-properties</artifactId>
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-record-sink-service-bundle/nifi-record-sink-service/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-record-sink-service-bundle/nifi-record-sink-service/pom.xml
index d8d03c4cc3..bda8d00109 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-record-sink-service-bundle/nifi-record-sink-service/pom.xml
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-record-sink-service-bundle/nifi-record-sink-service/pom.xml
@@ -59,6 +59,11 @@
             <artifactId>nifi-event-transport</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils-api</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-mock</artifactId>
diff --git a/nifi-nar-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/pom.xml b/nifi-nar-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/pom.xml
index 50fc33db6a..5383368a08 100644
--- a/nifi-nar-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/pom.xml
+++ b/nifi-nar-bundles/nifi-standard-services/nifi-web-client-provider-bundle/nifi-web-client-provider-service/pom.xml
@@ -57,6 +57,12 @@
             <artifactId>nifi-utils</artifactId>
             <version>2.0.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-security-utils</artifactId>
+            <version>2.0.0-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-mock</artifactId>