Network Map signing (#87)

* Network Map signing

* Fixing failing tests

* Fixing integration tests

* Addressing review comments

* Addressing review comments

* Rebasing to the new network parameters + network map ownership redesign

* Addressing review comments

* Addressing review comments

* Splitting the PR

* Reverting enum uppercasing

* Fixing the NetworkMapEntity comment

* Addressing review comments - round 3

* Fixing docs and adding some TODOS

* Removing nullification of the common name
This commit is contained in:
mkit
2017-11-14 08:29:07 +00:00
committed by GitHub
parent 359610ff14
commit 1ec40ee983
48 changed files with 1855 additions and 684 deletions

View File

@ -0,0 +1,96 @@
package com.r3.corda.networkmanage
import com.nhaarman.mockito_kotlin.mock
import com.r3.corda.networkmanage.common.persistence.CertificateData
import com.r3.corda.networkmanage.common.persistence.CertificateSigningRequest
import com.r3.corda.networkmanage.common.persistence.CertificateStatus
import com.r3.corda.networkmanage.common.persistence.RequestStatus
import com.r3.corda.networkmanage.common.persistence.entity.CertificateDataEntity
import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity
import net.corda.core.crypto.SecureHash
import net.corda.core.node.NetworkParameters
import net.corda.core.node.NotaryInfo
import net.corda.core.utilities.seconds
import net.corda.testing.SerializationEnvironmentRule
import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.junit.Rule
import java.security.cert.CertPath
import java.time.Duration
import java.time.Instant
abstract class TestBase {
@Rule
@JvmField
val testSerialization = SerializationEnvironmentRule()
protected fun certificateSigningRequestEntity(
requestId: String = SecureHash.randomSHA256().toString(),
status: RequestStatus = RequestStatus.New,
legalName: String = "TestLegalName",
modifiedBy: List<String> = emptyList(),
modifiedAt: Instant = Instant.now(),
remark: String = "Test remark",
certificateData: CertificateDataEntity? = null,
requestBytes: ByteArray = ByteArray(0)
): CertificateSigningRequestEntity {
return CertificateSigningRequestEntity(
requestId = requestId,
status = status,
legalName = legalName,
modifiedBy = modifiedBy,
modifiedAt = modifiedAt,
remark = remark,
certificateData = certificateData,
requestBytes = requestBytes
)
}
protected fun certificateSigningRequest(
requestId: String = SecureHash.randomSHA256().toString(),
status: RequestStatus = RequestStatus.New,
legalName: String = "TestLegalName",
remark: String = "Test remark",
request: PKCS10CertificationRequest = mock(),
certData: CertificateData = mock(),
modifiedBy: List<String> = emptyList()
): CertificateSigningRequest {
return CertificateSigningRequest(
requestId = requestId,
status = status,
legalName = legalName,
remark = remark,
certData = certData,
request = request,
modifiedBy = modifiedBy
)
}
protected fun certificateData(publicKeyHash: String = SecureHash.randomSHA256().toString(),
certStatus: CertificateStatus = CertificateStatus.VALID,
certPath: CertPath = mock()): CertificateData {
return CertificateData(
publicKeyHash = publicKeyHash,
certStatus = certStatus,
certPath = certPath
)
}
// TODO remove this once testNetworkParameters are updated with default parameters
protected fun createNetworkParameters(minimumPlatformVersion: Int = 1,
notaries: List<NotaryInfo> = emptyList(),
eventHorizon: Duration = 1.seconds,
maxMessageSize: Int = 0,
maxTransactionSize: Int = 0,
modifiedTime: Instant = Instant.now(),
epoch: Int = 1): NetworkParameters {
return NetworkParameters(
minimumPlatformVersion = minimumPlatformVersion,
notaries = notaries,
eventHorizon = eventHorizon,
maxMessageSize = maxMessageSize,
maxTransactionSize = maxTransactionSize,
modifiedTime = modifiedTime,
epoch = epoch
)
}
}

View File

@ -1,6 +1,8 @@
package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE
import com.r3.corda.networkmanage.common.persistence.entity.CertificateSigningRequestEntity
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import net.corda.core.crypto.Crypto
@ -22,14 +24,14 @@ import java.security.KeyPair
import java.util.*
import kotlin.test.*
class DBCertificateRequestStorageTest {
private lateinit var storage: DBCertificateRequestStorage
class DBCertificateRequestStorageTest : TestBase() {
private lateinit var storage: PersistentCertificateRequestStorage
private lateinit var persistence: CordaPersistence
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, SchemaService())
storage = DBCertificateRequestStorage(persistence)
storage = PersistentCertificateRequestStorage(persistence)
}
@After
@ -42,7 +44,7 @@ class DBCertificateRequestStorageTest {
val request = createRequest("LegalName").first
val requestId = storage.saveRequest(request)
assertNotNull(storage.getRequest(requestId)).apply {
assertEquals(request, PKCS10CertificationRequest(this.request))
assertEquals(request, this.request)
}
assertThat(storage.getRequests(RequestStatus.New).map { it.requestId }).containsOnly(requestId)
}
@ -55,11 +57,9 @@ class DBCertificateRequestStorageTest {
// Pending request should equals to 1.
assertEquals(1, storage.getRequests(RequestStatus.New).size)
// Certificate should be empty.
assertNull(storage.getRequest(requestId)!!.certificateData)
assertNull(storage.getRequest(requestId)!!.certData)
// Store certificate to DB.
val result = storage.approveRequest(requestId, DOORMAN_SIGNATURE)
// Check request request has been approved
assertTrue(result)
storage.approveRequest(requestId, DOORMAN_SIGNATURE)
// Check request is not ready yet.
// assertTrue(storage.getResponse(requestId) is CertificateResponse.NotReady)
// New request should be empty.
@ -72,12 +72,17 @@ class DBCertificateRequestStorageTest {
val (request, _) = createRequest("LegalName")
// Add request to DB.
val requestId = storage.saveRequest(request)
storage.approveRequest(requestId, DOORMAN_SIGNATURE)
storage.approveRequest(requestId, "ApproverA")
var thrown: Exception? = null
// When subsequent approval is performed
val result = storage.approveRequest(requestId, DOORMAN_SIGNATURE)
try {
storage.approveRequest(requestId, "ApproverB")
} catch (e: IllegalArgumentException) {
thrown = e
}
// Then check request has not been approved
assertFalse(result)
assertNotNull(thrown)
}
@Test
@ -88,7 +93,7 @@ class DBCertificateRequestStorageTest {
// New request should equals to 1.
assertEquals(1, storage.getRequests(RequestStatus.New).size)
// Certificate should be empty.
assertNull(storage.getRequest(requestId)!!.certificateData)
assertNull(storage.getRequest(requestId)!!.certData)
// Store certificate to DB.
storage.approveRequest(requestId, DOORMAN_SIGNATURE)
// Check request is not ready yet.
@ -105,7 +110,7 @@ class DBCertificateRequestStorageTest {
buildCertPath(ourCertificate, intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
}, listOf(DOORMAN_SIGNATURE))
// Check request is ready
assertNotNull(storage.getRequest(requestId)!!.certificateData)
assertNotNull(storage.getRequest(requestId)!!.certData)
}
@Test
@ -188,21 +193,15 @@ class DBCertificateRequestStorageTest {
// then
persistence.transaction {
val auditReader = AuditReaderFactory.get(persistence.entityManagerFactory.createEntityManager())
val newRevision = auditReader.find(CertificateSigningRequest::class.java, requestId, 1)
val newRevision = auditReader.find(CertificateSigningRequestEntity::class.java, requestId, 1)
assertEquals(RequestStatus.New, newRevision.status)
assertTrue(newRevision.modifiedBy.isEmpty())
val approvedRevision = auditReader.find(CertificateSigningRequest::class.java, requestId, 2)
val approvedRevision = auditReader.find(CertificateSigningRequestEntity::class.java, requestId, 2)
assertEquals(RequestStatus.Approved, approvedRevision.status)
assertEquals(approver, approvedRevision.modifiedBy.first())
}
}
private fun createRequest(legalName: String): Pair<PKCS10CertificationRequest, KeyPair> {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val request = X509Utilities.createCertificateSigningRequest(CordaX500Name(organisation = legalName, locality = "London", country = "GB"), "my@mail.com", keyPair)
return Pair(request, keyPair)
}
private fun makeTestDataSourceProperties(nodeName: String = SecureHash.randomSHA256().toString()): Properties {
val props = Properties()
props.setProperty("dataSourceClassName", "org.h2.jdbcx.JdbcDataSource")
@ -221,3 +220,9 @@ class DBCertificateRequestStorageTest {
return props
}
}
internal fun createRequest(organisation: String): Pair<PKCS10CertificationRequest, KeyPair> {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val request = X509Utilities.createCertificateSigningRequest(CordaX500Name(organisation = organisation, locality = "London", country = "GB"), "my@mail.com", keyPair)
return Pair(request, keyPair)
}

View File

@ -0,0 +1,164 @@
package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.signer.NetworkMap
import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
import com.r3.corda.networkmanage.common.signer.SignedNetworkMap
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.node.NotaryInfo
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.X509Utilities
import net.corda.node.utilities.configureDatabase
import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
import org.junit.After
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DBNetworkMapStorageTest : TestBase() {
private lateinit var networkMapStorage: NetworkMapStorage
private lateinit var requestStorage: CertificationRequestStorage
private lateinit var nodeInfoStorage: NodeInfoStorage
private lateinit var persistence: CordaPersistence
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 intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, CordaX500Name(commonName = "Corda Node Intermediate CA", locality = "London", organisation = "R3 LTD", country = "GB"), intermediateCAKey.public)
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, SchemaService())
networkMapStorage = PersistentNetworkMapStorage(persistence)
nodeInfoStorage = PersistentNodeInfoStorage(persistence)
requestStorage = PersistentCertificateRequestStorage(persistence)
}
@After
fun closeDb() {
persistence.close()
}
@Test
fun `signNetworkMap creates current network map`() {
// given
// Create node info.
val organisation = "Test"
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfo)
// Some random bytes
val signature = keyPair.sign(nodeInfo.serialize())
nodeInfoStorage.signNodeInfo(nodeInfoHash, signature)
// Create network parameters
val networkParametersHash = networkMapStorage.putNetworkParameters(testNetworkParameters(emptyList<NotaryInfo>()))
val signatureData = SignatureAndCertPath(signature, certPath)
val signedNetworkMap = SignedNetworkMap(NetworkMap(listOf(nodeInfoHash.toString()), networkParametersHash.toString()), signatureData)
// when
networkMapStorage.saveNetworkMap(signedNetworkMap)
// then
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
assertEquals(signedNetworkMap, persistedSignedNetworkMap)
}
@Test
fun `getLatestNetworkParameters returns last inserted`() {
// given
networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 1))
networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 2))
// when
val latest = networkMapStorage.getLatestNetworkParameters()
// then
assertEquals(2, latest.minimumPlatformVersion)
}
@Test
fun `getCurrentNetworkParameters returns current network map parameters`() {
// given
// Create network parameters
val networkMapParametersHash = networkMapStorage.putNetworkParameters(createNetworkParameters(1))
// 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)
val certPath = buildCertPath(intermediateCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
// Sign network map making it current network map
val hashedNetworkMap = NetworkMap(emptyList(), networkMapParametersHash.toString())
val signatureData = SignatureAndCertPath(keyPair.sign(hashedNetworkMap.serialize()), certPath)
val signedNetworkMap = SignedNetworkMap(hashedNetworkMap, signatureData)
networkMapStorage.saveNetworkMap(signedNetworkMap)
// Create new network parameters
networkMapStorage.putNetworkParameters(createNetworkParameters(2))
// when
val result = networkMapStorage.getCurrentNetworkParameters()
// then
assertEquals(1, result.minimumPlatformVersion)
}
@Test
fun `getDetachedSignedAndValidNodeInfoHashes returns only valid and signed node info hashes`() {
// given
// Create node info.
val organisationA = "TestA"
val requestIdA = requestStorage.saveRequest(createRequest(organisationA).first)
requestStorage.approveRequest(requestIdA, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertA = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationA, locality = "London", country = "GB"), keyPair.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.approveRequest(requestIdB, "TestUser")
val clientCertB = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationB, locality = "London", country = "GB"), Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME).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)
val nodeInfoHashA = nodeInfoStorage.putNodeInfo(nodeInfoA)
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(nodeInfoB)
// Sign node info
nodeInfoStorage.signNodeInfo(nodeInfoHashA, keyPair.sign(nodeInfoA.serialize()))
nodeInfoStorage.signNodeInfo(nodeInfoHashB, keyPair.sign(nodeInfoB.serialize()))
// Create network parameters
val networkParametersHash = networkMapStorage.putNetworkParameters(createNetworkParameters())
val networkMap = NetworkMap(listOf(nodeInfoHashA.toString()), networkParametersHash.toString())
val signatureData = SignatureAndCertPath(keyPair.sign(networkMap.serialize()), certPathA)
val signedNetworkMap = SignedNetworkMap(networkMap, signatureData)
// Sign network map
networkMapStorage.saveNetworkMap(signedNetworkMap)
// when
val detachedHashes = networkMapStorage.getDetachedSignedAndValidNodeInfoHashes()
// then
assertEquals(1, detachedHashes.size)
assertTrue(detachedHashes.contains(nodeInfoHashB))
}
}

