From f7445a5e6a8735442361fd92e4c1e3687ee3ad93 Mon Sep 17 00:00:00 2001 From: Andrzej Cichocki Date: Mon, 18 Dec 2017 17:09:24 +0000 Subject: [PATCH 1/3] CORDA-876 MockNetwork no longer leaks serialization env if init fails (#2272) --- testing/node-driver/build.gradle | 2 +- .../kotlin/net/corda/testing/node/MockNode.kt | 45 ++++++++++++------- .../corda/testing/node/MockNetworkTests.kt | 18 ++++++++ 3 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 testing/node-driver/src/test/kotlin/net/corda/testing/node/MockNetworkTests.kt diff --git a/testing/node-driver/build.gradle b/testing/node-driver/build.gradle index d3fda9b9c7..5663251bc2 100644 --- a/testing/node-driver/build.gradle +++ b/testing/node-driver/build.gradle @@ -28,7 +28,7 @@ dependencies { compile "net.corda.plugins:cordform-common:$gradle_plugins_version" // Integration test helpers - integrationTestCompile "org.assertj:assertj-core:${assertj_version}" + testCompile "org.assertj:assertj-core:$assertj_version" integrationTestCompile "junit:junit:$junit_version" // Jetty dependencies for NetworkMapClient test. diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt index 2ed3d9b65d..24b449e441 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -9,6 +9,7 @@ import net.corda.core.crypto.random63BitValue import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate +import net.corda.core.internal.VisibleForTesting import net.corda.core.internal.createDirectories import net.corda.core.internal.createDirectory import net.corda.core.internal.uncheckedCast @@ -124,14 +125,14 @@ data class MockNodeArgs( * By default a single notary node is automatically started, which forms part of the network parameters for all the nodes. * This node is available by calling [defaultNotaryNode]. */ -class MockNetwork(private val cordappPackages: List, - defaultParameters: MockNetworkParameters = MockNetworkParameters(), - private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped, - private val threadPerNode: Boolean = defaultParameters.threadPerNode, - servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy, - private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory, - initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, - private val notarySpecs: List = defaultParameters.notarySpecs) { +open class MockNetwork(private val cordappPackages: List, + defaultParameters: MockNetworkParameters = MockNetworkParameters(), + private val networkSendManuallyPumped: Boolean = defaultParameters.networkSendManuallyPumped, + private val threadPerNode: Boolean = defaultParameters.threadPerNode, + servicePeerAllocationStrategy: InMemoryMessagingNetwork.ServicePeerAllocationStrategy = defaultParameters.servicePeerAllocationStrategy, + private val defaultFactory: (MockNodeArgs) -> MockNode = defaultParameters.defaultFactory, + initialiseSerialization: Boolean = defaultParameters.initialiseSerialization, + private val notarySpecs: List = defaultParameters.notarySpecs) { /** Helper constructor for creating a [MockNetwork] with custom parameters from Java. */ @JvmOverloads constructor(cordappPackages: List, parameters: MockNetworkParameters = MockNetworkParameters()) : this(cordappPackages, defaultParameters = parameters) @@ -140,7 +141,7 @@ class MockNetwork(private val cordappPackages: List, // Apache SSHD for whatever reason registers a SFTP FileSystemProvider - which gets loaded by JimFS. // This SFTP support loads BouncyCastle, which we want to avoid. // Please see https://issues.apache.org/jira/browse/SSHD-736 - it's easier then to create our own fork of SSHD - SecurityUtils.setAPrioriDisabledProvider("BC", true) + SecurityUtils.setAPrioriDisabledProvider("BC", true) // XXX: Why isn't this static? } var nextNodeId = 0 @@ -221,11 +222,17 @@ class MockNetwork(private val cordappPackages: List, } init { - filesystem.getPath("/nodes").createDirectory() - val notaryInfos = generateNotaryIdentities() - // The network parameters must be serialised before starting any of the nodes - networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos)) - notaryNodes = createNotaries() + try { + filesystem.getPath("/nodes").createDirectory() + val notaryInfos = generateNotaryIdentities() + // The network parameters must be serialised before starting any of the nodes + networkParameters = NetworkParametersCopier(testNetworkParameters(notaryInfos)) + @Suppress("LeakingThis") + notaryNodes = createNotaries() + } catch (t: Throwable) { + stopNodes() + throw t + } } private fun generateNotaryIdentities(): List { @@ -238,7 +245,8 @@ class MockNetwork(private val cordappPackages: List, } } - private fun createNotaries(): List> { + @VisibleForTesting + internal open fun createNotaries(): List> { return notarySpecs.map { spec -> createNode(MockNodeParameters(legalName = spec.name, configOverrides = { doReturn(NotaryConfig(spec.validating)).whenever(it).notary @@ -455,8 +463,11 @@ class MockNetwork(private val cordappPackages: List, } fun stopNodes() { - nodes.forEach { it.started?.dispose() } - serializationEnv.unset() + try { + nodes.forEach { it.started?.dispose() } + } finally { + serializationEnv.unset() // Must execute even if other parts of this method fail. + } messagingNetwork.stop() } diff --git a/testing/node-driver/src/test/kotlin/net/corda/testing/node/MockNetworkTests.kt b/testing/node-driver/src/test/kotlin/net/corda/testing/node/MockNetworkTests.kt new file mode 100644 index 0000000000..10d9358243 --- /dev/null +++ b/testing/node-driver/src/test/kotlin/net/corda/testing/node/MockNetworkTests.kt @@ -0,0 +1,18 @@ +package net.corda.testing.node + +import net.corda.core.serialization.internal.effectiveSerializationEnv +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.Test + +class MockNetworkTests { + @Test + fun `does not leak serialization env if init fails`() { + val e = Exception("didn't work") + assertThatThrownBy { + object : MockNetwork(emptyList(), initialiseSerialization = true) { + override fun createNotaries() = throw e + } + }.isSameAs(e) + assertThatThrownBy { effectiveSerializationEnv }.isInstanceOf(IllegalStateException::class.java) + } +} From e1e715ee8112126274c837cc511cdc34347fb6bc Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Thu, 30 Nov 2017 19:02:44 +0000 Subject: [PATCH 2/3] Removed all remaining special treatment of the X500 common name. With network parameters the CN is no longer needed to identify notaries. This frees it up to be used in the node's name alongside the other attributes. Also, the identity generation logic has been simplified, removing the need to have magic string values for storing distributed identities in the keystore. Now there are just two alias prefixes: "identity" as it was previously, and "distributed-notary". --- .ci/api-current.txt | 2 +- .../net/corda/core/identity/CordaX500Name.kt | 4 +- .../net/corda/core/internal/InternalUtils.kt | 2 + .../corda/core/node/services/NotaryService.kt | 2 + .../corda/core/crypto/CompositeKeyTests.kt | 11 +- .../AttachmentSerializationTest.kt | 2 +- docs/source/generating-a-node.rst | 2 - docs/source/hello-world-running.rst | 2 +- ...ntityGenerator.kt => IdentityGenerator.kt} | 44 ++++--- .../nodeapi/internal/crypto/X509Utilities.kt | 12 +- .../node/services/BFTNotaryServiceTests.kt | 10 +- .../node/services/RaftNotaryServiceTests.kt | 12 +- .../services/messaging/P2PMessagingTest.kt | 3 +- .../net/corda/node/internal/AbstractNode.kt | 29 ++--- .../node/services/config/ConfigUtilities.kt | 9 +- .../identity/InMemoryIdentityService.kt | 1 + .../identity/PersistentIdentityService.kt | 1 + .../BFTNonValidatingNotaryService.kt | 11 +- .../RaftNonValidatingNotaryService.kt | 13 +- .../RaftValidatingNotaryService.kt | 13 +- .../transactions/ValidatingNotaryService.kt | 4 +- .../registration/NetworkRegistrationHelper.kt | 5 +- .../statemachine/FlowFrameworkTests.kt | 2 +- .../NetworkRegistrationHelperTest.kt | 111 +++++++++--------- .../net/corda/notarydemo/BFTNotaryCordform.kt | 12 +- .../corda/notarydemo/RaftNotaryCordform.kt | 11 +- .../kotlin/net/corda/testing/node/MockNode.kt | 43 +++---- .../testing/node/internal/DriverDSLImpl.kt | 42 ++----- .../kotlin/net/corda/testing/CoreTestUtils.kt | 4 +- .../corda/demobench/model/NodeController.kt | 7 +- 30 files changed, 200 insertions(+), 226 deletions(-) rename node-api/src/main/kotlin/net/corda/nodeapi/internal/{ServiceIdentityGenerator.kt => IdentityGenerator.kt} (53%) diff --git a/.ci/api-current.txt b/.ci/api-current.txt index c991ab4198..896cdd2592 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -1836,7 +1836,7 @@ public @interface net.corda.core.node.services.CordaService @org.jetbrains.annotations.NotNull public static final String ID_PREFIX = "corda.notary." ## public static final class net.corda.core.node.services.NotaryService$Companion extends java.lang.Object - @org.jetbrains.annotations.NotNull public final String constructId(boolean, boolean, boolean, boolean) + @kotlin.Deprecated @org.jetbrains.annotations.NotNull public final String constructId(boolean, boolean, boolean, boolean) ## public abstract class net.corda.core.node.services.PartyInfo extends java.lang.Object @org.jetbrains.annotations.NotNull public abstract net.corda.core.identity.Party getParty() diff --git a/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt b/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt index 0b6a3ddeb7..c7d5065390 100644 --- a/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt +++ b/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt @@ -36,7 +36,9 @@ data class CordaX500Name(val commonName: String?, val locality: String, val state: String?, val country: String) { - constructor(commonName: String, organisation: String, locality: String, country: String) : this(commonName = commonName, organisationUnit = null, organisation = organisation, locality = locality, state = null, country = country) + constructor(commonName: String, organisation: String, locality: String, country: String) : + this(commonName = commonName, organisationUnit = null, organisation = organisation, locality = locality, state = null, country = country) + /** * @param organisation name of the organisation. * @param locality locality of the organisation, typically nearest major city. diff --git a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt index 36022463ff..c2dd50ac50 100644 --- a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt +++ b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt @@ -118,6 +118,8 @@ fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(th inline val Path.size: Long get() = Files.size(this) inline fun Path.list(block: (Stream) -> R): R = Files.list(this).use(block) fun Path.deleteIfExists(): Boolean = Files.deleteIfExists(this) +fun Path.reader(charset: Charset = UTF_8): BufferedReader = Files.newBufferedReader(this, charset) +fun Path.writer(charset: Charset = UTF_8, vararg options: OpenOption): BufferedWriter = Files.newBufferedWriter(this, charset, *options) fun Path.readAll(): ByteArray = Files.readAllBytes(this) inline fun Path.read(vararg options: OpenOption, block: (InputStream) -> R): R = Files.newInputStream(this, *options).use(block) inline fun Path.write(createDirs: Boolean = false, vararg options: OpenOption = emptyArray(), block: (OutputStream) -> Unit) { diff --git a/core/src/main/kotlin/net/corda/core/node/services/NotaryService.kt b/core/src/main/kotlin/net/corda/core/node/services/NotaryService.kt index 46227d0027..8c6a160618 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/NotaryService.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/NotaryService.kt @@ -15,7 +15,9 @@ import java.security.PublicKey abstract class NotaryService : SingletonSerializeAsToken() { companion object { + @Deprecated("No longer used") const val ID_PREFIX = "corda.notary." + @Deprecated("No longer used") fun constructId(validating: Boolean, raft: Boolean = false, bft: Boolean = false, custom: Boolean = false): String { require(Booleans.countTrue(raft, bft, custom) <= 1) { "At most one of raft, bft or custom may be true" } return StringBuffer(ID_PREFIX).apply { diff --git a/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt b/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt index 734505498d..751037b1ee 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/CompositeKeyTests.kt @@ -9,8 +9,8 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.toBase58String import net.corda.nodeapi.internal.crypto.* -import net.corda.testing.internal.kryoSpecific import net.corda.testing.SerializationEnvironmentRule +import net.corda.testing.internal.kryoSpecific import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder @@ -24,6 +24,7 @@ class CompositeKeyTests { @Rule @JvmField val testSerialization = SerializationEnvironmentRule() + @Rule @JvmField val tempFolder: TemporaryFolder = TemporaryFolder() @@ -40,9 +41,9 @@ class CompositeKeyTests { private val secureHash = message.sha256() // By lazy is required so that the serialisers are configured before vals initialisation takes place (they internally invoke serialise). - val aliceSignature by lazy { aliceKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(alicePublicKey).schemeNumberID))) } - val bobSignature by lazy { bobKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(bobPublicKey).schemeNumberID))) } - val charlieSignature by lazy { charlieKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(charliePublicKey).schemeNumberID))) } + private val aliceSignature by lazy { aliceKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(alicePublicKey).schemeNumberID))) } + private val bobSignature by lazy { bobKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(bobPublicKey).schemeNumberID))) } + private val charlieSignature by lazy { charlieKey.sign(SignableData(secureHash, SignatureMetadata(1, Crypto.findSignatureScheme(charliePublicKey).schemeNumberID))) } @Test fun `(Alice) fulfilled by Alice signature`() { @@ -337,7 +338,7 @@ class CompositeKeyTests { val ca = X509Utilities.createSelfSignedCACertificate(caName, caKeyPair) // Sign the composite key with the self sign CA. - val compositeKeyCert = X509Utilities.createCertificate(CertificateType.LEGAL_IDENTITY, ca, caKeyPair, caName.copy(commonName = "CompositeKey"), compositeKey) + val compositeKeyCert = X509Utilities.createCertificate(CertificateType.LEGAL_IDENTITY, ca, caKeyPair, caName, compositeKey) // Store certificate to keystore. val keystorePath = tempFolder.root.toPath() / "keystore.jks" diff --git a/core/src/test/kotlin/net/corda/core/serialization/AttachmentSerializationTest.kt b/core/src/test/kotlin/net/corda/core/serialization/AttachmentSerializationTest.kt index 940d959860..d72d7068d4 100644 --- a/core/src/test/kotlin/net/corda/core/serialization/AttachmentSerializationTest.kt +++ b/core/src/test/kotlin/net/corda/core/serialization/AttachmentSerializationTest.kt @@ -159,7 +159,7 @@ class AttachmentSerializationTest { private fun rebootClientAndGetAttachmentContent(checkAttachmentsOnLoad: Boolean = true): String { client.dispose() - client = mockNet.createNode(MockNodeParameters(client.internals.id), { args -> + client = mockNet.createNode(MockNodeParameters(client.internals.id, client.internals.configuration.myLegalName), { args -> object : MockNetwork.MockNode(args) { override fun start() = super.start().apply { attachments.checkAttachmentsOnLoad = checkAttachmentsOnLoad } } diff --git a/docs/source/generating-a-node.rst b/docs/source/generating-a-node.rst index 4a721e304d..eee15b3d5d 100644 --- a/docs/source/generating-a-node.rst +++ b/docs/source/generating-a-node.rst @@ -92,7 +92,6 @@ nodes. Here is an example ``Cordform`` task called ``deployNodes`` that creates } node { name "O=PartyA,L=London,C=GB" - advertisedServices = [] p2pPort 10005 rpcPort 10006 webPort 10007 @@ -103,7 +102,6 @@ nodes. Here is an example ``Cordform`` task called ``deployNodes`` that creates } node { name "O=PartyB,L=New York,C=US" - advertisedServices = [] p2pPort 10009 rpcPort 10010 webPort 10011 diff --git a/docs/source/hello-world-running.rst b/docs/source/hello-world-running.rst index 592cfee44c..4ac394d26c 100644 --- a/docs/source/hello-world-running.rst +++ b/docs/source/hello-world-running.rst @@ -22,7 +22,7 @@ service. directory "./build/nodes" node { name "O=Controller,L=London,C=GB" - advertisedServices = ["corda.notary.validating"] + notary = [validating : true] p2pPort 10002 rpcPort 10003 cordapps = ["net.corda:corda-finance:$corda_release_version"] diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/ServiceIdentityGenerator.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/IdentityGenerator.kt similarity index 53% rename from node-api/src/main/kotlin/net/corda/nodeapi/internal/ServiceIdentityGenerator.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/IdentityGenerator.kt index 65b60433c7..97927e54db 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/ServiceIdentityGenerator.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/IdentityGenerator.kt @@ -13,42 +13,54 @@ import org.slf4j.LoggerFactory import java.nio.file.Path import java.security.cert.X509Certificate -object ServiceIdentityGenerator { +object IdentityGenerator { private val log = LoggerFactory.getLogger(javaClass) + const val NODE_IDENTITY_ALIAS_PREFIX = "identity" + const val DISTRIBUTED_NOTARY_ALIAS_PREFIX = "distributed-notary" + + fun generateNodeIdentity(dir: Path, legalName: CordaX500Name, customRootCert: X509Certificate? = null): Party { + return generateToDisk(listOf(dir), legalName, NODE_IDENTITY_ALIAS_PREFIX, threshold = 1, customRootCert = customRootCert) + } + + fun generateDistributedNotaryIdentity(dirs: List, notaryName: CordaX500Name, threshold: Int = 1, customRootCert: X509Certificate? = null): Party { + return generateToDisk(dirs, notaryName, DISTRIBUTED_NOTARY_ALIAS_PREFIX, threshold, customRootCert) + } + /** * Generates signing key pairs and a common distributed service identity for a set of nodes. * The key pairs and the group identity get serialized to disk in the corresponding node directories. * This method should be called *before* any of the nodes are started. * * @param dirs List of node directories to place the generated identity and key pairs in. - * @param serviceName The legal name of the distributed service. + * @param name The name of the identity. * @param threshold The threshold for the generated group [CompositeKey]. - * @param customRootCert the certificate to use a Corda root CA. If not specified the one in - * certificates/cordadevcakeys.jks is used. + * @param customRootCert the certificate to use as the Corda root CA. If not specified the one in + * internal/certificates/cordadevcakeys.jks is used. */ - fun generateToDisk(dirs: List, - serviceName: CordaX500Name, - serviceId: String, - threshold: Int = 1, - customRootCert: X509Certificate? = null): Party { - log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" } + private fun generateToDisk(dirs: List, + name: CordaX500Name, + aliasPrefix: String, + threshold: Int, + customRootCert: X509Certificate?): Party { + log.trace { "Generating identity \"$name\" for nodes: ${dirs.joinToString()}" } val keyPairs = (1..dirs.size).map { generateKeyPair() } - val notaryKey = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold) + val key = CompositeKey.Builder().addKeys(keyPairs.map { it.public }).build(threshold) val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass") val intermediateCa = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, "cordacadevkeypass") val rootCert = customRootCert ?: caKeyStore.getCertificate(X509Utilities.CORDA_ROOT_CA) keyPairs.zip(dirs) { keyPair, dir -> - val serviceKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, serviceName, keyPair.public) - val compositeKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, serviceName, notaryKey) + val serviceKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, name, keyPair.public) + val compositeKeyCert = X509Utilities.createCertificate(CertificateType.SERVICE_IDENTITY, intermediateCa.certificate, intermediateCa.keyPair, name, key) val certPath = (dir / "certificates").createDirectories() / "distributedService.jks" val keystore = loadOrCreateKeyStore(certPath, "cordacadevpass") - keystore.setCertificateEntry("$serviceId-composite-key", compositeKeyCert.cert) - keystore.setKeyEntry("$serviceId-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, intermediateCa.certificate.cert, rootCert)) + keystore.setCertificateEntry("$aliasPrefix-composite-key", compositeKeyCert.cert) + keystore.setKeyEntry("$aliasPrefix-private-key", keyPair.private, "cordacadevkeypass".toCharArray(), arrayOf(serviceKeyCert.cert, intermediateCa.certificate.cert, rootCert)) keystore.save(certPath, "cordacadevpass") } - return Party(serviceName, notaryKey) + + return Party(name, key) } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt index 70617daf76..563ddaa9f0 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt @@ -7,7 +7,8 @@ import net.corda.core.crypto.random63BitValue import net.corda.core.internal.CertRole import net.corda.core.identity.CordaX500Name import net.corda.core.internal.cert -import net.corda.core.internal.read +import net.corda.core.internal.reader +import net.corda.core.internal.writer import net.corda.core.internal.x500Name import net.corda.core.utilities.days import net.corda.core.utilities.millis @@ -48,8 +49,6 @@ object X509Utilities { const val CORDA_CLIENT_TLS = "cordaclienttls" const val CORDA_CLIENT_CA = "cordaclientca" - const val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate" - private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days) /** @@ -162,7 +161,7 @@ object X509Utilities { */ @JvmStatic fun saveCertificateAsPEMFile(x509Certificate: X509Certificate, file: Path) { - JcaPEMWriter(file.toFile().writer()).use { + JcaPEMWriter(file.writer()).use { it.writeObject(x509Certificate) } } @@ -174,9 +173,8 @@ object X509Utilities { */ @JvmStatic fun loadCertificateFromPEMFile(file: Path): X509Certificate { - return file.read { - val reader = PemReader(it.reader()) - val pemObject = reader.readPemObject() + return file.reader().use { + val pemObject = PemReader(it).readPemObject() val certHolder = X509CertificateHolder(pemObject.content) certHolder.isValidOn(Date()) certHolder.cert diff --git a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt index ef762be725..c63b97f09d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/BFTNotaryServiceTests.kt @@ -13,7 +13,6 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.internal.deleteIfExists import net.corda.core.internal.div -import net.corda.core.node.services.NotaryService import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.NetworkHostAndPort @@ -24,10 +23,10 @@ import net.corda.node.services.config.BFTSMaRtConfiguration import net.corda.node.services.config.NotaryConfig import net.corda.node.services.transactions.minClusterSize import net.corda.node.services.transactions.minCorrectReplicas -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator +import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NotaryInfo import net.corda.testing.chooseIdentity -import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.contracts.DummyContract import net.corda.testing.dummyCommand @@ -55,10 +54,9 @@ class BFTNotaryServiceTests { (Paths.get("config") / "currentView").deleteIfExists() // XXX: Make config object warn if this exists? val replicaIds = (0 until clusterSize) - notary = ServiceIdentityGenerator.generateToDisk( + notary = IdentityGenerator.generateDistributedNotaryIdentity( replicaIds.map { mockNet.baseDirectory(mockNet.nextNodeId + it) }, - CordaX500Name("BFT", "Zurich", "CH"), - NotaryService.constructId(validating = false, bft = true)) + CordaX500Name("BFT", "Zurich", "CH")) val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notary, false)))) diff --git a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt index 84383cf6e0..4f70f23f5d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/RaftNotaryServiceTests.kt @@ -11,30 +11,30 @@ import net.corda.core.internal.concurrent.map import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.getOrThrow import net.corda.node.internal.StartedNode -import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.testing.* +import net.corda.testing.DUMMY_BANK_A_NAME +import net.corda.testing.chooseIdentity import net.corda.testing.contracts.DummyContract import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver import net.corda.testing.dummyCommand -import net.corda.testing.node.startFlow import net.corda.testing.node.ClusterSpec import net.corda.testing.node.NotarySpec +import net.corda.testing.node.startFlow import org.junit.Test import java.util.* import kotlin.test.assertEquals import kotlin.test.assertFailsWith class RaftNotaryServiceTests { - private val notaryName = CordaX500Name(RaftValidatingNotaryService.id, "RAFT Notary Service", "London", "GB") + private val notaryName = CordaX500Name("RAFT Notary Service", "London", "GB") @Test fun `detect double spend`() { driver( startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.testing.contracts"), - notarySpecs = listOf(NotarySpec(notaryName, cluster = ClusterSpec.Raft(clusterSize = 3)))) - { + notarySpecs = listOf(NotarySpec(notaryName, cluster = ClusterSpec.Raft(clusterSize = 3))) + ) { val bankA = startNode(providedName = DUMMY_BANK_A_NAME).map { (it as NodeHandle.InProcess).node }.getOrThrow() val inputState = issueState(bankA, defaultNotaryIdentity) diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt index 7d8bf110e1..4e7035957d 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt @@ -15,7 +15,6 @@ import net.corda.core.utilities.seconds import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.services.messaging.* -import net.corda.node.services.transactions.RaftValidatingNotaryService import net.corda.testing.ALICE_NAME import net.corda.testing.chooseIdentity import net.corda.testing.driver.DriverDSL @@ -32,7 +31,7 @@ import java.util.concurrent.atomic.AtomicInteger class P2PMessagingTest { private companion object { - val DISTRIBUTED_SERVICE_NAME = CordaX500Name(RaftValidatingNotaryService.id, "DistributedService", "London", "GB") + val DISTRIBUTED_SERVICE_NAME = CordaX500Name("DistributedService", "London", "GB") } @Test diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index ab435d9e58..0a59cd1804 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -59,8 +59,12 @@ import net.corda.node.services.vault.NodeVaultService import net.corda.node.services.vault.VaultSoftLockManager import net.corda.node.shell.InteractiveShell import net.corda.node.utilities.AffinityExecutor +import net.corda.nodeapi.internal.IdentityGenerator import net.corda.nodeapi.internal.SignedNodeInfo -import net.corda.nodeapi.internal.crypto.* +import net.corda.nodeapi.internal.crypto.KeyStoreWrapper +import net.corda.nodeapi.internal.crypto.X509CertificateFactory +import net.corda.nodeapi.internal.crypto.X509Utilities +import net.corda.nodeapi.internal.crypto.loadKeyStore import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME import net.corda.nodeapi.internal.network.NetworkParameters import net.corda.nodeapi.internal.persistence.CordaPersistence @@ -133,25 +137,19 @@ abstract class AbstractNode(val configuration: NodeConfiguration, protected val services: ServiceHubInternal get() = _services private lateinit var _services: ServiceHubInternalImpl protected var myNotaryIdentity: PartyAndCertificate? = null - protected lateinit var checkpointStorage: CheckpointStorage + private lateinit var checkpointStorage: CheckpointStorage private lateinit var tokenizableServices: List protected lateinit var attachments: NodeAttachmentService protected lateinit var network: MessagingService protected val runOnStop = ArrayList<() -> Any?>() - protected val _nodeReadyFuture = openFuture() + private val _nodeReadyFuture = openFuture() protected var networkMapClient: NetworkMapClient? = null lateinit var securityManager: RPCSecurityManager get /** Completes once the node has successfully registered with the network map service * or has loaded network map data from local database */ - val nodeReadyFuture: CordaFuture - get() = _nodeReadyFuture - /** A [CordaX500Name] with null common name. */ - protected val myLegalName: CordaX500Name by lazy { - val cert = loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA) - CordaX500Name.build(cert.subjectX500Principal).copy(commonName = null) - } + val nodeReadyFuture: CordaFuture get() = _nodeReadyFuture open val serializationWhitelists: List by lazy { cordappLoader.cordapps.flatMap { it.serializationWhitelists } @@ -308,7 +306,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, ) // Check if we have already stored a version of 'our own' NodeInfo, this is to avoid regenerating it with // a different timestamp. - networkMapCache.getNodesByLegalName(myLegalName).firstOrNull()?.let { + networkMapCache.getNodesByLegalName(configuration.myLegalName).firstOrNull()?.let { if (info.copy(serial = it.serial) == it) { info = it } @@ -728,13 +726,10 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val (id, singleName) = if (notaryConfig == null || !notaryConfig.isClusterConfig) { // Node's main identity or if it's a single node notary - Pair("identity", myLegalName) + Pair(IdentityGenerator.NODE_IDENTITY_ALIAS_PREFIX, configuration.myLegalName) } else { - val notaryId = notaryConfig.run { - NotaryService.constructId(validating, raft != null, bftSMaRt != null, custom) - } // The node is part of a distributed notary whose identity must already be generated beforehand. - Pair(notaryId, null) + Pair(IdentityGenerator.DISTRIBUTED_NOTARY_ALIAS_PREFIX, null) } // TODO: Integrate with Key management service? val privateKeyAlias = "$id-private-key" @@ -742,7 +737,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, if (!keyStore.containsAlias(privateKeyAlias)) { singleName ?: throw IllegalArgumentException( "Unable to find in the key store the identity of the distributed notary ($id) the node is part of") - // TODO: Remove use of [ServiceIdentityGenerator.generateToDisk]. + // TODO: Remove use of [IdentityGenerator.generateToDisk]. log.info("$privateKeyAlias not found in key store ${configuration.nodeKeystore}, generating fresh key!") keyStore.signAndSaveNewKeyPair(singleName, privateKeyAlias, generateKeyPair()) } diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 8db5dd2d72..bface31bcc 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -56,7 +56,7 @@ fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500Name) { val caKeyStore = loadKeyStore(javaClass.classLoader.getResourceAsStream("certificates/cordadevcakeys.jks"), "cordacadevpass") createKeystoreForCordaNode(sslKeystore, nodeKeystore, keyStorePassword, keyStorePassword, caKeyStore, "cordacadevkeypass", myLegalName) - // Move distributed service composite key (generated by ServiceIdentityGenerator.generateToDisk) to keystore if exists. + // Move distributed service composite key (generated by IdentityGenerator.generateToDisk) to keystore if exists. val distributedServiceKeystore = certificatesDirectory / "distributedService.jks" if (distributedServiceKeystore.exists()) { val serviceKeystore = loadKeyStore(distributedServiceKeystore, "cordacadevpass") @@ -98,18 +98,17 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path, val (intermediateCACert, intermediateCAKeyPair) = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caKeyPassword) val clientKey = Crypto.generateKeyPair(signatureScheme) - val clientName = legalName.copy(commonName = null) - val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, clientName.x500Name))), arrayOf()) + val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName.x500Name))), arrayOf()) val clientCACert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKeyPair, - clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN), + legalName, clientKey.public, nameConstraints = nameConstraints) val tlsKey = Crypto.generateKeyPair(signatureScheme) - val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName, tlsKey.public) + val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, legalName, tlsKey.public) val keyPass = keyPassword.toCharArray() diff --git a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt index bac9ef6902..4654473ef1 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt @@ -24,6 +24,7 @@ import javax.annotation.concurrent.ThreadSafe * * @param identities initial set of identities for the service, typically only used for unit tests. */ +// TODO There is duplicated logic between this and PersistentIdentityService @ThreadSafe class InMemoryIdentityService(identities: Array, trustRoot: X509CertificateHolder) : SingletonSerializeAsToken(), IdentityServiceInternal { diff --git a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt index 54d02979eb..0a07bc40c6 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt @@ -26,6 +26,7 @@ import javax.persistence.Entity import javax.persistence.Id import javax.persistence.Lob +// TODO There is duplicated logic between this and InMemoryIdentityService @ThreadSafe class PersistentIdentityService(override val trustRoot: X509Certificate, vararg caCertificates: X509Certificate) : SingletonSerializeAsToken(), IdentityServiceInternal { diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt index 780c4815c6..9f6ffe1d08 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/BFTNonValidatingNotaryService.kt @@ -34,12 +34,13 @@ import kotlin.concurrent.thread * * A transaction is notarised when the consensus is reached by the cluster on its uniqueness, and time-window validity. */ -class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, - override val notaryIdentityKey: PublicKey, - private val bftSMaRtConfig: BFTSMaRtConfiguration, - cluster: BFTSMaRt.Cluster) : NotaryService() { +class BFTNonValidatingNotaryService( + override val services: ServiceHubInternal, + override val notaryIdentityKey: PublicKey, + private val bftSMaRtConfig: BFTSMaRtConfiguration, + cluster: BFTSMaRt.Cluster +) : NotaryService() { companion object { - val id = constructId(validating = false, bft = true) private val log = contextLogger() } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftNonValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftNonValidatingNotaryService.kt index 1433e71f85..e672380398 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftNonValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftNonValidatingNotaryService.kt @@ -8,14 +8,13 @@ import net.corda.core.node.services.TrustedAuthorityNotaryService import java.security.PublicKey /** A non-validating notary service operated by a group of mutually trusting parties, uses the Raft algorithm to achieve consensus. */ -class RaftNonValidatingNotaryService(override val services: ServiceHub, - override val notaryIdentityKey: PublicKey, - override val uniquenessProvider: RaftUniquenessProvider) : TrustedAuthorityNotaryService() { - companion object { - val id = constructId(validating = false, raft = true) - } - +class RaftNonValidatingNotaryService( + override val services: ServiceHub, + override val notaryIdentityKey: PublicKey, + override val uniquenessProvider: RaftUniquenessProvider +) : TrustedAuthorityNotaryService() { override val timeWindowChecker: TimeWindowChecker = TimeWindowChecker(services.clock) + override fun createServiceFlow(otherPartySession: FlowSession): NotaryFlow.Service { return NonValidatingNotaryFlow(otherPartySession, this) } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt index 8fd3448512..3e4899ae0a 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt @@ -8,14 +8,13 @@ import net.corda.core.node.services.TrustedAuthorityNotaryService import java.security.PublicKey /** A validating notary service operated by a group of mutually trusting parties, uses the Raft algorithm to achieve consensus. */ -class RaftValidatingNotaryService(override val services: ServiceHub, - override val notaryIdentityKey: PublicKey, - override val uniquenessProvider: RaftUniquenessProvider) : TrustedAuthorityNotaryService() { - companion object { - val id = constructId(validating = true, raft = true) - } - +class RaftValidatingNotaryService( + override val services: ServiceHub, + override val notaryIdentityKey: PublicKey, + override val uniquenessProvider: RaftUniquenessProvider +) : TrustedAuthorityNotaryService() { override val timeWindowChecker: TimeWindowChecker = TimeWindowChecker(services.clock) + override fun createServiceFlow(otherPartySession: FlowSession): NotaryFlow.Service { return ValidatingNotaryFlow(otherPartySession, this) } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt index 6c7e36046b..5e687c3b6d 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt @@ -9,10 +9,8 @@ import java.security.PublicKey /** A Notary service that validates the transaction chain of the submitted transaction before committing it */ class ValidatingNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() { - companion object { - val id = constructId(validating = true) - } override val timeWindowChecker = TimeWindowChecker(services.clock) + override val uniquenessProvider = PersistentUniquenessProvider() override fun createServiceFlow(otherPartySession: FlowSession): NotaryFlow.Service = ValidatingNotaryFlow(otherPartySession, this) diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt index f24cf56f11..698420ca0a 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt @@ -103,10 +103,9 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v println("Generating SSL certificate for node messaging service.") val sslKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val caCert = caKeyStore.getX509Certificate(CORDA_CLIENT_CA).toX509CertHolder() - val sslCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, keyPair, CordaX500Name.build(caCert.cert.subjectX500Principal).copy(commonName = null), sslKey.public) + val sslCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, keyPair, CordaX500Name.build(caCert.cert.subjectX500Principal), sslKey.public) val sslKeyStore = loadOrCreateKeyStore(config.sslKeystore, keystorePassword) - sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(), - arrayOf(sslCert.cert, *certificates)) + sslKeyStore.addOrReplaceKey(CORDA_CLIENT_TLS, sslKey.private, privateKeyPassword.toCharArray(), arrayOf(sslCert.cert, *certificates)) sslKeyStore.save(config.sslKeystore, config.keyStorePassword) println("SSL private key and certificate stored in ${config.sslKeystore}.") // All done, clean up temp files. diff --git a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt index b5ba9320ca..4090d9d342 100644 --- a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt @@ -659,7 +659,7 @@ class FlowFrameworkTests { private inline fun > StartedNode.restartAndGetRestoredFlow() = internals.run { disableDBCloseOnStop() // Handover DB to new node copy stop() - val newNode = mockNet.createNode(MockNodeParameters(id)) + val newNode = mockNet.createNode(MockNodeParameters(id, configuration.myLegalName)) newNode.internals.acceptableLiveFiberCountOnStop = 1 manuallyCloseDB() mockNet.runNetwork() diff --git a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt index 50922e9fde..209153fdb8 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelperTest.kt @@ -1,5 +1,7 @@ package net.corda.node.utilities.registration +import com.google.common.jimfs.Configuration.unix +import com.google.common.jimfs.Jimfs import com.nhaarman.mockito_kotlin.any import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.eq @@ -7,68 +9,61 @@ import com.nhaarman.mockito_kotlin.whenever import net.corda.core.crypto.Crypto import net.corda.core.crypto.SecureHash import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.* +import net.corda.core.internal.cert +import net.corda.core.internal.createDirectories import net.corda.node.services.config.NodeConfiguration import net.corda.nodeapi.internal.crypto.* -import net.corda.nodeapi.internal.crypto.X509Utilities -import net.corda.nodeapi.internal.crypto.getX509Certificate -import net.corda.nodeapi.internal.crypto.loadKeyStore import net.corda.testing.ALICE_NAME import net.corda.testing.internal.rigorousMock +import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.After import org.junit.Before -import org.junit.Rule import org.junit.Test -import org.junit.rules.TemporaryFolder import java.security.cert.Certificate -import kotlin.test.assertEquals +import java.security.cert.X509Certificate import kotlin.test.assertFalse import kotlin.test.assertTrue class NetworkRegistrationHelperTest { - @Rule - @JvmField - val tempFolder = TemporaryFolder() - + private val fs = Jimfs.newFileSystem(unix()) private val requestId = SecureHash.randomSHA256().toString() + private val nodeLegalName = ALICE_NAME + private val intermediateCaName = CordaX500Name("CORDA_INTERMEDIATE_CA", "R3 Ltd", "London", "GB") + private val rootCaName = CordaX500Name("CORDA_ROOT_CA", "R3 Ltd", "London", "GB") + private val nodeCaCert = createCaCert(nodeLegalName) + private val intermediateCaCert = createCaCert(intermediateCaName) + private val rootCaCert = createCaCert(rootCaName) + private lateinit var config: NodeConfiguration - private val identities = listOf("CORDA_CLIENT_CA", - "CORDA_INTERMEDIATE_CA", - "CORDA_ROOT_CA") - .map { CordaX500Name(commonName = it, organisation = "R3 Ltd", locality = "London", country = "GB") } - private val certs = identities.map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) } - .map { it.cert }.toTypedArray() - - private val certService = mockRegistrationResponse(*certs) - @Before fun init() { + val baseDirectory = fs.getPath("/baseDir").createDirectories() abstract class AbstractNodeConfiguration : NodeConfiguration config = rigorousMock().also { - doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory + doReturn(baseDirectory).whenever(it).baseDirectory doReturn("trustpass").whenever(it).trustStorePassword doReturn("cordacadevpass").whenever(it).keyStorePassword - doReturn(ALICE_NAME).whenever(it).myLegalName + doReturn(nodeLegalName).whenever(it).myLegalName doReturn("").whenever(it).emailAddress } } + @After + fun cleanUp() { + fs.close() + } + @Test fun `successful registration`() { - assertFalse(config.nodeKeystore.exists()) - assertFalse(config.sslKeystore.exists()) - config.trustStoreFile.parent.createDirectories() - loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also { - it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, certs.last()) - it.save(config.trustStoreFile, config.trustStorePassword) - } + assertThat(config.nodeKeystore).doesNotExist() + assertThat(config.sslKeystore).doesNotExist() + assertThat(config.trustStoreFile).doesNotExist() - NetworkRegistrationHelper(config, certService).buildKeystore() + saveTrustStoreWithRootCa(rootCaCert) - assertTrue(config.nodeKeystore.exists()) - assertTrue(config.sslKeystore.exists()) - assertTrue(config.trustStoreFile.exists()) + createRegistrationHelper().buildKeystore() val nodeKeystore = loadKeyStore(config.nodeKeystore, config.keyStorePassword) val sslKeystore = loadKeyStore(config.sslKeystore, config.keyStorePassword) @@ -79,9 +74,8 @@ class NetworkRegistrationHelperTest { assertFalse(containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA)) assertFalse(containsAlias(X509Utilities.CORDA_ROOT_CA)) assertFalse(containsAlias(X509Utilities.CORDA_CLIENT_TLS)) - val certificateChain = getCertificateChain(X509Utilities.CORDA_CLIENT_CA) - assertEquals(3, certificateChain.size) - assertEquals(listOf("CORDA_CLIENT_CA", "CORDA_INTERMEDIATE_CA", "CORDA_ROOT_CA"), certificateChain.map { it.toX509CertHolder().subject.commonName }) + val nodeCaCertChain = getCertificateChain(X509Utilities.CORDA_CLIENT_CA) + assertThat(nodeCaCertChain).containsExactly(nodeCaCert, intermediateCaCert, rootCaCert) } sslKeystore.run { @@ -89,46 +83,55 @@ class NetworkRegistrationHelperTest { assertFalse(containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA)) assertFalse(containsAlias(X509Utilities.CORDA_ROOT_CA)) assertTrue(containsAlias(X509Utilities.CORDA_CLIENT_TLS)) - val certificateChain = getCertificateChain(X509Utilities.CORDA_CLIENT_TLS) - assertEquals(4, certificateChain.size) - assertEquals(listOf(CordaX500Name(organisation = "R3 Ltd", locality = "London", country = "GB").x500Name) + identities.map { it.x500Name }, - certificateChain.map { it.toX509CertHolder().subject }) - assertEquals(CordaX500Name(organisation = "R3 Ltd", locality = "London", country = "GB").x500Principal, - getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subjectX500Principal) + val nodeTlsCertChain = getCertificateChain(X509Utilities.CORDA_CLIENT_TLS) + assertThat(nodeTlsCertChain).hasSize(4) + // The TLS cert has the same subject as the node CA cert + assertThat(CordaX500Name.build((nodeTlsCertChain[0] as X509Certificate).subjectX500Principal)).isEqualTo(nodeLegalName) + assertThat(nodeTlsCertChain.drop(1)).containsExactly(nodeCaCert, intermediateCaCert, rootCaCert) } trustStore.run { assertFalse(containsAlias(X509Utilities.CORDA_CLIENT_CA)) assertFalse(containsAlias(X509Utilities.CORDA_INTERMEDIATE_CA)) assertTrue(containsAlias(X509Utilities.CORDA_ROOT_CA)) + val trustStoreRootCaCert = getCertificate(X509Utilities.CORDA_ROOT_CA) + assertThat(trustStoreRootCaCert).isEqualTo(rootCaCert) } } @Test fun `missing truststore`() { assertThatThrownBy { - NetworkRegistrationHelper(config, certService).buildKeystore() + createRegistrationHelper() }.hasMessageContaining("This file must contain the root CA cert of your compatibility zone. Please contact your CZ operator.") - .isInstanceOf(IllegalArgumentException::class.java) } @Test fun `wrong root cert in truststore`() { - val someCert = X509Utilities.createSelfSignedCACertificate(CordaX500Name("Foo", "MU", "GB"), Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)).cert - config.trustStoreFile.parent.createDirectories() - loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also { - it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, someCert) - it.save(config.trustStoreFile, config.trustStorePassword) - } + saveTrustStoreWithRootCa(createCaCert(CordaX500Name("Foo", "MU", "GB"))) + val registrationHelper = createRegistrationHelper() assertThatThrownBy { - NetworkRegistrationHelper(config, certService).buildKeystore() + registrationHelper.buildKeystore() }.isInstanceOf(WrongRootCertException::class.java) } - private fun mockRegistrationResponse(vararg response: Certificate): NetworkRegistrationService { - return rigorousMock().also { + private fun createRegistrationHelper(): NetworkRegistrationHelper { + val certService = rigorousMock().also { doReturn(requestId).whenever(it).submitRequest(any()) - doReturn(response).whenever(it).retrieveCertificates(eq(requestId)) + doReturn(arrayOf(nodeCaCert, intermediateCaCert, rootCaCert)).whenever(it).retrieveCertificates(eq(requestId)) + } + return NetworkRegistrationHelper(config, certService) + } + + private fun saveTrustStoreWithRootCa(rootCa: X509Certificate) { + config.trustStoreFile.parent.createDirectories() + loadOrCreateKeyStore(config.trustStoreFile, config.trustStorePassword).also { + it.addOrReplaceCertificate(X509Utilities.CORDA_ROOT_CA, rootCa) + it.save(config.trustStoreFile, config.trustStorePassword) } } + + private fun createCaCert(name: CordaX500Name): X509Certificate { + return X509Utilities.createSelfSignedCACertificate(name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)).cert + } } diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt index eb11a9b443..311a5c51b2 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt @@ -4,13 +4,11 @@ import net.corda.cordform.CordformContext import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformNode import net.corda.core.identity.CordaX500Name -import net.corda.core.node.services.NotaryService import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.BFTSMaRtConfiguration import net.corda.node.services.config.NotaryConfig -import net.corda.node.services.transactions.BFTNonValidatingNotaryService import net.corda.node.services.transactions.minCorrectReplicas -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator import net.corda.testing.node.internal.demorun.* import net.corda.testing.ALICE_NAME import net.corda.testing.BOB_NAME @@ -24,7 +22,7 @@ private val notaryNames = createNotaryNames(clusterSize) // This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO // NOT use this as a design to copy. class BFTNotaryCordform : CordformDefinition() { - private val clusterName = CordaX500Name(BFTNonValidatingNotaryService.id, "BFT", "Zurich", "CH") + private val clusterName = CordaX500Name("BFT", "Zurich", "CH") init { nodesDirectory = Paths.get("build", "nodes", "nodesBFT") @@ -64,10 +62,10 @@ class BFTNotaryCordform : CordformDefinition() { } override fun setup(context: CordformContext) { - ServiceIdentityGenerator.generateToDisk( + IdentityGenerator.generateDistributedNotaryIdentity( notaryNames.map { context.baseDirectory(it.toString()) }, clusterName, - NotaryService.constructId(validating = false, bft = true), - minCorrectReplicas(clusterSize)) + minCorrectReplicas(clusterSize) + ) } } diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt index cfc21fa060..59384a412f 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt @@ -8,8 +8,7 @@ import net.corda.core.node.services.NotaryService import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.NotaryConfig import net.corda.node.services.config.RaftConfig -import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator import net.corda.testing.node.internal.demorun.* import net.corda.testing.ALICE_NAME import net.corda.testing.BOB_NAME @@ -24,7 +23,7 @@ private val notaryNames = createNotaryNames(3) // This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO // NOT use this as a design to copy. class RaftNotaryCordform : CordformDefinition() { - private val clusterName = CordaX500Name(RaftValidatingNotaryService.id, "Raft", "Zurich", "CH") + private val clusterName = CordaX500Name("Raft", "Zurich", "CH") init { nodesDirectory = Paths.get("build", "nodes", "nodesRaft") @@ -60,9 +59,9 @@ class RaftNotaryCordform : CordformDefinition() { } override fun setup(context: CordformContext) { - ServiceIdentityGenerator.generateToDisk( + IdentityGenerator.generateDistributedNotaryIdentity( notaryNames.map { context.baseDirectory(it.toString()) }, - clusterName, - NotaryService.constructId(validating = true, raft = true)) + clusterName + ) } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt index 24b449e441..65c12cc77b 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -38,7 +38,7 @@ import net.corda.node.services.transactions.BFTSMaRt import net.corda.node.services.transactions.InMemoryTransactionVerifierService import net.corda.node.utilities.AffinityExecutor import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NotaryInfo @@ -159,6 +159,7 @@ open class MockNetwork(private val cordappPackages: List, throw IllegalStateException("Using more than one MockNetwork simultaneously is not supported.", e) } private val sharedUserCount = AtomicInteger(0) + /** A read only view of the current set of nodes. */ val nodes: List get() = _nodes @@ -172,32 +173,29 @@ open class MockNetwork(private val cordappPackages: List, * Returns the single notary node on the network. Throws if there are none or more than one. * @see notaryNodes */ - val defaultNotaryNode: StartedNode - get() { - return when (notaryNodes.size) { - 0 -> throw IllegalStateException("There are no notaries defined on the network") - 1 -> notaryNodes[0] - else -> throw IllegalStateException("There is more than one notary defined on the network") - } + val defaultNotaryNode: StartedNode get() { + return when (notaryNodes.size) { + 0 -> throw IllegalStateException("There are no notaries defined on the network") + 1 -> notaryNodes[0] + else -> throw IllegalStateException("There is more than one notary defined on the network") } + } /** * Return the identity of the default notary node. * @see defaultNotaryNode */ - val defaultNotaryIdentity: Party - get() { - return defaultNotaryNode.info.legalIdentities.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities") - } + val defaultNotaryIdentity: Party get() { + return defaultNotaryNode.info.legalIdentities.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities") + } /** * Return the identity of the default notary node. * @see defaultNotaryNode */ - val defaultNotaryIdentityAndCert: PartyAndCertificate - get() { - return defaultNotaryNode.info.legalIdentitiesAndCerts.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities") - } + val defaultNotaryIdentityAndCert: PartyAndCertificate get() { + return defaultNotaryNode.info.legalIdentitiesAndCerts.singleOrNull() ?: throw IllegalStateException("Default notary has multiple identities") + } /** * Because this executor is shared, we need to be careful about nodes shutting it down. @@ -237,19 +235,16 @@ open class MockNetwork(private val cordappPackages: List, private fun generateNotaryIdentities(): List { return notarySpecs.mapIndexed { index, (name, validating) -> - val identity = ServiceIdentityGenerator.generateToDisk( - dirs = listOf(baseDirectory(nextNodeId + index)), - serviceName = name, - serviceId = "identity") + val identity = IdentityGenerator.generateNodeIdentity(baseDirectory(nextNodeId + index), name) NotaryInfo(identity, validating) } } @VisibleForTesting internal open fun createNotaries(): List> { - return notarySpecs.map { spec -> - createNode(MockNodeParameters(legalName = spec.name, configOverrides = { - doReturn(NotaryConfig(spec.validating)).whenever(it).notary + return notarySpecs.map { (name, validating) -> + createNode(MockNodeParameters(legalName = name, configOverrides = { + doReturn(NotaryConfig(validating)).whenever(it).notary })) } } @@ -306,7 +301,7 @@ open class MockNetwork(private val cordappPackages: List, id, serverThread, myNotaryIdentity, - myLegalName, + configuration.myLegalName, database).also { runOnStop += it::stop } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt index df1cb0ac03..700d37b7f2 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt @@ -19,7 +19,6 @@ import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.messaging.CordaRPCOps import net.corda.core.node.services.NetworkMapCache -import net.corda.core.node.services.NotaryService import net.corda.core.toFuture import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.contextLogger @@ -30,12 +29,9 @@ import net.corda.node.internal.NodeStartup import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions import net.corda.node.services.config.* -import net.corda.node.services.transactions.BFTNonValidatingNotaryService -import net.corda.node.services.transactions.RaftNonValidatingNotaryService -import net.corda.node.services.transactions.RaftValidatingNotaryService import net.corda.node.utilities.registration.HTTPNetworkRegistrationService import net.corda.node.utilities.registration.NetworkRegistrationHelper -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.internal.config.parseAs @@ -245,9 +241,9 @@ class DriverDSLImpl( } private enum class ClusterType(val validating: Boolean, val clusterName: CordaX500Name) { - VALIDATING_RAFT(true, CordaX500Name(RaftValidatingNotaryService.id, "Raft", "Zurich", "CH")), - NON_VALIDATING_RAFT(false, CordaX500Name(RaftNonValidatingNotaryService.id, "Raft", "Zurich", "CH")), - NON_VALIDATING_BFT(false, CordaX500Name(BFTNonValidatingNotaryService.id, "BFT", "Zurich", "CH")) + VALIDATING_RAFT(true, CordaX500Name("Raft", "Zurich", "CH")), + NON_VALIDATING_RAFT(false, CordaX500Name("Raft", "Zurich", "CH")), + NON_VALIDATING_BFT(false, CordaX500Name("BFT", "Zurich", "CH")) } internal fun startCordformNodes(cordforms: List): CordaFuture<*> { @@ -270,24 +266,15 @@ class DriverDSLImpl( clusterNodes.put(ClusterType.NON_VALIDATING_BFT, name) } else { // We have all we need here to generate the identity for single node notaries - val identity = ServiceIdentityGenerator.generateToDisk( - dirs = listOf(baseDirectory(name)), - serviceName = name, - serviceId = "identity" - ) + val identity = IdentityGenerator.generateNodeIdentity(baseDirectory(name), legalName = name) notaryInfos += NotaryInfo(identity, notaryConfig.validating) } } clusterNodes.asMap().forEach { type, nodeNames -> - val identity = ServiceIdentityGenerator.generateToDisk( + val identity = IdentityGenerator.generateDistributedNotaryIdentity( dirs = nodeNames.map { baseDirectory(it) }, - serviceName = type.clusterName, - serviceId = NotaryService.constructId( - validating = type.validating, - raft = type in setOf(VALIDATING_RAFT, NON_VALIDATING_RAFT), - bft = type == ClusterType.NON_VALIDATING_BFT - ) + notaryName = type.clusterName ) notaryInfos += NotaryInfo(identity, type.validating) } @@ -369,20 +356,11 @@ class DriverDSLImpl( private fun generateNotaryIdentities(): List { return notarySpecs.map { spec -> val identity = if (spec.cluster == null) { - ServiceIdentityGenerator.generateToDisk( - dirs = listOf(baseDirectory(spec.name)), - serviceName = spec.name, - serviceId = "identity", - customRootCert = compatibilityZone?.rootCert - ) + IdentityGenerator.generateNodeIdentity(baseDirectory(spec.name), spec.name, compatibilityZone?.rootCert) } else { - ServiceIdentityGenerator.generateToDisk( + IdentityGenerator.generateDistributedNotaryIdentity( dirs = generateNodeNames(spec).map { baseDirectory(it) }, - serviceName = spec.name, - serviceId = NotaryService.constructId( - validating = spec.validating, - raft = spec.cluster is ClusterSpec.Raft - ), + notaryName = spec.name, customRootCert = compatibilityZone?.rootCert ) } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 11e572e2d7..15c0046742 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -91,13 +91,13 @@ fun getTestPartyAndCertificate(party: Party): PartyAndCertificate { val trustRoot: X509CertificateHolder = DEV_TRUST_ROOT val intermediate: CertificateAndKeyPair = DEV_CA - val nodeCaName = party.name.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN) + val nodeCaKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val nodeCaCert = X509Utilities.createCertificate( CertificateType.NODE_CA, intermediate.certificate, intermediate.keyPair, - nodeCaName, + party.name, nodeCaKeyPair.public, nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, party.name.x500Name))), arrayOf())) diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt index 37e019b367..ee6b38fdb5 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt @@ -13,7 +13,7 @@ import net.corda.demobench.pty.R3Pty import net.corda.nodeapi.internal.network.NetworkParameters import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NotaryInfo -import net.corda.nodeapi.internal.ServiceIdentityGenerator +import net.corda.nodeapi.internal.IdentityGenerator import tornadofx.* import java.io.IOException import java.lang.management.ManagementFactory @@ -153,10 +153,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() { // Generate notary identity and save it into node's directory. This identity will be used in network parameters. private fun getNotaryIdentity(config: NodeConfigWrapper): Party { - return ServiceIdentityGenerator.generateToDisk( - dirs = listOf(config.nodeDir), - serviceName = config.nodeConfig.myLegalName, - serviceId = "identity") + return IdentityGenerator.generateNodeIdentity(config.nodeDir, config.nodeConfig.myLegalName) } fun reset() { From 313d21f0683f7878b0d28b65161405eca83198e1 Mon Sep 17 00:00:00 2001 From: Andrzej Cichocki Date: Tue, 19 Dec 2017 12:09:31 +0000 Subject: [PATCH 3/3] Move unspecifiedCountry to internal. (#2274) --- .../main/kotlin/net/corda/core/identity/CordaX500Name.kt | 4 +--- .../main/kotlin/net/corda/core/internal/InternalUtils.kt | 6 ++++++ .../src/main/kotlin/net/corda/testing/CoreTestUtils.kt | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt b/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt index c7d5065390..ad315c065e 100644 --- a/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt +++ b/core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt @@ -2,7 +2,7 @@ package net.corda.core.identity import com.google.common.collect.ImmutableSet import net.corda.core.internal.LegalNameValidator -import net.corda.core.internal.VisibleForTesting +import net.corda.core.internal.unspecifiedCountry import net.corda.core.internal.x500Name import net.corda.core.serialization.CordaSerializable import org.bouncycastle.asn1.ASN1Encodable @@ -81,8 +81,6 @@ data class CordaX500Name(val commonName: String?, const val MAX_LENGTH_ORGANISATION_UNIT = 64 const val MAX_LENGTH_COMMON_NAME = 64 private val supportedAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L, BCStyle.CN, BCStyle.ST, BCStyle.OU) - @VisibleForTesting - val unspecifiedCountry = "ZZ" private val countryCodes: Set = ImmutableSet.copyOf(Locale.getISOCountries() + unspecifiedCountry) @JvmStatic fun build(principal: X500Principal): CordaX500Name { diff --git a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt index c2dd50ac50..42145a2f26 100644 --- a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt +++ b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt @@ -5,6 +5,7 @@ package net.corda.core.internal import net.corda.core.cordapp.CordappProvider import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 +import net.corda.core.identity.CordaX500Name import net.corda.core.node.ServicesForResolution import net.corda.core.serialization.SerializationContext import net.corda.core.transactions.TransactionBuilder @@ -318,3 +319,8 @@ fun ExecutorService.join() { // Try forever. Do not give up, tests use this method to assert the executor has no more tasks. } } + +@Suppress("unused") +@VisibleForTesting +val CordaX500Name.Companion.unspecifiedCountry + get() = "ZZ" diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 15c0046742..860af415ac 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -10,6 +10,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.identity.PartyAndCertificate import net.corda.core.internal.cert +import net.corda.core.internal.unspecifiedCountry import net.corda.core.internal.x500Name import net.corda.core.node.NodeInfo import net.corda.core.utilities.NetworkHostAndPort