Checks for SSL certificate on Node startup

This commit is contained in:
Patrick Kuo 2016-09-22 15:38:19 +01:00
parent 46d6749616
commit 8f00ec03a3
5 changed files with 40 additions and 21 deletions

View File

@ -3,6 +3,7 @@ package com.r3corda.node.driver
import com.google.common.net.HostAndPort
import com.r3corda.core.ThreadBox
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.X509Utilities
import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.NetworkMapCache

View File

@ -6,6 +6,7 @@ import com.google.common.util.concurrent.MoreExecutors
import com.google.common.util.concurrent.SettableFuture
import com.r3corda.core.RunOnCallerThread
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.X509Utilities
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.messaging.createMessage
import com.r3corda.core.messaging.runOnNextMessage
@ -158,6 +159,13 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val networkMap
open fun start(): AbstractNode {
require(!started) { "Node has already been started" }
if (configuration.devMode) {
log.warn("Corda node is running in dev mode.")
configuration.configureWithDevSSLCertificate()
}
require(hasSSLCertificates()) { "SSL certificates not found." }
log.info("Node starting up ...")
// Do all of this in a database transaction so anything that might need a connection has one.
@ -226,6 +234,16 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val networkMap
return this
}
private fun hasSSLCertificates(): Boolean {
val keyStore = try {
// This will throw exception if key file not found or keystore password is incorrect.
X509Utilities.loadKeyStore(configuration.keyStorePath, configuration.keyStorePassword)
} catch (e: Exception) {
null
}
return keyStore?.containsAlias(X509Utilities.CORDA_CLIENT_CA) ?: false
}
// Specific class so that MockNode can catch it.
class DatabaseConfigurationException(msg: String) : Exception(msg)

View File

@ -133,7 +133,6 @@ class Node(val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
override fun startMessagingService() {
// Start up the embedded MQ server
messageBroker?.apply {
configureWithDevSSLCertificate() // TODO: Create proper certificate provisioning process
runOnStop += Runnable { messageBroker?.stop() }
start()
bridgeToNetworkMapService(networkMapService)
@ -141,7 +140,6 @@ class Node(val p2pAddr: HostAndPort, val webServerAddr: HostAndPort,
// Start up the MQ client.
(net as NodeMessagingClient).apply {
configureWithDevSSLCertificate() // TODO: Client might need a separate certificate
start()
}
}

View File

@ -1,6 +1,7 @@
package com.r3corda.node.services.config
import com.google.common.net.HostAndPort
import com.r3corda.core.crypto.X509Utilities
import com.r3corda.core.div
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.services.ServiceType
@ -14,6 +15,7 @@ import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigParseOptions
import com.typesafe.config.ConfigRenderOptions
import org.slf4j.LoggerFactory
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.time.Clock
@ -29,6 +31,24 @@ interface NodeSSLConfiguration {
val certificatesPath: Path
val keyStorePath: Path get() = certificatesPath / "sslkeystore.jks"
val trustStorePath: Path get() = certificatesPath / "truststore.jks"
/**
* Strictly for dev only automatically construct a server certificate/private key signed from
* the CA certs in Node resources. Then provision KeyStores into certificates folder under node path.
*/
fun configureWithDevSSLCertificate() {
Files.createDirectories(certificatesPath)
if (!Files.exists(trustStorePath)) {
Files.copy(javaClass.classLoader.getResourceAsStream("com/r3corda/node/internal/certificates/cordatruststore.jks"),
trustStorePath)
}
if (!Files.exists(keyStorePath)) {
val caKeyStore = X509Utilities.loadKeyStore(
javaClass.classLoader.getResourceAsStream("com/r3corda/node/internal/certificates/cordadevcakeys.jks"),
"cordacadevpass")
X509Utilities.createKeystoreForSSL(keyStorePath, keyStorePassword, keyStorePassword, caKeyStore, "cordacadevkeypass")
}
}
}
interface NodeConfiguration : NodeSSLConfiguration {

View File

@ -2,10 +2,8 @@ package com.r3corda.node.services.messaging
import com.google.common.annotations.VisibleForTesting
import com.google.common.net.HostAndPort
import com.r3corda.core.crypto.X509Utilities
import com.r3corda.core.crypto.parsePublicKeyBase58
import com.r3corda.core.crypto.toBase58String
import com.r3corda.core.div
import com.r3corda.core.messaging.MessageRecipients
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.serialization.SingletonSerializeAsToken
@ -16,8 +14,6 @@ import org.apache.activemq.artemis.api.core.TransportConfiguration
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants
import java.nio.file.Files
import java.nio.file.Path
import java.security.KeyStore
import java.security.PublicKey
@ -154,21 +150,7 @@ abstract class ArtemisMessagingComponent(val config: NodeSSLConfiguration) : Sin
)
)
/**
* Strictly for dev only automatically construct a server certificate/private key signed from
* the CA certs in Node resources. Then provision KeyStores into certificates folder under node path.
*/
fun configureWithDevSSLCertificate() {
Files.createDirectories(config.certificatesPath)
if (!Files.exists(config.trustStorePath)) {
Files.copy(javaClass.classLoader.getResourceAsStream("com/r3corda/node/internal/certificates/cordatruststore.jks"),
config.trustStorePath)
}
if (!Files.exists(config.keyStorePath)) {
val caKeyStore = X509Utilities.loadKeyStore(
javaClass.classLoader.getResourceAsStream("com/r3corda/node/internal/certificates/cordadevcakeys.jks"),
"cordacadevpass")
X509Utilities.createKeystoreForSSL(config.keyStorePath, config.keyStorePassword, config.keyStorePassword, caKeyStore, "cordacadevkeypass")
}
config.configureWithDevSSLCertificate()
}
}