mirror of
https://github.com/corda/corda.git
synced 2025-04-19 08:36:39 +00:00
commit
2f9763ed47
@ -112,7 +112,8 @@ Unreleased
|
||||
* ``WireTransaction.Companion.createComponentGroups`` has been marked as ``@CordaInternal``. It was never intended to be
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
---------------------
|
||||
|
@ -12,15 +12,19 @@ import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.node.internal.NodeStartup
|
||||
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.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_BANK_A_NAME
|
||||
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.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
import net.corda.testing.internal.toDatabaseSchemaName
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.internal.startNode
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
@ -38,12 +42,21 @@ class BootTests : IntegrationTest() {
|
||||
}
|
||||
@Test
|
||||
fun `java deserialization is disabled`() {
|
||||
driver(DriverParameters(notarySpecs = emptyList())) {
|
||||
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
||||
val future = CordaRPCClient(startNode(rpcUsers = listOf(user)).getOrThrow().rpcAddress).
|
||||
start(user.username, user.password).proxy.startFlow(::ObjectInputStreamFlow).returnValue
|
||||
assertThatThrownBy { future.getOrThrow() }
|
||||
.isInstanceOf(CordaRuntimeException::class.java)
|
||||
val user = User("u", "p", setOf(startFlow<ObjectInputStreamFlow>()))
|
||||
val params = NodeParameters(rpcUsers = listOf(user))
|
||||
|
||||
fun NodeHandle.attemptJavaDeserialization() {
|
||||
CordaRPCClient(rpcAddress).use(user.username, user.password) { connection ->
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,4 +247,4 @@ class NetworkMapTest(var initFunc: (URL, NetworkMapServer) -> CompatibilityZoneP
|
||||
}
|
||||
assertThat(rpc.networkMapSnapshot()).containsOnly(*nodes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,24 +3,18 @@ package net.corda.node.services.rpc
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.ClientRelevantException
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.core.flows.FlowException
|
||||
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.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.unwrap
|
||||
import net.corda.node.services.Permissions
|
||||
import net.corda.nodeapi.exceptions.InternalNodeException
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.driver.DriverDSL
|
||||
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.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.driver.*
|
||||
import net.corda.testing.internal.IntegrationTest
|
||||
import net.corda.testing.internal.IntegrationTestSchemas
|
||||
import net.corda.testing.internal.toDatabaseSchemaName
|
||||
@ -39,7 +33,6 @@ class RpcExceptionHandlingTest : IntegrationTest() {
|
||||
@JvmField
|
||||
val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName())
|
||||
}
|
||||
|
||||
private val user = User("mark", "dadada", setOf(Permissions.all()))
|
||||
private val users = listOf(user)
|
||||
|
||||
@ -165,4 +158,4 @@ class FlowExceptionFlow(private val message: String, private val errorId: Long?
|
||||
errorId?.let { exception.originalErrorId = it }
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class NodeCmdLineOptions {
|
||||
names = ["-b", "--base-directory"],
|
||||
description = ["The node working directory where all the files are kept."]
|
||||
)
|
||||
var baseDirectory: Path = Paths.get(".")
|
||||
var baseDirectory: Path = Paths.get(".").toAbsolutePath().normalize()
|
||||
|
||||
@Option(
|
||||
names = ["-f", "--config-file"],
|
||||
@ -57,7 +57,7 @@ class NodeCmdLineOptions {
|
||||
names = ["-t", "--network-root-truststore"],
|
||||
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(
|
||||
names = ["-p", "--network-root-truststore-password"],
|
||||
|
@ -122,4 +122,4 @@ internal class ExceptionMaskingRpcOpsProxy(private val delegate: CordaRPCOps, do
|
||||
override fun toString(): String {
|
||||
return "ExceptionMaskingRpcOpsProxy"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,20 +15,18 @@ class NodeCmdLineOptionsTest {
|
||||
|
||||
companion object {
|
||||
private lateinit var workingDirectory: Path
|
||||
private lateinit var buildDirectory: Path
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun initDirectories() {
|
||||
workingDirectory = Paths.get(".").normalize().toAbsolutePath()
|
||||
buildDirectory = workingDirectory.resolve("build")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `no command line arguments`() {
|
||||
assertThat(parser.cmdLineOptions.baseDirectory.normalize().toAbsolutePath()).isEqualTo(workingDirectory)
|
||||
assertThat(parser.cmdLineOptions.configFile.normalize().toAbsolutePath()).isEqualTo(workingDirectory / "node.conf")
|
||||
assertThat(parser.cmdLineOptions.baseDirectory).isEqualTo(workingDirectory)
|
||||
assertThat(parser.cmdLineOptions.configFile).isEqualTo(workingDirectory / "node.conf")
|
||||
assertThat(parser.verbose).isEqualTo(false)
|
||||
assertThat(parser.loggingLevel).isEqualTo(Level.INFO)
|
||||
assertThat(parser.cmdLineOptions.nodeRegistrationOption).isEqualTo(null)
|
||||
@ -40,5 +38,6 @@ class NodeCmdLineOptionsTest {
|
||||
assertThat(parser.cmdLineOptions.unknownConfigKeysPolicy).isEqualTo(UnknownConfigKeysPolicy.FAIL)
|
||||
assertThat(parser.cmdLineOptions.devMode).isEqualTo(null)
|
||||
assertThat(parser.cmdLineOptions.clearNetworkMapCache).isEqualTo(false)
|
||||
assertThat(parser.cmdLineOptions.networkRootTrustStorePath).isEqualTo(workingDirectory / "certificates" / "network-root-truststore.jks")
|
||||
}
|
||||
}
|
||||
|
@ -1190,4 +1190,4 @@ fun DriverDSL.startNode(providedName: CordaX500Name, devMode: Boolean, parameter
|
||||
customOverrides = mapOf("devMode" to "false")
|
||||
}
|
||||
return startNode(parameters, providedName = providedName, customOverrides = customOverrides)
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import org.fusesource.jansi.AnsiConsole
|
||||
import org.slf4j.event.Level
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.*
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.system.exitProcess
|
||||
import java.util.*
|
||||
@ -45,22 +46,24 @@ interface Validated {
|
||||
|
||||
/** This is generally covered by commons-lang. */
|
||||
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"
|
||||
const val WIN_PREFIX = "Windows"
|
||||
|
||||
fun isOsMac() = getOsName().startsWith(MAC_PREFIX)
|
||||
fun isOsWindows() = getOsName().startsWith(WIN_PREFIX)
|
||||
fun getOsName() = System.getProperty(OS_NAME)
|
||||
fun isOsMac(): Boolean = getOsName().startsWith(MAC_PREFIX)
|
||||
fun isOsWindows(): Boolean = getOsName().startsWith(WIN_PREFIX)
|
||||
fun getOsName(): String = System.getProperty(OS_NAME)
|
||||
}
|
||||
|
||||
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.
|
||||
AnsiConsole.systemInstall()
|
||||
|
||||
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.usageMessage().description(description)
|
||||
try {
|
||||
|
Loading…
x
Reference in New Issue
Block a user