View File

@ -1,139 +0,0 @@
package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage.Companion.DOORMAN_SIGNATURE
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.sha256
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.X509Utilities
import net.corda.node.utilities.configureDatabase
import net.corda.nodeapi.internal.serialization.*
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
class PersistenceNodeInfoStorageTest {
private lateinit var nodeInfoStorage: NodeInfoStorage
private lateinit var requestStorage: CertificationRequestStorage
private lateinit var persistence: CordaPersistence
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 intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, CordaX500Name(commonName = "Corda Node Intermediate CA", locality = "London", organisation = "R3 LTD", country = "GB"), intermediateCAKey.public)
companion object {
@BeforeClass
@JvmStatic
fun initSerialization() {
try {
SerializationDefaults.SERIALIZATION_FACTORY = SerializationFactoryImpl().apply {
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPServerSerializationScheme())
}
SerializationDefaults.P2P_CONTEXT = KRYO_P2P_CONTEXT
SerializationDefaults.RPC_SERVER_CONTEXT = KRYO_RPC_SERVER_CONTEXT
SerializationDefaults.STORAGE_CONTEXT = KRYO_STORAGE_CONTEXT
SerializationDefaults.CHECKPOINT_CONTEXT = KRYO_CHECKPOINT_CONTEXT
} catch (ignored: Exception) {
// Ignored
}
}
}
@Before
fun startDb() {
persistence = configureDatabase(makeTestDataSourceProperties(), makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, SchemaService())
nodeInfoStorage = PersistenceNodeInfoStorage(persistence)
requestStorage = DBCertificateRequestStorage(persistence)
}
@After
fun closeDb() {
persistence.close()
}
@Test
fun `test get CertificatePath`() {
// Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 request = X509Utilities.createCertificateSigningRequest(nodeInfo.legalIdentities.first().name, "my@mail.com", keyPair)
val requestId = requestStorage.saveRequest(request)
requestStorage.approveRequest(requestId, DOORMAN_SIGNATURE)
assertNull(nodeInfoStorage.getCertificatePath(keyPair.public.hash()))
requestStorage.putCertificatePath(requestId, buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()), listOf(DOORMAN_SIGNATURE))
val storedCertPath = nodeInfoStorage.getCertificatePath(keyPair.public.hash())
assertNotNull(storedCertPath)
assertEquals(clientCert.toX509Certificate(), storedCertPath!!.certificates.first())
}
@Test
fun `test getNodeInfoHashes`() {
// Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Test", locality = "London", country = "GB"), keyPair.public)
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
val clientCert2 = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = "Test", locality = "London", country = "GB"), Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME).public)
val certPath2 = buildCertPath(clientCert2.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
val nodeInfo = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val nodeInfoSame = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
val nodeInfo2 = NodeInfo(listOf(NetworkHostAndPort("my.company.com", 1234)), listOf(PartyAndCertificate(certPath2)), 1, serial = 1L)
nodeInfoStorage.putNodeInfo(nodeInfo)
nodeInfoStorage.putNodeInfo(nodeInfoSame)
// getNodeInfoHashes should contain 1 hash.
assertEquals(listOf(nodeInfo.serialize().sha256().toString()), nodeInfoStorage.getNodeInfoHashes())
nodeInfoStorage.putNodeInfo(nodeInfo2)
// getNodeInfoHashes should contain 2 hash.
assertEquals(listOf(nodeInfo2.serialize().sha256().toString(), nodeInfo.serialize().sha256().toString()).sorted(), nodeInfoStorage.getNodeInfoHashes().sorted())
// Test retrieve NodeInfo.
assertEquals(nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfo.serialize().sha256().toString()))
assertEquals(nodeInfo2, nodeInfoStorage.getNodeInfo(nodeInfo2.serialize().sha256().toString()))
}
@Test
fun `same pub key with different node info`() {
// Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 nodeInfoSamePubKey = NodeInfo(listOf(NetworkHostAndPort("my.company2.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
nodeInfoStorage.putNodeInfo(nodeInfo)
assertEquals(nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfo.serialize().sha256().toString()))
// This should replace the node info.
nodeInfoStorage.putNodeInfo(nodeInfoSamePubKey)
// Old node info should be removed.
assertNull(nodeInfoStorage.getNodeInfo(nodeInfo.serialize().sha256().toString()))
assertEquals(nodeInfoSamePubKey, nodeInfoStorage.getNodeInfo(nodeInfoSamePubKey.serialize().sha256().toString()))
}
}

