mirror of
https://github.com/corda/corda.git
synced 2025-06-22 17:09:00 +00:00
ENT-1226 Check minimum platform version when submitting node info (#300)
* Adding min platform version check when submitting node info * Return error message to developer * Fixing integration test * Added todo to move checks out of data layer * Added extra logging in nodeinfowebservice and use nodeinfo.verified instead of deserialize * Tidy up tests * Cache network parameters * Add NodeInfoWithSigned class to stop calling to only verify node data once * Fixing review comments * Return correct response code if doorman not initialised properly * Fix merge conflict
This commit is contained in:
@ -148,7 +148,7 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
assertThat(validNodeInfoHash).containsOnly(nodeInfoHashA, nodeInfoHashB)
|
||||
}
|
||||
|
||||
private fun createValidSignedNodeInfo(organisation: String): SignedNodeInfo {
|
||||
private fun createValidSignedNodeInfo(organisation: String): NodeInfoWithSigned {
|
||||
val nodeInfoBuilder = TestNodeInfoBuilder()
|
||||
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
|
||||
requestStorage.markRequestTicketCreated(requestId)
|
||||
@ -156,6 +156,6 @@ class PersistentNetworkMapStorageTest : TestBase() {
|
||||
val (identity) = nodeInfoBuilder.addIdentity(CordaX500Name(organisation, "London", "GB"))
|
||||
val nodeCaCertPath = X509CertificateFactory().generateCertPath(identity.certPath.certificates.drop(1))
|
||||
requestStorage.putCertificatePath(requestId, nodeCaCertPath, emptyList())
|
||||
return nodeInfoBuilder.buildWithSigned().second
|
||||
return NodeInfoWithSigned(nodeInfoBuilder.buildWithSigned().second)
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
import kotlin.test.assertNull
|
||||
|
||||
class PersitenceNodeInfoStorageTest : TestBase() {
|
||||
class PersistentNodeInfoStorageTest : TestBase() {
|
||||
private lateinit var requestStorage: CertificationRequestStorage
|
||||
private lateinit var nodeInfoStorage: PersistentNodeInfoStorage
|
||||
private lateinit var persistence: CordaPersistence
|
||||
@ -85,34 +85,34 @@ class PersitenceNodeInfoStorageTest : TestBase() {
|
||||
@Test
|
||||
fun `getNodeInfo returns persisted SignedNodeInfo using the hash of just the NodeInfo`() {
|
||||
// given
|
||||
val (nodeInfoA, signedNodeInfoA) = createValidSignedNodeInfo("TestA")
|
||||
val (nodeInfoB, signedNodeInfoB) = createValidSignedNodeInfo("TestB")
|
||||
val (nodeA) = createValidSignedNodeInfo("TestA")
|
||||
val (nodeB) = createValidSignedNodeInfo("TestB")
|
||||
|
||||
// Put signed node info data
|
||||
nodeInfoStorage.putNodeInfo(signedNodeInfoA)
|
||||
nodeInfoStorage.putNodeInfo(signedNodeInfoB)
|
||||
nodeInfoStorage.putNodeInfo(nodeA)
|
||||
nodeInfoStorage.putNodeInfo(nodeB)
|
||||
|
||||
// when
|
||||
val persistedSignedNodeInfoA = nodeInfoStorage.getNodeInfo(nodeInfoA.serialize().hash)
|
||||
val persistedSignedNodeInfoB = nodeInfoStorage.getNodeInfo(nodeInfoB.serialize().hash)
|
||||
val persistedSignedNodeInfoA = nodeInfoStorage.getNodeInfo(nodeA.nodeInfo.serialize().hash)
|
||||
val persistedSignedNodeInfoB = nodeInfoStorage.getNodeInfo(nodeB.nodeInfo.serialize().hash)
|
||||
|
||||
// then
|
||||
assertEquals(persistedSignedNodeInfoA?.verified(), nodeInfoA)
|
||||
assertEquals(persistedSignedNodeInfoB?.verified(), nodeInfoB)
|
||||
assertEquals(persistedSignedNodeInfoA?.verified(), nodeA.nodeInfo)
|
||||
assertEquals(persistedSignedNodeInfoB?.verified(), nodeB.nodeInfo)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `same public key with different node info`() {
|
||||
// Create node info.
|
||||
val (nodeInfo1, signedNodeInfo1, key) = createValidSignedNodeInfo("Test", serial = 1)
|
||||
val nodeInfo2 = nodeInfo1.copy(serial = 2)
|
||||
val signedNodeInfo2 = nodeInfo2.signWith(listOf(key))
|
||||
val (node1, key) = createValidSignedNodeInfo("Test", serial = 1)
|
||||
val nodeInfo2 = node1.nodeInfo.copy(serial = 2)
|
||||
val node2 = NodeInfoWithSigned(nodeInfo2.signWith(listOf(key)))
|
||||
|
||||
val nodeInfo1Hash = nodeInfoStorage.putNodeInfo(signedNodeInfo1)
|
||||
assertEquals(nodeInfo1, nodeInfoStorage.getNodeInfo(nodeInfo1Hash)?.verified())
|
||||
val nodeInfo1Hash = nodeInfoStorage.putNodeInfo(node1)
|
||||
assertEquals(node1.nodeInfo, nodeInfoStorage.getNodeInfo(nodeInfo1Hash)?.verified())
|
||||
|
||||
// This should replace the node info.
|
||||
nodeInfoStorage.putNodeInfo(signedNodeInfo2)
|
||||
nodeInfoStorage.putNodeInfo(node2)
|
||||
|
||||
// Old node info should be removed.
|
||||
assertNull(nodeInfoStorage.getNodeInfo(nodeInfo1Hash))
|
||||
@ -122,17 +122,17 @@ class PersitenceNodeInfoStorageTest : TestBase() {
|
||||
@Test
|
||||
fun `putNodeInfo persists SignedNodeInfo with its signature`() {
|
||||
// given
|
||||
val (_, signedNodeInfo) = createValidSignedNodeInfo("Test")
|
||||
val (nodeInfoWithSigned) = createValidSignedNodeInfo("Test")
|
||||
|
||||
// when
|
||||
val nodeInfoHash = nodeInfoStorage.putNodeInfo(signedNodeInfo)
|
||||
val nodeInfoHash = nodeInfoStorage.putNodeInfo(nodeInfoWithSigned)
|
||||
|
||||
// then
|
||||
val persistedSignedNodeInfo = nodeInfoStorage.getNodeInfo(nodeInfoHash)
|
||||
assertThat(persistedSignedNodeInfo?.signatures).isEqualTo(signedNodeInfo.signatures)
|
||||
assertThat(persistedSignedNodeInfo?.signatures).isEqualTo(nodeInfoWithSigned.signedNodeInfo.signatures)
|
||||
}
|
||||
|
||||
private fun createValidSignedNodeInfo(organisation: String, serial: Long = 1): Triple<NodeInfo, SignedNodeInfo, PrivateKey> {
|
||||
private fun createValidSignedNodeInfo(organisation: String, serial: Long = 1): Pair<NodeInfoWithSigned, PrivateKey> {
|
||||
val nodeInfoBuilder = TestNodeInfoBuilder()
|
||||
val requestId = requestStorage.saveRequest(createRequest(organisation).first)
|
||||
requestStorage.markRequestTicketCreated(requestId)
|
||||
@ -140,7 +140,7 @@ class PersitenceNodeInfoStorageTest : TestBase() {
|
||||
val (identity, key) = nodeInfoBuilder.addIdentity(CordaX500Name(organisation, "London", "GB"))
|
||||
val nodeCaCertPath = X509CertificateFactory().generateCertPath(identity.certPath.certificates.drop(1))
|
||||
requestStorage.putCertificatePath(requestId, nodeCaCertPath, emptyList())
|
||||
val (nodeInfo, signedNodeInfo) = nodeInfoBuilder.buildWithSigned(serial)
|
||||
return Triple(nodeInfo, signedNodeInfo, key)
|
||||
val (_, signedNodeInfo) = nodeInfoBuilder.buildWithSigned(serial)
|
||||
return Pair(NodeInfoWithSigned(signedNodeInfo), key)
|
||||
}
|
||||
}
|
@ -25,13 +25,15 @@ import net.corda.testing.SerializationEnvironmentRule
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||
import net.corda.testing.internal.createNodeInfoAndSigned
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.apache.commons.io.IOUtils
|
||||
import org.assertj.core.api.Assertions.*
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.nio.charset.Charset
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.ws.rs.core.MediaType
|
||||
import kotlin.test.assertEquals
|
||||
@ -44,7 +46,7 @@ class NodeInfoWebServiceTest {
|
||||
private lateinit var rootCaCert: X509Certificate
|
||||
private lateinit var intermediateCa: CertificateAndKeyPair
|
||||
|
||||
private val testNetworkMapConfig = NetworkMapConfig(10.seconds.toMillis(), 10.seconds.toMillis())
|
||||
private val testNetworkMapConfig = NetworkMapConfig(10.seconds.toMillis(), 10.seconds.toMillis())
|
||||
|
||||
@Before
|
||||
fun init() {
|
||||
@ -55,10 +57,13 @@ class NodeInfoWebServiceTest {
|
||||
|
||||
@Test
|
||||
fun `submit nodeInfo`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(testNetworkParameters(emptyList()))
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"))
|
||||
|
||||
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), mock(), testNetworkMapConfig)).use {
|
||||
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage, testNetworkMapConfig)).use {
|
||||
it.start()
|
||||
val nodeInfoAndSignature = signedNodeInfo.serialize().bytes
|
||||
// Post node info and signature to doorman, this should pass without any exception.
|
||||
@ -66,6 +71,38 @@ class NodeInfoWebServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `submit old nodeInfo`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(testNetworkParameters(emptyList(), minimumPlatformVersion = 2))
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1)
|
||||
|
||||
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage, testNetworkMapConfig)).use {
|
||||
it.start()
|
||||
val nodeInfoAndSignature = signedNodeInfo.serialize().bytes
|
||||
assertThatThrownBy { it.doPost("publish", nodeInfoAndSignature) }
|
||||
.hasMessageStartingWith("Response Code 400: Minimum platform version is 2")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `submit nodeInfo when no network parameters`() {
|
||||
val networkMapStorage: NetworkMapStorage = mock {
|
||||
on { getCurrentNetworkParameters() }.thenReturn(null)
|
||||
}
|
||||
// Create node info.
|
||||
val (_, signedNodeInfo) = createNodeInfoAndSigned(CordaX500Name("Test", "London", "GB"), platformVersion = 1)
|
||||
|
||||
NetworkManagementWebServer(NetworkHostAndPort("localhost", 0), NodeInfoWebService(mock(), networkMapStorage, testNetworkMapConfig)).use {
|
||||
it.start()
|
||||
val nodeInfoAndSignature = signedNodeInfo.serialize().bytes
|
||||
assertThatThrownBy { it.doPost("publish", nodeInfoAndSignature) }
|
||||
.hasMessageStartingWith("Response Code 503: Network parameters have not been initialised")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `get network map`() {
|
||||
val networkMap = NetworkMap(listOf(randomSHA256(), randomSHA256()), randomSHA256())
|
||||
@ -136,7 +173,10 @@ class NodeInfoWebServiceTest {
|
||||
requestMethod = "POST"
|
||||
setRequestProperty("Content-Type", MediaType.APPLICATION_OCTET_STREAM)
|
||||
outputStream.write(payload)
|
||||
inputStream.close() // This will give us a nice IOException if the response isn't HTTP 200
|
||||
if (responseCode != 200) {
|
||||
throw IOException("Response Code $responseCode: ${IOUtils.toString(errorStream, Charset.defaultCharset())}")
|
||||
}
|
||||
inputStream.close()
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user