mirror of
https://github.com/corda/corda.git
synced 2025-04-07 19:34:41 +00:00
CORDA-1968 Ensure we check for the trustroot existence and alias validity. (#3917)
* Ensure we check for the trustroot existence and alias validity. * fix missing keystore message on integration test after changes. * adding more requirements to check for missing aliases to validateKeyStores * import X509Utilities const values (CORDA_ROOT_CA, CORDA_CLIENT_CA, CORDA_CLIENT_TLS) to AbstractNode. * address review comment: avoid using !! (not null)
This commit is contained in:
parent
37c7fff8b1
commit
3ff7fc2585
@ -20,14 +20,14 @@ class NodeKeystoreCheckTest {
|
||||
driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) {
|
||||
assertThatThrownBy {
|
||||
startNode(customOverrides = mapOf("devMode" to false)).getOrThrow()
|
||||
}.hasMessageContaining("Identity certificate not found")
|
||||
}.hasMessageContaining("One or more keyStores (identity or TLS) or trustStore not found.")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `node should throw exception if cert path doesn't chain to the trust root`() {
|
||||
driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) {
|
||||
// Create keystores
|
||||
// Create keystores.
|
||||
val keystorePassword = "password"
|
||||
val certificatesDirectory = baseDirectory(ALICE_NAME) / "certificates"
|
||||
val signingCertStore = CertificateStoreStubs.Signing.withCertificatesDirectory(certificatesDirectory, keystorePassword)
|
||||
@ -46,7 +46,7 @@ class NodeKeystoreCheckTest {
|
||||
|
||||
// Fiddle with node keystore.
|
||||
signingCertStore.get().update {
|
||||
// Self signed root
|
||||
// Self signed root.
|
||||
val badRootKeyPair = Crypto.generateKeyPair()
|
||||
val badRoot = X509Utilities.createSelfSignedCACertificate(X500Principal("O=Bad Root,L=Lodnon,C=GB"), badRootKeyPair)
|
||||
val nodeCA = getCertificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
||||
|
@ -69,7 +69,11 @@ import net.corda.node.utilities.NamedThreadFactory
|
||||
import net.corda.node.utilities.NodeBuildProperties
|
||||
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.config.CertificateStore
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_CA
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_CLIENT_TLS
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities.CORDA_ROOT_CA
|
||||
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.persistence.*
|
||||
@ -239,20 +243,20 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
return proxies.fold(ops) { delegate, decorate -> decorate(delegate) }
|
||||
}
|
||||
|
||||
private fun initKeyStore(): X509Certificate {
|
||||
private fun initKeyStores(): X509Certificate {
|
||||
if (configuration.devMode) {
|
||||
configuration.configureWithDevSSLCertificate()
|
||||
}
|
||||
return validateKeyStore()
|
||||
return validateKeyStores()
|
||||
}
|
||||
|
||||
open fun generateAndSaveNodeInfo(): NodeInfo {
|
||||
check(started == null) { "Node has already been started" }
|
||||
log.info("Generating nodeInfo ...")
|
||||
val trustRoot = initKeyStore()
|
||||
val trustRoot = initKeyStores()
|
||||
val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null)
|
||||
startDatabase()
|
||||
val nodeCa = configuration.signingCertificateStore.get()[X509Utilities.CORDA_CLIENT_CA]
|
||||
val nodeCa = configuration.signingCertificateStore.get()[CORDA_CLIENT_CA]
|
||||
identityService.start(trustRoot, listOf(identity.certificate, nodeCa))
|
||||
return database.use {
|
||||
it.transaction {
|
||||
@ -279,8 +283,8 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
}
|
||||
log.info("Node starting up ...")
|
||||
|
||||
val trustRoot = initKeyStore()
|
||||
val nodeCa = configuration.signingCertificateStore.get()[X509Utilities.CORDA_CLIENT_CA]
|
||||
val trustRoot = initKeyStores()
|
||||
val nodeCa = configuration.signingCertificateStore.get()[CORDA_CLIENT_CA]
|
||||
initialiseJVMAgents()
|
||||
|
||||
schemaService.mappedSchemasWarnings().forEach {
|
||||
@ -694,30 +698,50 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
@VisibleForTesting
|
||||
protected open fun acceptableLiveFiberCountOnStop(): Int = 0
|
||||
|
||||
private fun validateKeyStore(): X509Certificate {
|
||||
val containCorrectKeys = try {
|
||||
// This will throw IOException if key file not found or KeyStoreException if keystore password is incorrect.
|
||||
val sslKeystore = configuration.p2pSslOptions.keyStore.get()
|
||||
val identitiesKeystore = configuration.signingCertificateStore.get()
|
||||
X509Utilities.CORDA_CLIENT_TLS in sslKeystore && X509Utilities.CORDA_CLIENT_CA in identitiesKeystore
|
||||
private fun getCertificateStores(): AllCertificateStores? {
|
||||
return try {
|
||||
// The following will throw IOException if key file not found or KeyStoreException if keystore password is incorrect.
|
||||
val sslKeyStore = configuration.p2pSslOptions.keyStore.get()
|
||||
val identitiesKeyStore = configuration.signingCertificateStore.get()
|
||||
val trustStore = configuration.p2pSslOptions.trustStore.get()
|
||||
AllCertificateStores(trustStore, sslKeyStore, identitiesKeyStore)
|
||||
} catch (e: KeyStoreException) {
|
||||
log.warn("Certificate key store found but key store password does not match configuration.")
|
||||
false
|
||||
log.warn("At least one of the keystores or truststore passwords does not match configuration.")
|
||||
null
|
||||
} catch (e: IOException) {
|
||||
log.error("IO exception while trying to validate keystore", e)
|
||||
false
|
||||
log.error("IO exception while trying to validate keystores and truststore", e)
|
||||
null
|
||||
}
|
||||
require(containCorrectKeys) {
|
||||
"Identity certificate not found. " +
|
||||
"Please either copy your existing identity key and certificate from another node, " +
|
||||
}
|
||||
|
||||
private data class AllCertificateStores(val trustStore: CertificateStore, val sslKeyStore: CertificateStore, val identitiesKeyStore: CertificateStore)
|
||||
|
||||
private fun validateKeyStores(): X509Certificate {
|
||||
// Step 1. Check trustStore, sslKeyStore and identitiesKeyStore exist.
|
||||
val certStores = requireNotNull(getCertificateStores()) {
|
||||
"One or more keyStores (identity or TLS) or trustStore not found. " +
|
||||
"Please either copy your existing keys and certificates from another node, " +
|
||||
"or if you don't have one yet, fill out the config file and run corda.jar --initial-registration. " +
|
||||
"Read more at: https://docs.corda.net/permissioning.html"
|
||||
}
|
||||
// Step 2. Check that trustStore contains the correct key-alias entry.
|
||||
require(CORDA_ROOT_CA in certStores.trustStore) {
|
||||
"Alias for trustRoot key not found. Please ensure you have an updated trustStore file."
|
||||
}
|
||||
// Step 3. Check that tls keyStore contains the correct key-alias entry.
|
||||
require(CORDA_CLIENT_TLS in certStores.sslKeyStore) {
|
||||
"Alias for TLS key not found. Please ensure you have an updated TLS keyStore file."
|
||||
}
|
||||
|
||||
// Check all cert path chain to the trusted root
|
||||
val sslCertChainRoot = configuration.p2pSslOptions.keyStore.get().query { getCertificateChain(X509Utilities.CORDA_CLIENT_TLS) }.last()
|
||||
val nodeCaCertChainRoot = configuration.signingCertificateStore.get().query { getCertificateChain(X509Utilities.CORDA_CLIENT_CA) }.last()
|
||||
val trustRoot = configuration.p2pSslOptions.trustStore.get()[X509Utilities.CORDA_ROOT_CA]
|
||||
// Step 4. Check that identity keyStores contain the correct key-alias entry for Node CA.
|
||||
require(CORDA_CLIENT_CA in certStores.identitiesKeyStore) {
|
||||
"Alias for Node CA key not found. Please ensure you have an updated identity keyStore file."
|
||||
}
|
||||
|
||||
// Step 5. Check all cert paths chain to the trusted root.
|
||||
val trustRoot = certStores.trustStore[CORDA_ROOT_CA]
|
||||
val sslCertChainRoot = certStores.sslKeyStore.query { getCertificateChain(CORDA_CLIENT_TLS) }.last()
|
||||
val nodeCaCertChainRoot = certStores.identitiesKeyStore.query { getCertificateChain(CORDA_CLIENT_CA) }.last()
|
||||
|
||||
require(sslCertChainRoot == trustRoot) { "TLS certificate must chain to the trusted root." }
|
||||
require(nodeCaCertChainRoot == trustRoot) { "Client CA certificate must chain to the trusted root." }
|
||||
|
Loading…
x
Reference in New Issue
Block a user