Merge fixes, which includes fixing the doorman tests and updating the doorman to not set a CN in the CSR responses

This commit is contained in:
Shams Asari 2017-12-19 22:39:34 +00:00
parent de9565b96a
commit 3c64e9feec
12 changed files with 146 additions and 227 deletions

View File

@ -25,7 +25,6 @@ abstract class NotaryService : SingletonSerializeAsToken() {
if (raft) append(".raft") if (raft) append(".raft")
if (bft) append(".bft") if (bft) append(".bft")
if (custom) append(".custom") if (custom) append(".custom")
if (mysql) append(".mysql")
}.toString() }.toString()
} }
} }

View File

@ -3,7 +3,6 @@ package com.r3.corda.networkmanage.doorman
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import com.r3.corda.networkmanage.common.persistence.configureDatabase import com.r3.corda.networkmanage.common.persistence.configureDatabase
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.doorman.signer.LocalSigner import com.r3.corda.networkmanage.doorman.signer.LocalSigner
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
@ -30,7 +29,6 @@ import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.rigorousMock
import org.bouncycastle.cert.X509CertificateHolder import org.bouncycastle.cert.X509CertificateHolder
import org.junit.Ignore
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.TemporaryFolder import org.junit.rules.TemporaryFolder
@ -78,7 +76,7 @@ class DoormanIntegrationTest {
loadKeyStore(config.nodeKeystore, config.keyStorePassword).apply { loadKeyStore(config.nodeKeystore, config.keyStorePassword).apply {
assert(containsAlias(X509Utilities.CORDA_CLIENT_CA)) assert(containsAlias(X509Utilities.CORDA_CLIENT_CA))
assertEquals(ALICE_NAME.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Principal, getX509Certificate(X509Utilities.CORDA_CLIENT_CA).subjectX500Principal) assertEquals(ALICE_NAME.x500Principal, getX509Certificate(X509Utilities.CORDA_CLIENT_CA).subjectX500Principal)
assertEquals(listOf(intermediateCACert.cert, rootCACert.cert), getCertificateChain(X509Utilities.CORDA_CLIENT_CA).drop(1).toList()) assertEquals(listOf(intermediateCACert.cert, rootCACert.cert), getCertificateChain(X509Utilities.CORDA_CLIENT_CA).drop(1).toList())
} }
@ -120,13 +118,18 @@ class DoormanIntegrationTest {
// Publish NodeInfo // Publish NodeInfo
val networkMapClient = NetworkMapClient(config.compatibilityZoneURL!!, rootCertAndKey.certificate.cert) val networkMapClient = NetworkMapClient(config.compatibilityZoneURL!!, rootCertAndKey.certificate.cert)
val certs = loadKeyStore(config.nodeKeystore, config.keyStorePassword).getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
val keyPair = loadKeyStore(config.nodeKeystore, config.keyStorePassword).getKeyPair(X509Utilities.CORDA_CLIENT_CA, config.keyStorePassword) val keyStore = loadKeyStore(config.nodeKeystore, config.keyStorePassword)
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(buildCertPath(*certs))), 1, serial = 1L) val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
val clientCA = keyStore.getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA, config.keyStorePassword)
val identityKeyPair = Crypto.generateKeyPair()
val identityCert = X509Utilities.createCertificate(CertificateType.LEGAL_IDENTITY, clientCA.certificate, clientCA.keyPair, ALICE_NAME, identityKeyPair.public)
val certPath = X509CertificateFactory().generateCertPath(identityCert.cert, *clientCertPath)
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val nodeInfoBytes = nodeInfo.serialize() val nodeInfoBytes = nodeInfo.serialize()
// When // When
val signedNodeInfo = SignedNodeInfo(nodeInfoBytes, listOf(keyPair.sign(nodeInfoBytes))) val signedNodeInfo = SignedNodeInfo(nodeInfoBytes, listOf(identityKeyPair.private.sign(nodeInfoBytes.bytes)))
networkMapClient.publish(signedNodeInfo) networkMapClient.publish(signedNodeInfo)
// Then // Then
@ -137,7 +140,7 @@ class DoormanIntegrationTest {
doorman.close() doorman.close()
} }
fun createConfig(): NodeConfiguration { private fun createConfig(): NodeConfiguration {
return rigorousMock<NodeConfiguration>().also { return rigorousMock<NodeConfiguration>().also {
doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory doReturn(tempFolder.root.toPath()).whenever(it).baseDirectory
doReturn(ALICE_NAME).whenever(it).myLegalName doReturn(ALICE_NAME).whenever(it).myLegalName

View File

@ -1,65 +1,60 @@
package com.r3.corda.networkmanage.common.persistence package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.common.persistence.entity.* import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity
import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity
import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity
import com.r3.corda.networkmanage.common.utils.buildCertPath import com.r3.corda.networkmanage.common.utils.buildCertPath
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256 import net.corda.core.crypto.sha256
import net.corda.core.identity.CordaX500Name import net.corda.core.internal.CertRole
import net.corda.core.serialization.SerializedBytes
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.nodeapi.internal.SignedNodeInfo import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel import net.corda.nodeapi.internal.persistence.TransactionIsolationLevel
import java.security.cert.CertPath import java.security.cert.CertPath
import java.security.cert.X509Certificate
/** /**
* Database implementation of the [NetworkMapStorage] interface * Database implementation of the [NetworkMapStorage] interface
*/ */
class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeInfoStorage { class PersistentNodeInfoStorage(private val database: CordaPersistence) : NodeInfoStorage {
override fun putNodeInfo(signedNodeInfo: SignedNodeInfo): SecureHash = database.transaction(TransactionIsolationLevel.SERIALIZABLE) { override fun putNodeInfo(signedNodeInfo: SignedNodeInfo): SecureHash {
val nodeInfo = signedNodeInfo.verified() return database.transaction(TransactionIsolationLevel.SERIALIZABLE) {
val orgName = nodeInfo.legalIdentities.first().name.organisation val nodeInfo = signedNodeInfo.verified()
// TODO: use cert extension to identify NodeCA cert when Ross's work is in. val nodeCaCert = nodeInfo.legalIdentitiesAndCerts[0].certPath.certificates.find { CertRole.extract(it) == CertRole.NODE_CA }
val nodeCACert = nodeInfo.legalIdentitiesAndCerts.first().certPath.certificates.map { it as X509Certificate }
.find { CordaX500Name.build(it.issuerX500Principal).organisation != orgName && CordaX500Name.build(it.subjectX500Principal).organisation == orgName }
val request = nodeCACert?.let { val request = nodeCaCert?.let {
singleRequestWhere(CertificateDataEntity::class.java) { builder, path -> singleRequestWhere(CertificateDataEntity::class.java) { builder, path ->
val certPublicKeyHashEq = builder.equal(path.get<String>(CertificateDataEntity::publicKeyHash.name), it.publicKey.encoded.sha256().toString()) val certPublicKeyHashEq = builder.equal(path.get<String>(CertificateDataEntity::publicKeyHash.name), it.publicKey.encoded.sha256().toString())
val certStatusValid = builder.equal(path.get<CertificateStatus>(CertificateDataEntity::certificateStatus.name), CertificateStatus.VALID) val certStatusValid = builder.equal(path.get<CertificateStatus>(CertificateDataEntity::certificateStatus.name), CertificateStatus.VALID)
builder.and(certPublicKeyHashEq, certStatusValid) builder.and(certPublicKeyHashEq, certStatusValid)
}
} }
} request ?: throw IllegalArgumentException("Unknown node info, this public key is not registered with the network management service.")
request ?: throw IllegalArgumentException("Unknown node info, this public key is not registered with the network management service.")
/*
* Delete any previous [NodeInfoEntity] instance for this CSR
* Possibly it should be moved at the network signing process at the network signing process
* as for a while the network map will have invalid entries (i.e. hashes for node info which have been
* removed). Either way, there will be a period of time when the network map data will be invalid
* but it has been confirmed that this fact has been acknowledged at the design time and we are fine with it.
*/
deleteRequest(NodeInfoEntity::class.java) { builder, path ->
builder.equal(path.get<CertificateSigningRequestEntity>(NodeInfoEntity::certificateSigningRequest.name), request.certificateSigningRequest)
}
val hash = signedNodeInfo.raw.hash
val hashedNodeInfo = NodeInfoEntity( /*
nodeInfoHash = hash.toString(), * Delete any previous [NodeInfoEntity] instance for this CSR
certificateSigningRequest = request.certificateSigningRequest, * Possibly it should be moved at the network signing process at the network signing process
signedNodeInfoBytes = signedNodeInfo.serialize().bytes) * as for a while the network map will have invalid entries (i.e. hashes for node info which have been
session.save(hashedNodeInfo) * removed). Either way, there will be a period of time when the network map data will be invalid
hash * but it has been confirmed that this fact has been acknowledged at the design time and we are fine with it.
*/
deleteRequest(NodeInfoEntity::class.java) { builder, path ->
builder.equal(path.get<CertificateSigningRequestEntity>(NodeInfoEntity::certificateSigningRequest.name), request.certificateSigningRequest)
}
val hash = signedNodeInfo.raw.hash
val hashedNodeInfo = NodeInfoEntity(
nodeInfoHash = hash.toString(),
certificateSigningRequest = request.certificateSigningRequest,
signedNodeInfoBytes = signedNodeInfo.serialize().bytes)
session.save(hashedNodeInfo)
hash
}
} }
override fun getNodeInfo(nodeInfoHash: SecureHash): SignedNodeInfo? { override fun getNodeInfo(nodeInfoHash: SecureHash): SignedNodeInfo? {
return database.transaction { return database.transaction {
val nodeInfoEntity = session.find(NodeInfoEntity::class.java, nodeInfoHash.toString()) session.find(NodeInfoEntity::class.java, nodeInfoHash.toString())?.signedNodeInfo()
if (nodeInfoEntity == null) {
null
} else {
nodeInfoEntity.signedNodeInfo()
}
} }
} }

View File

@ -2,10 +2,10 @@ package com.r3.corda.networkmanage.doorman.signer
import com.r3.corda.networkmanage.common.signer.Signer import com.r3.corda.networkmanage.common.signer.Signer
import com.r3.corda.networkmanage.common.utils.buildCertPath import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.common.utils.withCert import com.r3.corda.networkmanage.common.utils.withCert
import net.corda.core.crypto.sign import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.cert
import net.corda.core.internal.toX509CertHolder import net.corda.core.internal.toX509CertHolder
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
@ -33,13 +33,14 @@ class LocalSigner(private val caKeyPair: KeyPair, private val caCertPath: Array<
val nameConstraints = NameConstraints( val nameConstraints = NameConstraints(
arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, request.subject))), arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, request.subject))),
arrayOf()) arrayOf())
val clientCertificate = X509Utilities.createCertificate(CertificateType.NODE_CA, val nodeCaCert = X509Utilities.createCertificate(
CertificateType.NODE_CA,
caCertPath.first().toX509CertHolder(), caCertPath.first().toX509CertHolder(),
caKeyPair, caKeyPair,
CordaX500Name.parse(request.subject.toString()).copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN), CordaX500Name.parse(request.subject.toString()),
request.publicKey, request.publicKey,
nameConstraints = nameConstraints).toX509Certificate() nameConstraints = nameConstraints)
return buildCertPath(clientCertificate, *caCertPath) return buildCertPath(nodeCaCert.cert, *caCertPath)
} }
override fun sign(data: ByteArray): DigitalSignatureWithCert { override fun sign(data: ByteArray): DigitalSignatureWithCert {

View File

@ -7,7 +7,6 @@ import net.corda.core.internal.toX509CertHolder
import net.corda.core.internal.x500Name import net.corda.core.internal.x500Name
import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.crypto.getX509Certificate import net.corda.nodeapi.internal.crypto.getX509Certificate
import org.bouncycastle.asn1.ASN1EncodableVector import org.bouncycastle.asn1.ASN1EncodableVector
import org.bouncycastle.asn1.ASN1Sequence import org.bouncycastle.asn1.ASN1Sequence
@ -184,7 +183,7 @@ object X509Utilities {
val certificateType = CertificateType.NODE_CA val certificateType = CertificateType.NODE_CA
val validityWindow = getCertificateValidityWindow(0, validDays, issuerCertificate.notBefore, issuerCertificate.notAfter) val validityWindow = getCertificateValidityWindow(0, validDays, issuerCertificate.notBefore, issuerCertificate.notAfter)
val serial = BigInteger.valueOf(random63BitValue(provider)) val serial = BigInteger.valueOf(random63BitValue(provider))
val subject = CordaX500Name.parse(jcaRequest.subject.toString()).copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name val subject = CordaX500Name.parse(jcaRequest.subject.toString()).x500Name
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(jcaRequest.publicKey.encoded)) val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(jcaRequest.publicKey.encoded))
val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } }) val keyPurposes = DERSequence(ASN1EncodableVector().apply { certificateType.purposes.forEach { add(it) } })
val builder = JcaX509v3CertificateBuilder(issuerCertificate.subject, serial, validityWindow.first, validityWindow.second, subject, jcaRequest.publicKey) val builder = JcaX509v3CertificateBuilder(issuerCertificate.subject, serial, validityWindow.first, validityWindow.second, subject, jcaRequest.publicKey)

