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.InVMConnectorFactory
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ
import org.bouncycastle.asn1.x500.X500Name
import org.junit.After
import org.junit.Before
import java.util.*
@ -74,7 +75,7 @@ abstract class AbstractClientRPCTest {
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) {
val msg = serverSession.createMessage(false).apply {
writeBodyBufferBytes(data.bytes)
@ -99,4 +100,4 @@ abstract class AbstractClientRPCTest {
} catch (e: Exception) {
}
}
}
}

View File

@ -110,6 +110,8 @@ object X509Utilities {
* Return a bogus X509 for dev purposes. Use [getX509Name] for something more real.
*/
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)
nameBuilder.addRDN(BCStyle.CN, commonName)
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.ConfigUtil
import net.corda.core.noneOrSingle
import org.bouncycastle.asn1.x500.X500Name
import org.slf4j.LoggerFactory
import java.net.Proxy
import java.net.URL
@ -70,6 +71,7 @@ private fun Config.getSingleValue(path: String, type: KType): Any? {
Path::class -> Paths.get(getString(path))
URL::class -> URL(getString(path))
Properties::class -> getConfig(path).toProperties()
X500Name::class -> X500Name(getString(path))
else -> if (typeClass.java.isEnum) {
parseEnum(typeClass.java, getString(path))
} else {

View File

@ -8,6 +8,7 @@ import net.corda.core.node.services.ServiceInfo
import net.corda.core.readLines
import net.corda.core.utilities.DUMMY_BANK_A
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.services.api.RegulatorService
import net.corda.node.services.transactions.SimpleNotaryService
@ -42,7 +43,7 @@ class DriverTests {
fun `simple node startup and shutdown`() {
val handles = driver {
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))
}
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.ListenableFuture
import net.corda.core.*
import net.corda.core.crypto.X509Utilities
import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient
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.node.NodeBasedTest
import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test
import java.util.*
import java.util.concurrent.CountDownLatch
@ -27,6 +29,11 @@ import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
class P2PMessagingTest : NodeBasedTest() {
private companion object {
val DISTRIBUTED_SERVICE_NAME = X509Utilities.getDevX509Name("DistributedService")
val SERVICE_2_NAME = X509Utilities.getDevX509Name("Service Node 2")
}
@Test
fun `network map will work after restart`() {
val identities = listOf(DUMMY_BANK_A, DUMMY_BANK_B, DUMMY_NOTARY)
@ -55,15 +62,14 @@ class P2PMessagingTest : NodeBasedTest() {
// TODO Use a dummy distributed service
@Test
fun `communicating with a distributed service which the network map node is part of`() {
val serviceName = "DistributedService"
val root = tempFolder.root.toPath()
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,
serviceName)
DISTRIBUTED_SERVICE_NAME)
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, serviceName)
val distributedService = ServiceInfo(RaftValidatingNotaryService.type, DISTRIBUTED_SERVICE_NAME)
val notaryClusterAddress = freeLocalHostAndPort()
startNetworkMapNode(
DUMMY_MAP.name,
@ -71,7 +77,7 @@ class P2PMessagingTest : NodeBasedTest() {
configOverrides = mapOf("notaryNodeAddress" to notaryClusterAddress.toString()))
val (serviceNode2, alice) = Futures.allAsList(
startNode(
"Service Node 2",
SERVICE_2_NAME,
advertisedServices = setOf(distributedService),
configOverrides = mapOf(
"notaryNodeAddress" to freeLocalHostAndPort().toString(),
@ -79,14 +85,13 @@ class P2PMessagingTest : NodeBasedTest() {
startNode(ALICE.name)
).getOrThrow()
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), serviceName, alice)
assertAllNodesAreUsed(listOf(networkMapNode, serviceNode2), DISTRIBUTED_SERVICE_NAME, alice)
}
@Test
fun `communicating with a distributed service which we're part of`() {
val serviceName = "Distributed Service"
val distributedService = startNotaryCluster(serviceName, 2).getOrThrow()
assertAllNodesAreUsed(distributedService, serviceName, distributedService[0])
val distributedService = startNotaryCluster(DISTRIBUTED_SERVICE_NAME, 2).getOrThrow()
assertAllNodesAreUsed(distributedService, DISTRIBUTED_SERVICE_NAME, distributedService[0])
}
@Test
@ -183,13 +188,13 @@ class P2PMessagingTest : NodeBasedTest() {
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
participatingServiceNodes.forEach { node ->
node.respondWith(node.info)
}
val serviceAddress = originatingNode.services.networkMapCache.run {
originatingNode.net.getAddressOfParty(getPartyInfo(getNotary(serviceName)!!)!!)
originatingNode.net.getAddressOfParty(getPartyInfo(getNotary(serviceName.toString())!!)!!)
}
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

View File

@ -2,12 +2,15 @@ package net.corda.services.messaging
import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.crypto.Party
import net.corda.core.crypto.commonName
import net.corda.core.div
import net.corda.core.getOrThrow
import net.corda.core.node.NodeInfo
import net.corda.core.random63BitValue
import net.corda.core.seconds
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.services.config.configureWithDevSSLCertificate
import net.corda.node.services.messaging.sendRequest
@ -21,6 +24,7 @@ import net.corda.testing.node.NodeBasedTest
import net.corda.testing.node.SimpleNode
import org.assertj.core.api.Assertions.assertThatExceptionOfType
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test
import java.time.Instant
import java.util.concurrent.TimeoutException
@ -42,9 +46,9 @@ class P2PSecurityTest : NodeBasedTest() {
@Test
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
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
// to the attacker as the TLS CN will not match the legal name it has just provided
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(
baseDirectory = tempFolder.root.toPath() / legalName,
baseDirectory = tempFolder.root.toPath() / legalName.commonName,
myLegalName = legalName,
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
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 registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
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.
val privKeyFile = dir / privateKeyFileName
val pubIdentityFile = dir / publicKeyFileName
val identityName = serviceName ?: configuration.myLegalName
val identityName = serviceName ?: configuration.myLegalName.toString()
val identityAndKey = if (!privKeyFile.exists()) {
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.utilities.loggerFor
import net.corda.nodeapi.config.SSLConfiguration
import org.bouncycastle.asn1.x500.X500Name
import java.nio.file.Path
object ConfigHelper {
@ -45,7 +46,7 @@ object ConfigHelper {
*/
fun NodeConfiguration.configureWithDevSSLCertificate() = configureDevKeyAndTrustStores(myLegalName)
fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: String) {
fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: X500Name) {
certificatesDirectory.createDirectories()
if (!trustStoreFile.exists()) {
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.config.OldConfig
import net.corda.nodeapi.config.SSLConfiguration
import org.bouncycastle.asn1.x500.X500Name
import java.net.URL
import java.nio.file.Path
import java.util.*
@ -20,7 +21,7 @@ import java.util.*
interface NodeConfiguration : SSLConfiguration {
val baseDirectory: Path
override val certificatesDirectory: Path get() = baseDirectory / "certificates"
val myLegalName: String
val myLegalName: X500Name
val networkMapService: NetworkMapInfo?
val minimumPlatformVersion: Int
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",
ReplaceWith("baseDirectory"))
val basedir: Path,
override val myLegalName: String,
override val myLegalName: X500Name,
override val nearestCity: String,
override val emailAddress: 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)
val ourSubjectDN = X500Name(ourCertificate.subjectDN.name)
// 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"
}
val defaultCertPolicies = mapOf(
@ -398,18 +398,18 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
private fun getBridgeName(queueName: String, hostAndPort: HostAndPort): String = "$queueName -> $hostAndPort"
// This is called on one of Artemis' background threads
internal fun hostVerificationFail(peerLegalName: String, expectedCommonName: String) {
log.error("Peer has wrong CN - expected $expectedCommonName but got $peerLegalName. This is either a fatal " +
internal fun hostVerificationFail(peerLegalName: X500Name, expectedLegalName: X500Name) {
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!")
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!
_networkMapConnectionFuture!!.setException(IOException("${config.networkMapService} failed host verification check"))
}
}
// This is called on one of Artemis' background threads
internal fun onTcpConnection(peerLegalName: String) {
if (peerLegalName == config.networkMapService?.legalName) {
internal fun onTcpConnection(peerLegalName: X500Name) {
if (peerLegalName.toString() == config.networkMapService?.legalName) {
_networkMapConnectionFuture!!.set(Unit)
}
}
@ -437,7 +437,9 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>?,
protocolManager: ClientProtocolManager?) :
NettyConnector(configuration, handler, listener, closeExecutor, threadPool, scheduledThreadPool, protocolManager) {
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? {
val connection = super.createConnection() as NettyConnection?
@ -451,9 +453,8 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>?,
.peerPrincipal
.name
.let(::X500Name)
.commonName
// TODO Verify on the entire principle (subject)
if (peerLegalName != expectedCommonName) {
if (peerLegalName.commonName != expectedCommonName.commonName) {
connection.close()
server!!.hostVerificationFail(peerLegalName, expectedCommonName)
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) {
override fun send(data: SerializedBytes<*>, toAddress: String) {
messagingExecutor.fetchFrom {

View File

@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger
* are handled, this is probably the wrong system.
*/
// 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
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)
if (rpcUser != null) {
return rpcUser
} else if (X500Name(validatedUser).commonName == nodeLegalName) {
return nodeUser
} 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")
}
}

View File

@ -100,7 +100,7 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
// Retrieve request id from file if exists, else post a request to server.
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()
JcaPEMWriter(writer).use {
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))

View File

@ -34,7 +34,7 @@ class InteractiveShellTest {
}
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 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.testing.testConfiguration
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test
import java.nio.file.Paths
@ -11,7 +12,7 @@ class FullNodeConfigurationTest {
@Test
fun `Artemis special characters not permitted in RPC usernames`() {
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())))
}

View File

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

View File

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

View File

@ -72,8 +72,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = "CN=Bank $letter,O=Bank $letter,L=$city,C=$country",
nearestCity = city,
myLegalName = X500Name("CN=Bank $letter,O=Bank $letter,L=$city,C=$country"),
networkMapService = null)
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
}
@ -95,8 +94,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
require(advertisedServices.containsType(NetworkMapService.type))
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = DUMMY_MAP.name,
nearestCity = X500Name(DUMMY_MAP.name).location,
myLegalName = X500Name(DUMMY_MAP.name),
networkMapService = null)
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))
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = DUMMY_NOTARY.name,
nearestCity = X500Name(DUMMY_NOTARY.name).location,
myLegalName = X500Name(DUMMY_NOTARY.name),
networkMapService = null)
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
}
@ -118,7 +115,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
object RatesOracleFactory : MockNetwork.Factory {
// 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?,
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
@ -127,7 +124,6 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = RATES_SERVICE_NAME,
nearestCity = X500Name(RATES_SERVICE_NAME).location,
networkMapService = null)
return object : SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot) {
override fun start(): MockNetwork.MockNode {
@ -149,8 +145,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
entropyRoot: BigInteger): MockNetwork.MockNode {
val cfg = TestNodeConfiguration(
baseDirectory = config.baseDirectory,
myLegalName = DUMMY_REGULATOR.name,
nearestCity = X500Name(DUMMY_REGULATOR.name).location,
myLegalName = X500Name(DUMMY_REGULATOR.name),
networkMapService = null)
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.

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 {
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
val pulse = Circle(initialRadius).apply {
@ -157,7 +157,7 @@ class VisualiserViewModel {
view.root.children += longPulseOuterDot
view.root.children += innerDot
val nameLabel = Label(label)
val nameLabel = Label(label.toString())
val nameLabelRect = StackPane(nameLabel).apply {
styleClass += "node-label"
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.makeTestDataSourceProperties
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x500.style.BCStyle
import java.net.ServerSocket
import java.net.URL
import java.nio.file.Files
@ -156,23 +157,24 @@ inline fun <reified P : FlowLogic<*>> AbstractNode.initiateSingleShotFlow(
// TODO Replace this with testConfiguration
data class TestNodeConfiguration(
override val baseDirectory: Path,
override val myLegalName: String,
override val myLegalName: X500Name,
override val networkMapService: NetworkMapInfo?,
override val minimumPlatformVersion: Int = 1,
override val keyStorePassword: String = "cordacadevpass",
override val trustStorePassword: String = "trustpass",
override val rpcUsers: List<User> = emptyList(),
override val dataSourceProperties: Properties = makeTestDataSourceProperties(myLegalName),
override val nearestCity: String = "Null Island",
override val emailAddress: String = "",
override val exportJMXto: String = "",
override val devMode: Boolean = true,
override val certificateSigningService: URL = URL("http://localhost"),
override val certificateChainCheckPolicies: List<CertChainPolicyConfig> = emptyList(),
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(
basedir = baseDirectory,
myLegalName = legalName,
@ -198,7 +200,7 @@ fun testConfiguration(baseDirectory: Path, legalName: String, basePort: Int): Fu
}
@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 keyStorePassword: String get() = "cordacadevpass"
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.testing.configureTestSSL
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.
*/
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 session: ClientSession
lateinit var producer: ClientProducer

View File

@ -127,10 +127,10 @@ class InMemoryMessagingNetwork(
id: Int,
executor: AffinityExecutor,
advertisedServices: List<ServiceEntry>,
description: String? = null,
description: X500Name? = null,
database: Database)
: 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 {
@ -198,8 +198,8 @@ class InMemoryMessagingNetwork(
}
@CordaSerializable
data class PeerHandle(val id: Int, val description: String) : SingleMessageRecipient {
override fun toString() = description
data class PeerHandle(val id: Int, val description: X500Name) : SingleMessageRecipient {
override fun toString() = description.toString()
override fun equals(other: Any?) = other is PeerHandle && other.id == id
override fun hashCode() = id.hashCode()
}
@ -468,6 +468,6 @@ class InMemoryMessagingNetwork(
1,
message.uniqueMessageId,
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.TestNodeConfiguration
import org.apache.activemq.artemis.utils.ReusableLatch
import org.bouncycastle.asn1.x500.X500Name
import org.slf4j.Logger
import java.math.BigInteger
import java.nio.file.FileSystem
@ -287,9 +288,9 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
val config = TestNodeConfiguration(
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,
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)
if (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.
*/
fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties {
fun makeTestDataSourceProperties(nodeName: X500Name = X509Utilities.getDevX509Name(SecureHash.randomSHA256().toString())): Properties {
val props = Properties()
props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
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.google.common.net.HostAndPort
import com.google.common.util.concurrent.SettableFuture
import net.corda.core.crypto.commonName
import net.corda.core.crypto.generateKeyPair
import net.corda.core.messaging.RPCOps
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.transaction
import net.corda.testing.freeLocalHostAndPort
import org.bouncycastle.asn1.x500.X500Name
import org.jetbrains.exposed.sql.Database
import java.io.Closeable
import java.security.KeyPair
@ -32,7 +34,7 @@ class SimpleNode(val config: NodeConfiguration, val address: HostAndPort = freeL
val userService = RPCUserServiceImpl(config.rpcUsers)
val monitoringService = MonitoringService(MetricRegistry())
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 networkMapRegistrationFuture: SettableFuture<Unit> = SettableFuture.create<Unit>()
val net = database.transaction {
@ -54,7 +56,7 @@ class SimpleNode(val config: NodeConfiguration, val address: HostAndPort = freeL
override val protocolVersion = 0
},
userService)
thread(name = config.myLegalName) {
thread(name = config.myLegalName.commonName) {
net.run()
}
}

View File

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

View File

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

View File

@ -2,6 +2,7 @@ package net.corda.demobench.model
import net.corda.demobench.plugin.PluginController
import net.corda.demobench.pty.R3Pty
import org.bouncycastle.asn1.x500.X500Name
import tornadofx.*
import java.io.IOException
import java.lang.management.ManagementFactory
@ -51,10 +52,9 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
fun validate(nodeData: NodeData): NodeConfig? {
val config = NodeConfig(
baseDir,
nodeData.legalName.value.trim(),
X500Name(nodeData.legalName.value.trim()),
nodeData.p2pPort.value,
nodeData.rpcPort.value,
nodeData.nearestCity.value.description.trim(),
nodeData.webPort.value,
nodeData.h2Port.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.settings.SettingsProvider
import com.pty4j.PtyProcess
import net.corda.core.crypto.commonName
import net.corda.core.utilities.loggerFor
import org.bouncycastle.asn1.x500.X500Name
import java.awt.Dimension
import java.io.IOException
import java.nio.charset.StandardCharsets.UTF_8
import java.util.concurrent.Executors
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 {
val log = loggerFor<R3Pty>()
}
@ -32,7 +34,7 @@ class R3Pty(val name: String, settings: SettingsProvider, dimension: Dimension,
val process = PtyProcess.exec(command, environment, workingDir)
try {
return PtyProcessTtyConnector(name, process, UTF_8)
return PtyProcessTtyConnector(name.commonName, process, UTF_8)
} catch (e: Exception) {
process.destroyForcibly()
process.waitFor(30, TimeUnit.SECONDS)

View File

@ -263,11 +263,11 @@ class NodeTabView : Fragment() {
}
private fun launchNode(config: NodeConfig) {
val countryCode = CityDatabase.cityMap[config.nearestCity]?.countryCode
val countryCode = CityDatabase.cityMap[config.nearestCity ?: "Nowhere"]?.countryCode
if (countryCode != null) {
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 ->
Platform.runLater {
if (exitCode == 0)

View File

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

View File

@ -1,5 +1,6 @@
package net.corda.demobench.model
import org.bouncycastle.asn1.x500.X500Name
import org.junit.Test
import kotlin.test.assertEquals
@ -7,7 +8,7 @@ class NetworkMapConfigTest {
@Test
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)
}

View File

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

View File

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