mirror of
https://github.com/corda/corda.git
synced 2024-12-27 08:22:35 +00:00
Use network map objects from corda instead of stubs (#146)
* * change corda dependencies to 3.0-NETWORKMAP_SNAPSHOT * packages move fix * fix up after rebase * rename test * address PR issues * address PR issues * fix failing test
This commit is contained in:
parent
60fca0bf16
commit
b3ca36132f
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -15,6 +15,8 @@
|
|||||||
<module name="business-network-demo_integrationTest" target="1.8" />
|
<module name="business-network-demo_integrationTest" target="1.8" />
|
||||||
<module name="business-network-demo_main" target="1.8" />
|
<module name="business-network-demo_main" target="1.8" />
|
||||||
<module name="business-network-demo_test" target="1.8" />
|
<module name="business-network-demo_test" target="1.8" />
|
||||||
|
<module name="capsule-hsm_main" target="1.8" />
|
||||||
|
<module name="capsule-hsm_test" target="1.8" />
|
||||||
<module name="client_main" target="1.8" />
|
<module name="client_main" target="1.8" />
|
||||||
<module name="client_test" target="1.8" />
|
<module name="client_test" target="1.8" />
|
||||||
<module name="confidential-identities_main" target="1.8" />
|
<module name="confidential-identities_main" target="1.8" />
|
||||||
|
@ -56,9 +56,7 @@ dependencies {
|
|||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
compile fileTree(dir: 'libs', include: '*.jar')
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
|
||||||
compile "net.corda:corda-core:$corda_dependency_version"
|
|
||||||
compile "net.corda:corda-node-api:$corda_dependency_version"
|
compile "net.corda:corda-node-api:$corda_dependency_version"
|
||||||
testCompile "net.corda:corda-test-utils:$corda_dependency_version"
|
|
||||||
testCompile "net.corda:corda-node-driver:$corda_dependency_version"
|
testCompile "net.corda:corda-node-driver:$corda_dependency_version"
|
||||||
testCompile "net.corda:corda-test-common:$corda_dependency_version"
|
testCompile "net.corda:corda-test-common:$corda_dependency_version"
|
||||||
|
|
||||||
|
@ -92,9 +92,7 @@ class DoormanIntegrationTest {
|
|||||||
doorman.close()
|
doorman.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO remove @Ignore once PR https://github.com/corda/corda/pull/2054 is merged
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
fun `nodeInfo is published to the network map`() {
|
fun `nodeInfo is published to the network map`() {
|
||||||
// Given
|
// Given
|
||||||
val rootCertAndKey = createDoormanRootCertificateAndKeyPair()
|
val rootCertAndKey = createDoormanRootCertificateAndKeyPair()
|
||||||
@ -111,6 +109,8 @@ class DoormanIntegrationTest {
|
|||||||
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
|
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
|
||||||
whenever(it.emailAddress).thenReturn("iTest@R3.com")
|
whenever(it.emailAddress).thenReturn("iTest@R3.com")
|
||||||
}
|
}
|
||||||
|
config.rootCaCertFile.parent.createDirectories()
|
||||||
|
X509Utilities.saveCertificateAsPEMFile(rootCertAndKey.certificate, config.rootCaCertFile)
|
||||||
|
|
||||||
NetworkRegistrationHelper(config, HTTPNetworkRegistrationService(config.compatibilityZoneURL!!)).buildKeystore()
|
NetworkRegistrationHelper(config, HTTPNetworkRegistrationService(config.compatibilityZoneURL!!)).buildKeystore()
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.r3.corda.networkmanage.common.persistence
|
package com.r3.corda.networkmanage.common.persistence
|
||||||
|
|
||||||
import com.r3.corda.networkmanage.common.signer.SignedNetworkMap
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.nodeapi.internal.NetworkParameters
|
import net.corda.nodeapi.internal.NetworkParameters
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data access object interface for NetworkMap persistence layer
|
* Data access object interface for NetworkMap persistence layer
|
||||||
@ -15,16 +15,13 @@ interface NetworkMapStorage {
|
|||||||
fun getCurrentNetworkMap(): SignedNetworkMap?
|
fun getCurrentNetworkMap(): SignedNetworkMap?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves current map node info hashes only. Hashes are further filtered by the [certificateStatuses] parameter
|
* Retrieves node info hashes where the certificate status matches [certificateStatus].
|
||||||
* that restricts considered node info to only those which [CertificateStatus] value corresponds to one in the passed
|
*
|
||||||
* collection. If null or empty list is passed then filtering has no effect and all node info hashes from the current
|
* @param certificateStatus certificate status to be used in the node info filtering. Node info hash is returned
|
||||||
* network map are returned.
|
* in the result collection if its certificate status matches [certificateStatus].
|
||||||
* @param certificateStatuses certificate statuses to be used in the node info filtering. Node info hash is returned
|
* @return list of node info hashes satisfying the filtering criteria given by [certificateStatus].
|
||||||
* in the result collection only if it is in the current network map and its certificate status belongs to the
|
|
||||||
* [certificateStatuses] collection or if [certificateStatuses] collection is null or empty.
|
|
||||||
* @return list of current network map node info hashes satisfying the filtering criteria given by [certificateStatuses].
|
|
||||||
*/
|
*/
|
||||||
fun getCurrentNetworkMapNodeInfoHashes(certificateStatuses: List<CertificateStatus>): List<SecureHash>
|
fun getNodeInfoHashes(certificateStatus: CertificateStatus): List<SecureHash>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persists a new instance of the signed network map.
|
* Persists a new instance of the signed network map.
|
||||||
@ -32,17 +29,11 @@ interface NetworkMapStorage {
|
|||||||
*/
|
*/
|
||||||
fun saveNetworkMap(signedNetworkMap: SignedNetworkMap)
|
fun saveNetworkMap(signedNetworkMap: SignedNetworkMap)
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve all node info hashes for all node info with valid certificates,
|
|
||||||
* that are not associated with any network map yet.
|
|
||||||
*/
|
|
||||||
fun getDetachedAndValidNodeInfoHashes(): List<SecureHash>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve network parameters by their hash.
|
* Retrieve network parameters by their hash.
|
||||||
* @return network parameters corresponding to the given hash or null if it does not exist
|
* @return network parameters corresponding to the given hash or null if it does not exist
|
||||||
*/
|
*/
|
||||||
fun getNetworkParameters(parameterHash: SecureHash): NetworkParameters
|
fun getNetworkParameters(parameterHash: SecureHash): NetworkParameters?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve network map parameters.
|
* Retrieve network map parameters.
|
||||||
@ -54,7 +45,7 @@ interface NetworkMapStorage {
|
|||||||
* Persists given network parameters.
|
* Persists given network parameters.
|
||||||
* @return hash corresponding to newly create network parameters entry
|
* @return hash corresponding to newly create network parameters entry
|
||||||
*/
|
*/
|
||||||
fun putNetworkParameters(networkParameters: NetworkParameters): SecureHash
|
fun saveNetworkParameters(networkParameters: NetworkParameters): SecureHash
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the latest (i.e. most recently inserted) network parameters
|
* Retrieves the latest (i.e. most recently inserted) network parameters
|
||||||
|
@ -1,77 +1,64 @@
|
|||||||
package com.r3.corda.networkmanage.common.persistence
|
package com.r3.corda.networkmanage.common.persistence
|
||||||
|
|
||||||
import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity
|
import com.r3.corda.networkmanage.common.persistence.entity.*
|
||||||
import com.r3.corda.networkmanage.common.persistence.entity.NetworkParametersEntity
|
|
||||||
import com.r3.corda.networkmanage.common.persistence.entity.NodeInfoEntity
|
|
||||||
import com.r3.corda.networkmanage.common.signer.NetworkMap
|
|
||||||
import com.r3.corda.networkmanage.common.signer.SignedNetworkMap
|
|
||||||
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.serialization.SerializedBytes
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.nodeapi.internal.NetworkMap
|
||||||
import net.corda.nodeapi.internal.NetworkParameters
|
import net.corda.nodeapi.internal.NetworkParameters
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import org.hibernate.Session
|
|
||||||
import org.hibernate.jpa.QueryHints
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database implementation of the [NetworkMapStorage] interface
|
* Database implementation of the [NetworkMapStorage] interface
|
||||||
*/
|
*/
|
||||||
class PersistentNetworkMapStorage(private val database: CordaPersistence) : NetworkMapStorage {
|
class PersistentNetworkMapStorage(private val database: CordaPersistence) : NetworkMapStorage {
|
||||||
override fun getCurrentNetworkMap(): SignedNetworkMap? = database.transaction {
|
override fun getCurrentNetworkMap(): SignedNetworkMap? = database.transaction {
|
||||||
val networkMapEntity = getCurrentNetworkMapEntity(getNetworkMapWithNodeInfoAndParametersHint(session))
|
val networkMapEntity = getCurrentNetworkMapEntity()
|
||||||
networkMapEntity?.let {
|
networkMapEntity?.let {
|
||||||
val nodeInfoHashes = it.nodeInfoList.map { it.nodeInfoHash }
|
|
||||||
val networkParameterHash = it.parameters.parametersHash
|
|
||||||
val signatureAndCertPath = it.signatureAndCertificate()
|
val signatureAndCertPath = it.signatureAndCertificate()
|
||||||
SignedNetworkMap(NetworkMap(nodeInfoHashes, networkParameterHash), signatureAndCertPath!!)
|
SignedNetworkMap(SerializedBytes(it.networkMap), signatureAndCertPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCurrentNetworkParameters(): NetworkParameters? = database.transaction {
|
override fun getCurrentNetworkParameters(): NetworkParameters? = database.transaction {
|
||||||
getCurrentNetworkMapEntity(getNetworkMapWithParametersHint(session))?.parameters?.networkParameters()
|
getCurrentNetworkMapEntity()?.let {
|
||||||
|
val parameterHash = it.networkMap.deserialize<NetworkMap>().networkParameterHash
|
||||||
|
getNetworkParameters(parameterHash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveNetworkMap(signedNetworkMap: SignedNetworkMap) {
|
override fun saveNetworkMap(signedNetworkMap: SignedNetworkMap) {
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val networkMap = signedNetworkMap.networkMap
|
|
||||||
val signatureAndCertPath = signedNetworkMap.signatureData
|
|
||||||
val signature = signatureAndCertPath.signature
|
|
||||||
val networkParametersEntity = getNetworkParametersEntity(networkMap.parametersHash)
|
|
||||||
networkParametersEntity ?: throw IllegalArgumentException("Error when retrieving network parameters entity for network map signing! - Entity does not exist")
|
|
||||||
val networkMapEntity = NetworkMapEntity(
|
val networkMapEntity = NetworkMapEntity(
|
||||||
parameters = networkParametersEntity,
|
networkMap = signedNetworkMap.raw.bytes,
|
||||||
signatureBytes = signature.bytes,
|
signature = signedNetworkMap.sig.signatureBytes,
|
||||||
certificatePathBytes = signatureAndCertPath.certPath.serialize().bytes
|
certificate = signedNetworkMap.sig.by.encoded
|
||||||
)
|
)
|
||||||
session.save(networkMapEntity)
|
session.save(networkMapEntity)
|
||||||
networkMap.nodeInfoHashes.forEach {
|
|
||||||
val nodeInfoEntity = session.find(NodeInfoEntity::class.java, it)
|
|
||||||
session.merge(nodeInfoEntity.copy(networkMap = networkMapEntity))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getNetworkParameters(parameterHash: SecureHash): NetworkParameters {
|
|
||||||
val entity = getNetworkParametersEntity(parameterHash.toString())
|
|
||||||
if (entity != null) {
|
|
||||||
return entity.networkParameters()
|
|
||||||
} else {
|
|
||||||
throw NoSuchElementException("Network parameters with $parameterHash do not exist")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCurrentNetworkMapNodeInfoHashes(certificateStatuses: List<CertificateStatus>): List<SecureHash> = database.transaction {
|
override fun getNetworkParameters(parameterHash: SecureHash): NetworkParameters? {
|
||||||
val networkMapEntity = getCurrentNetworkMapEntity(getNetworkMapWithNodeInfoAndCsrHint(session))
|
return getNetworkParametersEntity(parameterHash.toString())?.networkParameters()
|
||||||
if (networkMapEntity != null) {
|
|
||||||
networkMapEntity.nodeInfoList.filter({
|
|
||||||
certificateStatuses.isEmpty() || certificateStatuses.contains(it.certificateSigningRequest?.certificateData?.certificateStatus)
|
|
||||||
}).map { SecureHash.parse(it.nodeInfoHash) }
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun putNetworkParameters(networkParameters: NetworkParameters): SecureHash = database.transaction {
|
override fun getNodeInfoHashes(certificateStatus: CertificateStatus): List<SecureHash> = database.transaction {
|
||||||
|
val builder = session.criteriaBuilder
|
||||||
|
val query = builder.createQuery(String::class.java).run {
|
||||||
|
from(NodeInfoEntity::class.java).run {
|
||||||
|
select(get<String>(NodeInfoEntity::nodeInfoHash.name))
|
||||||
|
.where(builder.equal(get<CertificateSigningRequestEntity>(NodeInfoEntity::certificateSigningRequest.name)
|
||||||
|
.get<CertificateDataEntity>(CertificateSigningRequestEntity::certificateData.name)
|
||||||
|
.get<CertificateStatus>(CertificateDataEntity::certificateStatus.name), certificateStatus))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.createQuery(query).resultList.map { SecureHash.parse(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun saveNetworkParameters(networkParameters: NetworkParameters): SecureHash = database.transaction {
|
||||||
val bytes = networkParameters.serialize().bytes
|
val bytes = networkParameters.serialize().bytes
|
||||||
val hash = bytes.sha256()
|
val hash = bytes.sha256()
|
||||||
session.save(NetworkParametersEntity(
|
session.save(NetworkParametersEntity(
|
||||||
@ -94,29 +81,16 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence) : Netw
|
|||||||
session.createQuery(query).resultList.first()
|
session.createQuery(query).resultList.first()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDetachedAndValidNodeInfoHashes(): List<SecureHash> = database.transaction {
|
private fun getCurrentNetworkMapEntity(): NetworkMapEntity? = database.transaction {
|
||||||
val builder = session.criteriaBuilder
|
|
||||||
// Get signed NodeInfoEntities
|
|
||||||
val query = builder.createQuery(NodeInfoEntity::class.java).run {
|
|
||||||
from(NodeInfoEntity::class.java).run {
|
|
||||||
where(builder.and(
|
|
||||||
builder.isNull(get<ByteArray>(NodeInfoEntity::networkMap.name)),
|
|
||||||
builder.isNotNull(get<ByteArray>(NodeInfoEntity::signatureBytes.name))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
session.createQuery(query).resultList.map { SecureHash.parse(it.nodeInfoHash) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCurrentNetworkMapEntity(hint: Pair<String, Any>): NetworkMapEntity? = database.transaction {
|
|
||||||
val builder = session.criteriaBuilder
|
val builder = session.criteriaBuilder
|
||||||
val query = builder.createQuery(NetworkMapEntity::class.java).run {
|
val query = builder.createQuery(NetworkMapEntity::class.java).run {
|
||||||
from(NetworkMapEntity::class.java).run {
|
from(NetworkMapEntity::class.java).run {
|
||||||
where(builder.isNotNull(get<ByteArray?>(NetworkMapEntity::signatureBytes.name)))
|
where(builder.isNotNull(get<ByteArray?>(NetworkMapEntity::signature.name)))
|
||||||
orderBy(builder.desc(get<String>(NetworkMapEntity::version.name)))
|
orderBy(builder.desc(get<String>(NetworkMapEntity::version.name)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We just want the last signed entry
|
// We just want the last signed entry
|
||||||
session.createQuery(query).setHint(hint.first, hint.second).resultList.firstOrNull()
|
session.createQuery(query).resultList.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getNetworkParametersEntity(parameterHash: String): NetworkParametersEntity? = database.transaction {
|
private fun getNetworkParametersEntity(parameterHash: String): NetworkParametersEntity? = database.transaction {
|
||||||
@ -124,33 +98,4 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence) : Netw
|
|||||||
builder.equal(path.get<String>(NetworkParametersEntity::parametersHash.name), parameterHash)
|
builder.equal(path.get<String>(NetworkParametersEntity::parametersHash.name), parameterHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates Hibernate query hint for pulling [NetworkParametersEntity] when querying for [NetworkMapEntity]
|
|
||||||
*/
|
|
||||||
private fun getNetworkMapWithParametersHint(session: Session): Pair<String, Any> {
|
|
||||||
val graph = session.createEntityGraph(NetworkMapEntity::class.java)
|
|
||||||
graph.addAttributeNodes(NetworkMapEntity::parameters.name)
|
|
||||||
return QueryHints.HINT_LOADGRAPH to graph
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates Hibernate query hint for pulling [NodeInfoEntity] and [CertificateSigningRequestEntity] when querying for [NetworkMapEntity]
|
|
||||||
*/
|
|
||||||
private fun getNetworkMapWithNodeInfoAndCsrHint(session: Session): Pair<String, Any> {
|
|
||||||
val graph = session.createEntityGraph(NetworkMapEntity::class.java)
|
|
||||||
val subGraph = graph.addSubgraph(NetworkMapEntity::nodeInfoList.name, NodeInfoEntity::class.java)
|
|
||||||
subGraph.addAttributeNodes(NodeInfoEntity::certificateSigningRequest.name)
|
|
||||||
return QueryHints.HINT_LOADGRAPH to graph
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates Hibernate query hint for pulling [NodeInfoEntity] and [NetworkParametersEntity] when querying for [NetworkMapEntity]
|
|
||||||
*/
|
|
||||||
private fun getNetworkMapWithNodeInfoAndParametersHint(session: Session): Pair<String, Any> {
|
|
||||||
val graph = session.createEntityGraph(NetworkMapEntity::class.java)
|
|
||||||
graph.addAttributeNodes(NetworkMapEntity::nodeInfoList.name)
|
|
||||||
graph.addAttributeNodes(NetworkMapEntity::parameters.name)
|
|
||||||
return QueryHints.HINT_LOADGRAPH to graph
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,8 +1,7 @@
|
|||||||
package com.r3.corda.networkmanage.common.persistence.entity
|
package com.r3.corda.networkmanage.common.persistence.entity
|
||||||
|
|
||||||
import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
|
import net.corda.nodeapi.internal.DigitalSignatureWithCert
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import javax.persistence.*
|
import javax.persistence.*
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@ -12,27 +11,23 @@ class NetworkMapEntity(
|
|||||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
val version: Long? = null,
|
val version: Long? = null,
|
||||||
|
|
||||||
// Reverting relation ownership due to (potentially) unlimited number of node info items.
|
@Lob
|
||||||
@OneToMany(mappedBy = "networkMap", fetch = FetchType.LAZY)
|
@Column(name = "serialized_network_map")
|
||||||
val nodeInfoList: List<NodeInfoEntity> = mutableListOf(),
|
val networkMap: ByteArray,
|
||||||
|
|
||||||
@OneToOne
|
|
||||||
@JoinColumn(name = "network_parameters")
|
|
||||||
val parameters: NetworkParametersEntity,
|
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(name = "signature_bytes")
|
@Column(name = "signature")
|
||||||
val signatureBytes: ByteArray,
|
val signature: ByteArray,
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(name = "certificate_path_bytes")
|
@Column(name = "certificate")
|
||||||
val certificatePathBytes: ByteArray
|
val certificate: ByteArray
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Deserializes NetworkMapEntity.signatureBytes into the [SignatureAndCertPath] instance
|
* Deserializes NetworkMapEntity.signatureBytes into the [SignatureAndCertPath] instance
|
||||||
*/
|
*/
|
||||||
fun signatureAndCertificate(): SignatureAndCertPath? {
|
fun signatureAndCertificate(): DigitalSignatureWithCert {
|
||||||
return SignatureAndCertPath(DigitalSignature(signatureBytes), certificatePathBytes.deserialize())
|
return DigitalSignatureWithCert(X509CertificateFactory().generateCertificate(certificate.inputStream()), signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,10 +18,6 @@ class NodeInfoEntity(
|
|||||||
@JoinColumn(name = "certificate_signing_request", nullable = true)
|
@JoinColumn(name = "certificate_signing_request", nullable = true)
|
||||||
val certificateSigningRequest: CertificateSigningRequestEntity? = null,
|
val certificateSigningRequest: CertificateSigningRequestEntity? = null,
|
||||||
|
|
||||||
@OneToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "network_map", nullable = true)
|
|
||||||
val networkMap: NetworkMapEntity? = null,
|
|
||||||
|
|
||||||
@Lob
|
@Lob
|
||||||
@Column(name = "node_info_bytes")
|
@Column(name = "node_info_bytes")
|
||||||
val nodeInfoBytes: ByteArray,
|
val nodeInfoBytes: ByteArray,
|
||||||
@ -55,7 +51,6 @@ class NodeInfoEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun copy(nodeInfoHash: String = this.nodeInfoHash,
|
fun copy(nodeInfoHash: String = this.nodeInfoHash,
|
||||||
networkMap: NetworkMapEntity? = this.networkMap,
|
|
||||||
certificateSigningRequest: CertificateSigningRequestEntity? = this.certificateSigningRequest,
|
certificateSigningRequest: CertificateSigningRequestEntity? = this.certificateSigningRequest,
|
||||||
nodeInfoBytes: ByteArray = this.nodeInfoBytes,
|
nodeInfoBytes: ByteArray = this.nodeInfoBytes,
|
||||||
signatureBytes: ByteArray? = this.signatureBytes,
|
signatureBytes: ByteArray? = this.signatureBytes,
|
||||||
@ -68,8 +63,7 @@ class NodeInfoEntity(
|
|||||||
nodeInfoBytes = nodeInfoBytes,
|
nodeInfoBytes = nodeInfoBytes,
|
||||||
signatureBytes = signatureBytes,
|
signatureBytes = signatureBytes,
|
||||||
signaturePublicKeyBytes = signaturePublicKeyBytes,
|
signaturePublicKeyBytes = signaturePublicKeyBytes,
|
||||||
signaturePublicKeyAlgorithm = signaturePublicKeyAlgorithm,
|
signaturePublicKeyAlgorithm = signaturePublicKeyAlgorithm
|
||||||
networkMap = networkMap
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,43 +2,22 @@ package com.r3.corda.networkmanage.common.signer
|
|||||||
|
|
||||||
import com.r3.corda.networkmanage.common.persistence.CertificateStatus
|
import com.r3.corda.networkmanage.common.persistence.CertificateStatus
|
||||||
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
||||||
import net.corda.core.serialization.CordaSerializable
|
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.nodeapi.internal.NetworkMap
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
|
|
||||||
/**
|
class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage, private val signer: Signer) {
|
||||||
* Encapsulates the network map signing procedure.
|
|
||||||
* To sign a network map following steps need to be done:
|
|
||||||
* 1) Collect all node info data that has been signed and has valid certificates
|
|
||||||
* 2) Retrieve most up-to-date network parameters
|
|
||||||
* 3) Sign hashed version of the network map
|
|
||||||
* 4) Persist network map data together with its signature
|
|
||||||
* Once the network map is signed it is considered to be the current network map.
|
|
||||||
*
|
|
||||||
* This class resides in the common package as it is intended to be used in both local and distributed deployments.
|
|
||||||
* This means that it can be executed by a remote (e.g. HSM) signing service or locally by Doorman.
|
|
||||||
*/
|
|
||||||
@CordaSerializable
|
|
||||||
data class NetworkMap(val nodeInfoHashes: List<String>, val parametersHash: String)
|
|
||||||
|
|
||||||
@CordaSerializable
|
|
||||||
data class SignedNetworkMap(val networkMap: NetworkMap, val signatureData: SignatureAndCertPath)
|
|
||||||
|
|
||||||
class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage,
|
|
||||||
private val signer: Signer) {
|
|
||||||
/**
|
/**
|
||||||
* Signs the network map.
|
* Signs the network map.
|
||||||
*/
|
*/
|
||||||
fun signNetworkMap() {
|
fun signNetworkMap() {
|
||||||
val currentSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
val currentSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
||||||
val currentNetworkMapValidNodeInfo = networkMapStorage.getCurrentNetworkMapNodeInfoHashes(listOf(CertificateStatus.VALID))
|
val nodeInfoHashes = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
|
||||||
val detachedValidNodeInfo = networkMapStorage.getDetachedAndValidNodeInfoHashes()
|
|
||||||
val nodeInfoHashes = currentNetworkMapValidNodeInfo + detachedValidNodeInfo
|
|
||||||
val networkParameters = networkMapStorage.getLatestNetworkParameters()
|
val networkParameters = networkMapStorage.getLatestNetworkParameters()
|
||||||
val networkMap = NetworkMap(nodeInfoHashes.map { it.toString() }, networkParameters.serialize().hash.toString())
|
val networkMap = NetworkMap(nodeInfoHashes, networkParameters.serialize().hash)
|
||||||
if (networkMap != currentSignedNetworkMap?.networkMap) {
|
if (networkMap != currentSignedNetworkMap?.verified()) {
|
||||||
val digitalSignature = signer.sign(networkMap.serialize().bytes)
|
val digitalSignature = signer.sign(networkMap.serialize().bytes)
|
||||||
require(digitalSignature != null) { "Error while signing network map." }
|
val signedHashedNetworkMap = SignedNetworkMap(networkMap.serialize(), digitalSignature)
|
||||||
val signedHashedNetworkMap = SignedNetworkMap(networkMap, digitalSignature!!)
|
|
||||||
networkMapStorage.saveNetworkMap(signedHashedNetworkMap)
|
networkMapStorage.saveNetworkMap(signedHashedNetworkMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,19 +2,19 @@ package com.r3.corda.networkmanage.common.signer
|
|||||||
|
|
||||||
import net.corda.core.crypto.DigitalSignature
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.nodeapi.internal.DigitalSignatureWithCert
|
||||||
import java.security.cert.CertPath
|
import java.security.cert.CertPath
|
||||||
|
|
||||||
@CordaSerializable
|
|
||||||
data class SignatureAndCertPath(val signature: DigitalSignature, val certPath: CertPath)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface for arbitrary data signing functionality.
|
* An interface for arbitrary data signing functionality.
|
||||||
*/
|
*/
|
||||||
interface Signer {
|
interface Signer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs given [data]. The signing key selction strategy is left to the implementing class.
|
* Signs given [data]. The signing key selction strategy is left to the implementing class.
|
||||||
* @return [SignatureAndCertPath] that encapsulates the signature and the certificate path used in the signing process.
|
* @return [SignatureAndCertPath] that encapsulates the signature and the certificate path used in the signing process.
|
||||||
|
* @throws [AuthenticationException] if fails authentication
|
||||||
*/
|
*/
|
||||||
fun sign(data: ByteArray): SignatureAndCertPath?
|
fun sign(data: ByteArray): DigitalSignatureWithCert
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AuthenticationException : Exception()
|
||||||
|
@ -4,7 +4,9 @@ import com.typesafe.config.Config
|
|||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import joptsimple.ArgumentAcceptingOptionSpec
|
import joptsimple.ArgumentAcceptingOptionSpec
|
||||||
import joptsimple.OptionParser
|
import joptsimple.OptionParser
|
||||||
|
import net.corda.core.crypto.DigitalSignature
|
||||||
import net.corda.core.crypto.sha256
|
import net.corda.core.crypto.sha256
|
||||||
|
import net.corda.nodeapi.internal.DigitalSignatureWithCert
|
||||||
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -41,3 +43,5 @@ fun X509CertificateHolder.toX509Certificate(): X509Certificate = X509Certificate
|
|||||||
fun buildCertPath(vararg certificates: Certificate): CertPath = X509CertificateFactory().delegate.generateCertPath(certificates.asList())
|
fun buildCertPath(vararg certificates: Certificate): CertPath = X509CertificateFactory().delegate.generateCertPath(certificates.asList())
|
||||||
|
|
||||||
fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream())
|
fun buildCertPath(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream())
|
||||||
|
|
||||||
|
fun DigitalSignature.WithKey.withCert(cert: X509Certificate): DigitalSignatureWithCert = DigitalSignatureWithCert(cert, bytes)
|
@ -11,7 +11,6 @@ import com.r3.corda.networkmanage.doorman.signer.JiraCsrHandler
|
|||||||
import com.r3.corda.networkmanage.doorman.signer.LocalSigner
|
import com.r3.corda.networkmanage.doorman.signer.LocalSigner
|
||||||
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
|
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
|
||||||
import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService
|
import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService
|
||||||
import com.typesafe.config.ConfigFactory
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
@ -32,6 +31,7 @@ import java.io.Closeable
|
|||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import java.security.cert.X509Certificate
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -190,7 +190,7 @@ fun startDoorman(hostAndPort: NetworkHostAndPort,
|
|||||||
// Persisting new network parameters
|
// Persisting new network parameters
|
||||||
val currentNetworkParameters = networkMapStorage.getCurrentNetworkParameters()
|
val currentNetworkParameters = networkMapStorage.getCurrentNetworkParameters()
|
||||||
if (currentNetworkParameters == null) {
|
if (currentNetworkParameters == null) {
|
||||||
networkMapStorage.putNetworkParameters(networkMapParameters)
|
networkMapStorage.saveNetworkParameters(networkMapParameters)
|
||||||
} else {
|
} else {
|
||||||
throw UnsupportedOperationException("Network parameters already exist. Updating them via the file config is not supported yet.")
|
throw UnsupportedOperationException("Network parameters already exist. Updating them via the file config is not supported yet.")
|
||||||
}
|
}
|
||||||
@ -242,8 +242,8 @@ private fun buildLocalSigner(parameters: DoormanParameters): LocalSigner? {
|
|||||||
val caPrivateKeyPassword = parameters.caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
val caPrivateKeyPassword = parameters.caPrivateKeyPassword ?: readPassword("CA Private Key Password: ")
|
||||||
val keystore = loadOrCreateKeyStore(parameters.keystorePath, keystorePassword)
|
val keystore = loadOrCreateKeyStore(parameters.keystorePath, keystorePassword)
|
||||||
val caKeyPair = keystore.getKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caPrivateKeyPassword)
|
val caKeyPair = keystore.getKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caPrivateKeyPassword)
|
||||||
val caCertPath = keystore.getCertificateChain(X509Utilities.CORDA_INTERMEDIATE_CA)
|
val caCertPath = keystore.getCertificateChain(X509Utilities.CORDA_INTERMEDIATE_CA).map { it as X509Certificate }
|
||||||
LocalSigner(caKeyPair, caCertPath)
|
LocalSigner(caKeyPair, caCertPath.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class JiraCsrHandler(private val jiraClient: JiraClient, private val storage: Ce
|
|||||||
jiraClient.getApprovedRequests().forEach { (id, approvedBy) -> storage.approveRequest(id, approvedBy) }
|
jiraClient.getApprovedRequests().forEach { (id, approvedBy) -> storage.approveRequest(id, approvedBy) }
|
||||||
delegate.processApprovedRequests()
|
delegate.processApprovedRequests()
|
||||||
val signedRequests = storage.getRequests(RequestStatus.SIGNED).mapNotNull {
|
val signedRequests = storage.getRequests(RequestStatus.SIGNED).mapNotNull {
|
||||||
it.certData?.certPath.let { certs -> it.requestId to certs!! }
|
it.certData?.certPath?.let { certs -> it.requestId to certs }
|
||||||
}.toMap()
|
}.toMap()
|
||||||
jiraClient.updateSignedRequests(signedRequests)
|
jiraClient.updateSignedRequests(signedRequests)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package com.r3.corda.networkmanage.doorman.signer
|
package com.r3.corda.networkmanage.doorman.signer
|
||||||
|
|
||||||
import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
|
|
||||||
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.toX509Certificate
|
||||||
|
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.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
|
import net.corda.nodeapi.internal.DigitalSignatureWithCert
|
||||||
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
|
||||||
import org.bouncycastle.asn1.x509.GeneralName
|
import org.bouncycastle.asn1.x509.GeneralName
|
||||||
@ -16,13 +17,13 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
|||||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.cert.CertPath
|
import java.security.cert.CertPath
|
||||||
import java.security.cert.Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [LocalSigner] class signs [PKCS10CertificationRequest] using provided CA key pair and certificate path.
|
* The [LocalSigner] class signs [PKCS10CertificationRequest] using provided CA key pair and certificate path.
|
||||||
* This is intended to be used in testing environment where hardware signing module is not available.
|
* This is intended to be used in testing environment where hardware signing module is not available.
|
||||||
*/
|
*/
|
||||||
class LocalSigner(private val caKeyPair: KeyPair, private val caCertPath: Array<Certificate>) : Signer {
|
class LocalSigner(private val caKeyPair: KeyPair, private val caCertPath: Array<X509Certificate>) : Signer {
|
||||||
fun createSignedClientCertificate(certificationRequest: PKCS10CertificationRequest): CertPath {
|
fun createSignedClientCertificate(certificationRequest: PKCS10CertificationRequest): CertPath {
|
||||||
// The sub certs issued by the client must satisfy this directory name (or legal name in Corda) constraints, sub certs' directory name must be within client CA's name's subtree,
|
// The sub certs issued by the client must satisfy this directory name (or legal name in Corda) constraints, sub certs' directory name must be within client CA's name's subtree,
|
||||||
// please see [sun.security.x509.X500Name.isWithinSubtree()] for more information.
|
// please see [sun.security.x509.X500Name.isWithinSubtree()] for more information.
|
||||||
@ -41,7 +42,7 @@ class LocalSigner(private val caKeyPair: KeyPair, private val caCertPath: Array<
|
|||||||
return buildCertPath(clientCertificate, *caCertPath)
|
return buildCertPath(clientCertificate, *caCertPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sign(data: ByteArray): SignatureAndCertPath {
|
override fun sign(data: ByteArray): DigitalSignatureWithCert {
|
||||||
return SignatureAndCertPath(caKeyPair.sign(data), buildCertPath(*caCertPath))
|
return caKeyPair.sign(data).withCert(caCertPath.first())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("{nodeInfoHash}")
|
@Path("node-info/{nodeInfoHash}")
|
||||||
fun getNodeInfo(@PathParam("nodeInfoHash") nodeInfoHash: String): Response {
|
fun getNodeInfo(@PathParam("nodeInfoHash") nodeInfoHash: String): Response {
|
||||||
val nodeInfo = nodeInfoStorage.getNodeInfo(SecureHash.parse(nodeInfoHash))
|
val nodeInfo = nodeInfoStorage.getNodeInfo(SecureHash.parse(nodeInfoHash))
|
||||||
return if (nodeInfo != null) {
|
return if (nodeInfo != null) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.r3.corda.networkmanage.hsm.authentication
|
package com.r3.corda.networkmanage.hsm.authentication
|
||||||
|
|
||||||
import CryptoServerJCE.CryptoServerProvider
|
import CryptoServerJCE.CryptoServerProvider
|
||||||
|
import com.r3.corda.networkmanage.common.signer.AuthenticationException
|
||||||
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
import com.r3.corda.networkmanage.hsm.configuration.Parameters
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
@ -25,8 +26,8 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
* 1) [CryptoServerProvider] instance
|
* 1) [CryptoServerProvider] instance
|
||||||
* 2) List of strings that corresponds to user names authenticated against the HSM.
|
* 2) List of strings that corresponds to user names authenticated against the HSM.
|
||||||
*/
|
*/
|
||||||
fun connectAndAuthenticate(block: (CryptoServerProvider, List<String>) -> Unit) {
|
fun <T : Any> connectAndAuthenticate(block: (CryptoServerProvider, List<String>) -> T): T {
|
||||||
try {
|
return try {
|
||||||
val authenticated = mutableListOf<String>()
|
val authenticated = mutableListOf<String>()
|
||||||
loop@ while (true) {
|
loop@ while (true) {
|
||||||
val user = if (autoUsername.isNullOrEmpty()) {
|
val user = if (autoUsername.isNullOrEmpty()) {
|
||||||
@ -78,6 +79,8 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
}
|
}
|
||||||
if (!authenticated.isEmpty()) {
|
if (!authenticated.isEmpty()) {
|
||||||
block(provider, authenticated)
|
block(provider, authenticated)
|
||||||
|
} else {
|
||||||
|
throw AuthenticationException()
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
@ -89,8 +92,8 @@ class Authenticator(private val provider: CryptoServerProvider,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
* Configuration class for [CryptoServerProvider]
|
* Configuration class for [CryptoServerProvider]
|
||||||
*/
|
*/
|
||||||
data class CryptoServerProviderConfig(
|
data class CryptoServerProviderConfig(
|
||||||
|
@ -3,15 +3,17 @@ package com.r3.corda.networkmanage.hsm.signer
|
|||||||
import com.google.common.util.concurrent.MoreExecutors
|
import com.google.common.util.concurrent.MoreExecutors
|
||||||
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
||||||
import com.r3.corda.networkmanage.common.signer.NetworkMapSigner
|
import com.r3.corda.networkmanage.common.signer.NetworkMapSigner
|
||||||
import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
|
|
||||||
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.withCert
|
||||||
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
import com.r3.corda.networkmanage.hsm.authentication.Authenticator
|
||||||
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.getAndInitializeKeyStore
|
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.getAndInitializeKeyStore
|
||||||
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.signData
|
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.signData
|
||||||
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.verify
|
import com.r3.corda.networkmanage.hsm.utils.X509Utilities.verify
|
||||||
|
import net.corda.core.internal.cert
|
||||||
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.minutes
|
import net.corda.core.utilities.minutes
|
||||||
|
import net.corda.nodeapi.internal.DigitalSignatureWithCert
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
@ -59,16 +61,14 @@ class HsmNetworkMapSigner(networkMapStorage: NetworkMapStorage,
|
|||||||
/**
|
/**
|
||||||
* Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM.
|
* Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM.
|
||||||
*/
|
*/
|
||||||
override fun sign(data: ByteArray): SignatureAndCertPath? {
|
override fun sign(data: ByteArray): DigitalSignatureWithCert {
|
||||||
var result: SignatureAndCertPath? = null
|
return authenticator.connectAndAuthenticate { provider, _ ->
|
||||||
authenticator.connectAndAuthenticate { provider, _ ->
|
|
||||||
val keyStore = getAndInitializeKeyStore(provider)
|
val keyStore = getAndInitializeKeyStore(provider)
|
||||||
val caCertificateChain = keyStore.getCertificateChain(caCertificateKeyName)
|
val caCertificateChain = keyStore.getCertificateChain(caCertificateKeyName)
|
||||||
val caKey = keyStore.getKey(caCertificateKeyName, caPrivateKeyPass.toCharArray()) as PrivateKey
|
val caKey = keyStore.getKey(caCertificateKeyName, caPrivateKeyPass.toCharArray()) as PrivateKey
|
||||||
val signature = signData(data, KeyPair(caCertificateChain.first().publicKey, caKey), provider)
|
val signature = signData(data, KeyPair(caCertificateChain.first().publicKey, caKey), provider)
|
||||||
verify(data, signature, caCertificateChain.first().publicKey)
|
verify(data, signature, caCertificateChain.first().publicKey)
|
||||||
result = SignatureAndCertPath(signature, buildCertPath(*caCertificateChain))
|
signature.withCert(caCertificateChain.first().toX509CertHolder().cert)
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,6 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
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
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
import org.bouncycastle.pkcs.PKCS10CertificationRequest
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
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.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.buildCertPath
|
||||||
import com.r3.corda.networkmanage.common.utils.toX509Certificate
|
import com.r3.corda.networkmanage.common.utils.toX509Certificate
|
||||||
|
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.SignedData
|
import net.corda.core.crypto.SignedData
|
||||||
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.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.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.nodeapi.internal.NetworkMap
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
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
|
||||||
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
import net.corda.nodeapi.internal.persistence.DatabaseConfig
|
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
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.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class DBNetworkMapStorageTest : TestBase() {
|
class DBNetworkMapStorageTest : TestBase() {
|
||||||
private lateinit var networkMapStorage: NetworkMapStorage
|
private lateinit var networkMapStorage: NetworkMapStorage
|
||||||
@ -57,7 +57,7 @@ class DBNetworkMapStorageTest : TestBase() {
|
|||||||
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 keyPair = Crypto.generateKeyPair()
|
||||||
val clientCert = X509Utilities.createCertificate(CertificateType.CLIENT_CA, intermediateCACert, intermediateCAKey, CordaX500Name(organisation = organisation, locality = "London", country = "GB"), keyPair.public)
|
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())
|
val certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
|
||||||
requestStorage.putCertificatePath(requestId, certPath, emptyList())
|
requestStorage.putCertificatePath(requestId, certPath, emptyList())
|
||||||
@ -67,25 +67,28 @@ class DBNetworkMapStorageTest : TestBase() {
|
|||||||
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBytes, keyPair.sign(nodeInfoBytes)))
|
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBytes, keyPair.sign(nodeInfoBytes)))
|
||||||
|
|
||||||
// Create network parameters
|
// Create network parameters
|
||||||
val networkParametersHash = networkMapStorage.putNetworkParameters(testNetworkParameters(emptyList()))
|
val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
|
||||||
|
|
||||||
val networkMap = NetworkMap(listOf(nodeInfoHash.toString()), networkParametersHash.toString())
|
val networkMap = NetworkMap(listOf(nodeInfoHash), networkParametersHash)
|
||||||
val signatureData = SignatureAndCertPath(keyPair.sign(networkMap.serialize()), certPath)
|
val serializedNetworkMap = networkMap.serialize()
|
||||||
val signedNetworkMap = SignedNetworkMap(NetworkMap(listOf(nodeInfoHash.toString()), networkParametersHash.toString()), signatureData)
|
val signatureData = intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)
|
||||||
|
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
|
||||||
assertEquals(signedNetworkMap, persistedSignedNetworkMap)
|
|
||||||
|
assertEquals(signedNetworkMap.sig, persistedSignedNetworkMap?.sig)
|
||||||
|
assertEquals(signedNetworkMap.verified(), persistedSignedNetworkMap?.verified())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getLatestNetworkParameters returns last inserted`() {
|
fun `getLatestNetworkParameters returns last inserted`() {
|
||||||
// given
|
// given
|
||||||
networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 1))
|
networkMapStorage.saveNetworkParameters(createNetworkParameters(minimumPlatformVersion = 1))
|
||||||
networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 2))
|
networkMapStorage.saveNetworkParameters(createNetworkParameters(minimumPlatformVersion = 2))
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val latest = networkMapStorage.getLatestNetworkParameters()
|
val latest = networkMapStorage.getLatestNetworkParameters()
|
||||||
@ -98,20 +101,20 @@ class DBNetworkMapStorageTest : TestBase() {
|
|||||||
fun `getCurrentNetworkParameters returns current network map parameters`() {
|
fun `getCurrentNetworkParameters returns current network map parameters`() {
|
||||||
// given
|
// given
|
||||||
// Create network parameters
|
// Create network parameters
|
||||||
val networkMapParametersHash = networkMapStorage.putNetworkParameters(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 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 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
|
// Sign network map making it current network map
|
||||||
val hashedNetworkMap = NetworkMap(emptyList(), networkMapParametersHash.toString())
|
val networkMap = NetworkMap(emptyList(), networkMapParametersHash)
|
||||||
val signatureData = SignatureAndCertPath(keyPair.sign(hashedNetworkMap.serialize()), certPath)
|
val serializedNetworkMap = networkMap.serialize()
|
||||||
val signedNetworkMap = SignedNetworkMap(hashedNetworkMap, signatureData)
|
val signatureData = keyPair.sign(serializedNetworkMap).withCert(intermediateCert.cert)
|
||||||
|
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
|
||||||
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
||||||
|
|
||||||
// Create new network parameters
|
// Create new network parameters
|
||||||
networkMapStorage.putNetworkParameters(createNetworkParameters(2))
|
networkMapStorage.saveNetworkParameters(createNetworkParameters(2))
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val result = networkMapStorage.getCurrentNetworkParameters()
|
val result = networkMapStorage.getCurrentNetworkParameters()
|
||||||
@ -121,7 +124,7 @@ class DBNetworkMapStorageTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `getDetachedAndValidNodeInfoHashes 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 info.
|
||||||
val organisationA = "TestA"
|
val organisationA = "TestA"
|
||||||
@ -148,19 +151,19 @@ class DBNetworkMapStorageTest : TestBase() {
|
|||||||
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBBytes, keyPair.sign(nodeInfoBBytes)))
|
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBBytes, keyPair.sign(nodeInfoBBytes)))
|
||||||
|
|
||||||
// Create network parameters
|
// Create network parameters
|
||||||
val networkParametersHash = networkMapStorage.putNetworkParameters(createNetworkParameters())
|
val networkParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters())
|
||||||
val networkMap = NetworkMap(listOf(nodeInfoHashA.toString()), networkParametersHash.toString())
|
val networkMap = NetworkMap(listOf(nodeInfoHashA), networkParametersHash)
|
||||||
val signatureData = SignatureAndCertPath(keyPair.sign(networkMap.serialize()), certPathA)
|
val serializedNetworkMap = networkMap.serialize()
|
||||||
val signedNetworkMap = SignedNetworkMap(networkMap, signatureData)
|
val signatureData = keyPair.sign(serializedNetworkMap).withCert(clientCertA.cert)
|
||||||
|
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
|
||||||
|
|
||||||
// Sign network map
|
// Sign network map
|
||||||
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
networkMapStorage.saveNetworkMap(signedNetworkMap)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val detachedHashes = networkMapStorage.getDetachedAndValidNodeInfoHashes()
|
val validNodeInfoHash = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertEquals(1, detachedHashes.size)
|
assertThat(validNodeInfoHash).containsOnly(nodeInfoHashA, nodeInfoHashB)
|
||||||
assertTrue(detachedHashes.contains(nodeInfoHashB))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,9 +3,18 @@ package com.r3.corda.networkmanage.common.signer
|
|||||||
import com.nhaarman.mockito_kotlin.*
|
import com.nhaarman.mockito_kotlin.*
|
||||||
import com.r3.corda.networkmanage.TestBase
|
import com.r3.corda.networkmanage.TestBase
|
||||||
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
|
||||||
|
import com.r3.corda.networkmanage.common.utils.withCert
|
||||||
|
import net.corda.core.crypto.Crypto
|
||||||
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.crypto.sign
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.cert
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.nodeapi.internal.NetworkMap
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
|
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -15,7 +24,10 @@ class NetworkMapSignerTest : TestBase() {
|
|||||||
private lateinit var signer: Signer
|
private lateinit var signer: Signer
|
||||||
private lateinit var networkMapStorage: NetworkMapStorage
|
private lateinit var networkMapStorage: NetworkMapStorage
|
||||||
private lateinit var networkMapSigner: NetworkMapSigner
|
private lateinit var networkMapSigner: NetworkMapSigner
|
||||||
|
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
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
signer = mock()
|
signer = mock()
|
||||||
@ -27,30 +39,29 @@ class NetworkMapSignerTest : TestBase() {
|
|||||||
fun `signNetworkMap builds and signs network map`() {
|
fun `signNetworkMap builds and signs network map`() {
|
||||||
// given
|
// given
|
||||||
val signedNodeInfoHashes = listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256())
|
val signedNodeInfoHashes = listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256())
|
||||||
val detachedNodeInfoHashes = listOf(SecureHash.randomSHA256())
|
|
||||||
val networkMapParameters = createNetworkParameters()
|
val networkMapParameters = createNetworkParameters()
|
||||||
|
val serializedNetworkMap = NetworkMap(signedNodeInfoHashes, SecureHash.randomSHA256()).serialize()
|
||||||
whenever(networkMapStorage.getCurrentNetworkMap())
|
whenever(networkMapStorage.getCurrentNetworkMap())
|
||||||
.thenReturn(SignedNetworkMap(NetworkMap(signedNodeInfoHashes.map { it.toString() }, "Dummy"), mock()))
|
.thenReturn(SignedNetworkMap(serializedNetworkMap, intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)))
|
||||||
whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
|
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
|
||||||
whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(detachedNodeInfoHashes)
|
|
||||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
||||||
whenever(signer.sign(any())).thenReturn(mock())
|
whenever(signer.sign(any())).then {
|
||||||
|
intermediateCAKey.sign(it.arguments.first() as ByteArray).withCert(intermediateCACert.cert)
|
||||||
|
}
|
||||||
|
|
||||||
// when
|
// when
|
||||||
networkMapSigner.signNetworkMap()
|
networkMapSigner.signNetworkMap()
|
||||||
|
|
||||||
// then
|
// then
|
||||||
// Verify networkMapStorage calls
|
// Verify networkMapStorage calls
|
||||||
verify(networkMapStorage).getCurrentNetworkMapNodeInfoHashes(any())
|
verify(networkMapStorage).getNodeInfoHashes(any())
|
||||||
verify(networkMapStorage).getDetachedAndValidNodeInfoHashes()
|
|
||||||
verify(networkMapStorage).getLatestNetworkParameters()
|
verify(networkMapStorage).getLatestNetworkParameters()
|
||||||
argumentCaptor<SignedNetworkMap>().apply {
|
argumentCaptor<SignedNetworkMap>().apply {
|
||||||
verify(networkMapStorage).saveNetworkMap(capture())
|
verify(networkMapStorage).saveNetworkMap(capture())
|
||||||
val networkMap = firstValue.networkMap
|
val networkMap = firstValue.verified()
|
||||||
assertEquals(networkMapParameters.serialize().hash.toString(), networkMap.parametersHash)
|
assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
|
||||||
assertEquals(signedNodeInfoHashes.size + detachedNodeInfoHashes.size, networkMap.nodeInfoHashes.size)
|
assertEquals(signedNodeInfoHashes.size, networkMap.nodeInfoHashes.size)
|
||||||
assertTrue(networkMap.nodeInfoHashes.containsAll(signedNodeInfoHashes.map { it.toString() }))
|
assertTrue(networkMap.nodeInfoHashes.containsAll(signedNodeInfoHashes))
|
||||||
assertTrue(networkMap.nodeInfoHashes.containsAll(detachedNodeInfoHashes.map { it.toString() }))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,11 +70,11 @@ class NetworkMapSignerTest : TestBase() {
|
|||||||
// given
|
// given
|
||||||
val networkMapParameters = createNetworkParameters()
|
val networkMapParameters = createNetworkParameters()
|
||||||
val networkMapParametersHash = networkMapParameters.serialize().bytes.sha256()
|
val networkMapParametersHash = networkMapParameters.serialize().bytes.sha256()
|
||||||
val networkMap = NetworkMap(emptyList(), networkMapParametersHash.toString())
|
val networkMap = NetworkMap(emptyList(), networkMapParametersHash)
|
||||||
val signedNetworkMap = SignedNetworkMap(networkMap, mock())
|
val serializedNetworkMap = networkMap.serialize()
|
||||||
|
val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert))
|
||||||
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
|
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
|
||||||
whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(emptyList())
|
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
|
||||||
whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(emptyList())
|
|
||||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
||||||
|
|
||||||
// when
|
// when
|
||||||
@ -79,23 +90,22 @@ class NetworkMapSignerTest : TestBase() {
|
|||||||
// given
|
// given
|
||||||
val networkMapParameters = createNetworkParameters()
|
val networkMapParameters = createNetworkParameters()
|
||||||
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(null)
|
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(null)
|
||||||
whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(emptyList())
|
whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
|
||||||
whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(emptyList())
|
|
||||||
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
|
||||||
whenever(signer.sign(any())).thenReturn(mock())
|
whenever(signer.sign(any())).then {
|
||||||
|
intermediateCAKey.sign(it.arguments.first() as ByteArray).withCert(intermediateCACert.cert)
|
||||||
|
}
|
||||||
// when
|
// when
|
||||||
networkMapSigner.signNetworkMap()
|
networkMapSigner.signNetworkMap()
|
||||||
|
|
||||||
// then
|
// then
|
||||||
// Verify networkMapStorage calls
|
// Verify networkMapStorage calls
|
||||||
verify(networkMapStorage).getCurrentNetworkMapNodeInfoHashes(any())
|
verify(networkMapStorage).getNodeInfoHashes(any())
|
||||||
verify(networkMapStorage).getDetachedAndValidNodeInfoHashes()
|
|
||||||
verify(networkMapStorage).getLatestNetworkParameters()
|
verify(networkMapStorage).getLatestNetworkParameters()
|
||||||
argumentCaptor<SignedNetworkMap>().apply {
|
argumentCaptor<SignedNetworkMap>().apply {
|
||||||
verify(networkMapStorage).saveNetworkMap(capture())
|
verify(networkMapStorage).saveNetworkMap(capture())
|
||||||
val networkMap = firstValue.networkMap
|
val networkMap = firstValue.verified()
|
||||||
assertEquals(networkMapParameters.serialize().hash.toString(), networkMap.parametersHash)
|
assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,18 +6,20 @@ 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.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.buildCertPath
|
||||||
import com.r3.corda.networkmanage.common.utils.toX509Certificate
|
import com.r3.corda.networkmanage.common.utils.toX509Certificate
|
||||||
|
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.*
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
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.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
|
||||||
|
import net.corda.nodeapi.internal.NetworkMap
|
||||||
|
import net.corda.nodeapi.internal.SignedNetworkMap
|
||||||
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
|
||||||
import net.corda.testing.SerializationEnvironmentRule
|
import net.corda.testing.SerializationEnvironmentRule
|
||||||
@ -97,16 +99,17 @@ class NodeInfoWebServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get network map`() {
|
fun `get network map`() {
|
||||||
val hashedNetworkMap = NetworkMap(listOf(SecureHash.randomSHA256().toString(), SecureHash.randomSHA256().toString()), SecureHash.randomSHA256().toString())
|
val networkMap = NetworkMap(listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256()), SecureHash.randomSHA256())
|
||||||
|
val serializedNetworkMap = networkMap.serialize()
|
||||||
val networkMapStorage: NetworkMapStorage = mock {
|
val networkMapStorage: NetworkMapStorage = mock {
|
||||||
on { getCurrentNetworkMap() }.thenReturn(SignedNetworkMap(hashedNetworkMap, mock()))
|
on { getCurrentNetworkMap() }.thenReturn(SignedNetworkMap(serializedNetworkMap, intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)))
|
||||||
}
|
}
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage)).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage)).use {
|
||||||
it.start()
|
it.start()
|
||||||
val conn = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}").openConnection() as HttpURLConnection
|
val conn = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}").openConnection() as HttpURLConnection
|
||||||
val signedHashedNetworkMap = conn.inputStream.readBytes().deserialize<SignedNetworkMap>()
|
val signedNetworkMap = conn.inputStream.readBytes().deserialize<SignedNetworkMap>()
|
||||||
verify(networkMapStorage, times(1)).getCurrentNetworkMap()
|
verify(networkMapStorage, times(1)).getCurrentNetworkMap()
|
||||||
assertEquals(signedHashedNetworkMap.networkMap, hashedNetworkMap)
|
assertEquals(signedNetworkMap.verified(), networkMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +129,7 @@ class NodeInfoWebServiceTest {
|
|||||||
|
|
||||||
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock())).use {
|
DoormanServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(nodeInfoStorage, mock())).use {
|
||||||
it.start()
|
it.start()
|
||||||
val nodeInfoURL = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}/$nodeInfoHash")
|
val nodeInfoURL = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}/node-info/$nodeInfoHash")
|
||||||
val conn = nodeInfoURL.openConnection()
|
val conn = nodeInfoURL.openConnection()
|
||||||
val nodeInfoResponse = conn.inputStream.readBytes().deserialize<SignedData<NodeInfo>>()
|
val nodeInfoResponse = conn.inputStream.readBytes().deserialize<SignedData<NodeInfo>>()
|
||||||
verify(nodeInfoStorage, times(1)).getNodeInfo(nodeInfoHash)
|
verify(nodeInfoStorage, times(1)).getNodeInfo(nodeInfoHash)
|
||||||
|
@ -3,9 +3,10 @@ package com.r3.corda.networkmanage.hsm.authentication
|
|||||||
import CryptoServerJCE.CryptoServerProvider
|
import CryptoServerJCE.CryptoServerProvider
|
||||||
import com.nhaarman.mockito_kotlin.*
|
import com.nhaarman.mockito_kotlin.*
|
||||||
import com.r3.corda.networkmanage.TestBase
|
import com.r3.corda.networkmanage.TestBase
|
||||||
|
import com.r3.corda.networkmanage.common.signer.AuthenticationException
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFailsWith
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class AuthenticatorTest : TestBase() {
|
class AuthenticatorTest : TestBase() {
|
||||||
@ -24,15 +25,15 @@ class AuthenticatorTest : TestBase() {
|
|||||||
fun `connectAndAuthenticate aborts when user inputs Q`() {
|
fun `connectAndAuthenticate aborts when user inputs Q`() {
|
||||||
// given
|
// given
|
||||||
givenUserConsoleInputOnReadLine("Q")
|
givenUserConsoleInputOnReadLine("Q")
|
||||||
var executed = false
|
|
||||||
|
|
||||||
// when
|
// when
|
||||||
Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true }
|
assertFailsWith<AuthenticationException> {
|
||||||
|
Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> }
|
||||||
|
}
|
||||||
|
|
||||||
// then
|
//then
|
||||||
assertFalse(executed)
|
verify(provider, never()).loginPassword(any(), any<String>())
|
||||||
verify(provider, never()).loginPassword(any<String>(), any<String>())
|
verify(provider, never()).loginSign(any(), any(), any())
|
||||||
verify(provider, never()).loginSign(any<String>(), any<String>(), any<String>())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -50,7 +51,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider).loginPassword(username, password)
|
verify(provider).loginPassword(username, password)
|
||||||
verify(provider, never()).loginSign(any<String>(), any<String>(), any<String>())
|
verify(provider, never()).loginSign(any(), any(), any())
|
||||||
assertTrue(executed)
|
assertTrue(executed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider).loginSign(username, ":cs2:cyb:USB0", null)
|
verify(provider).loginSign(username, ":cs2:cyb:USB0", null)
|
||||||
verify(provider, never()).loginPassword(any<String>(), any<String>())
|
verify(provider, never()).loginPassword(any(), any<String>())
|
||||||
assertTrue(executed)
|
assertTrue(executed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
|
|
||||||
// then
|
// then
|
||||||
verify(provider, times(3)).loginPassword(username, password)
|
verify(provider, times(3)).loginPassword(username, password)
|
||||||
verify(provider, never()).loginSign(any<String>(), any<String>(), any<String>())
|
verify(provider, never()).loginSign(any(), any(), any())
|
||||||
assertTrue(executed)
|
assertTrue(executed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +99,7 @@ class AuthenticatorTest : TestBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun givenUserConsoleInputOnReadPassword(input: String) {
|
private fun givenUserConsoleInputOnReadPassword(input: String) {
|
||||||
whenever(inputReader.readPassword(any<String>())).thenReturn(input)
|
whenever(inputReader.readPassword(any())).thenReturn(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun givenUserConsoleInputOnReadLine(input: String) {
|
private fun givenUserConsoleInputOnReadLine(input: String) {
|
||||||
|
Loading…
Reference in New Issue
Block a user