diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt index 0abe86076e..2dcfdf709c 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt @@ -114,7 +114,18 @@ object X509Utilities { fun validateCertPath(trustedRoot: X509Certificate, certPath: CertPath) { val params = PKIXParameters(setOf(TrustAnchor(trustedRoot, null))) params.isRevocationEnabled = false - CertPathValidator.getInstance("PKIX").validate(certPath, params) + try { + CertPathValidator.getInstance("PKIX").validate(certPath, params) + } catch (e: CertPathValidatorException) { + throw CertPathValidatorException( + """Cert path failed to validate against root certificate. +Reason: ${e.reason} +Offending cert index: ${e.index} +Cert path: $certPath + +Root certificate: +$trustedRoot""", e, certPath, e.index) + } } /** diff --git a/node/src/main/kotlin/net/corda/node/ArgsParser.kt b/node/src/main/kotlin/net/corda/node/ArgsParser.kt index 1c3a2b8857..3107e8bff0 100644 --- a/node/src/main/kotlin/net/corda/node/ArgsParser.kt +++ b/node/src/main/kotlin/net/corda/node/ArgsParser.kt @@ -108,18 +108,23 @@ data class CmdLineOptions(val baseDirectory: Path, val help: Boolean, val loggingLevel: Level, val logToConsole: Boolean, - val nodeRegistrationConfig: NodeRegistrationOption?, + val nodeRegistrationOption: NodeRegistrationOption?, val isVersion: Boolean, val noLocalShell: Boolean, val sshdServer: Boolean, val justGenerateNodeInfo: Boolean, val bootstrapRaftCluster: Boolean) { fun loadConfig(): NodeConfiguration { - val config = ConfigHelper.loadConfig(baseDirectory, configFile, configOverrides = ConfigFactory.parseMap( - mapOf("noLocalShell" to this.noLocalShell) - )).parseAsNodeConfiguration() - if (nodeRegistrationConfig != null) { - requireNotNull(config.compatibilityZoneURL) { "Compatibility Zone URL (compatibilityZoneURL) must be present in node configuration file in registration mode." } + val config = ConfigHelper.loadConfig( + baseDirectory, + configFile, + configOverrides = ConfigFactory.parseMap(mapOf("noLocalShell" to this.noLocalShell)) + ).parseAsNodeConfiguration() + if (nodeRegistrationOption != null) { + require(!config.devMode) { "registration cannot occur in devMode" } + requireNotNull(config.compatibilityZoneURL) { + "compatibilityZoneURL must be present in node configuration file in registration mode." + } } return config } diff --git a/node/src/main/kotlin/net/corda/node/internal/NetworkParametersReader.kt b/node/src/main/kotlin/net/corda/node/internal/NetworkParametersReader.kt index a578781cff..760711f244 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NetworkParametersReader.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NetworkParametersReader.kt @@ -20,6 +20,7 @@ import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME 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.net.ConnectException import java.nio.file.Path import java.nio.file.StandardCopyOption import java.security.cert.X509Certificate @@ -36,7 +37,13 @@ class NetworkParametersReader(private val trustRoot: X509Certificate, val networkParameters by lazy { retrieveNetworkParameters() } private fun retrieveNetworkParameters(): NetworkParameters { - val advertisedParametersHash = networkMapClient?.getNetworkMap()?.payload?.networkParameterHash + val advertisedParametersHash = try { + networkMapClient?.getNetworkMap()?.payload?.networkParameterHash + } catch (e: ConnectException) { + logger.info("Couldn't connect to NetworkMap", e) + // If NetworkMap is down while restarting the node, we should be still able to continue with parameters from file + null + } val signedParametersFromFile = if (networkParamsFile.exists()) { networkParamsFile.readObject() } else { @@ -54,7 +61,7 @@ class NetworkParametersReader(private val trustRoot: X509Certificate, readParametersUpdate(advertisedParametersHash, signedParametersFromFile.raw.hash).verifiedNetworkMapCert(trustRoot) } } else { // No compatibility zone configured. Node should proceed with parameters from file. - signedParametersFromFile?.verifiedNetworkMapCert(trustRoot) ?: throw IllegalArgumentException("Couldn't find network parameters file and compatibility zone wasn't configured") + signedParametersFromFile?.verifiedNetworkMapCert(trustRoot) ?: throw IllegalArgumentException("Couldn't find network parameters file and compatibility zone wasn't configured/isn't reachable") } logger.info("Loaded network parameters: $parameters") return parameters diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index 524675b42f..b61a54a032 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -115,9 +115,9 @@ open class NodeStartup(val args: Array) { try { banJavaSerialisation(conf) preNetworkRegistration(conf) - if (cmdlineOptions.nodeRegistrationConfig != null) { + if (cmdlineOptions.nodeRegistrationOption != null) { // Null checks for [compatibilityZoneURL], [rootTruststorePath] and [rootTruststorePassword] has been done in [CmdLineOptions.loadConfig] - registerWithNetwork(conf, cmdlineOptions.nodeRegistrationConfig) + registerWithNetwork(conf, cmdlineOptions.nodeRegistrationOption) return true } logStartupInfo(versionInfo, cmdlineOptions, conf) diff --git a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapUpdater.kt b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapUpdater.kt index b44bfe5270..6d15d0af8b 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapUpdater.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapUpdater.kt @@ -15,6 +15,8 @@ import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SignedData import net.corda.core.internal.copyTo import net.corda.core.internal.div +import net.corda.core.internal.exists +import net.corda.core.internal.readObject import net.corda.core.messaging.DataFeed import net.corda.core.messaging.ParametersUpdateInfo import net.corda.core.serialization.serialize @@ -121,10 +123,16 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal, networkMap.parametersUpdate?.let { handleUpdateNetworkParameters(networkMapClient, it) } if (currentParametersHash != networkMap.networkParameterHash) { - // TODO This needs special handling (node omitted update process/didn't accept new parameters or didn't restart on updateDeadline) - logger.error("Node is using parameters with hash: $currentParametersHash but network map is " + - "advertising: ${networkMap.networkParameterHash}.\n" + - "Please update node to use correct network parameters file.\"") + val updatesFile = baseDirectory / NETWORK_PARAMS_UPDATE_FILE_NAME + val acceptedHash = if (updatesFile.exists()) updatesFile.readObject().raw.hash else null + if (acceptedHash == networkMap.networkParameterHash) { + logger.info("Flag day occurred. Network map switched to the new network parameters: ${networkMap.networkParameterHash}. Node will shutdown now and needs to be started again.") + } else { + // TODO This needs special handling (node omitted update process or didn't accept new parameters) + logger.error("Node is using parameters with hash: $currentParametersHash but network map is " + + "advertising: ${networkMap.networkParameterHash}.\n" + + "Node will shutdown now. Please update node to use correct network parameters file.") + } System.exit(1) } @@ -170,7 +178,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal, } fun acceptNewNetworkParameters(parametersHash: SecureHash, sign: (SecureHash) -> SignedData) { - networkMapClient ?: throw IllegalStateException("Network parameters updates are not support without compatibility zone configured") + networkMapClient ?: throw IllegalStateException("Network parameters updates are not supported without compatibility zone configured") // TODO This scenario will happen if node was restarted and didn't download parameters yet, but we accepted them. // Add persisting of newest parameters from update. val (update, signedNewNetParams) = requireNotNull(newNetworkParameters) { "Couldn't find parameters update for the hash: $parametersHash" } diff --git a/node/src/test/kotlin/net/corda/node/ArgsParserTest.kt b/node/src/test/kotlin/net/corda/node/ArgsParserTest.kt index 2d6364d6cf..8c50074f92 100644 --- a/node/src/test/kotlin/net/corda/node/ArgsParserTest.kt +++ b/node/src/test/kotlin/net/corda/node/ArgsParserTest.kt @@ -47,7 +47,7 @@ class ArgsParserTest { help = false, logToConsole = false, loggingLevel = Level.INFO, - nodeRegistrationConfig = null, + nodeRegistrationOption = null, isVersion = false, noLocalShell = false, sshdServer = false, @@ -146,9 +146,9 @@ class ArgsParserTest { X509KeyStore.fromFile(truststorePath, "dummy_password", createNew = true) try { val cmdLineOptions = parser.parse("--initial-registration", "--network-root-truststore", "$truststorePath", "--network-root-truststore-password", "password-test") - assertNotNull(cmdLineOptions.nodeRegistrationConfig) - assertEquals(truststorePath.toAbsolutePath(), cmdLineOptions.nodeRegistrationConfig?.networkRootTrustStorePath) - assertEquals("password-test", cmdLineOptions.nodeRegistrationConfig?.networkRootTrustStorePassword) + assertNotNull(cmdLineOptions.nodeRegistrationOption) + assertEquals(truststorePath.toAbsolutePath(), cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePath) + assertEquals("password-test", cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePassword) } finally { Files.delete(truststorePath) } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt index 462e9ac8a0..dead4cd9f5 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/DriverDSLImpl.kt @@ -256,7 +256,8 @@ class DriverDSLImpl( configOverrides = configOf( "p2pAddress" to "localhost:1222", // required argument, not really used "compatibilityZoneURL" to compatibilityZoneURL.toString(), - "myLegalName" to providedName.toString()) + "myLegalName" to providedName.toString(), + "devMode" to false) )) config.corda.certificatesDirectory.createDirectories()