ENT-11118: Netty SSL handshake fix (#5028)

* ENT-11118: Added fix for netty SSL handshake fail
This commit is contained in:
Tom Stark 2023-12-15 16:24:11 +00:00 committed by tomstark99
parent bf6fcb2a8f
commit 71e187dddb

View File

@ -4,13 +4,19 @@ import io.netty.handler.ssl.SslContext
import io.netty.handler.ssl.SslContextBuilder import io.netty.handler.ssl.SslContextBuilder
import io.netty.handler.ssl.SslProvider import io.netty.handler.ssl.SslProvider
import net.corda.nodeapi.internal.ArtemisTcpTransport.Companion.TRUST_MANAGER_FACTORY_NAME import net.corda.nodeapi.internal.ArtemisTcpTransport.Companion.TRUST_MANAGER_FACTORY_NAME
import net.corda.nodeapi.internal.config.CertificateStore
import net.corda.nodeapi.internal.protonwrapper.netty.createAndInitSslContext import net.corda.nodeapi.internal.protonwrapper.netty.createAndInitSslContext
import net.corda.nodeapi.internal.protonwrapper.netty.keyManagerFactory
import org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultOpenSSLContextFactory import org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultOpenSSLContextFactory
import org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultSSLContextFactory import org.apache.activemq.artemis.core.remoting.impl.ssl.DefaultSSLContextFactory
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextConfig import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextConfig
import java.nio.file.Paths import org.apache.activemq.artemis.utils.ClassloadingUtil
import org.apache.commons.io.IOUtils
import java.io.File
import java.io.InputStream
import java.net.MalformedURLException
import java.net.URL
import java.security.AccessController
import java.security.KeyStore
import java.security.PrivilegedAction
import javax.net.ssl.KeyManagerFactory import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory import javax.net.ssl.TrustManagerFactory
@ -54,6 +60,69 @@ class NodeOpenSSLContextFactory : DefaultOpenSSLContextFactory() {
private fun loadKeyManagerFactory(config: SSLContextConfig): KeyManagerFactory { private fun loadKeyManagerFactory(config: SSLContextConfig): KeyManagerFactory {
val keyStore = CertificateStore.fromFile(Paths.get(config.keystorePath), config.keystorePassword, config.keystorePassword, false) val keyStore = loadKeystore(config.keystoreProvider, config.keystoreType, config.keystorePath, config.keystorePassword)
return keyManagerFactory(keyStore) val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
keyManagerFactory.init(keyStore, config.keystorePassword?.toCharArray())
return keyManagerFactory
} }
/**
* This is a copy of [SSLSupport.loadKeystore] so that we can use the [NodeSSLContextFactory] and
* maintain keystore loading with the correct [keystoreProvider].
*/
private fun loadKeystore(
keystoreProvider: String?,
keystoreType: String,
keystorePath: String?,
keystorePassword: String?
) : KeyStore {
val keyStore = keystoreProvider?.let { KeyStore.getInstance(keystoreType, it) } ?: KeyStore.getInstance(keystoreType)
var inputStream : InputStream? = null
try {
if (keystorePath != null && keystorePath.isNotEmpty()) {
val keystoreURL = validateStoreURL(keystorePath)
inputStream = keystoreURL.openStream()
}
keyStore.load(inputStream, keystorePassword?.toCharArray())
} finally {
inputStream?.closeQuietly()
}
return keyStore
}
/**
* This is a copy of [SSLSupport.validateStoreURL] so we can have a full copy of
* [SSLSupport.loadKeystore].
*/
private fun validateStoreURL(storePath: String): URL {
return try {
URL(storePath)
} catch (e: MalformedURLException) {
val file = File(storePath)
if (file.exists() && file.isFile) {
file.toURI().toURL()
} else {
findResource(storePath)
}
}
}
/**
* This is a copy of [SSLSupport.findResource] so we can have a full copy of
* [SSLSupport.validateStoreURL] and.
*/
private fun findResource(resourceName: String): URL {
return AccessController.doPrivileged(PrivilegedAction {
ClassloadingUtil.findResource(resourceName)
})
}
/**
* This is an inline function for [InputStream] so it can be closed and
* ignore an exception.
*/
private fun InputStream?.closeQuietly() = IOUtils.closeQuietly(this)