mirror of
https://github.com/corda/corda.git
synced 2025-06-18 15:18:16 +00:00
Make SSL optional in the RPC client
This commit is contained in:
@ -19,10 +19,9 @@ import java.nio.file.Path
|
|||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base class for Artemis services that defines shared data structures and transport configuration
|
* The base class for Artemis services that defines shared data structures and SSL transport configuration.
|
||||||
*/
|
*/
|
||||||
abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
init {
|
init {
|
||||||
System.setProperty("org.jboss.logging.provider", "slf4j")
|
System.setProperty("org.jboss.logging.provider", "slf4j")
|
||||||
@ -106,7 +105,7 @@ abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The config object is used to pass in the passwords for the certificate KeyStore and TrustStore */
|
/** The config object is used to pass in the passwords for the certificate KeyStore and TrustStore */
|
||||||
abstract val config: NodeSSLConfiguration
|
abstract val config: NodeSSLConfiguration?
|
||||||
|
|
||||||
// Restrict enabled Cipher Suites to AES and GCM as minimum for the bulk cipher.
|
// Restrict enabled Cipher Suites to AES and GCM as minimum for the bulk cipher.
|
||||||
// Our self-generated certificates all use ECDSA for handshakes, but we allow classical RSA certificates to work
|
// Our self-generated certificates all use ECDSA for handshakes, but we allow classical RSA certificates to work
|
||||||
@ -126,6 +125,7 @@ abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
|||||||
* unfortunately Artemis tends to bury the exception when the password is wrong.
|
* unfortunately Artemis tends to bury the exception when the password is wrong.
|
||||||
*/
|
*/
|
||||||
fun checkStorePasswords() {
|
fun checkStorePasswords() {
|
||||||
|
val config = config ?: return
|
||||||
config.keyStorePath.read {
|
config.keyStorePath.read {
|
||||||
KeyStore.getInstance("JKS").load(it, config.keyStorePassword.toCharArray())
|
KeyStore.getInstance("JKS").load(it, config.keyStorePassword.toCharArray())
|
||||||
}
|
}
|
||||||
@ -135,14 +135,8 @@ abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun tcpTransport(direction: ConnectionDirection, host: String, port: Int): TransportConfiguration {
|
protected fun tcpTransport(direction: ConnectionDirection, host: String, port: Int): TransportConfiguration {
|
||||||
config.keyStorePath.expectedOnDefaultFileSystem()
|
val config = config
|
||||||
config.trustStorePath.expectedOnDefaultFileSystem()
|
val options = mutableMapOf<String, Any?>(
|
||||||
return TransportConfiguration(
|
|
||||||
when (direction) {
|
|
||||||
is Inbound -> NettyAcceptorFactory::class.java.name
|
|
||||||
is Outbound -> VerifyingNettyConnectorFactory::class.java.name
|
|
||||||
},
|
|
||||||
mapOf(
|
|
||||||
// Basic TCP target details
|
// Basic TCP target details
|
||||||
TransportConstants.HOST_PROP_NAME to host,
|
TransportConstants.HOST_PROP_NAME to host,
|
||||||
TransportConstants.PORT_PROP_NAME to port,
|
TransportConstants.PORT_PROP_NAME to port,
|
||||||
@ -151,8 +145,13 @@ abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
|||||||
// Unfortunately we cannot disable core protocol as artemis only uses AMQP for interop
|
// Unfortunately we cannot disable core protocol as artemis only uses AMQP for interop
|
||||||
// It does not use AMQP messages for its own messages e.g. topology and heartbeats
|
// It does not use AMQP messages for its own messages e.g. topology and heartbeats
|
||||||
// TODO further investigate how to ensure we use a well defined wire level protocol for Node to Node communications
|
// TODO further investigate how to ensure we use a well defined wire level protocol for Node to Node communications
|
||||||
TransportConstants.PROTOCOLS_PROP_NAME to "CORE,AMQP",
|
TransportConstants.PROTOCOLS_PROP_NAME to "CORE,AMQP"
|
||||||
|
)
|
||||||
|
|
||||||
|
if (config != null) {
|
||||||
|
config.keyStorePath.expectedOnDefaultFileSystem()
|
||||||
|
config.trustStorePath.expectedOnDefaultFileSystem()
|
||||||
|
val tlsOptions = mapOf<String, Any?>(
|
||||||
// Enable TLS transport layer with client certs and restrict to at least SHA256 in handshake
|
// Enable TLS transport layer with client certs and restrict to at least SHA256 in handshake
|
||||||
// and AES encryption
|
// and AES encryption
|
||||||
TransportConstants.SSL_ENABLED_PROP_NAME to true,
|
TransportConstants.SSL_ENABLED_PROP_NAME to true,
|
||||||
@ -167,7 +166,13 @@ abstract class ArtemisMessagingComponent() : SingletonSerializeAsToken() {
|
|||||||
TransportConstants.NEED_CLIENT_AUTH_PROP_NAME to true,
|
TransportConstants.NEED_CLIENT_AUTH_PROP_NAME to true,
|
||||||
VERIFY_PEER_COMMON_NAME to (direction as? Outbound)?.expectedCommonName
|
VERIFY_PEER_COMMON_NAME to (direction as? Outbound)?.expectedCommonName
|
||||||
)
|
)
|
||||||
)
|
options.putAll(tlsOptions)
|
||||||
|
}
|
||||||
|
val factoryName = when (direction) {
|
||||||
|
is Inbound -> NettyAcceptorFactory::class.java.name
|
||||||
|
is Outbound -> VerifyingNettyConnectorFactory::class.java.name
|
||||||
|
}
|
||||||
|
return TransportConfiguration(factoryName, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun Path.expectedOnDefaultFileSystem() {
|
protected fun Path.expectedOnDefaultFileSystem() {
|
||||||
|
@ -17,9 +17,12 @@ import javax.annotation.concurrent.ThreadSafe
|
|||||||
/**
|
/**
|
||||||
* An RPC client connects to the specified server and allows you to make calls to the server that perform various
|
* An RPC client connects to the specified server and allows you to make calls to the server that perform various
|
||||||
* useful tasks. See the documentation for [proxy] or review the docsite to learn more about how this API works.
|
* useful tasks. See the documentation for [proxy] or review the docsite to learn more about how this API works.
|
||||||
|
*
|
||||||
|
* @param host The hostname and messaging port of the node.
|
||||||
|
* @param config If specified, the SSL configuration to use. If not specified, SSL will be disabled and the node will not be authenticated, nor will RPC traffic be encrypted.
|
||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
class CordaRPCClient(val host: HostAndPort, override val config: NodeSSLConfiguration) : Closeable, ArtemisMessagingComponent() {
|
class CordaRPCClient(val host: HostAndPort, override val config: NodeSSLConfiguration?) : Closeable, ArtemisMessagingComponent() {
|
||||||
// TODO: Certificate handling for clients needs more work.
|
// TODO: Certificate handling for clients needs more work.
|
||||||
private inner class State {
|
private inner class State {
|
||||||
var running = false
|
var running = false
|
||||||
@ -106,6 +109,7 @@ class CordaRPCClient(val host: HostAndPort, override val config: NodeSSLConfigur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNUSED")
|
||||||
private fun finalize() {
|
private fun finalize() {
|
||||||
state.locked {
|
state.locked {
|
||||||
if (running) {
|
if (running) {
|
||||||
|
Reference in New Issue
Block a user