View File

@ -1,24 +1,21 @@
package com.r3.corda.networkmanage.common.persistence package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.common.utils.withCert import com.r3.corda.networkmanage.common.utils.withCert
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.sign import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.cert import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.SignedNodeInfo import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.NetworkMap import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.SignedNetworkMap import net.corda.nodeapi.internal.network.SignedNetworkMap
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.internal.TestNodeInfoBuilder
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
@ -31,6 +28,7 @@ class DBNetworkMapStorageTest : TestBase() {
private lateinit var requestStorage: CertificationRequestStorage private lateinit var requestStorage: CertificationRequestStorage
private lateinit var nodeInfoStorage: NodeInfoStorage private lateinit var nodeInfoStorage: NodeInfoStorage
private lateinit var persistence: CordaPersistence private lateinit var persistence: CordaPersistence
private val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) private val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", locality = "London", organisation = "R3 LTD", country = "GB"), rootCAKey) private val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", locality = "London", organisation = "R3 LTD", country = "GB"), rootCAKey)
private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
@ -53,18 +51,8 @@ class DBNetworkMapStorageTest : TestBase() {
fun `signNetworkMap creates current network map`() { fun `signNetworkMap creates current network map`() {
// given // given
// Create node info. // Create node info.
val organisation = "Test" val signedNodeInfo = createValidSignedNodeInfo("Test")
val requestId = requestStorage.saveRequest(createRequest(organisation).first) val nodeInfoHash = nodeInfoStorage.putNodeInfo(signedNodeInfo)
requestStorage.markRequestTicketCreated(requestId)
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair()
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisation, locality = "London", country = "GB"), keyPair.public)
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestId, certPath, emptyList())
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
// Put signed node info data
val nodeInfoBytes = nodeInfo.serialize()
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoBytes, listOf(keyPair.sign(nodeInfoBytes))))
// Create network parameters // Create network parameters
val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList())) val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
@ -103,13 +91,11 @@ class DBNetworkMapStorageTest : TestBase() {
// Create network parameters // Create network parameters
val networkMapParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters(1)) val networkMapParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters(1))
// Create empty network map // Create empty network map
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val intermediateCert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Corda", locality = "London", country = "GB"), keyPair.public)
// Sign network map making it current network map // Sign network map making it current network map
val networkMap = NetworkMap(emptyList(), networkMapParametersHash) val networkMap = NetworkMap(emptyList(), networkMapParametersHash)
val serializedNetworkMap = networkMap.serialize() val serializedNetworkMap = networkMap.serialize()
val signatureData = keyPair.sign(serializedNetworkMap).withCert(intermediateCert.cert) val signatureData = intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData) val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
networkMapStorage.saveNetworkMap(signedNetworkMap) networkMapStorage.saveNetworkMap(signedNetworkMap)
@ -126,36 +112,19 @@ class DBNetworkMapStorageTest : TestBase() {
@Test @Test
fun `getValidNodeInfoHashes returns only valid and signed node info hashes`() { fun `getValidNodeInfoHashes returns only valid and signed node info hashes`() {
// given // given
// Create node info. // Create node infos.
val organisationA = "TestA" val signedNodeInfoA = createValidSignedNodeInfo("TestA")
val requestIdA = requestStorage.saveRequest(createRequest(organisationA).first) val signedNodeInfoB = createValidSignedNodeInfo("TestB")
requestStorage.markRequestTicketCreated(requestIdA)
requestStorage.approveRequest(requestIdA, "TestUser")
val keyPairA = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertA = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationA, locality = "London", country = "GB"), keyPairA.public)
val certPathA = buildCertPath(clientCertA.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestIdA, certPathA, emptyList())
val organisationB = "TestB"
val requestIdB = requestStorage.saveRequest(createRequest(organisationB).first)
requestStorage.markRequestTicketCreated(requestIdB)
requestStorage.approveRequest(requestIdB, "TestUser")
val keyPairB = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertB = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationB, locality = "London", country = "GB"), keyPairB.public)
val certPathB = buildCertPath(clientCertB.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestIdB, certPathB, emptyList())
val nodeInfoA = NodeInfo(listOf(NetworkHostAndPort("my.companyA.com", 1234)), listOf(PartyAndCertificate(certPathA)), 1, serial = 1L)
val nodeInfoB = NodeInfo(listOf(NetworkHostAndPort("my.companyB.com", 1234)), listOf(PartyAndCertificate(certPathB)), 1, serial = 1L)
// Put signed node info data // Put signed node info data
val nodeInfoABytes = nodeInfoA.serialize() val nodeInfoHashA = nodeInfoStorage.putNodeInfo(signedNodeInfoA)
val nodeInfoBBytes = nodeInfoB.serialize() val nodeInfoHashB = nodeInfoStorage.putNodeInfo(signedNodeInfoB)
val nodeInfoHashA = nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoABytes, listOf(keyPairA.sign(nodeInfoABytes))))
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoBBytes, listOf(keyPairB.sign(nodeInfoBBytes))))
// Create network parameters // Create network parameters
val networkParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters()) val networkParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters())
val networkMap = NetworkMap(listOf(nodeInfoHashA), networkParametersHash) val networkMap = NetworkMap(listOf(nodeInfoHashA), networkParametersHash)
val serializedNetworkMap = networkMap.serialize() val serializedNetworkMap = networkMap.serialize()
val signatureData = keyPairA.sign(serializedNetworkMap).withCert(clientCertA.cert) val signatureData = intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData) val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
// Sign network map // Sign network map
@ -167,4 +136,15 @@ class DBNetworkMapStorageTest : TestBase() {
// then // then
assertThat(validNodeInfoHash).containsOnly(nodeInfoHashA, nodeInfoHashB) assertThat(validNodeInfoHash).containsOnly(nodeInfoHashA, nodeInfoHashB)
} }
private fun createValidSignedNodeInfo(organisation: String): SignedNodeInfo {
val nodeInfoBuilder = TestNodeInfoBuilder()
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.markRequestTicketCreated(requestId)
requestStorage.approveRequest(requestId, "TestUser")
val (identity) = nodeInfoBuilder.addIdentity(CordaX500Name(organisation, "London", "GB"))
val nodeCaCertPath = X509CertificateFactory().generateCertPath(identity.certPath.certificates.drop(1))
requestStorage.putCertificatePath(requestId, nodeCaCertPath, emptyList())
return nodeInfoBuilder.buildWithSigned().second
}
} }

