diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index d72e565e78..198a957a38 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -15,6 +15,8 @@
+
+
@@ -172,4 +174,4 @@
-
+
\ No newline at end of file
diff --git a/network-management/build.gradle b/network-management/build.gradle
index b6bd4e5ac6..38512eca90 100644
--- a/network-management/build.gradle
+++ b/network-management/build.gradle
@@ -56,9 +56,7 @@ dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
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"
- testCompile "net.corda:corda-test-utils:$corda_dependency_version"
testCompile "net.corda:corda-node-driver:$corda_dependency_version"
testCompile "net.corda:corda-test-common:$corda_dependency_version"
diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt
index dbd2f66527..093b04fc38 100644
--- a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt
+++ b/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt
@@ -92,9 +92,7 @@ class DoormanIntegrationTest {
doorman.close()
}
- //TODO remove @Ignore once PR https://github.com/corda/corda/pull/2054 is merged
@Test
- @Ignore
fun `nodeInfo is published to the network map`() {
// Given
val rootCertAndKey = createDoormanRootCertificateAndKeyPair()
@@ -111,6 +109,8 @@ class DoormanIntegrationTest {
whenever(it.compatibilityZoneURL).thenReturn(URL("http://${doormanHostAndPort.host}:${doormanHostAndPort.port}"))
whenever(it.emailAddress).thenReturn("iTest@R3.com")
}
+ config.rootCaCertFile.parent.createDirectories()
+ X509Utilities.saveCertificateAsPEMFile(rootCertAndKey.certificate, config.rootCaCertFile)
NetworkRegistrationHelper(config, HTTPNetworkRegistrationService(config.compatibilityZoneURL!!)).buildKeystore()
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt
index 629a5d8d7e..4a91aa0c7c 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/NetworkMapStorage.kt
@@ -1,8 +1,8 @@
package com.r3.corda.networkmanage.common.persistence
-import com.r3.corda.networkmanage.common.signer.SignedNetworkMap
import net.corda.core.crypto.SecureHash
import net.corda.nodeapi.internal.NetworkParameters
+import net.corda.nodeapi.internal.SignedNetworkMap
/**
* Data access object interface for NetworkMap persistence layer
@@ -15,16 +15,13 @@ interface NetworkMapStorage {
fun getCurrentNetworkMap(): SignedNetworkMap?
/**
- * Retrieves current map node info hashes only. Hashes are further filtered by the [certificateStatuses] parameter
- * 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
- * network map are returned.
- * @param certificateStatuses certificate statuses to be used in the node info filtering. Node info hash is returned
- * 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].
+ * Retrieves node info hashes where the certificate status matches [certificateStatus].
+ *
+ * @param certificateStatus certificate status to be used in the node info filtering. Node info hash is returned
+ * in the result collection if its certificate status matches [certificateStatus].
+ * @return list of node info hashes satisfying the filtering criteria given by [certificateStatus].
*/
- fun getCurrentNetworkMapNodeInfoHashes(certificateStatuses: List): List
+ fun getNodeInfoHashes(certificateStatus: CertificateStatus): List
/**
* Persists a new instance of the signed network map.
@@ -32,17 +29,11 @@ interface NetworkMapStorage {
*/
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
-
/**
* Retrieve network parameters by their hash.
* @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.
@@ -54,7 +45,7 @@ interface NetworkMapStorage {
* Persists given network parameters.
* @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
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt
index f8f00bb257..477e2b7003 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentNetworkMapStorage.kt
@@ -1,77 +1,64 @@
package com.r3.corda.networkmanage.common.persistence
-import com.r3.corda.networkmanage.common.persistence.entity.NetworkMapEntity
-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 com.r3.corda.networkmanage.common.persistence.entity.*
import net.corda.core.crypto.SecureHash
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.nodeapi.internal.NetworkMap
import net.corda.nodeapi.internal.NetworkParameters
+import net.corda.nodeapi.internal.SignedNetworkMap
import net.corda.nodeapi.internal.persistence.CordaPersistence
-import org.hibernate.Session
-import org.hibernate.jpa.QueryHints
/**
* Database implementation of the [NetworkMapStorage] interface
*/
class PersistentNetworkMapStorage(private val database: CordaPersistence) : NetworkMapStorage {
override fun getCurrentNetworkMap(): SignedNetworkMap? = database.transaction {
- val networkMapEntity = getCurrentNetworkMapEntity(getNetworkMapWithNodeInfoAndParametersHint(session))
+ val networkMapEntity = getCurrentNetworkMapEntity()
networkMapEntity?.let {
- val nodeInfoHashes = it.nodeInfoList.map { it.nodeInfoHash }
- val networkParameterHash = it.parameters.parametersHash
val signatureAndCertPath = it.signatureAndCertificate()
- SignedNetworkMap(NetworkMap(nodeInfoHashes, networkParameterHash), signatureAndCertPath!!)
+ SignedNetworkMap(SerializedBytes(it.networkMap), signatureAndCertPath)
}
}
override fun getCurrentNetworkParameters(): NetworkParameters? = database.transaction {
- getCurrentNetworkMapEntity(getNetworkMapWithParametersHint(session))?.parameters?.networkParameters()
+ getCurrentNetworkMapEntity()?.let {
+ val parameterHash = it.networkMap.deserialize().networkParameterHash
+ getNetworkParameters(parameterHash)
+ }
}
override fun saveNetworkMap(signedNetworkMap: SignedNetworkMap) {
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(
- parameters = networkParametersEntity,
- signatureBytes = signature.bytes,
- certificatePathBytes = signatureAndCertPath.certPath.serialize().bytes
+ networkMap = signedNetworkMap.raw.bytes,
+ signature = signedNetworkMap.sig.signatureBytes,
+ certificate = signedNetworkMap.sig.by.encoded
)
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? {
+ return getNetworkParametersEntity(parameterHash.toString())?.networkParameters()
+ }
+
+ override fun getNodeInfoHashes(certificateStatus: CertificateStatus): List = database.transaction {
+ val builder = session.criteriaBuilder
+ val query = builder.createQuery(String::class.java).run {
+ from(NodeInfoEntity::class.java).run {
+ select(get(NodeInfoEntity::nodeInfoHash.name))
+ .where(builder.equal(get(NodeInfoEntity::certificateSigningRequest.name)
+ .get(CertificateSigningRequestEntity::certificateData.name)
+ .get(CertificateDataEntity::certificateStatus.name), certificateStatus))
}
}
+ session.createQuery(query).resultList.map { SecureHash.parse(it) }
}
- 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): List = database.transaction {
- val networkMapEntity = getCurrentNetworkMapEntity(getNetworkMapWithNodeInfoAndCsrHint(session))
- 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 saveNetworkParameters(networkParameters: NetworkParameters): SecureHash = database.transaction {
val bytes = networkParameters.serialize().bytes
val hash = bytes.sha256()
session.save(NetworkParametersEntity(
@@ -94,29 +81,16 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence) : Netw
session.createQuery(query).resultList.first()
}
- override fun getDetachedAndValidNodeInfoHashes(): List = 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(NodeInfoEntity::networkMap.name)),
- builder.isNotNull(get(NodeInfoEntity::signatureBytes.name))))
- }
- }
- session.createQuery(query).resultList.map { SecureHash.parse(it.nodeInfoHash) }
- }
-
- private fun getCurrentNetworkMapEntity(hint: Pair): NetworkMapEntity? = database.transaction {
+ private fun getCurrentNetworkMapEntity(): NetworkMapEntity? = database.transaction {
val builder = session.criteriaBuilder
val query = builder.createQuery(NetworkMapEntity::class.java).run {
from(NetworkMapEntity::class.java).run {
- where(builder.isNotNull(get(NetworkMapEntity::signatureBytes.name)))
+ where(builder.isNotNull(get(NetworkMapEntity::signature.name)))
orderBy(builder.desc(get(NetworkMapEntity::version.name)))
}
}
// 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 {
@@ -124,33 +98,4 @@ class PersistentNetworkMapStorage(private val database: CordaPersistence) : Netw
builder.equal(path.get(NetworkParametersEntity::parametersHash.name), parameterHash)
}
}
-
- /**
- * Creates Hibernate query hint for pulling [NetworkParametersEntity] when querying for [NetworkMapEntity]
- */
- private fun getNetworkMapWithParametersHint(session: Session): Pair {
- 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 {
- 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 {
- val graph = session.createEntityGraph(NetworkMapEntity::class.java)
- graph.addAttributeNodes(NetworkMapEntity::nodeInfoList.name)
- graph.addAttributeNodes(NetworkMapEntity::parameters.name)
- return QueryHints.HINT_LOADGRAPH to graph
- }
-}
\ No newline at end of file
+}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/SchemaService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/SchemaService.kt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt
index 19ab90f2b7..ff9865a6e1 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NetworkMapEntity.kt
@@ -1,8 +1,7 @@
package com.r3.corda.networkmanage.common.persistence.entity
-import com.r3.corda.networkmanage.common.signer.SignatureAndCertPath
-import net.corda.core.crypto.DigitalSignature
-import net.corda.core.serialization.deserialize
+import net.corda.nodeapi.internal.DigitalSignatureWithCert
+import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import javax.persistence.*
@Entity
@@ -12,27 +11,23 @@ class NetworkMapEntity(
@GeneratedValue(strategy = GenerationType.SEQUENCE)
val version: Long? = null,
- // Reverting relation ownership due to (potentially) unlimited number of node info items.
- @OneToMany(mappedBy = "networkMap", fetch = FetchType.LAZY)
- val nodeInfoList: List = mutableListOf(),
-
- @OneToOne
- @JoinColumn(name = "network_parameters")
- val parameters: NetworkParametersEntity,
+ @Lob
+ @Column(name = "serialized_network_map")
+ val networkMap: ByteArray,
@Lob
- @Column(name = "signature_bytes")
- val signatureBytes: ByteArray,
+ @Column(name = "signature")
+ val signature: ByteArray,
@Lob
- @Column(name = "certificate_path_bytes")
- val certificatePathBytes: ByteArray
+ @Column(name = "certificate")
+ val certificate: ByteArray
) {
/**
* Deserializes NetworkMapEntity.signatureBytes into the [SignatureAndCertPath] instance
*/
- fun signatureAndCertificate(): SignatureAndCertPath? {
- return SignatureAndCertPath(DigitalSignature(signatureBytes), certificatePathBytes.deserialize())
+ fun signatureAndCertificate(): DigitalSignatureWithCert {
+ return DigitalSignatureWithCert(X509CertificateFactory().generateCertificate(certificate.inputStream()), signature)
}
}
\ No newline at end of file
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt
index 3161539202..78e450aea9 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/entity/NodeInfoEntity.kt
@@ -18,10 +18,6 @@ class NodeInfoEntity(
@JoinColumn(name = "certificate_signing_request", nullable = true)
val certificateSigningRequest: CertificateSigningRequestEntity? = null,
- @OneToOne(fetch = FetchType.LAZY)
- @JoinColumn(name = "network_map", nullable = true)
- val networkMap: NetworkMapEntity? = null,
-
@Lob
@Column(name = "node_info_bytes")
val nodeInfoBytes: ByteArray,
@@ -55,7 +51,6 @@ class NodeInfoEntity(
}
fun copy(nodeInfoHash: String = this.nodeInfoHash,
- networkMap: NetworkMapEntity? = this.networkMap,
certificateSigningRequest: CertificateSigningRequestEntity? = this.certificateSigningRequest,
nodeInfoBytes: ByteArray = this.nodeInfoBytes,
signatureBytes: ByteArray? = this.signatureBytes,
@@ -68,8 +63,7 @@ class NodeInfoEntity(
nodeInfoBytes = nodeInfoBytes,
signatureBytes = signatureBytes,
signaturePublicKeyBytes = signaturePublicKeyBytes,
- signaturePublicKeyAlgorithm = signaturePublicKeyAlgorithm,
- networkMap = networkMap
+ signaturePublicKeyAlgorithm = signaturePublicKeyAlgorithm
)
}
}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt
index 55ffb21286..438ad8c17b 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSigner.kt
@@ -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.NetworkMapStorage
-import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.serialize
+import net.corda.nodeapi.internal.NetworkMap
+import net.corda.nodeapi.internal.SignedNetworkMap
-/**
- * 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, val parametersHash: String)
-
-@CordaSerializable
-data class SignedNetworkMap(val networkMap: NetworkMap, val signatureData: SignatureAndCertPath)
-
-class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage,
- private val signer: Signer) {
+class NetworkMapSigner(private val networkMapStorage: NetworkMapStorage, private val signer: Signer) {
/**
* Signs the network map.
*/
fun signNetworkMap() {
val currentSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
- val currentNetworkMapValidNodeInfo = networkMapStorage.getCurrentNetworkMapNodeInfoHashes(listOf(CertificateStatus.VALID))
- val detachedValidNodeInfo = networkMapStorage.getDetachedAndValidNodeInfoHashes()
- val nodeInfoHashes = currentNetworkMapValidNodeInfo + detachedValidNodeInfo
+ val nodeInfoHashes = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
val networkParameters = networkMapStorage.getLatestNetworkParameters()
- val networkMap = NetworkMap(nodeInfoHashes.map { it.toString() }, networkParameters.serialize().hash.toString())
- if (networkMap != currentSignedNetworkMap?.networkMap) {
+ val networkMap = NetworkMap(nodeInfoHashes, networkParameters.serialize().hash)
+ if (networkMap != currentSignedNetworkMap?.verified()) {
val digitalSignature = signer.sign(networkMap.serialize().bytes)
- require(digitalSignature != null) { "Error while signing network map." }
- val signedHashedNetworkMap = SignedNetworkMap(networkMap, digitalSignature!!)
+ val signedHashedNetworkMap = SignedNetworkMap(networkMap.serialize(), digitalSignature)
networkMapStorage.saveNetworkMap(signedHashedNetworkMap)
}
}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt
index ee47e8825f..ed43651748 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/signer/Signer.kt
@@ -2,19 +2,19 @@ package com.r3.corda.networkmanage.common.signer
import net.corda.core.crypto.DigitalSignature
import net.corda.core.serialization.CordaSerializable
+import net.corda.nodeapi.internal.DigitalSignatureWithCert
import java.security.cert.CertPath
-@CordaSerializable
-data class SignatureAndCertPath(val signature: DigitalSignature, val certPath: CertPath)
-
/**
* An interface for arbitrary data signing functionality.
*/
interface Signer {
-
/**
* 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.
+ * @throws [AuthenticationException] if fails authentication
*/
- fun sign(data: ByteArray): SignatureAndCertPath?
-}
\ No newline at end of file
+ fun sign(data: ByteArray): DigitalSignatureWithCert
+}
+
+class AuthenticationException : Exception()
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt
index 13c3ab188f..a6d46e6ccc 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/utils/Utils.kt
@@ -4,7 +4,9 @@ import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import joptsimple.ArgumentAcceptingOptionSpec
import joptsimple.OptionParser
+import net.corda.core.crypto.DigitalSignature
import net.corda.core.crypto.sha256
+import net.corda.nodeapi.internal.DigitalSignatureWithCert
import net.corda.nodeapi.internal.crypto.X509CertificateFactory
import org.bouncycastle.cert.X509CertificateHolder
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(certPathBytes: ByteArray): CertPath = X509CertificateFactory().delegate.generateCertPath(certPathBytes.inputStream())
+
+fun DigitalSignature.WithKey.withCert(cert: X509Certificate): DigitalSignatureWithCert = DigitalSignatureWithCert(cert, bytes)
\ No newline at end of file
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt
index 510370cd66..913283b54d 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/Main.kt
@@ -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.webservice.NodeInfoWebService
import com.r3.corda.networkmanage.doorman.webservice.RegistrationWebService
-import com.typesafe.config.ConfigFactory
import net.corda.core.crypto.Crypto
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.createDirectories
@@ -32,6 +31,7 @@ import java.io.Closeable
import java.net.InetSocketAddress
import java.net.URI
import java.nio.file.Path
+import java.security.cert.X509Certificate
import java.time.Instant
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
@@ -190,7 +190,7 @@ fun startDoorman(hostAndPort: NetworkHostAndPort,
// Persisting new network parameters
val currentNetworkParameters = networkMapStorage.getCurrentNetworkParameters()
if (currentNetworkParameters == null) {
- networkMapStorage.putNetworkParameters(networkMapParameters)
+ networkMapStorage.saveNetworkParameters(networkMapParameters)
} else {
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 keystore = loadOrCreateKeyStore(parameters.keystorePath, keystorePassword)
val caKeyPair = keystore.getKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caPrivateKeyPassword)
- val caCertPath = keystore.getCertificateChain(X509Utilities.CORDA_INTERMEDIATE_CA)
- LocalSigner(caKeyPair, caCertPath)
+ val caCertPath = keystore.getCertificateChain(X509Utilities.CORDA_INTERMEDIATE_CA).map { it as X509Certificate }
+ LocalSigner(caKeyPair, caCertPath.toTypedArray())
}
}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt
index 923143b4a1..0a930434e4 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/CsrHandler.kt
@@ -71,7 +71,7 @@ class JiraCsrHandler(private val jiraClient: JiraClient, private val storage: Ce
jiraClient.getApprovedRequests().forEach { (id, approvedBy) -> storage.approveRequest(id, approvedBy) }
delegate.processApprovedRequests()
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()
jiraClient.updateSignedRequests(signedRequests)
}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt
index 7139df39fa..900c8c8017 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/signer/LocalSigner.kt
@@ -1,12 +1,13 @@
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.utils.buildCertPath
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.identity.CordaX500Name
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.X509Utilities
import org.bouncycastle.asn1.x509.GeneralName
@@ -16,13 +17,13 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest
import java.security.KeyPair
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.
* 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) : Signer {
+class LocalSigner(private val caKeyPair: KeyPair, private val caCertPath: Array) : Signer {
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,
// 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)
}
- override fun sign(data: ByteArray): SignatureAndCertPath {
- return SignatureAndCertPath(caKeyPair.sign(data), buildCertPath(*caCertPath))
+ override fun sign(data: ByteArray): DigitalSignatureWithCert {
+ return caKeyPair.sign(data).withCert(caCertPath.first())
}
}
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt
index 9d325dd628..be35136028 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt
@@ -74,7 +74,7 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage,
}
@GET
- @Path("{nodeInfoHash}")
+ @Path("node-info/{nodeInfoHash}")
fun getNodeInfo(@PathParam("nodeInfoHash") nodeInfoHash: String): Response {
val nodeInfo = nodeInfoStorage.getNodeInfo(SecureHash.parse(nodeInfoHash))
return if (nodeInfo != null) {
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt
index 02348e0561..65921ab418 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/authentication/Authenticator.kt
@@ -1,6 +1,7 @@
package com.r3.corda.networkmanage.hsm.authentication
import CryptoServerJCE.CryptoServerProvider
+import com.r3.corda.networkmanage.common.signer.AuthenticationException
import com.r3.corda.networkmanage.hsm.configuration.Parameters
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
@@ -25,8 +26,8 @@ class Authenticator(private val provider: CryptoServerProvider,
* 1) [CryptoServerProvider] instance
* 2) List of strings that corresponds to user names authenticated against the HSM.
*/
- fun connectAndAuthenticate(block: (CryptoServerProvider, List) -> Unit) {
- try {
+ fun connectAndAuthenticate(block: (CryptoServerProvider, List) -> T): T {
+ return try {
val authenticated = mutableListOf()
loop@ while (true) {
val user = if (autoUsername.isNullOrEmpty()) {
@@ -78,6 +79,8 @@ class Authenticator(private val provider: CryptoServerProvider,
}
if (!authenticated.isEmpty()) {
block(provider, authenticated)
+ } else {
+ throw AuthenticationException()
}
} finally {
try {
@@ -89,8 +92,8 @@ class Authenticator(private val provider: CryptoServerProvider,
}
}
}
-
/*
+
* Configuration class for [CryptoServerProvider]
*/
data class CryptoServerProviderConfig(
diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmNetworkMapSigner.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmNetworkMapSigner.kt
index ed63c7fa24..0950b1e3b8 100644
--- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmNetworkMapSigner.kt
+++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/signer/HsmNetworkMapSigner.kt
@@ -3,15 +3,17 @@ package com.r3.corda.networkmanage.hsm.signer
import com.google.common.util.concurrent.MoreExecutors
import com.r3.corda.networkmanage.common.persistence.NetworkMapStorage
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.utils.buildCertPath
+import com.r3.corda.networkmanage.common.utils.withCert
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.signData
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.minutes
+import net.corda.nodeapi.internal.DigitalSignatureWithCert
import java.security.KeyPair
import java.security.PrivateKey
import java.time.Duration
@@ -59,16 +61,14 @@ class HsmNetworkMapSigner(networkMapStorage: NetworkMapStorage,
/**
* Signs given data using [CryptoServerJCE.CryptoServerProvider], which connects to the underlying HSM.
*/
- override fun sign(data: ByteArray): SignatureAndCertPath? {
- var result: SignatureAndCertPath? = null
- authenticator.connectAndAuthenticate { provider, _ ->
+ override fun sign(data: ByteArray): DigitalSignatureWithCert {
+ return authenticator.connectAndAuthenticate { provider, _ ->
val keyStore = getAndInitializeKeyStore(provider)
val caCertificateChain = keyStore.getCertificateChain(caCertificateKeyName)
val caKey = keyStore.getKey(caCertificateKeyName, caPrivateKeyPass.toCharArray()) as PrivateKey
val signature = signData(data, KeyPair(caCertificateChain.first().publicKey, caKey), provider)
verify(data, signature, caCertificateChain.first().publicKey)
- result = SignatureAndCertPath(signature, buildCertPath(*caCertificateChain))
+ signature.withCert(caCertificateChain.first().toX509CertHolder().cert)
}
- return result
}
-}
\ No newline at end of file
+}
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBCertificateRequestStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBCertificateRequestStorageTest.kt
index 36d9893644..e06e2fbdd8 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBCertificateRequestStorageTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBCertificateRequestStorageTest.kt
@@ -11,7 +11,6 @@ import net.corda.core.identity.CordaX500Name
import net.corda.nodeapi.internal.crypto.CertificateType
import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.persistence.CordaPersistence
-import net.corda.nodeapi.internal.persistence.DatabaseConfig
import org.assertj.core.api.Assertions.assertThat
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.pkcs.PKCS10CertificationRequest
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBNetworkMapStorageTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBNetworkMapStorageTest.kt
index 6f208e072b..0cf16e0d71 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBNetworkMapStorageTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/DBNetworkMapStorageTest.kt
@@ -1,30 +1,30 @@
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 com.r3.corda.networkmanage.common.utils.withCert
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SignedData
import net.corda.core.crypto.sign
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
+import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize
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.X509Utilities
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.node.MockServices.Companion.makeTestDataSourceProperties
+import org.assertj.core.api.Assertions.assertThat
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
@@ -57,7 +57,7 @@ class DBNetworkMapStorageTest : TestBase() {
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
requestStorage.markRequestTicketCreated(requestId)
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 certPath = buildCertPath(clientCert.toX509Certificate(), intermediateCACert.toX509Certificate(), rootCACert.toX509Certificate())
requestStorage.putCertificatePath(requestId, certPath, emptyList())
@@ -67,25 +67,28 @@ class DBNetworkMapStorageTest : TestBase() {
val nodeInfoHash = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBytes, keyPair.sign(nodeInfoBytes)))
// Create network parameters
- val networkParametersHash = networkMapStorage.putNetworkParameters(testNetworkParameters(emptyList()))
+ val networkParametersHash = networkMapStorage.saveNetworkParameters(testNetworkParameters(emptyList()))
- val networkMap = NetworkMap(listOf(nodeInfoHash.toString()), networkParametersHash.toString())
- val signatureData = SignatureAndCertPath(keyPair.sign(networkMap.serialize()), certPath)
- val signedNetworkMap = SignedNetworkMap(NetworkMap(listOf(nodeInfoHash.toString()), networkParametersHash.toString()), signatureData)
+ val networkMap = NetworkMap(listOf(nodeInfoHash), networkParametersHash)
+ val serializedNetworkMap = networkMap.serialize()
+ val signatureData = intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)
+ val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
// when
networkMapStorage.saveNetworkMap(signedNetworkMap)
// then
val persistedSignedNetworkMap = networkMapStorage.getCurrentNetworkMap()
- assertEquals(signedNetworkMap, persistedSignedNetworkMap)
+
+ assertEquals(signedNetworkMap.sig, persistedSignedNetworkMap?.sig)
+ assertEquals(signedNetworkMap.verified(), persistedSignedNetworkMap?.verified())
}
@Test
fun `getLatestNetworkParameters returns last inserted`() {
// given
- networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 1))
- networkMapStorage.putNetworkParameters(createNetworkParameters(minimumPlatformVersion = 2))
+ networkMapStorage.saveNetworkParameters(createNetworkParameters(minimumPlatformVersion = 1))
+ networkMapStorage.saveNetworkParameters(createNetworkParameters(minimumPlatformVersion = 2))
// when
val latest = networkMapStorage.getLatestNetworkParameters()
@@ -98,20 +101,20 @@ class DBNetworkMapStorageTest : TestBase() {
fun `getCurrentNetworkParameters returns current network map parameters`() {
// given
// Create network parameters
- val networkMapParametersHash = networkMapStorage.putNetworkParameters(createNetworkParameters(1))
+ val networkMapParametersHash = networkMapStorage.saveNetworkParameters(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)
+ val networkMap = NetworkMap(emptyList(), networkMapParametersHash)
+ val serializedNetworkMap = networkMap.serialize()
+ val signatureData = keyPair.sign(serializedNetworkMap).withCert(intermediateCert.cert)
+ val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
networkMapStorage.saveNetworkMap(signedNetworkMap)
// Create new network parameters
- networkMapStorage.putNetworkParameters(createNetworkParameters(2))
+ networkMapStorage.saveNetworkParameters(createNetworkParameters(2))
// when
val result = networkMapStorage.getCurrentNetworkParameters()
@@ -121,7 +124,7 @@ class DBNetworkMapStorageTest : TestBase() {
}
@Test
- fun `getDetachedAndValidNodeInfoHashes returns only valid and signed node info hashes`() {
+ fun `getValidNodeInfoHashes returns only valid and signed node info hashes`() {
// given
// Create node info.
val organisationA = "TestA"
@@ -148,19 +151,19 @@ class DBNetworkMapStorageTest : TestBase() {
val nodeInfoHashB = nodeInfoStorage.putNodeInfo(SignedData(nodeInfoBBytes, keyPair.sign(nodeInfoBBytes)))
// 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)
+ val networkParametersHash = networkMapStorage.saveNetworkParameters(createNetworkParameters())
+ val networkMap = NetworkMap(listOf(nodeInfoHashA), networkParametersHash)
+ val serializedNetworkMap = networkMap.serialize()
+ val signatureData = keyPair.sign(serializedNetworkMap).withCert(clientCertA.cert)
+ val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, signatureData)
// Sign network map
networkMapStorage.saveNetworkMap(signedNetworkMap)
// when
- val detachedHashes = networkMapStorage.getDetachedAndValidNodeInfoHashes()
+ val validNodeInfoHash = networkMapStorage.getNodeInfoHashes(CertificateStatus.VALID)
// then
- assertEquals(1, detachedHashes.size)
- assertTrue(detachedHashes.contains(nodeInfoHashB))
+ assertThat(validNodeInfoHash).containsOnly(nodeInfoHashA, nodeInfoHashB)
}
}
\ No newline at end of file
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt
index c8dbca7f83..29e05f0ae5 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt
@@ -3,9 +3,18 @@ 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 com.r3.corda.networkmanage.common.utils.withCert
+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.internal.cert
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.Test
import kotlin.test.assertEquals
@@ -15,7 +24,10 @@ class NetworkMapSignerTest : TestBase() {
private lateinit var signer: Signer
private lateinit var networkMapStorage: NetworkMapStorage
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
fun setUp() {
signer = mock()
@@ -27,30 +39,29 @@ class NetworkMapSignerTest : TestBase() {
fun `signNetworkMap builds and signs network map`() {
// given
val signedNodeInfoHashes = listOf(SecureHash.randomSHA256(), SecureHash.randomSHA256())
- val detachedNodeInfoHashes = listOf(SecureHash.randomSHA256())
val networkMapParameters = createNetworkParameters()
+ val serializedNetworkMap = NetworkMap(signedNodeInfoHashes, SecureHash.randomSHA256()).serialize()
whenever(networkMapStorage.getCurrentNetworkMap())
- .thenReturn(SignedNetworkMap(NetworkMap(signedNodeInfoHashes.map { it.toString() }, "Dummy"), mock()))
- whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
- whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(detachedNodeInfoHashes)
+ .thenReturn(SignedNetworkMap(serializedNetworkMap, intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert)))
+ whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(signedNodeInfoHashes)
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
networkMapSigner.signNetworkMap()
// then
// Verify networkMapStorage calls
- verify(networkMapStorage).getCurrentNetworkMapNodeInfoHashes(any())
- verify(networkMapStorage).getDetachedAndValidNodeInfoHashes()
+ verify(networkMapStorage).getNodeInfoHashes(any())
verify(networkMapStorage).getLatestNetworkParameters()
argumentCaptor().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() }))
+ val networkMap = firstValue.verified()
+ assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
+ assertEquals(signedNodeInfoHashes.size, networkMap.nodeInfoHashes.size)
+ assertTrue(networkMap.nodeInfoHashes.containsAll(signedNodeInfoHashes))
}
}
@@ -59,11 +70,11 @@ class NetworkMapSignerTest : TestBase() {
// given
val networkMapParameters = createNetworkParameters()
val networkMapParametersHash = networkMapParameters.serialize().bytes.sha256()
- val networkMap = NetworkMap(emptyList(), networkMapParametersHash.toString())
- val signedNetworkMap = SignedNetworkMap(networkMap, mock())
+ val networkMap = NetworkMap(emptyList(), networkMapParametersHash)
+ val serializedNetworkMap = networkMap.serialize()
+ val signedNetworkMap = SignedNetworkMap(serializedNetworkMap, intermediateCAKey.sign(serializedNetworkMap).withCert(intermediateCACert.cert))
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(signedNetworkMap)
- whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(emptyList())
- whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(emptyList())
+ whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
whenever(networkMapStorage.getLatestNetworkParameters()).thenReturn(networkMapParameters)
// when
@@ -79,23 +90,22 @@ class NetworkMapSignerTest : TestBase() {
// given
val networkMapParameters = createNetworkParameters()
whenever(networkMapStorage.getCurrentNetworkMap()).thenReturn(null)
- whenever(networkMapStorage.getCurrentNetworkMapNodeInfoHashes(any())).thenReturn(emptyList())
- whenever(networkMapStorage.getDetachedAndValidNodeInfoHashes()).thenReturn(emptyList())
+ whenever(networkMapStorage.getNodeInfoHashes(any())).thenReturn(emptyList())
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
networkMapSigner.signNetworkMap()
// then
// Verify networkMapStorage calls
- verify(networkMapStorage).getCurrentNetworkMapNodeInfoHashes(any())
- verify(networkMapStorage).getDetachedAndValidNodeInfoHashes()
+ verify(networkMapStorage).getNodeInfoHashes(any())
verify(networkMapStorage).getLatestNetworkParameters()
argumentCaptor().apply {
verify(networkMapStorage).saveNetworkMap(capture())
- val networkMap = firstValue.networkMap
- assertEquals(networkMapParameters.serialize().hash.toString(), networkMap.parametersHash)
+ val networkMap = firstValue.verified()
+ assertEquals(networkMapParameters.serialize().hash, networkMap.networkParameterHash)
}
}
}
\ No newline at end of file
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NodeInfoWebServiceTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NodeInfoWebServiceTest.kt
index 2502acbd5f..3240fd35a1 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NodeInfoWebServiceTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/doorman/NodeInfoWebServiceTest.kt
@@ -6,18 +6,20 @@ import com.nhaarman.mockito_kotlin.times
import com.nhaarman.mockito_kotlin.verify
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.common.utils.withCert
import com.r3.corda.networkmanage.doorman.webservice.NodeInfoWebService
import net.corda.core.crypto.*
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.PartyAndCertificate
+import net.corda.core.internal.cert
import net.corda.core.node.NodeInfo
import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize
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.X509Utilities
import net.corda.testing.SerializationEnvironmentRule
@@ -97,16 +99,17 @@ class NodeInfoWebServiceTest {
@Test
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 {
- 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 {
it.start()
val conn = URL("http://${it.hostAndPort}/${NodeInfoWebService.NETWORK_MAP_PATH}").openConnection() as HttpURLConnection
- val signedHashedNetworkMap = conn.inputStream.readBytes().deserialize()
+ val signedNetworkMap = conn.inputStream.readBytes().deserialize()
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 {
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 nodeInfoResponse = conn.inputStream.readBytes().deserialize>()
verify(nodeInfoStorage, times(1)).getNodeInfo(nodeInfoHash)
diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt
index 2ae412619a..bb920779f9 100644
--- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt
+++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/hsm/authentication/AuthenticatorTest.kt
@@ -3,9 +3,10 @@ package com.r3.corda.networkmanage.hsm.authentication
import CryptoServerJCE.CryptoServerProvider
import com.nhaarman.mockito_kotlin.*
import com.r3.corda.networkmanage.TestBase
+import com.r3.corda.networkmanage.common.signer.AuthenticationException
import org.junit.Before
import org.junit.Test
-import kotlin.test.assertFalse
+import kotlin.test.assertFailsWith
import kotlin.test.assertTrue
class AuthenticatorTest : TestBase() {
@@ -24,15 +25,15 @@ class AuthenticatorTest : TestBase() {
fun `connectAndAuthenticate aborts when user inputs Q`() {
// given
givenUserConsoleInputOnReadLine("Q")
- var executed = false
// when
- Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> executed = true }
+ assertFailsWith {
+ Authenticator(provider = provider, inputReader = inputReader).connectAndAuthenticate { _, _ -> }
+ }
- // then
- assertFalse(executed)
- verify(provider, never()).loginPassword(any(), any())
- verify(provider, never()).loginSign(any(), any(), any())
+ //then
+ verify(provider, never()).loginPassword(any(), any())
+ verify(provider, never()).loginSign(any(), any(), any())
}
@Test
@@ -50,7 +51,7 @@ class AuthenticatorTest : TestBase() {
// then
verify(provider).loginPassword(username, password)
- verify(provider, never()).loginSign(any(), any(), any())
+ verify(provider, never()).loginSign(any(), any(), any())
assertTrue(executed)
}
@@ -67,7 +68,7 @@ class AuthenticatorTest : TestBase() {
// then
verify(provider).loginSign(username, ":cs2:cyb:USB0", null)
- verify(provider, never()).loginPassword(any(), any())
+ verify(provider, never()).loginPassword(any(), any())
assertTrue(executed)
}
@@ -86,7 +87,7 @@ class AuthenticatorTest : TestBase() {
// then
verify(provider, times(3)).loginPassword(username, password)
- verify(provider, never()).loginSign(any(), any(), any())
+ verify(provider, never()).loginSign(any(), any(), any())
assertTrue(executed)
}
@@ -98,7 +99,7 @@ class AuthenticatorTest : TestBase() {
}
private fun givenUserConsoleInputOnReadPassword(input: String) {
- whenever(inputReader.readPassword(any())).thenReturn(input)
+ whenever(inputReader.readPassword(any())).thenReturn(input)
}
private fun givenUserConsoleInputOnReadLine(input: String) {