Enforce X.500 distinguished names in configuration

This commit is contained in:
Ross Nicoll 2017-04-27 18:39:46 +01:00
parent 8c3b9ac589
commit b64e7f51f6
35 changed files with 163 additions and 133 deletions

View File

@ -20,6 +20,7 @@ import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ
import org.bouncycastle.asn1.x500.X500Name
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import java.util.* import java.util.*
@ -74,7 +75,7 @@ abstract class AbstractClientRPCTest {
override val users: List<User> get() = listOf(rpcUser) override val users: List<User> get() = listOf(rpcUser)
} }
val dispatcher = object : RPCDispatcher(rpcImpl, userService, ALICE.name) { val dispatcher = object : RPCDispatcher(rpcImpl, userService, X500Name(ALICE.name)) {
override fun send(data: SerializedBytes<*>, toAddress: String) { override fun send(data: SerializedBytes<*>, toAddress: String) {
val msg = serverSession.createMessage(false).apply { val msg = serverSession.createMessage(false).apply {
writeBodyBufferBytes(data.bytes) writeBodyBufferBytes(data.bytes)

View File

@ -110,6 +110,8 @@ object X509Utilities {
* Return a bogus X509 for dev purposes. Use [getX509Name] for something more real. * Return a bogus X509 for dev purposes. Use [getX509Name] for something more real.
*/ */
fun getDevX509Name(commonName: String): X500Name { fun getDevX509Name(commonName: String): X500Name {
// Check that we haven't been accidentally given a full X500 distinguished name
require(!commonName.startsWith("CN=")) { "Provided common name must not start \"CN=\"" }
val nameBuilder = X500NameBuilder(BCStyle.INSTANCE) val nameBuilder = X500NameBuilder(BCStyle.INSTANCE)
nameBuilder.addRDN(BCStyle.CN, commonName) nameBuilder.addRDN(BCStyle.CN, commonName)
nameBuilder.addRDN(BCStyle.O, "R3") nameBuilder.addRDN(BCStyle.O, "R3")

View File

@ -4,6 +4,7 @@ import com.google.common.net.HostAndPort
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigUtil import com.typesafe.config.ConfigUtil
import net.corda.core.noneOrSingle import net.corda.core.noneOrSingle
import org.bouncycastle.asn1.x500.X500Name
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.net.Proxy import java.net.Proxy
import java.net.URL import java.net.URL
@ -70,6 +71,7 @@ private fun Config.getSingleValue(path: String, type: KType): Any? {
Path::class -> Paths.get(getString(path)) Path::class -> Paths.get(getString(path))
URL::class -> URL(getString(path)) URL::class -> URL(getString(path))
Properties::class -> getConfig(path).toProperties() Properties::class -> getConfig(path).toProperties()
X500Name::class -> X500Name(getString(path))
else -> if (typeClass.java.isEnum) { else -> if (typeClass.java.isEnum) {
parseEnum(typeClass.java, getString(path)) parseEnum(typeClass.java, getString(path))
} else { } else {

View File

@ -8,6 +8,7 @@ import net.corda.core.node.services.ServiceInfo
import net.corda.core.readLines import net.corda.core.readLines
import net.corda.core.utilities.DUMMY_BANK_A import net.corda.core.utilities.DUMMY_BANK_A
import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.core.utilities.DUMMY_REGULATOR
import net.corda.node.LOGS_DIRECTORY_NAME import net.corda.node.LOGS_DIRECTORY_NAME
import net.corda.node.services.api.RegulatorService import net.corda.node.services.api.RegulatorService
import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.services.transactions.SimpleNotaryService
@ -42,7 +43,7 @@ class DriverTests {
fun `simple node startup and shutdown`() { fun `simple node startup and shutdown`() {
val handles = driver { val handles = driver {
val notary = startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type))) val notary = startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type)))
val regulator = startNode("CN=Regulator,O=R3,OU=corda,L=London,C=UK", setOf(ServiceInfo(RegulatorService.type))) val regulator = startNode(DUMMY_REGULATOR.name, setOf(ServiceInfo(RegulatorService.type)))
listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator)) listOf(nodeMustBeUp(notary), nodeMustBeUp(regulator))
} }
handles.map { nodeMustBeDown(it) } handles.map { nodeMustBeDown(it) }

View File

@ -3,6 +3,7 @@ package net.corda.services.messaging
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.* import net.corda.core.*
import net.corda.core.crypto.X509Utilities
import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
import net.corda.core.node.services.DEFAULT_SESSION_ID import net.corda.core.node.services.DEFAULT_SESSION_ID
@ -19,6 +20,7 @@ import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.testing.freeLocalHostAndPort import net.corda.testing.freeLocalHostAndPort
import net.corda.testing.node.NodeBasedTest import net.corda.testing.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import java.util.concurrent.CountDownLatch import java.util.concurrent.CountDownLatch
@ -27,6 +29,11 @@ import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
class P2PMessagingTest : NodeBasedTest() { class P2PMessagingTest : NodeBasedTest() {
private companion object {
val DISTRIBUTED_SERVICE_NAME = X509Utilities.getDevX509Name("DistributedService")
val SERVICE_2_NAME = X509Utilities.getDevX509Name("Service Node 2")
}
@Test @Test
fun `network map will work after restart`() { fun `network map will work after restart`() {
val identities = listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY) val identities = listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY)
@ -55,15 +62,14 @@ class P2PMessagingTest : NodeBasedTest() {
// TODO Use a dummy distributed service // TODO Use a dummy distributed service
@Test @Test
fun `communicating with a distributed service which the network map node is part of`() { fun `communicating with a distributed service which the network map node is part of`() {
val serviceName = "DistributedService"
val root = tempFolder.root.toPath() val root = tempFolder.root.toPath()
ServiceIdentityGenerator.generateToDisk( ServiceIdentityGenerator.generateToDisk(
listOf(root / DUMMY_MAP.name, root / "Service Node 2"), listOf(root / DUMMY_MAP.name.toString(), root / SERVICE_2_NAME.toString()),
RaftValidatingNotaryService.type.id, RaftValidatingNotaryService.type.id,
serviceName) DISTRIBUTED_SERVICE_NAME)
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, serviceName) val distributedService = ServiceInfo(RaftValidatingNotaryService.type, DISTRIBUTED_SERVICE_NAME)
val notaryClusterAddress = freeLocalHostAndPort() val notaryClusterAddress = freeLocalHostAndPort()
startNetworkMapNode( startNetworkMapNode(
DUMMY_MAP.name, DUMMY_MAP.name,
@ -71,7 +77,7 @@ class P2PMessagingTest : NodeBasedTest() {
configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString())) configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
val (serviceNode2, alice) = Futures.allAsList( val (serviceNode2, alice) = Futures.allAsList(
startNode( startNode(
"Service Node 2", SERVICE_2_NAME,
advertisedServices = setOf(distributedService), advertisedServices = setOf(distributedService),
configOverrides = mapOf( configOverrides = mapOf(
"notaryNodeAddress" to freeLocalHostAndPort().toString(), "notaryNodeAddress" to freeLocalHostAndPort().toString(),
@ -79,14 +85,13 @@ class P2PMessagingTest : NodeBasedTest() {
startNode(ALICE.name) startNode(ALICE.name)
).getOrThrow() ).getOrThrow()
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), serviceName, alice) assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), DISTRIBUTED_SERVICE_NAME, alice)
} }
@Test @Test
fun `communicating with a distributed service which we're part of`() { fun `communicating with a distributed service which we're part of`() {
val serviceName = "Distributed Service" val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow()
val distributedService = startNotaryCluster(serviceName, 2).getOrThrow() assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0])
assertAllNodesAreUsed(distributedService, serviceName, distributedService[0])
} }
@Test @Test
@ -183,13 +188,13 @@ class P2PMessagingTest : NodeBasedTest() {
return Pair(firstRequestReceived, requestsReceived) return Pair(firstRequestReceived, requestsReceived)
} }
private fun assertAllNodesAreUsed(participatingServiceNodes: List<Node>, serviceName: String, originatingNode: Node) { private fun assertAllNodesAreUsed(participatingServiceNodes: List<Node>, serviceName: X500Name, originatingNode: Node) {
// Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used // Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used
participatingServiceNodes.forEach { node -> participatingServiceNodes.forEach { node ->
node.respondWith(node.info) node.respondWith(node.info)
} }
val serviceAddress = originatingNode.services.networkMapCache.run { val serviceAddress = originatingNode.services.networkMapCache.run {
originatingNode.net.getAddressOfParty(getPartyInfo(getNotary(serviceName)!!)!!) originatingNode.net.getAddressOfParty(getPartyInfo(getNotary(serviceName.toString())!!)!!)
} }
val participatingNodes = HashSet<Any>() val participatingNodes = HashSet<Any>()
// Try several times so that we can be fairly sure that any node not participating is not due to Artemis' selection // Try several times so that we can be fairly sure that any node not participating is not due to Artemis' selection

View File

@ -2,12 +2,15 @@ package net.corda.services.messaging
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.crypto.Party import net.corda.core.crypto.Party
import net.corda.core.crypto.commonName
import net.corda.core.div import net.corda.core.div
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.random63BitValue import net.corda.core.random63BitValue
import net.corda.core.seconds import net.corda.core.seconds
import net.corda.core.utilities.BOB import net.corda.core.utilities.BOB
import net.corda.core.utilities.DUMMY_BANK_A
import net.corda.core.utilities.DUMMY_BANK_B
import net.corda.node.internal.NetworkMapInfo import net.corda.node.internal.NetworkMapInfo
import net.corda.node.services.config.configureWithDevSSLCertificate import net.corda.node.services.config.configureWithDevSSLCertificate
import net.corda.node.services.messaging.sendRequest import net.corda.node.services.messaging.sendRequest
@ -21,6 +24,7 @@ import net.corda.testing.node.NodeBasedTest
import net.corda.testing.node.SimpleNode import net.corda.testing.node.SimpleNode
import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import java.time.Instant import java.time.Instant
import java.util.concurrent.TimeoutException import java.util.concurrent.TimeoutException
@ -42,9 +46,9 @@ class P2PSecurityTest : NodeBasedTest() {
@Test @Test
fun `register with the network map service using a legal name different from the TLS CN`() { fun `register with the network map service using a legal name different from the TLS CN`() {
startSimpleNode("CN=Attacker,O=R3,OU=corda,L=London,C=UK").use { startSimpleNode(X500Name(DUMMY_BANK_A.name)).use {
// Register with the network map using a different legal name // Register with the network map using a different legal name
val response = it.registerWithNetworkMap("CN=Legit Business,O=R3,OU=corda,L=London,C=UK") val response = it.registerWithNetworkMap(X500Name(DUMMY_BANK_B.name))
// We don't expect a response because the network map's host verification will prevent a connection back // We don't expect a response because the network map's host verification will prevent a connection back
// to the attacker as the TLS CN will not match the legal name it has just provided // to the attacker as the TLS CN will not match the legal name it has just provided
assertThatExceptionOfType(TimeoutException::class.java).isThrownBy { assertThatExceptionOfType(TimeoutException::class.java).isThrownBy {
@ -53,16 +57,16 @@ class P2PSecurityTest : NodeBasedTest() {
} }
} }
private fun startSimpleNode(legalName: String): SimpleNode { private fun startSimpleNode(legalName: X500Name): SimpleNode {
val config = TestNodeConfiguration( val config = TestNodeConfiguration(
baseDirectory = tempFolder.root.toPath() / legalName, baseDirectory = tempFolder.root.toPath() / legalName.commonName,
myLegalName = legalName, myLegalName = legalName,
networkMapService = NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name)) networkMapService = NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name config.configureWithDevSSLCertificate() // This creates the node's TLS cert with the CN as the legal name
return SimpleNode(config).apply { start() } return SimpleNode(config).apply { start() }
} }
private fun SimpleNode.registerWithNetworkMap(registrationName: String): ListenableFuture<NetworkMapService.RegistrationResponse> { private fun SimpleNode.registerWithNetworkMap(registrationName: X500Name): ListenableFuture<NetworkMapService.RegistrationResponse> {
val nodeInfo = NodeInfo(net.myAddress, Party(registrationName, identity.public), MOCK_VERSION_INFO.platformVersion) val nodeInfo = NodeInfo(net.myAddress, Party(registrationName, identity.public), MOCK_VERSION_INFO.platformVersion)
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX) val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
val request = RegistrationRequest(registration.toWire(identity.private), net.myAddress) val request = RegistrationRequest(registration.toWire(identity.private), net.myAddress)

View File

@ -566,7 +566,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
// the legal name is actually validated in some way. // the legal name is actually validated in some way.
val privKeyFile = dir / privateKeyFileName val privKeyFile = dir / privateKeyFileName
val pubIdentityFile = dir / publicKeyFileName val pubIdentityFile = dir / publicKeyFileName
val identityName = serviceName ?: configuration.myLegalName val identityName = serviceName ?: configuration.myLegalName.toString()
val identityAndKey = if (!privKeyFile.exists()) { val identityAndKey = if (!privKeyFile.exists()) {
log.info("Identity key not found, generating fresh key!") log.info("Identity key not found, generating fresh key!")

View File

@ -14,6 +14,7 @@ import net.corda.core.div
import net.corda.core.exists import net.corda.core.exists
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import org.bouncycastle.asn1.x500.X500Name
import java.nio.file.Path import java.nio.file.Path
object ConfigHelper { object ConfigHelper {
@ -45,7 +46,7 @@ object ConfigHelper {
*/ */
fun NodeConfiguration.configureWithDevSSLCertificate() = configureDevKeyAndTrustStores(myLegalName) fun NodeConfiguration.configureWithDevSSLCertificate() = configureDevKeyAndTrustStores(myLegalName)
fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: String) { fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: X500Name) {
certificatesDirectory.createDirectories() certificatesDirectory.createDirectories()
if (!trustStoreFile.exists()) { if (!trustStoreFile.exists()) {
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordatruststore.jks").copyTo(trustStoreFile) javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordatruststore.jks").copyTo(trustStoreFile)

View File

@ -13,6 +13,7 @@ import net.corda.node.utilities.TestClock
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.config.OldConfig import net.corda.nodeapi.config.OldConfig
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import org.bouncycastle.asn1.x500.X500Name
import java.net.URL import java.net.URL
import java.nio.file.Path import java.nio.file.Path
import java.util.* import java.util.*
@ -20,7 +21,7 @@ import java.util.*
interface NodeConfiguration : SSLConfiguration { interface NodeConfiguration : SSLConfiguration {
val baseDirectory: Path val baseDirectory: Path
override val certificatesDirectory: Path get() = baseDirectory / "certificates" override val certificatesDirectory: Path get() = baseDirectory / "certificates"
val myLegalName: String val myLegalName: X500Name
val networkMapService: NetworkMapInfo? val networkMapService: NetworkMapInfo?
val minimumPlatformVersion: Int val minimumPlatformVersion: Int
val nearestCity: String val nearestCity: String
@ -41,7 +42,7 @@ data class FullNodeConfiguration(
"This is a subsitution value which points to the baseDirectory and is manually added into the config before parsing", "This is a subsitution value which points to the baseDirectory and is manually added into the config before parsing",
ReplaceWith("baseDirectory")) ReplaceWith("baseDirectory"))
val basedir: Path, val basedir: Path,
override val myLegalName: String, override val myLegalName: X500Name,
override val nearestCity: String, override val nearestCity: String,
override val emailAddress: String, override val emailAddress: String,
override val keyStorePassword: String, override val keyStorePassword: String,

View File

@ -238,7 +238,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
.loadCertificateFromKeyStore(config.keyStoreFile, config.keyStorePassword, CORDA_CLIENT_CA) .loadCertificateFromKeyStore(config.keyStoreFile, config.keyStorePassword, CORDA_CLIENT_CA)
val ourSubjectDN = X500Name(ourCertificate.subjectDN.name) val ourSubjectDN = X500Name(ourCertificate.subjectDN.name)
// This is a sanity check and should not fail unless things have been misconfigured // This is a sanity check and should not fail unless things have been misconfigured
require(ourSubjectDN.commonName == config.myLegalName) { require(ourSubjectDN.commonName == config.myLegalName.commonName) {
"Legal name does not match with our subject CN: $ourSubjectDN" "Legal name does not match with our subject CN: $ourSubjectDN"
} }
val defaultCertPolicies = mapOf( val defaultCertPolicies = mapOf(
@ -398,18 +398,18 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun getBridgeName(queueName: String, hostAndPort: HostAndPort): String = "$queueName -> $hostAndPort" private fun getBridgeName(queueName: String, hostAndPort: HostAndPort): String = "$queueName -> $hostAndPort"
// This is called on one of Artemis' background threads // This is called on one of Artemis' background threads
internal fun hostVerificationFail(peerLegalName: String, expectedCommonName: String) { internal fun hostVerificationFail(peerLegalName: X500Name, expectedLegalName: X500Name) {
log.error("Peer has wrong CN - expected $expectedCommonName but got $peerLegalName. This is either a fatal " + log.error("Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " +
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!") "misconfiguration by the remote peer or an SSL man-in-the-middle attack!")
if (expectedCommonName == config.networkMapService?.legalName) { if (expectedLegalName.toString() == config.networkMapService?.legalName) {
// If the peer that failed host verification was the network map node then we're in big trouble and need to bail! // If the peer that failed host verification was the network map node then we're in big trouble and need to bail!
_networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check")) _networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check"))
} }
} }
// This is called on one of Artemis' background threads // This is called on one of Artemis' background threads
internal fun onTcpConnection(peerLegalName: String) { internal fun onTcpConnection(peerLegalName: X500Name) {
if (peerLegalName == config.networkMapService?.legalName) { if (peerLegalName.toString() == config.networkMapService?.legalName) {
_networkMapConnectionFuture!!.set(Unit) _networkMapConnectionFuture!!.set(Unit)
} }
} }
@ -437,7 +437,9 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>?,
protocolManager: ClientProtocolManager?) : protocolManager: ClientProtocolManager?) :
NettyConnector(configuration, handler, listener, closeExecutor, threadPool, scheduledThreadPool, protocolManager) { NettyConnector(configuration, handler, listener, closeExecutor, threadPool, scheduledThreadPool, protocolManager) {
private val server = configuration?.get(ArtemisMessagingServer::class.java.name) as? ArtemisMessagingServer private val server = configuration?.get(ArtemisMessagingServer::class.java.name) as? ArtemisMessagingServer
private val expectedCommonName = configuration?.get(ArtemisTcpTransport.VERIFY_PEER_COMMON_NAME) as? String private val expectedCommonName = (configuration?.get(ArtemisTcpTransport.VERIFY_PEER_COMMON_NAME) as? String)?.let {
X500Name(it)
}
override fun createConnection(): Connection? { override fun createConnection(): Connection? {
val connection = super.createConnection() as NettyConnection? val connection = super.createConnection() as NettyConnection?
@ -451,9 +453,8 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>?,
.peerPrincipal .peerPrincipal
.name .name
.let(::X500Name) .let(::X500Name)
.commonName
// TODO Verify on the entire principle (subject) // TODO Verify on the entire principle (subject)
if (peerLegalName != expectedCommonName) { if (peerLegalName.commonName != expectedCommonName.commonName) {
connection.close() connection.close()
server!!.hostVerificationFail(peerLegalName, expectedCommonName) server!!.hostVerificationFail(peerLegalName, expectedCommonName)
return null // Artemis will keep trying to reconnect until it's told otherwise return null // Artemis will keep trying to reconnect until it's told otherwise

View File

@ -547,7 +547,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
} }
} }
private fun createRPCDispatcher(ops: RPCOps, userService: RPCUserService, nodeLegalName: String) = private fun createRPCDispatcher(ops: RPCOps, userService: RPCUserService, nodeLegalName: X500Name): RPCDispatcher =
object : RPCDispatcher(ops, userService, nodeLegalName) { object : RPCDispatcher(ops, userService, nodeLegalName) {
override fun send(data: SerializedBytes<*>, toAddress: String) { override fun send(data: SerializedBytes<*>, toAddress: String) {
messagingExecutor.fetchFrom { messagingExecutor.fetchFrom {

View File

@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger
* are handled, this is probably the wrong system. * are handled, this is probably the wrong system.
*/ */
// TODO remove the nodeLegalName parameter once the webserver doesn't need special privileges // TODO remove the nodeLegalName parameter once the webserver doesn't need special privileges
abstract class RPCDispatcher(val ops: RPCOps, val userService: RPCUserService, val nodeLegalName: String) { abstract class RPCDispatcher(val ops: RPCOps, val userService: RPCUserService, val nodeLegalName: X500Name) {
// Throw an exception if there are overloaded methods // Throw an exception if there are overloaded methods
private val methodTable = ops.javaClass.declaredMethods.groupBy { it.name }.mapValues { it.value.single() } private val methodTable = ops.javaClass.declaredMethods.groupBy { it.name }.mapValues { it.value.single() }
@ -184,9 +184,14 @@ abstract class RPCDispatcher(val ops: RPCOps, val userService: RPCUserService, v
val rpcUser = userService.getUser(validatedUser) val rpcUser = userService.getUser(validatedUser)
if (rpcUser != null) { if (rpcUser != null) {
return rpcUser return rpcUser
} else if (X500Name(validatedUser).commonName == nodeLegalName) {
return nodeUser
} else { } else {
try {
if (X500Name(validatedUser) == nodeLegalName) {
return nodeUser
}
} catch (ex: IllegalArgumentException) {
// Just means the two can't be compared, treat as no match
}
throw IllegalArgumentException("Validated user '$validatedUser' is not an RPC user nor the NODE user") throw IllegalArgumentException("Validated user '$validatedUser' is not an RPC user nor the NODE user")
} }
} }

View File

@ -100,7 +100,7 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String { private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
// Retrieve request id from file if exists, else post a request to server. // Retrieve request id from file if exists, else post a request to server.
return if (!requestIdStore.exists()) { return if (!requestIdStore.exists()) {
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, config.nearestCity, config.emailAddress, keyPair) val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, keyPair)
val writer = StringWriter() val writer = StringWriter()
JcaPEMWriter(writer).use { JcaPEMWriter(writer).use {
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded)) it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))

View File

@ -34,7 +34,7 @@ class InteractiveShellTest {
} }
private val someCorpLegalName = MEGA_CORP.name private val someCorpLegalName = MEGA_CORP.name
private val ids = InMemoryIdentityService().apply { registerIdentity(Party(MEGA_CORP.name, DUMMY_PUBKEY_1)) } private val ids = InMemoryIdentityService().apply { registerIdentity(Party(someCorpLegalName, DUMMY_PUBKEY_1)) }
private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory()) private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory())
private fun check(input: String, expected: String) { private fun check(input: String, expected: String) {

View File

@ -4,6 +4,7 @@ import net.corda.core.utilities.ALICE
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.testing.testConfiguration import net.corda.testing.testConfiguration
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import java.nio.file.Paths import java.nio.file.Paths
@ -11,7 +12,7 @@ class FullNodeConfigurationTest {
@Test @Test
fun `Artemis special characters not permitted in RPC usernames`() { fun `Artemis special characters not permitted in RPC usernames`() {
fun configWithRPCUsername(username: String): FullNodeConfiguration { fun configWithRPCUsername(username: String): FullNodeConfiguration {
return testConfiguration(Paths.get("."), ALICE.name, 0).copy( return testConfiguration(Paths.get("."), X500Name(ALICE.name), 0).copy(
rpcUsers = listOf(User(username, "pass", emptySet()))) rpcUsers = listOf(User(username, "pass", emptySet())))
} }

View File

@ -27,6 +27,7 @@ import net.corda.testing.freeLocalHostAndPort
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
import org.bouncycastle.asn1.x500.X500Name
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
@ -71,7 +72,7 @@ class ArtemisMessagingTests {
userService = RPCUserServiceImpl(emptyList()) userService = RPCUserServiceImpl(emptyList())
config = TestNodeConfiguration( config = TestNodeConfiguration(
baseDirectory = baseDirectory, baseDirectory = baseDirectory,
myLegalName = ALICE.name, myLegalName = X500Name(ALICE.name),
networkMapService = null) networkMapService = null)
LogHelper.setLevel(PersistentUniquenessProvider::class) LogHelper.setLevel(PersistentUniquenessProvider::class)
val dataSourceAndDatabase = configureDatabase(makeTestDataSourceProperties()) val dataSourceAndDatabase = configureDatabase(makeTestDataSourceProperties())

View File

@ -39,7 +39,7 @@ class NetworkRegistrationHelperTest {
val config = TestNodeConfiguration( val config = TestNodeConfiguration(
baseDirectory = tempFolder.root.toPath(), baseDirectory = tempFolder.root.toPath(),
myLegalName = ALICE.name, myLegalName = X500Name(ALICE.name),
networkMapService = null) networkMapService = null)
assertFalse(config.keyStoreFile.exists()) assertFalse(config.keyStoreFile.exists())

View File

@ -72,8 +72,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = "CN=Bank $letter,O=Bank $letter,L=$city,C=$country", myLegalName = X500Name("CN=Bank $letter,O=Bank $letter,L=$city,C=$country"),
nearestCity = city,
networkMapService = null) networkMapService = null)
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
} }
@ -95,8 +94,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
require(advertisedServices.containsType(NetworkMapService.type)) require(advertisedServices.containsType(NetworkMapService.type))
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = DUMMY_MAP.name, myLegalName = X500Name(DUMMY_MAP.name),
nearestCity = X500Name(DUMMY_MAP.name).location,
networkMapService = null) networkMapService = null)
return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {} return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {}
} }
@ -109,8 +107,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
require(advertisedServices.containsType(SimpleNotaryService.type)) require(advertisedServices.containsType(SimpleNotaryService.type))
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = DUMMY_NOTARY.name, myLegalName = X500Name(DUMMY_NOTARY.name),
nearestCity = X500Name(DUMMY_NOTARY.name).location,
networkMapService = null) networkMapService = null)
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
} }
@ -118,7 +115,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
object RatesOracleFactory : MockNetwork.Factory { object RatesOracleFactory : MockNetwork.Factory {
// TODO: Make a more realistic legal name // TODO: Make a more realistic legal name
val RATES_SERVICE_NAME = "CN=Rates Service Provider,O=R3,OU=corda,L=Madrid,C=ES" val RATES_SERVICE_NAME = X500Name("CN=Rates Service Provider,O=R3,OU=corda,L=Madrid,C=ES")
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?, advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
@ -127,7 +124,6 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = RATES_SERVICE_NAME, myLegalName = RATES_SERVICE_NAME,
nearestCity = X500Name(RATES_SERVICE_NAME).location,
networkMapService = null) networkMapService = null)
return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) { return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
override fun start(): MockNetwork.MockNode { override fun start(): MockNetwork.MockNode {
@ -149,8 +145,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
entropyRoot: BigInteger): MockNetwork.MockNode { entropyRoot: BigInteger): MockNetwork.MockNode {
val cfg = TestNodeConfiguration( val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory, baseDirectory = config.baseDirectory,
myLegalName = DUMMY_REGULATOR.name, myLegalName = X500Name(DUMMY_REGULATOR.name),
nearestCity = X500Name(DUMMY_REGULATOR.name).location,
networkMapService = null) networkMapService = null)
return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) { return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
// TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request. // TODO: Regulatory nodes don't actually exist properly, this is a last minute demo request.

View File

@ -127,7 +127,7 @@ class VisualiserViewModel {
} }
} }
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: String = "Bank of Bologna", fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: X500Name = X500Name("CN=Bank of Bologna,OU=Corda QA Department,O=R3 CEV,L=Bologna,C=IT"),
nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget { nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget {
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> { fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
val pulse = Circle(initialRadius).apply { val pulse = Circle(initialRadius).apply {
@ -157,7 +157,7 @@ class VisualiserViewModel {
view.root.children += longPulseOuterDot view.root.children += longPulseOuterDot
view.root.children += innerDot view.root.children += innerDot
val nameLabel = Label(label) val nameLabel = Label(label.toString())
val nameLabelRect = StackPane(nameLabel).apply { val nameLabelRect = StackPane(nameLabel).apply {
styleClass += "node-label" styleClass += "node-label"
alignment = Pos.CENTER_RIGHT alignment = Pos.CENTER_RIGHT

View File

@ -28,6 +28,7 @@ import net.corda.testing.node.MockIdentityService
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import java.net.ServerSocket import java.net.ServerSocket
import java.net.URL import java.net.URL
import java.nio.file.Files import java.nio.file.Files
@ -156,23 +157,24 @@ inline fun <reified P : FlowLogic<*>> AbstractNode.initiateSingleShotFlow(
// TODO Replace this with testConfiguration // TODO Replace this with testConfiguration
data class TestNodeConfiguration( data class TestNodeConfiguration(
override val baseDirectory: Path, override val baseDirectory: Path,
override val myLegalName: String, override val myLegalName: X500Name,
override val networkMapService: NetworkMapInfo?, override val networkMapService: NetworkMapInfo?,
override val minimumPlatformVersion: Int = 1, override val minimumPlatformVersion: Int = 1,
override val keyStorePassword: String = "cordacadevpass", override val keyStorePassword: String = "cordacadevpass",
override val trustStorePassword: String = "trustpass", override val trustStorePassword: String = "trustpass",
override val rpcUsers: List<User> = emptyList(), override val rpcUsers: List<User> = emptyList(),
override val dataSourceProperties: Properties = makeTestDataSourceProperties(myLegalName), override val dataSourceProperties: Properties = makeTestDataSourceProperties(myLegalName),
override val nearestCity: String = "Null Island",
override val emailAddress: String = "", override val emailAddress: String = "",
override val exportJMXto: String = "", override val exportJMXto: String = "",
override val devMode: Boolean = true, override val devMode: Boolean = true,
override val certificateSigningService: URL = URL("http://localhost"), override val certificateSigningService: URL = URL("http://localhost"),
override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(), override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(),
override val verifierType: VerifierType = VerifierType.InMemory, override val verifierType: VerifierType = VerifierType.InMemory,
override val messageRedeliveryDelaySeconds: Int = 5) : NodeConfiguration override val messageRedeliveryDelaySeconds: Int = 5) : NodeConfiguration {
override val nearestCity = myLegalName.getRDNs(BCStyle.L).single().typesAndValues.single().value.toString()
}
fun testConfiguration(baseDirectory: Path, legalName: String, basePort: Int): FullNodeConfiguration { fun testConfiguration(baseDirectory: Path, legalName: X500Name, basePort: Int): FullNodeConfiguration {
return FullNodeConfiguration( return FullNodeConfiguration(
basedir = baseDirectory, basedir = baseDirectory,
myLegalName = legalName, myLegalName = legalName,
@ -198,7 +200,7 @@ fun testConfiguration(baseDirectory: Path, legalName: String, basePort: Int): Fu
} }
@JvmOverloads @JvmOverloads
fun configureTestSSL(legalName: String = "Mega Corp."): SSLConfiguration = object : SSLConfiguration { fun configureTestSSL(legalName: X500Name = X500Name(MEGA_CORP.name)): SSLConfiguration = object : SSLConfiguration {
override val certificatesDirectory = Files.createTempDirectory("certs") override val certificatesDirectory = Files.createTempDirectory("certs")
override val keyStorePassword: String get() = "cordacadevpass" override val keyStorePassword: String get() = "cordacadevpass"
override val trustStorePassword: String get() = "trustpass" override val trustStorePassword: String get() = "trustpass"

View File

@ -7,12 +7,16 @@ import net.corda.nodeapi.ConnectionDirection
import net.corda.nodeapi.config.SSLConfiguration import net.corda.nodeapi.config.SSLConfiguration
import net.corda.testing.configureTestSSL import net.corda.testing.configureTestSSL
import org.apache.activemq.artemis.api.core.client.* import org.apache.activemq.artemis.api.core.client.*
import org.bouncycastle.asn1.x500.X500Name
/** /**
* As the name suggests this is a simple client for connecting to MQ brokers. * As the name suggests this is a simple client for connecting to MQ brokers.
*/ */
class SimpleMQClient(val target: HostAndPort, class SimpleMQClient(val target: HostAndPort,
override val config: SSLConfiguration? = configureTestSSL("SimpleMQClient")) : ArtemisMessagingComponent() { override val config: SSLConfiguration? = configureTestSSL(DEFAULT_MQ_LEGAL_NAME)) : ArtemisMessagingComponent() {
companion object {
val DEFAULT_MQ_LEGAL_NAME = X500Name("CN=SimpleMQClient,O=R3,OU=corda,L=London,C=UK")
}
lateinit var sessionFactory: ClientSessionFactory lateinit var sessionFactory: ClientSessionFactory
lateinit var session: ClientSession lateinit var session: ClientSession
lateinit var producer: ClientProducer lateinit var producer: ClientProducer

View File

@ -127,10 +127,10 @@ class InMemoryMessagingNetwork(
id: Int, id: Int,
executor: AffinityExecutor, executor: AffinityExecutor,
advertisedServices: List<ServiceEntry>, advertisedServices: List<ServiceEntry>,
description: String? = null, description: X500Name? = null,
database: Database) database: Database)
: MessagingServiceBuilder<InMemoryMessaging> { : MessagingServiceBuilder<InMemoryMessaging> {
return Builder(manuallyPumped, PeerHandle(id, description ?: "In memory node $id"), advertisedServices.map(::ServiceHandle), executor, database = database) return Builder(manuallyPumped, PeerHandle(id, description ?: X509Utilities.getDevX509Name("In memory node $id")), advertisedServices.map(::ServiceHandle), executor, database = database)
} }
interface LatencyCalculator { interface LatencyCalculator {
@ -198,8 +198,8 @@ class InMemoryMessagingNetwork(
} }
@CordaSerializable @CordaSerializable
data class PeerHandle(val id: Int, val description: String) : SingleMessageRecipient { data class PeerHandle(val id: Int, val description: X500Name) : SingleMessageRecipient {
override fun toString() = description override fun toString() = description.toString()
override fun equals(other: Any?) = other is PeerHandle && other.id == id override fun equals(other: Any?) = other is PeerHandle && other.id == id
override fun hashCode() = id.hashCode() override fun hashCode() = id.hashCode()
} }
@ -468,6 +468,6 @@ class InMemoryMessagingNetwork(
1, 1,
message.uniqueMessageId, message.uniqueMessageId,
message.debugTimestamp, message.debugTimestamp,
X509Utilities.getDevX509Name(sender.description)) sender.description)
} }
} }

View File

@ -35,6 +35,7 @@ import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.testing.MOCK_VERSION_INFO import net.corda.testing.MOCK_VERSION_INFO
import net.corda.testing.TestNodeConfiguration import net.corda.testing.TestNodeConfiguration
import org.apache.activemq.artemis.utils.ReusableLatch import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x500.X500Name
import org.slf4j.Logger import org.slf4j.Logger
import java.math.BigInteger import java.math.BigInteger
import java.nio.file.FileSystem import java.nio.file.FileSystem
@ -287,9 +288,9 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
val config = TestNodeConfiguration( val config = TestNodeConfiguration(
baseDirectory = path, baseDirectory = path,
myLegalName = legalName ?: "Mock Company $id", myLegalName = X500Name(legalName ?: "CN=Mock Company $id,OU=Corda QA Department,O=R3 CEV,L=New York,C=US"),
networkMapService = null, networkMapService = null,
dataSourceProperties = makeTestDataSourceProperties("node_${id}_net_$networkId")) dataSourceProperties = makeTestDataSourceProperties(X500Name("CN=node_${id}_net_$networkId,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")))
val node = nodeFactory.create(config, this, networkMapAddress, advertisedServices.toSet(), id, overrideServices, entropyRoot) val node = nodeFactory.create(config, this, networkMapAddress, advertisedServices.toSet(), id, overrideServices, entropyRoot)
if (start) { if (start) {
node.setup().start() node.setup().start()

View File

@ -176,7 +176,7 @@ class MockStorageService(override val attachments: AttachmentStorage = MockAttac
* *
* @param nodeName Reflects the "instance" of the in-memory database. Defaults to a random string. * @param nodeName Reflects the "instance" of the in-memory database. Defaults to a random string.
*/ */
fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties { fun makeTestDataSourceProperties(nodeName: X500Name = X509Utilities.getDevX509Name(SecureHash.randomSHA256().toString())): Properties {
val props = Properties() val props = Properties()
props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource") props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
props.setProperty("dataSource.url", "jdbc:h2:mem:${nodeName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE") props.setProperty("dataSource.url", "jdbc:h2:mem:${nodeName}_persistence;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE")

View File

@ -3,6 +3,7 @@ package net.corda.testing.node
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry
import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import net.corda.core.crypto.commonName
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
import net.corda.core.messaging.RPCOps import net.corda.core.messaging.RPCOps
import net.corda.testing.MOCK_VERSION_INFO import net.corda.testing.MOCK_VERSION_INFO
@ -16,6 +17,7 @@ import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.configureDatabase
import net.corda.node.utilities.transaction import net.corda.node.utilities.transaction
import net.corda.testing.freeLocalHostAndPort import net.corda.testing.freeLocalHostAndPort
import org.bouncycastle.asn1.x500.X500Name
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import java.io.Closeable import java.io.Closeable
import java.security.KeyPair import java.security.KeyPair
@ -32,7 +34,7 @@ class SimpleNode(val config: NodeConfiguration, val address: HostAndPort = freeL
val userService = RPCUserServiceImpl(config.rpcUsers) val userService = RPCUserServiceImpl(config.rpcUsers)
val monitoringService = MonitoringService(MetricRegistry()) val monitoringService = MonitoringService(MetricRegistry())
val identity: KeyPair = generateKeyPair() val identity: KeyPair = generateKeyPair()
val executor = ServiceAffinityExecutor(config.myLegalName, 1) val executor = ServiceAffinityExecutor(config.myLegalName.commonName, 1)
val broker = ArtemisMessagingServer(config, address, rpcAddress, InMemoryNetworkMapCache(), userService) val broker = ArtemisMessagingServer(config, address, rpcAddress, InMemoryNetworkMapCache(), userService)
val networkMapRegistrationFuture: SettableFuture<Unit> = SettableFuture.create<Unit>() val networkMapRegistrationFuture: SettableFuture<Unit> = SettableFuture.create<Unit>()
val net = database.transaction { val net = database.transaction {
@ -54,7 +56,7 @@ class SimpleNode(val config: NodeConfiguration, val address: HostAndPort = freeL
override val protocolVersion = 0 override val protocolVersion = 0
}, },
userService) userService)
thread(name = config.myLegalName) { thread(name = config.myLegalName.commonName) {
net.run() net.run()
} }
} }

View File

@ -2,6 +2,8 @@ package net.corda.demobench.model
import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort
import com.typesafe.config.Config import com.typesafe.config.Config
import org.bouncycastle.asn1.x500.X500Name
import tornadofx.* import tornadofx.*
import java.io.IOException import java.io.IOException
import java.nio.file.Files import java.nio.file.Files
@ -23,10 +25,9 @@ class InstallFactory : Controller() {
val nodeConfig = NodeConfig( val nodeConfig = NodeConfig(
tempDir, tempDir,
config.getString("myLegalName"), X500Name(config.getString("myLegalName")),
p2pPort, p2pPort,
rpcPort, rpcPort,
config.getString("nearestCity"),
webPort, webPort,
h2Port, h2Port,
extraServices, extraServices,
@ -35,7 +36,7 @@ class InstallFactory : Controller() {
if (config.hasPath("networkMapService")) { if (config.hasPath("networkMapService")) {
val nmap = config.getConfig("networkMapService") val nmap = config.getConfig("networkMapService")
nodeConfig.networkMap = NetworkMapConfig(nmap.getString("legalName"), nmap.parsePort("address")) nodeConfig.networkMap = NetworkMapConfig(X500Name(nmap.getString("legalName")), nmap.parsePort("address"))
} else { } else {
log.info("Node '${nodeConfig.legalName}' is the network map") log.info("Node '${nodeConfig.legalName}' is the network map")
} }

View File

@ -1,8 +1,11 @@
package net.corda.demobench.model package net.corda.demobench.model
open class NetworkMapConfig(val legalName: String, val p2pPort: Int) { import net.corda.core.crypto.commonName
import org.bouncycastle.asn1.x500.X500Name
val key: String = legalName.toKey() open class NetworkMapConfig(val legalName: X500Name, val p2pPort: Int) {
val key: String = legalName.commonName.toKey()
} }

View File

@ -2,6 +2,8 @@ package net.corda.demobench.model
import com.typesafe.config.* import com.typesafe.config.*
import net.corda.nodeapi.User import net.corda.nodeapi.User
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
@ -9,10 +11,9 @@ import java.nio.file.StandardCopyOption
class NodeConfig( class NodeConfig(
baseDir: Path, baseDir: Path,
legalName: String, legalName: X500Name,
p2pPort: Int, p2pPort: Int,
val rpcPort: Int, val rpcPort: Int,
val nearestCity: String,
val webPort: Int, val webPort: Int,
val h2Port: Int, val h2Port: Int,
val extraServices: List<String>, val extraServices: List<String>,
@ -25,6 +26,7 @@ class NodeConfig(
val defaultUser = user("guest") val defaultUser = user("guest")
} }
val nearestCity: String? = legalName.getRDNs(BCStyle.L).singleOrNull()?.typesAndValues?.singleOrNull()?.value?.toString()
val nodeDir: Path = baseDir.resolve(key) val nodeDir: Path = baseDir.resolve(key)
override val pluginDir: Path = nodeDir.resolve("plugins") override val pluginDir: Path = nodeDir.resolve("plugins")
val explorerDir: Path = baseDir.resolve("$key-explorer") val explorerDir: Path = baseDir.resolve("$key-explorer")
@ -42,14 +44,13 @@ class NodeConfig(
* which is mutable. * which is mutable.
*/ */
fun toFileConfig(): Config = ConfigFactory.empty() fun toFileConfig(): Config = ConfigFactory.empty()
.withValue("myLegalName", valueFor(legalName)) .withValue("myLegalName", valueFor(legalName.toString()))
.withValue("p2pAddress", addressValueFor(p2pPort)) .withValue("p2pAddress", addressValueFor(p2pPort))
.withValue("nearestCity", valueFor(nearestCity))
.withValue("extraAdvertisedServiceIds", valueFor(extraServices)) .withValue("extraAdvertisedServiceIds", valueFor(extraServices))
.withFallback(optional("networkMapService", networkMap, { .withFallback(optional("networkMapService", networkMap, {
c, n -> c, n ->
c.withValue("address", addressValueFor(n.p2pPort)) c.withValue("address", addressValueFor(n.p2pPort))
.withValue("legalName", valueFor(n.legalName)) .withValue("legalName", valueFor(n.legalName.toString()))
})) }))
.withValue("webAddress", addressValueFor(webPort)) .withValue("webAddress", addressValueFor(webPort))
.withValue("rpcAddress", addressValueFor(rpcPort)) .withValue("rpcAddress", addressValueFor(rpcPort))
@ -60,7 +61,7 @@ class NodeConfig(
fun toText(): String = toFileConfig().root().render(renderOptions) fun toText(): String = toFileConfig().root().render(renderOptions)
fun moveTo(baseDir: Path) = NodeConfig( fun moveTo(baseDir: Path) = NodeConfig(
baseDir, legalName, p2pPort, rpcPort, nearestCity, webPort, h2Port, extraServices, users, networkMap baseDir, legalName, p2pPort, rpcPort, webPort, h2Port, extraServices, users, networkMap
) )
fun install(plugins: Collection<Path>) { fun install(plugins: Collection<Path>) {

View File

@ -2,6 +2,7 @@ package net.corda.demobench.model
import net.corda.demobench.plugin.PluginController import net.corda.demobench.plugin.PluginController
import net.corda.demobench.pty.R3Pty import net.corda.demobench.pty.R3Pty
import org.bouncycastle.asn1.x500.X500Name
import tornadofx.* import tornadofx.*
import java.io.IOException import java.io.IOException
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
@ -51,10 +52,9 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
fun validate(nodeData: NodeData): NodeConfig? { fun validate(nodeData: NodeData): NodeConfig? {
val config = NodeConfig( val config = NodeConfig(
baseDir, baseDir,
nodeData.legalName.value.trim(), X500Name(nodeData.legalName.value.trim()),
nodeData.p2pPort.value, nodeData.p2pPort.value,
nodeData.rpcPort.value, nodeData.rpcPort.value,
nodeData.nearestCity.value.description.trim(),
nodeData.webPort.value, nodeData.webPort.value,
nodeData.h2Port.value, nodeData.h2Port.value,
nodeData.extraServices.value nodeData.extraServices.value

View File

@ -4,14 +4,16 @@ import com.jediterm.terminal.ui.JediTermWidget
import com.jediterm.terminal.ui.UIUtil import com.jediterm.terminal.ui.UIUtil
import com.jediterm.terminal.ui.settings.SettingsProvider import com.jediterm.terminal.ui.settings.SettingsProvider
import com.pty4j.PtyProcess import com.pty4j.PtyProcess
import net.corda.core.crypto.commonName
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import org.bouncycastle.asn1.x500.X500Name
import java.awt.Dimension import java.awt.Dimension
import java.io.IOException import java.io.IOException
import java.nio.charset.StandardCharsets.UTF_8 import java.nio.charset.StandardCharsets.UTF_8
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class R3Pty(val name: String, settings: SettingsProvider, dimension: Dimension, val onExit: (Int) -> Unit) : AutoCloseable { class R3Pty(val name: X500Name, settings: SettingsProvider, dimension: Dimension, val onExit: (Int) -> Unit) : AutoCloseable {
private companion object { private companion object {
val log = loggerFor<R3Pty>() val log = loggerFor<R3Pty>()
} }
@ -32,7 +34,7 @@ class R3Pty(val name: String, settings: SettingsProvider, dimension: Dimension,
val process = PtyProcess.exec(command, environment, workingDir) val process = PtyProcess.exec(command, environment, workingDir)
try { try {
return PtyProcessTtyConnector(name, process, UTF_8) return PtyProcessTtyConnector(name.commonName, process, UTF_8)
} catch (e: Exception) { } catch (e: Exception) {
process.destroyForcibly() process.destroyForcibly()
process.waitFor(30, TimeUnit.SECONDS) process.waitFor(30, TimeUnit.SECONDS)

View File

@ -263,11 +263,11 @@ class NodeTabView : Fragment() {
} }
private fun launchNode(config: NodeConfig) { private fun launchNode(config: NodeConfig) {
val countryCode = CityDatabase.cityMap[config.nearestCity]?.countryCode val countryCode = CityDatabase.cityMap[config.nearestCity ?: "Nowhere"]?.countryCode
if (countryCode != null) { if (countryCode != null) {
nodeTab.graphic = ImageView(flags.get()[countryCode]).apply { fitWidth = 24.0; isPreserveRatio = true } nodeTab.graphic = ImageView(flags.get()[countryCode]).apply { fitWidth = 24.0; isPreserveRatio = true }
} }
nodeTab.text = config.legalName nodeTab.text = config.legalName.toString()
nodeTerminalView.open(config) { exitCode -> nodeTerminalView.open(config) { exitCode ->
Platform.runLater { Platform.runLater {
if (exitCode == 0) if (exitCode == 0)

View File

@ -64,7 +64,7 @@ class NodeTerminalView : Fragment() {
private lateinit var swingTerminal: SwingNode private lateinit var swingTerminal: SwingNode
fun open(config: NodeConfig, onExit: (Int) -> Unit) { fun open(config: NodeConfig, onExit: (Int) -> Unit) {
nodeName.text = config.legalName nodeName.text = config.legalName.toString()
swingTerminal = SwingNode() swingTerminal = SwingNode()
swingTerminal.setOnMouseClicked { swingTerminal.setOnMouseClicked {

View File

@ -1,5 +1,6 @@
package net.corda.demobench.model package net.corda.demobench.model
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -7,7 +8,7 @@ class NetworkMapConfigTest {
@Test @Test
fun keyValue() { fun keyValue() {
val config = NetworkMapConfig("My\tNasty Little\rLabel\n", 10000) val config = NetworkMapConfig(X500Name("CN=My\tNasty Little\rLabel\n"), 10000)
assertEquals("mynastylittlelabel", config.key) assertEquals("mynastylittlelabel", config.key)
} }

View File

@ -13,6 +13,7 @@ import net.corda.node.services.config.FullNodeConfiguration
import net.corda.nodeapi.User import net.corda.nodeapi.User
import net.corda.nodeapi.config.parseAs import net.corda.nodeapi.config.parseAs
import net.corda.webserver.WebServerConfig import net.corda.webserver.WebServerConfig
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import java.io.StringWriter import java.io.StringWriter
import java.nio.file.Path import java.nio.file.Path
@ -22,41 +23,39 @@ import kotlin.test.assertFalse
import kotlin.test.assertNull import kotlin.test.assertNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
class NodeConfigTest { class NodeConfigTest {
private val baseDir: Path = Paths.get(".").toAbsolutePath() companion object {
private val baseDir: Path = Paths.get(".").toAbsolutePath()
private val myLegalName = X500Name("CN=My Name,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")
}
@Test @Test
fun `test name`() { fun `test name`() {
val config = createConfig(legalName = "My Name") val config = createConfig(legalName = myLegalName)
assertEquals("My Name", config.legalName) assertEquals(myLegalName, config.legalName)
assertEquals("myname", config.key) assertEquals("myname", config.key)
} }
@Test @Test
fun `test node directory`() { fun `test node directory`() {
val config = createConfig(legalName = "My Name") val config = createConfig(legalName = myLegalName)
assertEquals(baseDir / "myname", config.nodeDir) assertEquals(baseDir / "myname", config.nodeDir)
} }
@Test @Test
fun `test explorer directory`() { fun `test explorer directory`() {
val config = createConfig(legalName = "My Name") val config = createConfig(legalName = myLegalName)
assertEquals(baseDir / "myname-explorer", config.explorerDir) assertEquals(baseDir / "myname-explorer", config.explorerDir)
} }
@Test @Test
fun `test plugin directory`() { fun `test plugin directory`() {
val config = createConfig(legalName = "My Name") val config = createConfig(legalName = myLegalName)
assertEquals(baseDir / "myname" / "plugins", config.pluginDir) assertEquals(baseDir / "myname" / "plugins", config.pluginDir)
} }
@Test
fun `test nearest city`() {
val config = createConfig(nearestCity = "Leicester")
assertEquals("Leicester", config.nearestCity)
}
@Test @Test
fun `test P2P port`() { fun `test P2P port`() {
val config = createConfig(p2pPort = 10001) val config = createConfig(p2pPort = 10001)
@ -134,8 +133,7 @@ class NodeConfigTest {
@Test @Test
fun `test config text`() { fun `test config text`() {
val config = createConfig( val config = createConfig(
legalName = "My Name", legalName = myLegalName,
nearestCity = "Stockholm",
p2pPort = 10001, p2pPort = 10001,
rpcPort = 40002, rpcPort = 40002,
webPort = 20001, webPort = 20001,
@ -147,7 +145,6 @@ class NodeConfigTest {
+ "\"extraAdvertisedServiceIds\":[\"my.service\"]," + "\"extraAdvertisedServiceIds\":[\"my.service\"],"
+ "\"h2port\":30001," + "\"h2port\":30001,"
+ "\"myLegalName\":\"My Name\"," + "\"myLegalName\":\"My Name\","
+ "\"nearestCity\":\"Stockholm\","
+ "\"p2pAddress\":\"localhost:10001\"," + "\"p2pAddress\":\"localhost:10001\","
+ "\"rpcAddress\":\"localhost:40002\"," + "\"rpcAddress\":\"localhost:40002\","
+ "\"rpcUsers\":[" + "\"rpcUsers\":["
@ -161,8 +158,7 @@ class NodeConfigTest {
@Test @Test
fun `test config text with network map`() { fun `test config text with network map`() {
val config = createConfig( val config = createConfig(
legalName = "My Name", legalName = myLegalName,
nearestCity = "Stockholm",
p2pPort = 10001, p2pPort = 10001,
rpcPort = 40002, rpcPort = 40002,
webPort = 20001, webPort = 20001,
@ -170,13 +166,12 @@ class NodeConfigTest {
services = listOf("my.service"), services = listOf("my.service"),
users = listOf(user("jenny")) users = listOf(user("jenny"))
) )
config.networkMap = NetworkMapConfig(DUMMY_NOTARY.name, 12345) config.networkMap = NetworkMapConfig(X500Name(DUMMY_NOTARY.name), 12345)
assertEquals(prettyPrint("{" assertEquals(prettyPrint("{"
+ "\"extraAdvertisedServiceIds\":[\"my.service\"]," + "\"extraAdvertisedServiceIds\":[\"my.service\"],"
+ "\"h2port\":30001," + "\"h2port\":30001,"
+ "\"myLegalName\":\"My Name\"," + "\"myLegalName\":\"My Name\","
+ "\"nearestCity\":\"Stockholm\","
+ "\"networkMapService\":{\"address\":\"localhost:12345\",\"legalName\":\"CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH\"}," + "\"networkMapService\":{\"address\":\"localhost:12345\",\"legalName\":\"CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH\"},"
+ "\"p2pAddress\":\"localhost:10001\"," + "\"p2pAddress\":\"localhost:10001\","
+ "\"rpcAddress\":\"localhost:40002\"," + "\"rpcAddress\":\"localhost:40002\","
@ -191,8 +186,7 @@ class NodeConfigTest {
@Test @Test
fun `reading node configuration`() { fun `reading node configuration`() {
val config = createConfig( val config = createConfig(
legalName = "My Name", legalName = myLegalName,
nearestCity = "Stockholm",
p2pPort = 10001, p2pPort = 10001,
rpcPort = 40002, rpcPort = 40002,
webPort = 20001, webPort = 20001,
@ -200,7 +194,7 @@ class NodeConfigTest {
services = listOf("my.service"), services = listOf("my.service"),
users = listOf(user("jenny")) users = listOf(user("jenny"))
) )
config.networkMap = NetworkMapConfig(DUMMY_NOTARY.name, 12345) config.networkMap = NetworkMapConfig(X500Name(DUMMY_NOTARY.name), 12345)
val nodeConfig = config.toFileConfig() val nodeConfig = config.toFileConfig()
.withValue("basedir", ConfigValueFactory.fromAnyRef(baseDir.toString())) .withValue("basedir", ConfigValueFactory.fromAnyRef(baseDir.toString()))
@ -208,8 +202,8 @@ class NodeConfigTest {
.resolve() .resolve()
val fullConfig = nodeConfig.parseAs<FullNodeConfiguration>() val fullConfig = nodeConfig.parseAs<FullNodeConfiguration>()
assertEquals("My Name", fullConfig.myLegalName) assertEquals(myLegalName, fullConfig.myLegalName)
assertEquals("Stockholm", fullConfig.nearestCity) assertEquals("London", fullConfig.nearestCity)
assertEquals(localPort(40002), fullConfig.rpcAddress) assertEquals(localPort(40002), fullConfig.rpcAddress)
assertEquals(localPort(10001), fullConfig.p2pAddress) assertEquals(localPort(10001), fullConfig.p2pAddress)
assertEquals(listOf("my.service"), fullConfig.extraAdvertisedServiceIds) assertEquals(listOf("my.service"), fullConfig.extraAdvertisedServiceIds)
@ -222,8 +216,7 @@ class NodeConfigTest {
@Test @Test
fun `reading webserver configuration`() { fun `reading webserver configuration`() {
val config = createConfig( val config = createConfig(
legalName = "My Name", legalName = myLegalName,
nearestCity = "Stockholm",
p2pPort = 10001, p2pPort = 10001,
rpcPort = 40002, rpcPort = 40002,
webPort = 20001, webPort = 20001,
@ -231,7 +224,7 @@ class NodeConfigTest {
services = listOf("my.service"), services = listOf("my.service"),
users = listOf(user("jenny")) users = listOf(user("jenny"))
) )
config.networkMap = NetworkMapConfig(DUMMY_NOTARY.name, 12345) config.networkMap = NetworkMapConfig(X500Name(DUMMY_NOTARY.name), 12345)
val nodeConfig = config.toFileConfig() val nodeConfig = config.toFileConfig()
.withValue("basedir", ConfigValueFactory.fromAnyRef(baseDir.toString())) .withValue("basedir", ConfigValueFactory.fromAnyRef(baseDir.toString()))
@ -247,7 +240,7 @@ class NodeConfigTest {
@Test @Test
fun `test moving`() { fun `test moving`() {
val config = createConfig(legalName = "My Name") val config = createConfig(legalName = myLegalName)
val elsewhere = baseDir / "elsewhere" val elsewhere = baseDir / "elsewhere"
val moved = config.moveTo(elsewhere) val moved = config.moveTo(elsewhere)
@ -257,8 +250,7 @@ class NodeConfigTest {
} }
private fun createConfig( private fun createConfig(
legalName: String = "Unknown", legalName: X500Name = X500Name("CN=Unknown,O=R3,OU=corda,L=Nowhere,C=UK"),
nearestCity: String = "Nowhere",
p2pPort: Int = -1, p2pPort: Int = -1,
rpcPort: Int = -1, rpcPort: Int = -1,
webPort: Int = -1, webPort: Int = -1,
@ -268,7 +260,6 @@ class NodeConfigTest {
) = NodeConfig( ) = NodeConfig(
baseDir, baseDir,
legalName = legalName, legalName = legalName,
nearestCity = nearestCity,
p2pPort = p2pPort, p2pPort = p2pPort,
rpcPort = rpcPort, rpcPort = rpcPort,
webPort = webPort, webPort = webPort,

View File

@ -1,7 +1,9 @@
package net.corda.demobench.model package net.corda.demobench.model
import net.corda.core.crypto.X509Utilities
import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.nodeapi.User import net.corda.nodeapi.User
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test import org.junit.Test
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
@ -11,11 +13,13 @@ class NodeControllerTest {
private val baseDir: Path = Paths.get(".").toAbsolutePath() private val baseDir: Path = Paths.get(".").toAbsolutePath()
private val controller = NodeController({ _, _ -> }) private val controller = NodeController({ _, _ -> })
private val node1Name = X500Name("CN=Node 1,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")
private val node2Name = X500Name("CN=Node 2,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")
@Test @Test
fun `test unique nodes after validate`() { fun `test unique nodes after validate`() {
val data = NodeData() val data = NodeData()
data.legalName.value = "Node 1" data.legalName.value = node1Name.toString()
assertNotNull(controller.validate(data)) assertNotNull(controller.validate(data))
assertNull(controller.validate(data)) assertNull(controller.validate(data))
} }
@ -23,7 +27,7 @@ class NodeControllerTest {
@Test @Test
fun `test unique key after validate`() { fun `test unique key after validate`() {
val data = NodeData() val data = NodeData()
data.legalName.value = "Node 1" data.legalName.value = node1Name.toString()
assertFalse(controller.keyExists("node1")) assertFalse(controller.keyExists("node1"))
controller.validate(data) controller.validate(data)
@ -33,7 +37,7 @@ class NodeControllerTest {
@Test @Test
fun `test matching name after validate`() { fun `test matching name after validate`() {
val data = NodeData() val data = NodeData()
data.legalName.value = "Node 1" data.legalName.value = node1Name.toString()
assertFalse(controller.nameExists("Node 1")) assertFalse(controller.nameExists("Node 1"))
assertFalse(controller.nameExists("Node1")) assertFalse(controller.nameExists("Node1"))
@ -47,7 +51,7 @@ class NodeControllerTest {
@Test @Test
fun `test first validated node becomes network map`() { fun `test first validated node becomes network map`() {
val data = NodeData() val data = NodeData()
data.legalName.value = "Node 1" data.legalName.value = node1Name.toString()
data.p2pPort.value = 100000 data.p2pPort.value = 100000
assertFalse(controller.hasNetworkMap()) assertFalse(controller.hasNetworkMap())
@ -57,14 +61,14 @@ class NodeControllerTest {
@Test @Test
fun `test register unique nodes`() { fun `test register unique nodes`() {
val config = createConfig(legalName = "Node 2") val config = createConfig(legalName = node2Name)
assertTrue(controller.register(config)) assertTrue(controller.register(config))
assertFalse(controller.register(config)) assertFalse(controller.register(config))
} }
@Test @Test
fun `test unique key after register`() { fun `test unique key after register`() {
val config = createConfig(legalName = "Node 2") val config = createConfig(legalName = node2Name)
assertFalse(controller.keyExists("node2")) assertFalse(controller.keyExists("node2"))
controller.register(config) controller.register(config)
@ -73,7 +77,7 @@ class NodeControllerTest {
@Test @Test
fun `test matching name after register`() { fun `test matching name after register`() {
val config = createConfig(legalName = "Node 2") val config = createConfig(legalName = node2Name)
assertFalse(controller.nameExists("Node 2")) assertFalse(controller.nameExists("Node 2"))
assertFalse(controller.nameExists("Node2")) assertFalse(controller.nameExists("Node2"))
@ -86,7 +90,7 @@ class NodeControllerTest {
@Test @Test
fun `test register network map node`() { fun `test register network map node`() {
val config = createConfig(legalName = "Node is Network Map") val config = createConfig(legalName = X500Name("CN=Node is Network Map,OU=Corda QA Department,O=R3 CEV,L=New York,C=US"))
assertTrue(config.isNetworkMap()) assertTrue(config.isNetworkMap())
assertFalse(controller.hasNetworkMap()) assertFalse(controller.hasNetworkMap())
@ -96,8 +100,8 @@ class NodeControllerTest {
@Test @Test
fun `test register non-network-map node`() { fun `test register non-network-map node`() {
val config = createConfig(legalName = "Node is not Network Map") val config = createConfig(legalName = X500Name("CN=Node is not Network Map,OU=Corda QA Department,O=R3 CEV,L=New York,C=US"))
config.networkMap = NetworkMapConfig(DUMMY_NOTARY.name, 10000) config.networkMap = NetworkMapConfig(X500Name(DUMMY_NOTARY.name), 10000)
assertFalse(config.isNetworkMap()) assertFalse(config.isNetworkMap())
assertFalse(controller.hasNetworkMap()) assertFalse(controller.hasNetworkMap())
@ -151,7 +155,7 @@ class NodeControllerTest {
@Test @Test
fun `dispose node`() { fun `dispose node`() {
val config = createConfig(legalName = "MyName") val config = createConfig(legalName = X500Name("CN=MyName,OU=Corda QA Department,O=R3 CEV,L=New York,C=US"))
controller.register(config) controller.register(config)
assertEquals(NodeState.STARTING, config.state) assertEquals(NodeState.STARTING, config.state)
@ -162,8 +166,7 @@ class NodeControllerTest {
} }
private fun createConfig( private fun createConfig(
legalName: String = "Unknown", legalName: X500Name = X509Utilities.getDevX509Name("Unknown"),
nearestCity: String = "Nowhere",
p2pPort: Int = -1, p2pPort: Int = -1,
rpcPort: Int = -1, rpcPort: Int = -1,
webPort: Int = -1, webPort: Int = -1,
@ -173,7 +176,6 @@ class NodeControllerTest {
) = NodeConfig( ) = NodeConfig(
baseDir, baseDir,
legalName = legalName, legalName = legalName,
nearestCity = nearestCity,
p2pPort = p2pPort, p2pPort = p2pPort,
rpcPort = rpcPort, rpcPort = rpcPort,
webPort = webPort, webPort = webPort,