mirror of
https://github.com/corda/corda.git
synced 2025-06-12 04:08:26 +00:00
[CORDA-2866] Prevent node startup if legal identity key is lost but node key isn't (#5090)
This commit is contained in:
@ -38,7 +38,7 @@ object DevIdentityGenerator {
|
|||||||
val p2pSslConfig = SslConfiguration.mutual(p2pKeyStore, p2pTrustStore)
|
val p2pSslConfig = SslConfiguration.mutual(p2pKeyStore, p2pTrustStore)
|
||||||
|
|
||||||
certificatesDirectory.createDirectories()
|
certificatesDirectory.createDirectories()
|
||||||
val nodeKeyStore = signingCertStore.get(true).also { it.registerDevSigningCertificates(legalName) }
|
val nodeKeyStore = signingCertStore.get(true).also { it.installDevNodeCaCertPath(legalName) }
|
||||||
p2pSslConfig.keyStore.get(true).also { it.registerDevP2pCertificates(legalName) }
|
p2pSslConfig.keyStore.get(true).also { it.registerDevP2pCertificates(legalName) }
|
||||||
|
|
||||||
val identity = nodeKeyStore.storeLegalIdentity("$NODE_IDENTITY_ALIAS_PREFIX-private-key")
|
val identity = nodeKeyStore.storeLegalIdentity("$NODE_IDENTITY_ALIAS_PREFIX-private-key")
|
||||||
|
@ -26,14 +26,14 @@ import javax.security.auth.x500.X500Principal
|
|||||||
* the given legal name), and the SSL key store will store the TLS cert which is a sub-cert of the node CA.
|
* the given legal name), and the SSL key store will store the TLS cert which is a sub-cert of the node CA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fun CertificateStore.registerDevSigningCertificates(legalName: CordaX500Name,
|
fun CertificateStore.installDevNodeCaCertPath(legalName: CordaX500Name,
|
||||||
rootCert: X509Certificate = DEV_ROOT_CA.certificate,
|
rootCert: X509Certificate = DEV_ROOT_CA.certificate,
|
||||||
intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA,
|
intermediateCa: CertificateAndKeyPair = DEV_INTERMEDIATE_CA,
|
||||||
devNodeCa: CertificateAndKeyPair = createDevNodeCa(intermediateCa, legalName)) {
|
devNodeCa: CertificateAndKeyPair = createDevNodeCa(intermediateCa, legalName)) {
|
||||||
|
|
||||||
update {
|
update {
|
||||||
setPrivateKey(X509Utilities.CORDA_CLIENT_CA, devNodeCa.keyPair.private, listOf(devNodeCa.certificate, intermediateCa.certificate, rootCert),
|
setPrivateKey(X509Utilities.CORDA_CLIENT_CA, devNodeCa.keyPair.private, listOf(devNodeCa.certificate, intermediateCa.certificate, rootCert),
|
||||||
this@registerDevSigningCertificates.entryPassword)
|
this@installDevNodeCaCertPath.entryPassword)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.nodeapi.internal.crypto
|
package net.corda.nodeapi.internal.crypto
|
||||||
|
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.Crypto.COMPOSITE_KEY
|
import net.corda.core.crypto.Crypto.COMPOSITE_KEY
|
||||||
import net.corda.core.crypto.Crypto.ECDSA_SECP256K1_SHA256
|
import net.corda.core.crypto.Crypto.ECDSA_SECP256K1_SHA256
|
||||||
import net.corda.core.crypto.Crypto.ECDSA_SECP256R1_SHA256
|
import net.corda.core.crypto.Crypto.ECDSA_SECP256R1_SHA256
|
||||||
@ -8,6 +8,8 @@ import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
|
|||||||
import net.corda.core.crypto.Crypto.RSA_SHA256
|
import net.corda.core.crypto.Crypto.RSA_SHA256
|
||||||
import net.corda.core.crypto.Crypto.SPHINCS256_SHA256
|
import net.corda.core.crypto.Crypto.SPHINCS256_SHA256
|
||||||
import net.corda.core.crypto.Crypto.generateKeyPair
|
import net.corda.core.crypto.Crypto.generateKeyPair
|
||||||
|
import net.corda.core.crypto.SignatureScheme
|
||||||
|
import net.corda.core.crypto.newSecureRandom
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
@ -18,9 +20,9 @@ import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
|||||||
import net.corda.nodeapi.internal.createDevNodeCa
|
import net.corda.nodeapi.internal.createDevNodeCa
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME
|
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
|
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
|
||||||
|
import net.corda.nodeapi.internal.installDevNodeCaCertPath
|
||||||
import net.corda.nodeapi.internal.protonwrapper.netty.init
|
import net.corda.nodeapi.internal.protonwrapper.netty.init
|
||||||
import net.corda.nodeapi.internal.registerDevP2pCertificates
|
import net.corda.nodeapi.internal.registerDevP2pCertificates
|
||||||
import net.corda.nodeapi.internal.registerDevSigningCertificates
|
|
||||||
import net.corda.serialization.internal.AllWhitelist
|
import net.corda.serialization.internal.AllWhitelist
|
||||||
import net.corda.serialization.internal.SerializationContextImpl
|
import net.corda.serialization.internal.SerializationContextImpl
|
||||||
import net.corda.serialization.internal.SerializationFactoryImpl
|
import net.corda.serialization.internal.SerializationFactoryImpl
|
||||||
@ -28,8 +30,8 @@ import net.corda.serialization.internal.amqp.amqpMagic
|
|||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.core.TestIdentity
|
import net.corda.testing.core.TestIdentity
|
||||||
import net.corda.testing.internal.stubs.CertificateStoreStubs
|
|
||||||
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
import net.corda.testing.internal.createDevIntermediateCaCertPath
|
||||||
|
import net.corda.testing.internal.stubs.CertificateStoreStubs
|
||||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x509.*
|
import org.bouncycastle.asn1.x509.*
|
||||||
@ -232,7 +234,7 @@ class X509UtilitiesTest {
|
|||||||
|
|
||||||
// Generate server cert and private key and populate another keystore suitable for SSL
|
// Generate server cert and private key and populate another keystore suitable for SSL
|
||||||
val nodeCa = createDevNodeCa(intermediateCa, MEGA_CORP.name)
|
val nodeCa = createDevNodeCa(intermediateCa, MEGA_CORP.name)
|
||||||
signingCertStore.get(createNew = true).also { it.registerDevSigningCertificates(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) }
|
signingCertStore.get(createNew = true).also { it.installDevNodeCaCertPath(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) }
|
||||||
p2pSslConfig.keyStore.get(createNew = true).also { it.registerDevP2pCertificates(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) }
|
p2pSslConfig.keyStore.get(createNew = true).also { it.registerDevP2pCertificates(MEGA_CORP.name, rootCa.certificate, intermediateCa, nodeCa) }
|
||||||
// Load back server certificate
|
// Load back server certificate
|
||||||
val certStore = signingCertStore.get()
|
val certStore = signingCertStore.get()
|
||||||
|
@ -5,27 +5,31 @@ import net.corda.client.rpc.CordaRPCClient
|
|||||||
import net.corda.core.CordaRuntimeException
|
import net.corda.core.CordaRuntimeException
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.isRegularFile
|
|
||||||
import net.corda.core.internal.list
|
|
||||||
import net.corda.core.internal.readLines
|
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.NodeStartup
|
import net.corda.node.internal.NodeStartup
|
||||||
import net.corda.node.services.Permissions.Companion.startFlow
|
import net.corda.node.services.Permissions.Companion.startFlow
|
||||||
import net.corda.nodeapi.exceptions.InternalNodeException
|
import net.corda.nodeapi.exceptions.InternalNodeException
|
||||||
|
import net.corda.nodeapi.internal.crypto.X509Utilities.NODE_IDENTITY_ALIAS_PREFIX
|
||||||
|
import net.corda.nodeapi.internal.installDevNodeCaCertPath
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.driver.DriverParameters
|
import net.corda.testing.driver.DriverParameters
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.NodeParameters
|
import net.corda.testing.driver.NodeParameters
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.internal.stubs.CertificateStoreStubs
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
import net.corda.testing.node.internal.startNode
|
import net.corda.testing.node.internal.startNode
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.*
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.ObjectInputStream
|
||||||
|
import java.io.ObjectOutputStream
|
||||||
|
import java.io.Serializable
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class BootTests {
|
class BootTests {
|
||||||
@Test
|
@Test
|
||||||
@ -64,6 +68,29 @@ class BootTests {
|
|||||||
assertEquals(1, numberOfNodesThatLogged)
|
assertEquals(1, numberOfNodesThatLogged)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `node fails to start if legal identity is lost`() {
|
||||||
|
driver(DriverParameters(notarySpecs = emptyList(), inMemoryDB = false, startNodesInProcess = false)) {
|
||||||
|
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
|
val aliceCertDir = alice.baseDirectory / "certificates"
|
||||||
|
(aliceCertDir / "nodekeystore.jks").delete()
|
||||||
|
val cert = CertificateStoreStubs.Signing.withCertificatesDirectory(aliceCertDir).get(true)
|
||||||
|
// Creating a new certificate store does not populate that store with the node certificate path. If the node certificate path is
|
||||||
|
// missing, the node will fail to start but not because the legal identity is missing. To test that a missing legal identity
|
||||||
|
// prevents the node from starting, the node certificate path must be installed.
|
||||||
|
cert.installDevNodeCaCertPath(ALICE_NAME)
|
||||||
|
alice.stop()
|
||||||
|
// The node shouldn't start, and the logs should indicate that the failure is due to a missing identity key
|
||||||
|
assertThatThrownBy {
|
||||||
|
startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
|
}
|
||||||
|
val logFolder = alice.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME
|
||||||
|
val logFile = logFolder.list { it.filter { a -> a.isRegularFile() && a.fileName.toString().startsWith("node") }.findFirst().get() }
|
||||||
|
val lines = logFile.readLines { lines -> lines.filter { "$NODE_IDENTITY_ALIAS_PREFIX-private-key" in it }.toArray() }
|
||||||
|
assertTrue(lines.count() > 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@StartableByRPC
|
@StartableByRPC
|
||||||
|
@ -17,13 +17,13 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_PREFIX
|
|||||||
import net.corda.nodeapi.internal.ArtemisTcpTransport
|
import net.corda.nodeapi.internal.ArtemisTcpTransport
|
||||||
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||||
|
import net.corda.nodeapi.internal.installDevNodeCaCertPath
|
||||||
import net.corda.nodeapi.internal.protonwrapper.messages.MessageStatus
|
import net.corda.nodeapi.internal.protonwrapper.messages.MessageStatus
|
||||||
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPClient
|
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPClient
|
||||||
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPConfiguration
|
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPConfiguration
|
||||||
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPServer
|
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPServer
|
||||||
import net.corda.nodeapi.internal.protonwrapper.netty.init
|
import net.corda.nodeapi.internal.protonwrapper.netty.init
|
||||||
import net.corda.nodeapi.internal.registerDevP2pCertificates
|
import net.corda.nodeapi.internal.registerDevP2pCertificates
|
||||||
import net.corda.nodeapi.internal.registerDevSigningCertificates
|
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.core.CHARLIE_NAME
|
import net.corda.testing.core.CHARLIE_NAME
|
||||||
@ -133,7 +133,7 @@ class ProtonWrapperTests {
|
|||||||
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
val (rootCa, intermediateCa) = createDevIntermediateCaCertPath()
|
||||||
|
|
||||||
// Generate server cert and private key and populate another keystore suitable for SSL
|
// Generate server cert and private key and populate another keystore suitable for SSL
|
||||||
signingCertificateStore.get(true).also { it.registerDevSigningCertificates(ALICE_NAME, rootCa.certificate, intermediateCa) }
|
signingCertificateStore.get(true).also { it.installDevNodeCaCertPath(ALICE_NAME, rootCa.certificate, intermediateCa) }
|
||||||
sslConfig.keyStore.get(true).also { it.registerDevP2pCertificates(ALICE_NAME, rootCa.certificate, intermediateCa) }
|
sslConfig.keyStore.get(true).also { it.registerDevP2pCertificates(ALICE_NAME, rootCa.certificate, intermediateCa) }
|
||||||
sslConfig.createTrustStore(rootCa.certificate)
|
sslConfig.createTrustStore(rootCa.certificate)
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ class HardRestartTest {
|
|||||||
Thread.sleep(ms.toLong())
|
Thread.sleep(ms.toLong())
|
||||||
(b as OutOfProcess).process.destroyForcibly()
|
(b as OutOfProcess).process.destroyForcibly()
|
||||||
b.stop()
|
b.stop()
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser), customOverrides = mapOf("p2pAddress" to "localhost:${b.rpcAddress.port}"))
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser))
|
||||||
}
|
}
|
||||||
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
||||||
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 1).returnValue
|
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 1).returnValue
|
||||||
@ -122,7 +122,7 @@ class HardRestartTest {
|
|||||||
Thread.sleep(ms.toLong())
|
Thread.sleep(ms.toLong())
|
||||||
(b as OutOfProcess).process.destroyForcibly()
|
(b as OutOfProcess).process.destroyForcibly()
|
||||||
b.stop()
|
b.stop()
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser), customOverrides = mapOf("p2pAddress" to "localhost:${b.rpcAddress.port}"))
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser))
|
||||||
}
|
}
|
||||||
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
||||||
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 100).returnValue
|
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 100).returnValue
|
||||||
@ -159,7 +159,7 @@ class HardRestartTest {
|
|||||||
println("Sleeping $ms ms before kill")
|
println("Sleeping $ms ms before kill")
|
||||||
Thread.sleep(ms.toLong())
|
Thread.sleep(ms.toLong())
|
||||||
b.stop()
|
b.stop()
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser), customOverrides = mapOf("p2pAddress" to "localhost:${b.rpcAddress.port}"))
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser))
|
||||||
}
|
}
|
||||||
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
CordaRPCClient(a.rpcAddress).use(demoUser.username, demoUser.password) {
|
||||||
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 100).returnValue
|
val returnValue = it.proxy.startFlow(::Ping, b.nodeInfo.singleIdentity(), 100).returnValue
|
||||||
@ -242,7 +242,7 @@ class HardRestartTest {
|
|||||||
Thread.sleep(ms.toLong())
|
Thread.sleep(ms.toLong())
|
||||||
(b as OutOfProcess).process.destroyForcibly()
|
(b as OutOfProcess).process.destroyForcibly()
|
||||||
b.stop()
|
b.stop()
|
||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser), customOverrides = mapOf("p2pAddress" to "localhost:${b.rpcAddress.port}"))
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser))
|
||||||
}
|
}
|
||||||
val executor = Executors.newFixedThreadPool(8)
|
val executor = Executors.newFixedThreadPool(8)
|
||||||
try {
|
try {
|
||||||
|
@ -55,7 +55,6 @@ import net.corda.node.services.events.ScheduledActivityObserver
|
|||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
import net.corda.node.services.keys.BasicHSMKeyManagementService
|
import net.corda.node.services.keys.BasicHSMKeyManagementService
|
||||||
import net.corda.node.services.keys.KeyManagementServiceInternal
|
import net.corda.node.services.keys.KeyManagementServiceInternal
|
||||||
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
|
||||||
import net.corda.node.services.messaging.DeduplicationHandler
|
import net.corda.node.services.messaging.DeduplicationHandler
|
||||||
import net.corda.node.services.messaging.MessagingService
|
import net.corda.node.services.messaging.MessagingService
|
||||||
import net.corda.node.services.network.NetworkMapClient
|
import net.corda.node.services.network.NetworkMapClient
|
||||||
@ -82,6 +81,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
|||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_VALIDITY_WINDOW
|
import net.corda.nodeapi.internal.crypto.X509Utilities.DEFAULT_VALIDITY_WINDOW
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.DISTRIBUTED_NOTARY_ALIAS_PREFIX
|
import net.corda.nodeapi.internal.crypto.X509Utilities.DISTRIBUTED_NOTARY_ALIAS_PREFIX
|
||||||
import net.corda.nodeapi.internal.crypto.X509Utilities.NODE_IDENTITY_ALIAS_PREFIX
|
import net.corda.nodeapi.internal.crypto.X509Utilities.NODE_IDENTITY_ALIAS_PREFIX
|
||||||
|
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
||||||
import net.corda.nodeapi.internal.persistence.*
|
import net.corda.nodeapi.internal.persistence.*
|
||||||
import net.corda.tools.shell.InteractiveShell
|
import net.corda.tools.shell.InteractiveShell
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
@ -286,8 +286,8 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
check(started == null) { "Node has already been started" }
|
check(started == null) { "Node has already been started" }
|
||||||
log.info("Generating nodeInfo ...")
|
log.info("Generating nodeInfo ...")
|
||||||
val trustRoot = initKeyStores()
|
val trustRoot = initKeyStores()
|
||||||
val (identity, identityKeyPair) = obtainIdentity()
|
|
||||||
startDatabase()
|
startDatabase()
|
||||||
|
val (identity, identityKeyPair) = obtainIdentity()
|
||||||
val nodeCa = configuration.signingCertificateStore.get()[CORDA_CLIENT_CA]
|
val nodeCa = configuration.signingCertificateStore.get()[CORDA_CLIENT_CA]
|
||||||
identityService.start(trustRoot, listOf(identity.certificate, nodeCa))
|
identityService.start(trustRoot, listOf(identity.certificate, nodeCa))
|
||||||
return database.use {
|
return database.use {
|
||||||
@ -838,6 +838,16 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
|||||||
|
|
||||||
var signingCertificateStore = configuration.signingCertificateStore.get()
|
var signingCertificateStore = configuration.signingCertificateStore.get()
|
||||||
if (!cryptoService.containsKey(legalIdentityPrivateKeyAlias) && !signingCertificateStore.contains(legalIdentityPrivateKeyAlias)) {
|
if (!cryptoService.containsKey(legalIdentityPrivateKeyAlias) && !signingCertificateStore.contains(legalIdentityPrivateKeyAlias)) {
|
||||||
|
// Directly use the X500 name to public key map, as the identity service requires the node identity to start correctly.
|
||||||
|
database.transaction {
|
||||||
|
val x500Map = PersistentIdentityService.createX500Map(cacheFactory)
|
||||||
|
require(configuration.myLegalName !in x500Map) {
|
||||||
|
// There is already a party in the identity store for this node, but the key has been lost. If this node starts up, it will
|
||||||
|
// publish it's new key to the network map, which Corda cannot currently handle. To prevent this, stop the node from starting.
|
||||||
|
"Private key for the node legal identity not found (alias $legalIdentityPrivateKeyAlias) but the corresponding public key" +
|
||||||
|
" for it exists in the database. This suggests the identity for this node has been lost. Shutting down to prevent network map issues."
|
||||||
|
}
|
||||||
|
}
|
||||||
log.info("$legalIdentityPrivateKeyAlias not found in key store, generating fresh key!")
|
log.info("$legalIdentityPrivateKeyAlias not found in key store, generating fresh key!")
|
||||||
createAndStoreLegalIdentity(legalIdentityPrivateKeyAlias)
|
createAndStoreLegalIdentity(legalIdentityPrivateKeyAlias)
|
||||||
signingCertificateStore = configuration.signingCertificateStore.get() // We need to resync after [createAndStoreLegalIdentity].
|
signingCertificateStore = configuration.signingCertificateStore.get() // We need to resync after [createAndStoreLegalIdentity].
|
||||||
|
@ -8,13 +8,16 @@ import net.corda.core.identity.CordaX500Name
|
|||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
import net.corda.nodeapi.internal.DEV_CA_KEY_STORE_PASS
|
||||||
import net.corda.nodeapi.internal.*
|
|
||||||
import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier
|
import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier
|
||||||
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
||||||
import net.corda.nodeapi.internal.config.toProperties
|
import net.corda.nodeapi.internal.config.toProperties
|
||||||
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||||
import net.corda.nodeapi.internal.cryptoservice.CryptoService
|
import net.corda.nodeapi.internal.cryptoservice.CryptoService
|
||||||
|
import net.corda.nodeapi.internal.cryptoservice.bouncycastle.BCCryptoService
|
||||||
|
import net.corda.nodeapi.internal.installDevNodeCaCertPath
|
||||||
|
import net.corda.nodeapi.internal.loadDevCaTrustStore
|
||||||
|
import net.corda.nodeapi.internal.registerDevP2pCertificates
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
@ -92,7 +95,7 @@ fun MutualSslConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500N
|
|||||||
when (cryptoService) {
|
when (cryptoService) {
|
||||||
is BCCryptoService, null -> {
|
is BCCryptoService, null -> {
|
||||||
val signingKeyStore = FileBasedCertificateStoreSupplier(signingCertificateStore.path, signingCertificateStore.storePassword, signingCertificateStore.entryPassword).get(true)
|
val signingKeyStore = FileBasedCertificateStoreSupplier(signingCertificateStore.path, signingCertificateStore.storePassword, signingCertificateStore.entryPassword).get(true)
|
||||||
.also { it.registerDevSigningCertificates(myLegalName) }
|
.also { it.installDevNodeCaCertPath(myLegalName) }
|
||||||
|
|
||||||
// Move distributed service composite key (generated by IdentityGenerator.generateToDisk) to keystore if exists.
|
// Move distributed service composite key (generated by IdentityGenerator.generateToDisk) to keystore if exists.
|
||||||
val distributedServiceKeystore = certificatesDirectory / "distributedService.jks"
|
val distributedServiceKeystore = certificatesDirectory / "distributedService.jks"
|
||||||
|
Reference in New Issue
Block a user