View File

@ -0,0 +1,180 @@
package com.r3.corda.networkmanage.common.persistence
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.utils.buildCertPath
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.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.CordaPersistence
import net.corda.node.utilities.X509Utilities
import net.corda.node.utilities.configureDatabase
import net.corda.testing.node.MockServices
import org.junit.After
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
class PersitenceNodeInfoStorageTest : TestBase() {
private lateinit var requestStorage: CertificationRequestStorage
private lateinit var nodeInfoStorage: NodeInfoStorage
private lateinit var persistence: CordaPersistence
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 intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
private val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, CordaX500Name(commonName = "Corda Node Intermediate CA", locality = "London", organisation = "R3 LTD", country = "GB"), intermediateCAKey.public)
@Before
fun startDb() {
persistence = configureDatabase(MockServices.makeTestDataSourceProperties(), MockServices.makeTestDatabaseProperties(), { throw UnsupportedOperationException() }, SchemaService())
nodeInfoStorage = PersistentNodeInfoStorage(persistence)
requestStorage = PersistentCertificateRequestStorage(persistence)
}
@After
fun closeDb() {
persistence.close()
}
@Test
fun `test get CertificatePath`() {
// Create node info.
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 request = X509Utilities.createCertificateSigningRequest(nodeInfo.legalIdentities.first().name, "my@mail.com", keyPair)
val requestId = requestStorage.saveRequest(request)
requestStorage.approveRequest(requestId, CertificationRequestStorage.DOORMAN_SIGNATURE)
assertNull(nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString())))
requestStorage.putCertificatePath(requestId, buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate()), listOf(CertificationRequestStorage.DOORMAN_SIGNATURE))
val storedCertPath = nodeInfoStorage.getCertificatePath(SecureHash.parse(keyPair.public.hashString()))
assertNotNull(storedCertPath)
assertEquals(clientCert.toX509Certificate(), storedCertPath!!.certificates.first())
}
@Test
fun `test getNodeInfoHashes`() {
// Create node info.
val organisationA = "TestA"
val requestIdA = requestStorage.saveRequest(createRequest(organisationA).first)
requestStorage.approveRequest(requestIdA, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCertA = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationA, locality = "London", country = "GB"), keyPair.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.approveRequest(requestIdB, "TestUser")
val clientCertB = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisationB, locality = "London", country = "GB"), Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME).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 nodeInfoSame = 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)
nodeInfoStorage.putNodeInfo(nodeInfoA)
nodeInfoStorage.putNodeInfo(nodeInfoSame)
// getNodeInfoHashes should contain 1 hash.
assertEquals(listOf(nodeInfoA.serialize().sha256()), nodeInfoStorage.getUnsignedNodeInfoHashes())
nodeInfoStorage.putNodeInfo(nodeInfoB)
// getNodeInfoHashes should contain 2 hash.
assertEquals(listOf(nodeInfoB.serialize().sha256(), nodeInfoA.serialize().sha256()).sorted(), nodeInfoStorage.getUnsignedNodeInfoHashes().sorted())
// Test retrieve NodeInfo.
assertEquals(nodeInfoA, nodeInfoStorage.getNodeInfo(nodeInfoA.serialize().sha256()))
assertEquals(nodeInfoB, nodeInfoStorage.getNodeInfo(nodeInfoB.serialize().sha256()))
}
@Test
fun `same pub key with different node info`() {
// Create node info.
val organisation = "Test"
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 nodeInfoSamePubKey = NodeInfo(listOf(NetworkHostAndPort("my.company2.com", 1234)), listOf(PartyAndCertificate(certPath)), 1, serial = 1L)
nodeInfoStorage.putNodeInfo(nodeInfo)
assertEquals(nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfo.serialize().sha256()))
// This should replace the node info.
nodeInfoStorage.putNodeInfo(nodeInfoSamePubKey)
// Old node info should be removed.
assertNull(nodeInfoStorage.getNodeInfo(nodeInfo.serialize().sha256()))
assertEquals(nodeInfoSamePubKey, nodeInfoStorage.getNodeInfo(nodeInfoSamePubKey.serialize().sha256()))
}
@Test
fun `signNodeInfo associates signature to with node info`() {
// given
// Create node info.
val organisation = "Test"
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfo)
// Some random bytes
val signature = keyPair.sign(nodeInfo.serialize())
// when
nodeInfoStorage.signNodeInfo(nodeInfoHash, signature)
// then
val signedNodeInfo = nodeInfoStorage.getSignedNodeInfo(nodeInfoHash)
assertEquals(signature, signedNodeInfo?.sig)
}
@Test
fun `getUnsignedNodeInfoBytes return node info bytes`() {
// given
// Create node info.
val organisation = "Test"
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.approveRequest(requestId, "TestUser")
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_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 nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfo)
// when
val nodeInfoBytes = nodeInfoStorage.getUnsignedNodeInfoBytes()
// then
assertTrue(nodeInfoBytes.containsKey(nodeInfoHash))
assertEquals(nodeInfo, nodeInfoBytes[nodeInfoHash]?.deserialize()!!)
}
}