View File

@ -3,31 +3,34 @@ package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.utils.buildCertPath import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.hashString import com.r3.corda.networkmanage.common.utils.hashString
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.nodeapi.internal.SignedNodeInfo import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.CordaPersistence
import net.corda.testing.internal.TestNodeInfoBuilder
import net.corda.testing.internal.signWith
import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices
import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.security.PrivateKey
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
import kotlin.test.assertNull import kotlin.test.assertNull
class PersitenceNodeInfoStorageTest : TestBase() { class PersitenceNodeInfoStorageTest : TestBase() {
private lateinit var requestStorage: CertificationRequestStorage private lateinit var requestStorage: CertificationRequestStorage
private lateinit var nodeInfoStorage: NodeInfoStorage private lateinit var nodeInfoStorage: PersistentNodeInfoStorage
private lateinit var persistence: CordaPersistence private lateinit var persistence: CordaPersistence
private val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) private val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", locality = "London", organisation = "R3 LTD", country = "GB"), rootCAKey) private val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(commonName = "Corda Node Root CA", locality = "London", organisation = "R3 LTD", country = "GB"), rootCAKey)
private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
@ -46,14 +49,13 @@ class PersitenceNodeInfoStorageTest : TestBase() {
} }
@Test @Test
fun `test get CertificatePath`() { fun `test getCertificatePath`() {
// Create node info. // Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Test", locality = "London", country = "GB"), keyPair.public) val name = CordaX500Name(organisation = "Test", locality = "London", country = "GB")
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()) val nodeCaCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, name, keyPair.public)
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val request = X509Utilities.createCertificateSigningRequest(nodeInfo.legalIdentities.first().name, "my@mail.com", keyPair) val request = X509Utilities.createCertificateSigningRequest(name, "my@mail.com", keyPair)
val requestId = requestStorage.saveRequest(request) val requestId = requestStorage.saveRequest(request)
requestStorage.markRequestTicketCreated(requestId) requestStorage.markRequestTicketCreated(requestId)
@ -61,104 +63,73 @@ class PersitenceNodeInfoStorageTest : TestBase() {
assertNull(nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString()))) assertNull(nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString())))
requestStorage.putCertificatePath(requestId, buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()), listOf(CertificationRequestStorage.DOORMAN_SIGNATURE)) requestStorage.putCertificatePath(requestId, buildCertPath(nodeCaCert.cert, intermediateCACert.cert, rootCACert.cert), listOf(CertificationRequestStorage.DOORMAN_SIGNATURE))
val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString())) val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString()))
assertNotNull(storedCertPath) assertNotNull(storedCertPath)
assertEquals(clientCert.toX509Certificate(), storedCertPath!!.certificates.first()) assertEquals(nodeCaCert.cert, storedCertPath!!.certificates.first())
} }
@Test @Test
fun `test getNodeInfoHash returns correct data`() { fun `getNodeInfo returns persisted SignedNodeInfo using the hash of just the NodeInfo`() {
// given // given
val organisationA = "TestA" val (nodeInfoA, signedNodeInfoA) = createValidSignedNodeInfo("TestA")
val requestIdA = requestStorage.saveRequest(createRequest(organisationA).first) val (nodeInfoB, signedNodeInfoB) = createValidSignedNodeInfo("TestB")
requestStorage.markRequestTicketCreated(requestIdA)
requestStorage.approveRequest(requestIdA, "TestUser")
val keyPairA = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertA = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationA, locality = "London", country = "GB"), keyPairA.public)
val certPathA = buildCertPath(clientCertA.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestIdA, certPathA, emptyList())
val organisationB = "TestB"
val requestIdB = requestStorage.saveRequest(createRequest(organisationB).first)
requestStorage.markRequestTicketCreated(requestIdB)
requestStorage.approveRequest(requestIdB, "TestUser")
val keyPairB = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertB = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationB, locality = "London", country = "GB"), keyPairB.public)
val certPathB = buildCertPath(clientCertB.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestIdB, certPathB, emptyList())
val nodeInfoA = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPathA)), 1, serial = 1L)
val nodeInfoB = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPathB)), 1, serial = 1L)
// Put signed node info data // Put signed node info data
val nodeInfoABytes = nodeInfoA.serialize() nodeInfoStorage.putNodeInfo(signedNodeInfoA)
val nodeInfoBBytes = nodeInfoB.serialize() nodeInfoStorage.putNodeInfo(signedNodeInfoB)
nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoABytes, listOf(keyPairA.sign(nodeInfoABytes))))
nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoBBytes, listOf(keyPairB.sign(nodeInfoBBytes))))
// when // when
val persistedNodeInfoA = nodeInfoStorage.getNodeInfo(nodeInfoABytes.hash) val persistedSignedNodeInfoA = nodeInfoStorage.getNodeInfo(nodeInfoA.serialize().hash)
val persistedNodeInfoB = nodeInfoStorage.getNodeInfo(nodeInfoBBytes.hash) val persistedSignedNodeInfoB = nodeInfoStorage.getNodeInfo(nodeInfoB.serialize().hash)
// then // then
assertNotNull(persistedNodeInfoA) assertEquals(persistedSignedNodeInfoA?.verified(), nodeInfoA)
assertNotNull(persistedNodeInfoB) assertEquals(persistedSignedNodeInfoB?.verified(), nodeInfoB)
assertEquals(persistedNodeInfoA!!.verified(), nodeInfoA)
assertEquals(persistedNodeInfoB!!.verified(), nodeInfoB)
} }
@Test @Test
fun `same pub key with different node info`() { fun `same public key with different node info`() {
// Create node info. // Create node info.
val organisation = "Test" val (nodeInfo1, signedNodeInfo1, key) = createValidSignedNodeInfo("Test", serial = 1)
val requestId = requestStorage.saveRequest(createRequest(organisation).first) val nodeInfo2 = nodeInfo1.copy(serial = 2)
requestStorage.markRequestTicketCreated(requestId) val signedNodeInfo2 = nodeInfo2.signWith(listOf(key))
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisation, locality = "London", country = "GB"), keyPair.public)
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestId, certPath, emptyList())
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L) val nodeInfo1Hash = nodeInfoStorage.putNodeInfo(signedNodeInfo1)
val nodeInfoSamePubKey = NodeInfo(listOf(NetworkHostAndPort("my.company2.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L) assertEquals(nodeInfo1, nodeInfoStorage.getNodeInfo(nodeInfo1Hash)?.verified())
val nodeInfoBytes = nodeInfo.serialize()
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoBytes, listOf(keyPair.sign(nodeInfoBytes))))
assertEquals(nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfoHash)?.verified())
val nodeInfoSamePubKeyBytes = nodeInfoSamePubKey.serialize()
// This should replace the node info. // This should replace the node info.
nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoSamePubKeyBytes, listOf(keyPair.sign(nodeInfoSamePubKeyBytes)))) nodeInfoStorage.putNodeInfo(signedNodeInfo2)
// Old node info should be removed. // Old node info should be removed.
assertNull(nodeInfoStorage.getNodeInfo(nodeInfoHash)) assertNull(nodeInfoStorage.getNodeInfo(nodeInfo1Hash))
assertEquals(nodeInfoSamePubKey, nodeInfoStorage.getNodeInfo(nodeInfoSamePubKeyBytes.hash)?.verified()) assertEquals(nodeInfo2, nodeInfoStorage.getNodeInfo(nodeInfo2.serialize().hash)?.verified())
} }
@Test @Test
fun `putNodeInfo persists node info data with its signature`() { fun `putNodeInfo persists SignedNodeInfo with its signature`() {
// given // given
// Create node info. val (_, signedNodeInfo) = createValidSignedNodeInfo("Test")
val organisation = "Test"
// when
val nodeInfoHash = nodeInfoStorage.putNodeInfo(signedNodeInfo)
// then
val persistedSignedNodeInfo = nodeInfoStorage.getNodeInfo(nodeInfoHash)
assertThat(persistedSignedNodeInfo?.signatures).isEqualTo(signedNodeInfo.signatures)
}
private fun createValidSignedNodeInfo(organisation: String, serial: Long = 1): Triple<NodeInfo, SignedNodeInfo, PrivateKey> {
val nodeInfoBuilder = TestNodeInfoBuilder()
val requestId = requestStorage.saveRequest(createRequest(organisation).first) val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.markRequestTicketCreated(requestId) requestStorage.markRequestTicketCreated(requestId)
requestStorage.approveRequest(requestId, "TestUser") requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val (identity, key) = nodeInfoBuilder.addIdentity(CordaX500Name(organisation, "London", "GB"))
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisation, locality = "London", country = "GB"), keyPair.public) val nodeCaCertPath = X509CertificateFactory().generateCertPath(identity.certPath.certificates.drop(1))
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()) requestStorage.putCertificatePath(requestId, nodeCaCertPath, emptyList())
requestStorage.putCertificatePath(requestId, certPath, emptyList()) val (nodeInfo, signedNodeInfo) = nodeInfoBuilder.buildWithSigned(serial)
return Triple(nodeInfo, signedNodeInfo, key)
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val nodeInfoBytes = nodeInfo.serialize()
val signature = keyPair.sign(nodeInfoBytes)
// when
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedNodeInfo(nodeInfoBytes, listOf(signature)))
// then
val persistedNodeInfo = nodeInfoStorage.getNodeInfo(nodeInfoHash)
assertNotNull(persistedNodeInfo)
assertEquals(nodeInfo, persistedNodeInfo!!.verified())
assertEquals(signature, persistedNodeInfo.signatures.firstOrNull())
} }
} }

