mirror of
https://github.com/corda/corda.git
synced 2025-06-20 16:10:26 +00:00
@ -112,7 +112,8 @@ Unreleased
|
|||||||
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
|
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
|
||||||
public and was already internal for Kotlin code.
|
public and was already internal for Kotlin code.
|
||||||
|
|
||||||
* RPC server will now mask internal errors to RPC clients if not in devMode. ``Throwable``s implementing ``ClientRelevantError`` will continue to be propagated to clients.
|
* RPC server will now mask internal errors to RPC clients if not in devMode. ``Throwable``s implementing ``ClientRelevantError``
|
||||||
|
will continue to be propagated to clients.
|
||||||
|
|
||||||
* RPC Framework moved from Kryo to the Corda AMQP implementation [Corda-847]. This completes the removal
|
* RPC Framework moved from Kryo to the Corda AMQP implementation [Corda-847]. This completes the removal
|
||||||
of ``Kryo`` from general use within Corda, remaining only for use in flow checkpointing.
|
of ``Kryo`` from general use within Corda, remaining only for use in flow checkpointing.
|
||||||
|
@ -344,7 +344,8 @@ In ``devMode``, if the server implementation throws an exception, that exception
|
|||||||
side as if it was thrown from inside the called RPC method. These exceptions can be caught as normal.
|
side as if it was thrown from inside the called RPC method. These exceptions can be caught as normal.
|
||||||
|
|
||||||
When not in ``devMode``, the server will mask exceptions not meant for clients and return an ``InternalNodeException`` instead.
|
When not in ``devMode``, the server will mask exceptions not meant for clients and return an ``InternalNodeException`` instead.
|
||||||
This does not expose internal information to clients, strengthening privacy and security. CorDapps can have exceptions implement ``ClientRelevantError`` to allow them to reach RPC clients.
|
This does not expose internal information to clients, strengthening privacy and security. CorDapps can have exceptions implement
|
||||||
|
``ClientRelevantError`` to allow them to reach RPC clients.
|
||||||
|
|
||||||
Connection management
|
Connection management
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -12,15 +12,19 @@ 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.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.DUMMY_BANK_A_NAME
|
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||||
import net.corda.testing.driver.DriverParameters
|
import net.corda.testing.driver.DriverParameters
|
||||||
|
import net.corda.testing.driver.NodeHandle
|
||||||
|
import net.corda.testing.driver.NodeParameters
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.internal.IntegrationTest
|
import net.corda.testing.internal.IntegrationTest
|
||||||
import net.corda.testing.internal.IntegrationTestSchemas
|
import net.corda.testing.internal.IntegrationTestSchemas
|
||||||
import net.corda.testing.internal.toDatabaseSchemaName
|
import net.corda.testing.internal.toDatabaseSchemaName
|
||||||
import net.corda.testing.node.User
|
import net.corda.testing.node.User
|
||||||
|
import net.corda.testing.node.internal.startNode
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.ClassRule
|
import org.junit.ClassRule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -38,12 +42,21 @@ class BootTests : IntegrationTest() {
|
|||||||
}
|
}
|
||||||
@Test
|
@Test
|
||||||
fun `java deserialization is disabled`() {
|
fun `java deserialization is disabled`() {
|
||||||
driver(DriverParameters(notarySpecs = emptyList())) {
|
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
||||||
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
val params = NodeParameters(rpcUsers = listOf(user))
|
||||||
val future = CordaRPCClient(startNode(rpcUsers = listOf(user)).getOrThrow().rpcAddress).
|
|
||||||
start(user.username, user.password).proxy.startFlow(::ObjectInputStreamFlow).returnValue
|
fun NodeHandle.attemptJavaDeserialization() {
|
||||||
assertThatThrownBy { future.getOrThrow() }
|
CordaRPCClient(rpcAddress).use(user.username, user.password) { connection ->
|
||||||
.isInstanceOf(CordaRuntimeException::class.java)
|
connection.proxy
|
||||||
|
rpc.startFlow(::ObjectInputStreamFlow).returnValue.getOrThrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
driver {
|
||||||
|
val devModeNode = startNode(params).getOrThrow()
|
||||||
|
val node = startNode(ALICE_NAME, devMode = false, parameters = params).getOrThrow()
|
||||||
|
|
||||||
|
assertThatThrownBy { devModeNode.attemptJavaDeserialization() }.isInstanceOf(CordaRuntimeException::class.java)
|
||||||
|
assertThatThrownBy { node.attemptJavaDeserialization() }.isInstanceOf(InternalNodeException::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,24 +3,18 @@ package net.corda.node.services.rpc
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.ClientRelevantException
|
import net.corda.ClientRelevantException
|
||||||
import net.corda.core.CordaRuntimeException
|
import net.corda.core.CordaRuntimeException
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.flows.FlowLogic
|
|
||||||
import net.corda.core.flows.FlowSession
|
|
||||||
import net.corda.core.flows.InitiatedBy
|
|
||||||
import net.corda.core.flows.InitiatingFlow
|
|
||||||
import net.corda.core.flows.StartableByRPC
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
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.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.node.services.Permissions
|
import net.corda.node.services.Permissions
|
||||||
import net.corda.nodeapi.exceptions.InternalNodeException
|
import net.corda.nodeapi.exceptions.InternalNodeException
|
||||||
import net.corda.testing.core.*
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.driver.DriverDSL
|
import net.corda.testing.core.BOB_NAME
|
||||||
import net.corda.testing.driver.DriverParameters
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.core.singleIdentity
|
||||||
import net.corda.testing.driver.NodeParameters
|
import net.corda.testing.driver.*
|
||||||
import net.corda.testing.driver.driver
|
|
||||||
import net.corda.testing.internal.IntegrationTest
|
import net.corda.testing.internal.IntegrationTest
|
||||||
import net.corda.testing.internal.IntegrationTestSchemas
|
import net.corda.testing.internal.IntegrationTestSchemas
|
||||||
import net.corda.testing.internal.toDatabaseSchemaName
|
import net.corda.testing.internal.toDatabaseSchemaName
|
||||||
@ -39,7 +33,6 @@ class RpcExceptionHandlingTest : IntegrationTest() {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName())
|
val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName())
|
||||||
}
|
}
|
||||||
|
|
||||||
private val user = User("mark", "dadada", setOf(Permissions.all()))
|
private val user = User("mark", "dadada", setOf(Permissions.all()))
|
||||||
private val users = listOf(user)
|
private val users = listOf(user)
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class NodeCmdLineOptions {
|
|||||||
names = ["-b", "--base-directory"],
|
names = ["-b", "--base-directory"],
|
||||||
description = ["The node working directory where all the files are kept."]
|
description = ["The node working directory where all the files are kept."]
|
||||||
)
|
)
|
||||||
var baseDirectory: Path = Paths.get(".")
|
var baseDirectory: Path = Paths.get(".").toAbsolutePath().normalize()
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
names = ["-f", "--config-file"],
|
names = ["-f", "--config-file"],
|
||||||
@ -57,7 +57,7 @@ class NodeCmdLineOptions {
|
|||||||
names = ["-t", "--network-root-truststore"],
|
names = ["-t", "--network-root-truststore"],
|
||||||
description = ["Network root trust store obtained from network operator."]
|
description = ["Network root trust store obtained from network operator."]
|
||||||
)
|
)
|
||||||
var networkRootTrustStorePath = Paths.get("certificates") / "network-root-truststore.jks"
|
var networkRootTrustStorePath: Path = baseDirectory / "certificates" / "network-root-truststore.jks"
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
names = ["-p", "--network-root-truststore-password"],
|
names = ["-p", "--network-root-truststore-password"],
|
||||||
|
@ -15,20 +15,18 @@ class NodeCmdLineOptionsTest {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private lateinit var workingDirectory: Path
|
private lateinit var workingDirectory: Path
|
||||||
private lateinit var buildDirectory: Path
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun initDirectories() {
|
fun initDirectories() {
|
||||||
workingDirectory = Paths.get(".").normalize().toAbsolutePath()
|
workingDirectory = Paths.get(".").normalize().toAbsolutePath()
|
||||||
buildDirectory = workingDirectory.resolve("build")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `no command line arguments`() {
|
fun `no command line arguments`() {
|
||||||
assertThat(parser.cmdLineOptions.baseDirectory.normalize().toAbsolutePath()).isEqualTo(workingDirectory)
|
assertThat(parser.cmdLineOptions.baseDirectory).isEqualTo(workingDirectory)
|
||||||
assertThat(parser.cmdLineOptions.configFile.normalize().toAbsolutePath()).isEqualTo(workingDirectory / "node.conf")
|
assertThat(parser.cmdLineOptions.configFile).isEqualTo(workingDirectory / "node.conf")
|
||||||
assertThat(parser.verbose).isEqualTo(false)
|
assertThat(parser.verbose).isEqualTo(false)
|
||||||
assertThat(parser.loggingLevel).isEqualTo(Level.INFO)
|
assertThat(parser.loggingLevel).isEqualTo(Level.INFO)
|
||||||
assertThat(parser.cmdLineOptions.nodeRegistrationOption).isEqualTo(null)
|
assertThat(parser.cmdLineOptions.nodeRegistrationOption).isEqualTo(null)
|
||||||
@ -40,5 +38,6 @@ class NodeCmdLineOptionsTest {
|
|||||||
assertThat(parser.cmdLineOptions.unknownConfigKeysPolicy).isEqualTo(UnknownConfigKeysPolicy.FAIL)
|
assertThat(parser.cmdLineOptions.unknownConfigKeysPolicy).isEqualTo(UnknownConfigKeysPolicy.FAIL)
|
||||||
assertThat(parser.cmdLineOptions.devMode).isEqualTo(null)
|
assertThat(parser.cmdLineOptions.devMode).isEqualTo(null)
|
||||||
assertThat(parser.cmdLineOptions.clearNetworkMapCache).isEqualTo(false)
|
assertThat(parser.cmdLineOptions.clearNetworkMapCache).isEqualTo(false)
|
||||||
|
assertThat(parser.cmdLineOptions.networkRootTrustStorePath).isEqualTo(workingDirectory / "certificates" / "network-root-truststore.jks")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import org.fusesource.jansi.AnsiConsole
|
|||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import picocli.CommandLine
|
import picocli.CommandLine
|
||||||
import picocli.CommandLine.*
|
import picocli.CommandLine.*
|
||||||
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -45,22 +46,24 @@ interface Validated {
|
|||||||
|
|
||||||
/** This is generally covered by commons-lang. */
|
/** This is generally covered by commons-lang. */
|
||||||
object CordaSystemUtils {
|
object CordaSystemUtils {
|
||||||
const val OS_NAME = "os.name"
|
private const val OS_NAME = "os.name"
|
||||||
|
private const val MAC_PREFIX = "Mac"
|
||||||
|
private const val WIN_PREFIX = "Windows"
|
||||||
|
|
||||||
const val MAC_PREFIX = "Mac"
|
fun isOsMac(): Boolean = getOsName().startsWith(MAC_PREFIX)
|
||||||
const val WIN_PREFIX = "Windows"
|
fun isOsWindows(): Boolean = getOsName().startsWith(WIN_PREFIX)
|
||||||
|
fun getOsName(): String = System.getProperty(OS_NAME)
|
||||||
fun isOsMac() = getOsName().startsWith(MAC_PREFIX)
|
|
||||||
fun isOsWindows() = getOsName().startsWith(WIN_PREFIX)
|
|
||||||
fun getOsName() = System.getProperty(OS_NAME)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CordaCliWrapper.start(args: Array<String>) {
|
fun CordaCliWrapper.start(args: Array<String>) {
|
||||||
|
this.args = args
|
||||||
|
|
||||||
// This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box.
|
// This line makes sure ANSI escapes work on Windows, where they aren't supported out of the box.
|
||||||
AnsiConsole.systemInstall()
|
AnsiConsole.systemInstall()
|
||||||
|
|
||||||
val cmd = CommandLine(this)
|
val cmd = CommandLine(this)
|
||||||
this.args = args
|
// Make sure any provided paths are absolute. Relative paths have caused issues and are less clear in logs.
|
||||||
|
cmd.registerConverter(Path::class.java) { Paths.get(it).toAbsolutePath().normalize() }
|
||||||
cmd.commandSpec.name(alias)
|
cmd.commandSpec.name(alias)
|
||||||
cmd.commandSpec.usageMessage().description(description)
|
cmd.commandSpec.usageMessage().description(description)
|
||||||
try {
|
try {
|
||||||
|
Reference in New Issue
Block a user