View File

@ -0,0 +1,74 @@
package com.r3.corda.networkmanage.common.signer
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.serialization.serialize
import org.junit.Before
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class NetworkMapSignerTest : TestBase() {
private lateinit var signer: Signer
private lateinit var networkMapStorage: NetworkMapStorage
private lateinit var networkMapSigner: NetworkMapSigner
@Before
fun setUp() {
signer = mock()
networkMapStorage = mock()
networkMapSigner = NetworkMapSigner(networkMapStorage, signer)
}
@Test
fun `signNetworkMap builds and signs network map`() {
// given
val signedNodeInfoHashes = listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256())
val detachedNodeInfoHashes = listOf(SecureHash.randomSHA256())
val networkMapParameters = createNetworkParameters()
whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
whenever(networkMapStorage.getDetachedSignedAndValidNodeInfoHashes()).thenReturn(detachedNodeInfoHashes)
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
whenever(signer.sign(any())).thenReturn(mock())
// when
networkMapSigner.signNetworkMap()
// then
// Verify networkMapStorage calls
verify(networkMapStorage).getCurrentNetworkMapNodeInfoHashes(any())
verify(networkMapStorage).getDetachedSignedAndValidNodeInfoHashes()
verify(networkMapStorage).getLatestNetworkParameters()
argumentCaptor<SignedNetworkMap>().apply {
verify(networkMapStorage).saveNetworkMap(capture())
val networkMap = firstValue.networkMap
assertEquals(networkMapParameters.serialize().hash.toString(), networkMap.parametersHash)
assertEquals(signedNodeInfoHashes.size + detachedNodeInfoHashes.size, networkMap.nodeInfoHashes.size)
assertTrue(networkMap.nodeInfoHashes.containsAll(signedNodeInfoHashes.map { it.toString() }))
assertTrue(networkMap.nodeInfoHashes.containsAll(detachedNodeInfoHashes.map { it.toString() }))
}
}
@Test
fun `signNetworkMap does NOT create a new network map if there are no changes`() {
// given
val networkMapParameters = createNetworkParameters()
val networkMapParametersHash = networkMapParameters.serialize().bytes.sha256()
val networkMap = NetworkMap(emptyList(), networkMapParametersHash.toString())
val signedNetworkMap = SignedNetworkMap(networkMap, mock())
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(emptyList())
whenever(networkMapStorage.getDetachedSignedAndValidNodeInfoHashes()).thenReturn(emptyList())
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
// when
networkMapSigner.signNetworkMap()
// then
// Verify networkMapStorage is not called
verify(networkMapStorage, never()).saveNetworkMap(any())
}
}

