CORDA-2199 NetworkParameters certificate role ()

This commit is contained in:
James Brown 2018-11-22 10:49:18 +00:00 committed by GitHub
parent 504f650022
commit 98a495fa84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 39 additions and 25 deletions
core/src/main/kotlin/net/corda/core/internal
node-api/src
main/kotlin/net/corda/nodeapi/internal
test/kotlin/net/corda/nodeapi/internal/network
node/src
main/kotlin/net/corda/node
test/kotlin/net/corda/node/services/network

@ -46,7 +46,10 @@ enum class CertRole(val validParents: NonEmptySet<CertRole?>, val isIdentity: Bo
LEGAL_IDENTITY(NonEmptySet.of(DOORMAN_CA, NODE_CA), true, true), LEGAL_IDENTITY(NonEmptySet.of(DOORMAN_CA, NODE_CA), true, true),
/** Confidential (limited visibility) identity of a legal entity. */ /** Confidential (limited visibility) identity of a legal entity. */
CONFIDENTIAL_LEGAL_IDENTITY(NonEmptySet.of(LEGAL_IDENTITY), true, false); CONFIDENTIAL_LEGAL_IDENTITY(NonEmptySet.of(LEGAL_IDENTITY), true, false),
/** Signing certificate for Network Parameters. */
NETWORK_PARAMETERS(NonEmptySet.of(null), false, false);
companion object { companion object {
private val values by lazy(LazyThreadSafetyMode.NONE, CertRole::values) private val values by lazy(LazyThreadSafetyMode.NONE, CertRole::values)

@ -465,6 +465,12 @@ enum class CertificateType(val keyUsage: KeyUsage, vararg val purposes: KeyPurpo
KeyPurposeId.anyExtendedKeyUsage, KeyPurposeId.anyExtendedKeyUsage,
isCA = false, isCA = false,
role = CertRole.CONFIDENTIAL_LEGAL_IDENTITY role = CertRole.CONFIDENTIAL_LEGAL_IDENTITY
),
NETWORK_PARAMETERS(
KeyUsage(KeyUsage.digitalSignature),
isCA = false,
role = CertRole.NETWORK_PARAMETERS
) )
} }