View File

@ -1,20 +1,18 @@
package com.r3.corda.networkmanage.doorman package com.r3.corda.networkmanage.doorman
import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.times import com.nhaarman.mockito_kotlin.times
import com.nhaarman.mockito_kotlin.verify import com.nhaarman.mockito_kotlin.verify
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.common.utils.withCert import com.r3.corda.networkmanage.common.utils.withCert
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
import net.corda.core.crypto.* import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.internal.cert import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
@ -25,6 +23,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.NetworkMap import net.corda.nodeapi.internal.network.NetworkMap
import net.corda.nodeapi.internal.network.SignedNetworkMap import net.corda.nodeapi.internal.network.SignedNetworkMap
import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.createNodeInfoAndSigned
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@ -41,31 +40,17 @@ class NodeInfoWebServiceTest {
@JvmField @JvmField
val testSerialization = SerializationEnvironmentRule(true) val testSerialization = SerializationEnvironmentRule(true)
private val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(locality = "London", organisation = "R3 LTD", country = "GB", commonName = "Corda Node Root CA"), rootCAKey)
private val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, X500Name("CN=Corda Node Intermediate CA,L=London"), intermediateCAKey.public)
private val testNetwotkMapConfig = NetworkMapConfig(10.seconds.toMillis(), 10.seconds.toMillis()) private val testNetwotkMapConfig = NetworkMapConfig(10.seconds.toMillis(), 10.seconds.toMillis())
@Test @Test
fun `submit nodeInfo`() { fun `submit nodeInfo`() {
// Create node info. // Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"))
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Test", locality = "London", country = "GB"), keyPair.public)
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
// Create digital signature. NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), mock(), testNetwotkMapConfig)).use {
val digitalSignature = DigitalSignature.WithKey(keyPair.public, Crypto.doSign(keyPair.private, nodeInfo.serialize().bytes))
val nodeInfoStorage: NodeInfoStorage = mock {
on { getCertificatePath(any()) }.thenReturn(certPath)
}
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock(), testNetwotkMapConfig)).use {
it.start() it.start()
val registerURL = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}/publish") val registerURL = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}/publish")
val nodeInfoAndSignature = SignedNodeInfo(nodeInfo.serialize(), listOf(digitalSignature)).serialize().bytes val nodeInfoAndSignature = signedNodeInfo.serialize().bytes
// Post node info and signature to doorman, this should pass without any exception. // Post node info and signature to doorman, this should pass without any exception.
doPost(registerURL, nodeInfoAndSignature) doPost(registerURL, nodeInfoAndSignature)
} }
@ -73,6 +58,11 @@ class NodeInfoWebServiceTest {
@Test @Test
fun `get network map`() { fun `get network map`() {
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val rootCACert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(locality = "London", organisation = "R3 LTD", country = "GB", commonName = "Corda Node Root CA"), rootCAKey)
val intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, X500Name("CN=Corda Node Intermediate CA,L=London"), intermediateCAKey.public)
val networkMap = NetworkMap(listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256()), SecureHash.randomSHA256()) val networkMap = NetworkMap(listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256()), SecureHash.randomSHA256())
val serializedNetworkMap = networkMap.serialize() val serializedNetworkMap = networkMap.serialize()
val networkMapStorage: NetworkMapStorage = mock { val networkMapStorage: NetworkMapStorage = mock {
@ -89,16 +79,12 @@ class NodeInfoWebServiceTest {
@Test @Test
fun `get node info`() { fun `get node info`() {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val (nodeInfo, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"))
val clientCert = X509Utilities.createCertificate(CertificateType.NODE_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Test", locality = "London", country = "GB"), keyPair.public)
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val nodeInfoHash = nodeInfo.serialize().sha256() val nodeInfoHash = nodeInfo.serialize().sha256()
val nodeInfoStorage: NodeInfoStorage = mock { val nodeInfoStorage: NodeInfoStorage = mock {
val serializedNodeInfo = nodeInfo.serialize() on { getNodeInfo(nodeInfoHash) }.thenReturn(signedNodeInfo)
on { getNodeInfo(nodeInfoHash) }.thenReturn(SignedNodeInfo(serializedNodeInfo, listOf(keyPair.sign(serializedNodeInfo))))
} }
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock(), testNetwotkMapConfig)).use { NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock(), testNetwotkMapConfig)).use {

View File

@ -23,8 +23,6 @@ import net.corda.node.services.config.BFTSMaRtConfiguration
import net.corda.node.services.config.NotaryConfig import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.transactions.minClusterSize import net.corda.node.services.transactions.minClusterSize
import net.corda.node.services.transactions.minCorrectReplicas import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.nodeapi.internal.ServiceIdentityGenerator
import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.IdentityGenerator import net.corda.nodeapi.internal.IdentityGenerator
import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo import net.corda.nodeapi.internal.network.NotaryInfo

View File

@ -14,7 +14,7 @@ import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.node.services.config.NotaryConfig import net.corda.node.services.config.NotaryConfig
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.NetworkParametersCopier
import net.corda.nodeapi.internal.network.NotaryInfo import net.corda.nodeapi.internal.network.NotaryInfo
import net.corda.testing.* import net.corda.testing.*
@ -49,11 +49,7 @@ class MySQLNotaryServiceTests : IntegrationTest() {
@Before @Before
fun before() { fun before() {
mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts")) mockNet = MockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
notaryParty = ServiceIdentityGenerator.generateToDisk( notaryParty = IdentityGenerator.generateNodeIdentity(mockNet.baseDirectory(mockNet.nextNodeId), notaryName)
listOf(mockNet.baseDirectory(mockNet.nextNodeId)),
notaryName,
"identity"
)
val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notaryParty, false)))) val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notaryParty, false))))
val notaryNodeUnstarted = createNotaryNode() val notaryNodeUnstarted = createNotaryNode()
val nodeUnstarted = mockNet.createUnstartedNode() val nodeUnstarted = mockNet.createUnstartedNode()