View File

@ -4,29 +4,33 @@ import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.times
import com.nhaarman.mockito_kotlin.verify
import com.r3.corda.networkmanage.common.persistence.*
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.CertificateResponse
import com.r3.corda.networkmanage.common.persistence.CertificateStatus
import com.r3.corda.networkmanage.common.persistence.CertificationRequestStorage
import com.r3.corda.networkmanage.common.persistence.RequestStatus
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.doorman.signer.DefaultCsrHandler
import com.r3.corda.networkmanage.doorman.signer.Signer
import com.r3.corda.networkmanage.doorman.signer.LocalSigner
import net.corda.core.crypto.Crypto
import net.corda.core.identity.CordaX500Name
import net.corda.node.utilities.X509Utilities
import org.junit.Test
import kotlin.test.assertEquals
class DefaultRequestProcessorTest {
class DefaultRequestProcessorTest : TestBase() {
@Test
fun `get response`() {
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
val cert = X509Utilities.createSelfSignedCACertificate(CordaX500Name(locality = "London", organisation = "Test", country = "GB"), keyPair)
val requestStorage: CertificationRequestStorage = mock {
on { getRequest("New") }.thenReturn(CertificateSigningRequest(status = RequestStatus.New))
on { getRequest("Signed") }.thenReturn(CertificateSigningRequest(status = RequestStatus.Signed, certificateData = CertificateData("", buildCertPath(cert.toX509Certificate()).encoded, CertificateStatus.VALID)))
on { getRequest("Rejected") }.thenReturn(CertificateSigningRequest(status = RequestStatus.Rejected, remark = "Random reason"))
on { getRequest("New") }.thenReturn(certificateSigningRequest())
on { getRequest("Signed") }.thenReturn(certificateSigningRequest(status = RequestStatus.Signed, certData = certificateData("", CertificateStatus.VALID, buildCertPath(cert.toX509Certificate()))))
on { getRequest("Rejected") }.thenReturn(certificateSigningRequest(status = RequestStatus.Rejected, remark = "Random reason"))
}
val signer: Signer = mock()
val signer: LocalSigner = mock()
val requestProcessor = DefaultCsrHandler(requestStorage, signer)
assertEquals(CertificateResponse.NotReady, requestProcessor.getResponse("random"))
@ -43,17 +47,17 @@ class DefaultRequestProcessorTest {
val requestStorage: CertificationRequestStorage = mock {
on { getRequests(RequestStatus.Approved) }.thenReturn(listOf(
CertificateSigningRequest(requestId = "1", request = request1.encoded),
CertificateSigningRequest(requestId = "2", request = request2.encoded),
CertificateSigningRequest(requestId = "3", request = request3.encoded)
certificateSigningRequest(requestId = "1", request = request1, status = RequestStatus.Approved),
certificateSigningRequest(requestId = "2", request = request2, status = RequestStatus.Approved),
certificateSigningRequest(requestId = "3", request = request3, status = RequestStatus.Approved)
))
}
val signer: Signer = mock()
val signer: LocalSigner = mock()
val requestProcessor = DefaultCsrHandler(requestStorage, signer)
requestProcessor.processApprovedRequests()
verify(signer, times(3)).sign(any())
verify(signer, times(3)).createSignedClientCertificate(any())
verify(requestStorage, times(1)).getRequests(any())
}
}

View File

@ -1,13 +1,15 @@
package com.r3.corda.networkmanage.doorman
import com.r3.corda.networkmanage.TestBase
import com.typesafe.config.ConfigException
import net.corda.core.utilities.seconds
import org.junit.Test
import java.io.File
import java.nio.file.Paths
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class DoormanParametersTest {
class DoormanParametersTest : TestBase() {
private val testDummyPath = ".${File.separator}testDummyPath.jks"
private val validInitialNetworkConfigPath = File(javaClass.getResource("/initial-network-parameters.conf").toURI()).absolutePath
private val validConfigPath = File(javaClass.getResource("/doorman.conf").toURI()).absolutePath

View File

@ -4,7 +4,11 @@ import com.nhaarman.mockito_kotlin.any
import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.times
import com.nhaarman.mockito_kotlin.verify
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
import com.r3.corda.networkmanage.common.persistence.NodeInfoStorage
import com.r3.corda.networkmanage.common.signer.NetworkMap
import com.r3.corda.networkmanage.common.signer.SignedNetworkMap
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
@ -12,19 +16,15 @@ import net.corda.core.crypto.*
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.SerializationDefaults
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.serialization.KryoServerSerializationScheme
import net.corda.node.utilities.CertificateType
import net.corda.node.utilities.X509Utilities
import net.corda.nodeapi.internal.serialization.*
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
import net.corda.testing.common.internal.testNetworkParameters
import org.bouncycastle.asn1.x500.X500Name
import org.codehaus.jackson.map.ObjectMapper
import org.junit.BeforeClass
import org.junit.Test
import java.io.FileNotFoundException
import java.io.IOException
@ -34,31 +34,12 @@ import javax.ws.rs.core.MediaType
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class NodeInfoWebServiceTest {
class NodeInfoWebServiceTest : TestBase() {
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)
companion object {
@BeforeClass
@JvmStatic
fun initSerialization() {
try {
SerializationDefaults.SERIALIZATION_FACTORY = SerializationFactoryImpl().apply {
registerScheme(KryoServerSerializationScheme())
registerScheme(AMQPServerSerializationScheme())
}
SerializationDefaults.P2P_CONTEXT = KRYO_P2P_CONTEXT
SerializationDefaults.RPC_SERVER_CONTEXT = KRYO_RPC_SERVER_CONTEXT
SerializationDefaults.STORAGE_CONTEXT = KRYO_STORAGE_CONTEXT
SerializationDefaults.CHECKPOINT_CONTEXT = KRYO_CHECKPOINT_CONTEXT
} catch (ignored: Exception) {
// Ignored
}
}
}
@Test
fun `submit nodeInfo`() {
// Create node info.
@ -74,8 +55,7 @@ class NodeInfoWebServiceTest {
on { getCertificatePath(any()) }.thenReturn(certPath)
}
DoormanServer(NetworkHostAndPort("localhost", 0),
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock())).use {
it.start()
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
@ -101,8 +81,7 @@ class NodeInfoWebServiceTest {
on { getCertificatePath(any()) }.thenReturn(certPath)
}
DoormanServer(NetworkHostAndPort("localhost", 0),
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock())).use {
it.start()
val registerURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/register")
val nodeInfoAndSignature = SignedData(nodeInfo.serialize(), digitalSignature).serialize().bytes
@ -116,18 +95,16 @@ class NodeInfoWebServiceTest {
@Test
fun `get network map`() {
val networkMapList = listOf(SecureHash.randomSHA256().toString(), SecureHash.randomSHA256().toString())
val nodeInfoStorage: NodeInfoStorage = mock {
on { getNodeInfoHashes() }.thenReturn(networkMapList)
val hashedNetworkMap = NetworkMap(listOf(SecureHash.randomSHA256().toString(), SecureHash.randomSHA256().toString()), SecureHash.randomSHA256().toString())
val networkMapStorage: NetworkMapStorage = mock {
on { getCurrentNetworkMap() }.thenReturn(SignedNetworkMap(hashedNetworkMap, mock()))
}
DoormanServer(NetworkHostAndPort("localhost", 0),
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage)).use {
it.start()
val conn = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}").openConnection() as HttpURLConnection
val response = conn.inputStream.bufferedReader().use { it.readLine() }
val list = ObjectMapper().readValue(response, List::class.java)
verify(nodeInfoStorage, times(1)).getNodeInfoHashes()
assertEquals(networkMapList, list)
val signedHashedNetworkMap = conn.inputStream.readBytes().deserialize<SignedNetworkMap>()
verify(networkMapStorage, times(1)).getCurrentNetworkMap()
assertEquals(signedHashedNetworkMap.networkMap, hashedNetworkMap)
}
}
@ -138,20 +115,20 @@ class NodeInfoWebServiceTest {
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().toString()
val nodeInfoHash = nodeInfo.serialize().sha256()
val nodeInfoStorage: NodeInfoStorage = mock {
on { getNodeInfo(nodeInfoHash) }.thenReturn(nodeInfo)
val serializedNodeInfo = nodeInfo.serialize()
on { getSignedNodeInfo(nodeInfoHash) }.thenReturn(SignedData(serializedNodeInfo, keyPair.sign(serializedNodeInfo)))
}
DoormanServer(NetworkHostAndPort("localhost", 0),
NodeInfoWebService(nodeInfoStorage, testNetworkParameters(emptyList()))).use {
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock())).use {
it.start()
val nodeInfoURL = URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/$nodeInfoHash")
val conn = nodeInfoURL.openConnection()
val nodeInfoResponse = conn.inputStream.readBytes().deserialize<NodeInfo>()
verify(nodeInfoStorage, times(1)).getNodeInfo(nodeInfoHash)
assertEquals(nodeInfo, nodeInfoResponse)
val nodeInfoResponse = conn.inputStream.readBytes().deserialize<SignedData<NodeInfo>>()
verify(nodeInfoStorage, times(1)).getSignedNodeInfo(nodeInfoHash)
assertEquals(nodeInfo, nodeInfoResponse.verified())
assertFailsWith(FileNotFoundException::class) {
URL("http://${it.hostAndPort}/api/${NodeInfoWebService.networkMapPath}/${SecureHash.randomSHA256()}").openConnection().getInputStream()

View File

@ -1,6 +1,7 @@
package com.r3.corda.networkmanage.doorman
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.common.persistence.CertificateResponse
import com.r3.corda.networkmanage.common.utils.buildCertPath
import com.r3.corda.networkmanage.common.utils.toX509Certificate
@ -36,7 +37,7 @@ import java.util.zip.ZipInputStream
import javax.ws.rs.core.MediaType
import kotlin.test.assertEquals
class RegistrationWebServiceTest {
class RegistrationWebServiceTest : TestBase() {
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 intermediateCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
@ -141,9 +142,7 @@ class RegistrationWebServiceTest {
}
startSigningServer(storage)
assertThat(pollForResponse(id)).isEqualTo(PollResponse.NotReady)
storage.processApprovedRequests()
val certificates = (pollForResponse(id) as PollResponse.Ready).certChain

View File

@ -1,15 +1,15 @@
package com.r3.corda.networkmanage.hsm.authentication
import CryptoServerCXI.CryptoServerCXI
import CryptoServerJCE.CryptoServerProvider
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.TestBase
import org.junit.Before
import org.junit.Test
import java.io.Console
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class AuthenticatorTest {
class AuthenticatorTest : TestBase() {
private lateinit var provider: CryptoServerProvider
private lateinit var console: Console
@ -17,7 +17,7 @@ class AuthenticatorTest {
@Before
fun setUp() {
provider = mock()
whenever(provider.cryptoServer).thenReturn(mock<CryptoServerCXI>())
whenever(provider.cryptoServer).thenReturn(mock())
console = mock()
}

View File

@ -1,5 +1,6 @@
package com.r3.corda.networkmanage.hsm.configuration
import com.r3.corda.networkmanage.TestBase
import com.r3.corda.networkmanage.hsm.authentication.AuthMode
import com.typesafe.config.ConfigException
import org.junit.Test
@ -7,7 +8,7 @@ import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class ConfigurationTest {
class ConfigurationTest : TestBase() {
private val validConfigPath = File(javaClass.getResource("/hsm.conf").toURI()).absolutePath
private val invalidConfigPath = File(javaClass.getResource("/hsm_fail.conf").toURI()).absolutePath