@ -357,7 +357,7 @@ internal constructor(private val initSerEnv: Boolean,
when (netParamsFilesGrouped.size) { when (netParamsFilesGrouped.size) {
0 -> return null 0 -> return null
1 -> return netParamsFilesGrouped.keys.first().deserialize().verifiedNetworkMapCert(DEV_ROOT_CA.certificate) 1 -> return netParamsFilesGrouped.keys.first().deserialize().verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
} }
val msg = StringBuilder("Differing sets of network parameters were found. Make sure all the nodes have the same " + val msg = StringBuilder("Differing sets of network parameters were found. Make sure all the nodes have the same " +
@ -367,7 +367,7 @@ internal constructor(private val initSerEnv: Boolean,
netParamsFiles.map { it.parent.fileName }.joinTo(msg, ", ") netParamsFiles.map { it.parent.fileName }.joinTo(msg, ", ")
msg.append(":\n") msg.append(":\n")
val netParamsString = try { val netParamsString = try {
bytes.deserialize().verifiedNetworkMapCert(DEV_ROOT_CA.certificate).toString() bytes.deserialize().verifiedNetworkParametersCert(DEV_ROOT_CA.certificate).toString()
} catch (e: Exception) { } catch (e: Exception) {
"Invalid network parameters file: $e" "Invalid network parameters file: $e"
} }

@ -54,9 +54,9 @@ data class ParametersUpdate(
val updateDeadline: Instant val updateDeadline: Instant
) )
/** Verify that a Network Map certificate path and its [CertRole] is correct. */ /** Verify that a certificate path and its [CertRole] is correct. */
fun <T : Any> SignedDataWithCert<T>.verifiedNetworkMapCert(rootCert: X509Certificate): T { fun <T : Any> SignedDataWithCert<T>.verifiedCertWithRole(rootCert: X509Certificate, vararg certRoles: CertRole): T {
require(CertRole.extract(sig.by) == CertRole.NETWORK_MAP) { "Incorrect cert role: ${CertRole.extract(sig.by)}" } require(CertRole.extract(sig.by) in certRoles) { "Incorrect cert role: ${CertRole.extract(sig.by)}" }
val path = if (sig.parentCertsChain.isEmpty()) { val path = if (sig.parentCertsChain.isEmpty()) {
listOf(sig.by, rootCert) listOf(sig.by, rootCert)
} else { } else {
@ -65,3 +65,15 @@ fun <T : Any> SignedDataWithCert<T>.verifiedNetworkMapCert(rootCert: X509Certifi
X509Utilities.validateCertificateChain(rootCert, path) X509Utilities.validateCertificateChain(rootCert, path)
return verified() return verified()
} }
/** Verify that a Network Map certificate path and its [CertRole] is correct. */
fun <T : Any> SignedDataWithCert<T>.verifiedNetworkMapCert(rootCert: X509Certificate): T {
return verifiedCertWithRole(rootCert, CertRole.NETWORK_MAP)
}
/** Verify that a Network Parameters certificate path and its [CertRole] is correct. */
fun <T : Any> SignedDataWithCert<T>.verifiedNetworkParametersCert(rootCert: X509Certificate): T {
// for backwards compatibility we allow network parameters to be signed with
// the networkmap cert, but going forwards we also accept the specific netparams cert as well
return verifiedCertWithRole(rootCert, CertRole.NETWORK_PARAMETERS, CertRole.NETWORK_MAP)
}

@ -321,7 +321,7 @@ class NetworkBootstrapperTest {
} }
private val Path.networkParameters: NetworkParameters get() { private val Path.networkParameters: NetworkParameters get() {
return (this / NETWORK_PARAMS_FILE_NAME).readObject<SignedNetworkParameters>().verifiedNetworkMapCert(DEV_ROOT_CA.certificate) return (this / NETWORK_PARAMS_FILE_NAME).readObject<SignedNetworkParameters>().verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
} }
private val Path.nodeInfoFile: Path get() { private val Path.nodeInfoFile: Path get() {

@ -6,10 +6,7 @@ import net.corda.core.node.NetworkParameters
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.utilities.contextLogger import net.corda.core.utilities.contextLogger
import net.corda.node.services.network.NetworkMapClient import net.corda.node.services.network.NetworkMapClient
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME import net.corda.nodeapi.internal.network.*
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
import net.corda.nodeapi.internal.network.SignedNetworkParameters
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.security.cert.X509Certificate import java.security.cert.X509Certificate
@ -93,7 +90,9 @@ class NetworkParametersReader(private val trustRoot: X509Certificate,
// By passing in just the SignedNetworkParameters object, this class guarantees that the networkParameters property // By passing in just the SignedNetworkParameters object, this class guarantees that the networkParameters property
// could have only been derived from it. // could have only been derived from it.
class NetworkParametersAndSigned(val signed: SignedNetworkParameters, trustRoot: X509Certificate) { class NetworkParametersAndSigned(val signed: SignedNetworkParameters, trustRoot: X509Certificate) {
val networkParameters: NetworkParameters = signed.verifiedNetworkMapCert(trustRoot) // for backwards compatibility we allow netparams to be signed with the networkmap cert,
// but going forwards we also accept the distinct netparams cert as well
val networkParameters: NetworkParameters = signed.verifiedNetworkParametersCert(trustRoot)
operator fun component1() = networkParameters operator fun component1() = networkParameters
operator fun component2() = signed operator fun component2() = signed
} }

@ -208,7 +208,7 @@ The node will shutdown now.""")
return return
} }
val newSignedNetParams = networkMapClient.getNetworkParameters(update.newParametersHash) val newSignedNetParams = networkMapClient.getNetworkParameters(update.newParametersHash)
val newNetParams = newSignedNetParams.verifiedNetworkMapCert(trustRoot) val newNetParams = newSignedNetParams.verifiedNetworkParametersCert(trustRoot)
logger.info("Downloaded new network parameters: $newNetParams from the update: $update") logger.info("Downloaded new network parameters: $newNetParams from the update: $update")
newNetworkParameters = Pair(update, newSignedNetParams) newNetworkParameters = Pair(update, newSignedNetParams)
val updateInfo = ParametersUpdateInfo( val updateInfo = ParametersUpdateInfo(
@ -233,7 +233,7 @@ The node will shutdown now.""")
// Add persisting of newest parameters from update. // Add persisting of newest parameters from update.
val (update, signedNewNetParams) = requireNotNull(newNetworkParameters) { "Couldn't find parameters update for the hash: $parametersHash" } val (update, signedNewNetParams) = requireNotNull(newNetworkParameters) { "Couldn't find parameters update for the hash: $parametersHash" }
// We should check that we sign the right data structure hash. // We should check that we sign the right data structure hash.
val newNetParams = signedNewNetParams.verifiedNetworkMapCert(trustRoot) val newNetParams = signedNewNetParams.verifiedNetworkParametersCert(trustRoot)
val newParametersHash = signedNewNetParams.raw.hash val newParametersHash = signedNewNetParams.raw.hash
if (parametersHash == newParametersHash) { if (parametersHash == newParametersHash) {
// The latest parameters have priority. // The latest parameters have priority.

@ -22,10 +22,7 @@ import net.corda.core.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.NodeInfoAndSigned import net.corda.nodeapi.internal.NodeInfoAndSigned
import net.corda.nodeapi.internal.SignedNodeInfo import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.X509Utilities
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME import net.corda.nodeapi.internal.network.*
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
import net.corda.nodeapi.internal.network.SignedNetworkParameters
import net.corda.nodeapi.internal.network.verifiedNetworkMapCert
import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.common.internal.testNetworkParameters
import net.corda.testing.core.* import net.corda.testing.core.*
import net.corda.testing.internal.DEV_ROOT_CA import net.corda.testing.internal.DEV_ROOT_CA
@ -240,7 +237,7 @@ class NetworkMapUpdaterTest {
assert(!updateFile.exists()) { "network parameters should not be auto accepted" } assert(!updateFile.exists()) { "network parameters should not be auto accepted" }
updater.acceptNewNetworkParameters(newHash) { it.serialize().sign(ourKeyPair) } updater.acceptNewNetworkParameters(newHash) { it.serialize().sign(ourKeyPair) }
val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>() val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>()
val paramsFromFile = signedNetworkParams.verifiedNetworkMapCert(DEV_ROOT_CA.certificate) val paramsFromFile = signedNetworkParams.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
assertEquals(newParameters, paramsFromFile) assertEquals(newParameters, paramsFromFile)
assertEquals(newHash, server.latestParametersAccepted(ourKeyPair.public)) assertEquals(newHash, server.latestParametersAccepted(ourKeyPair.public))
} }
@ -258,7 +255,7 @@ class NetworkMapUpdaterTest {
val newHash = newParameters.serialize().hash val newHash = newParameters.serialize().hash
val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME val updateFile = baseDir / NETWORK_PARAMS_UPDATE_FILE_NAME
val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>() val signedNetworkParams = updateFile.readObject<SignedNetworkParameters>()
val paramsFromFile = signedNetworkParams.verifiedNetworkMapCert(DEV_ROOT_CA.certificate) val paramsFromFile = signedNetworkParams.verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
assertEquals(newParameters, paramsFromFile) assertEquals(newParameters, paramsFromFile)
assertEquals(newHash, server.latestParametersAccepted(ourKeyPair.public)) assertEquals(newHash, server.latestParametersAccepted(ourKeyPair.public))
} }

@ -2,10 +2,7 @@ package net.corda.node.services.network
import com.google.common.jimfs.Configuration import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
import net.corda.core.internal.createDirectories import net.corda.core.internal.*
import net.corda.core.internal.div
import net.corda.core.internal.exists
import net.corda.core.internal.readObject
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.utilities.days import net.corda.core.utilities.days
import net.corda.core.utilities.seconds import net.corda.core.utilities.seconds
@ -64,7 +61,7 @@ class NetworkParametersReaderTest {
// Parameters from update should be moved to `network-parameters` file. // Parameters from update should be moved to `network-parameters` file.
val parametersFromFile = (baseDirectory / NETWORK_PARAMS_FILE_NAME) val parametersFromFile = (baseDirectory / NETWORK_PARAMS_FILE_NAME)
.readObject<SignedNetworkParameters>() .readObject<SignedNetworkParameters>()
.verifiedNetworkMapCert(DEV_ROOT_CA.certificate) .verifiedNetworkParametersCert(DEV_ROOT_CA.certificate)
assertEquals(server.networkParameters, parametersFromFile) assertEquals(server.networkParameters, parametersFromFile)
} }