View File

@ -11,17 +11,14 @@ import net.corda.core.internal.concurrent.map
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.node.internal.StartedNode import net.corda.node.internal.StartedNode
import net.corda.testing.DUMMY_BANK_A_NAME import net.corda.testing.*
import net.corda.testing.chooseIdentity
import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContract
import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.NodeHandle
import net.corda.testing.driver.driver import net.corda.testing.driver.driver
import net.corda.testing.dummyCommand
import net.corda.testing.node.ClusterSpec import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec import net.corda.testing.node.NotarySpec
import net.corda.testing.node.startFlow import net.corda.testing.node.startFlow
import org.junit.ClassRule import org.junit.ClassRule
import net.corda.testing.node.startFlow
import org.junit.Test import org.junit.Test
import java.util.* import java.util.*
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@ -35,9 +35,6 @@ class MySQLNonValidatingNotaryService(services: ServiceHubInternal,
notaryIdentityKey: PublicKey, notaryIdentityKey: PublicKey,
dataSourceProperties: Properties, dataSourceProperties: Properties,
devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) { devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) {
companion object {
val id = constructId(validating = false, mysql = true)
}
override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = NonValidatingNotaryFlow(otherPartySession, this) override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = NonValidatingNotaryFlow(otherPartySession, this)
} }
@ -45,8 +42,5 @@ class MySQLValidatingNotaryService(services: ServiceHubInternal,
notaryIdentityKey: PublicKey, notaryIdentityKey: PublicKey,
dataSourceProperties: Properties, dataSourceProperties: Properties,
devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) { devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, dataSourceProperties, devMode) {
companion object {
val id = constructId(validating = true, mysql = true)
}
override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = ValidatingNotaryFlow(otherPartySession, this) override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic<Void?> = ValidatingNotaryFlow(otherPartySession, this)
} }