Merge remote-tracking branch 'open-hc01/master' into colljos-os-hc01-merge-111217

This commit is contained in:
josecoll
2017-12-11 09:21:52 +00:00
148 changed files with 3463 additions and 1859 deletions

View File

@ -13,7 +13,7 @@ import net.corda.core.utilities.*
import net.corda.node.services.messaging.RPCServerConfiguration
import net.corda.nodeapi.RPCApi
import net.corda.testing.*
import net.corda.testing.driver.poll
import net.corda.testing.internal.poll
import net.corda.testing.internal.*
import org.apache.activemq.artemis.api.core.SimpleString
import org.junit.After
@ -70,8 +70,8 @@ class RPCStabilityTests : IntegrationTest() {
val executor = Executors.newScheduledThreadPool(1)
fun startAndStop() {
rpcDriver {
val server = startRpcServer<RPCOps>(ops = DummyOps)
startRpcClient<RPCOps>(server.get().broker.hostAndPort!!).get()
val server = startRpcServer<RPCOps>(ops = DummyOps).get()
startRpcClient<RPCOps>(server.broker.hostAndPort!!).get()
}
}
repeat(5) {
@ -238,6 +238,7 @@ class RPCStabilityTests : IntegrationTest() {
override val protocolVersion = 0
override fun ping() = "pong"
}
val serverFollower = shutdownManager.follower()
val serverPort = startRpcServer<ReconnectOps>(ops = ops).getOrThrow().broker.hostAndPort!!
serverFollower.unfollow()
@ -355,7 +356,7 @@ class RPCStabilityTests : IntegrationTest() {
}
fun RPCDriverExposedDSLInterface.pollUntilClientNumber(server: RpcServerHandle, expected: Int) {
fun RPCDriverDSL.pollUntilClientNumber(server: RpcServerHandle, expected: Int) {
pollUntilTrue("number of RPC clients to become $expected") {
val clientAddresses = server.broker.serverControl.addressNames.filter { it.startsWith(RPCApi.RPC_CLIENT_QUEUE_NAME_PREFIX) }
clientAddresses.size == expected

View File

@ -22,7 +22,10 @@ import net.corda.core.internal.ThreadBox
import net.corda.core.messaging.RPCOps
import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.serialize
import net.corda.core.utilities.*
import net.corda.core.utilities.Try
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug
import net.corda.core.utilities.getOrThrow
import net.corda.nodeapi.ArtemisConsumer
import net.corda.nodeapi.ArtemisProducer
import net.corda.nodeapi.RPCApi

View File

@ -7,7 +7,7 @@ import net.corda.core.messaging.RPCOps
import net.corda.node.services.messaging.RPCServerConfiguration
import net.corda.nodeapi.internal.config.User
import net.corda.testing.SerializationEnvironmentRule
import net.corda.testing.internal.RPCDriverExposedDSLInterface
import net.corda.testing.internal.RPCDriverDSL
import net.corda.testing.internal.rpcTestUser
import net.corda.testing.internal.startInVmRpcClient
import net.corda.testing.internal.startRpcClient
@ -41,7 +41,7 @@ open class AbstractRPCTest {
val createSession: () -> ClientSession
)
inline fun <reified I : RPCOps> RPCDriverExposedDSLInterface.testProxy(
inline fun <reified I : RPCOps> RPCDriverDSL.testProxy(
ops: I,
rpcUser: User = rpcTestUser,
clientConfiguration: RPCClientConfiguration = RPCClientConfiguration.default,
@ -55,9 +55,9 @@ open class AbstractRPCTest {
}
}
RPCTestMode.Netty ->
startRpcServer(ops = ops, rpcUser = rpcUser, configuration = serverConfiguration).flatMap { server ->
startRpcClient<I>(server.broker.hostAndPort!!, rpcUser.username, rpcUser.password, clientConfiguration).map {
TestProxy(it, { startArtemisSession(server.broker.hostAndPort!!, rpcUser.username, rpcUser.password) })
startRpcServer(ops = ops, rpcUser = rpcUser, configuration = serverConfiguration).flatMap { (broker) ->
startRpcClient<I>(broker.hostAndPort!!, rpcUser.username, rpcUser.password, clientConfiguration).map {
TestProxy(it, { startArtemisSession(broker.hostAndPort!!, rpcUser.username, rpcUser.password) })
}
}
}.get()

View File

@ -7,7 +7,7 @@ import net.corda.core.internal.concurrent.thenMatch
import net.corda.core.messaging.RPCOps
import net.corda.core.utilities.getOrThrow
import net.corda.node.services.messaging.rpcContext
import net.corda.testing.internal.RPCDriverExposedDSLInterface
import net.corda.testing.internal.RPCDriverDSL
import net.corda.testing.internal.rpcDriver
import net.corda.testing.internal.rpcTestUser
import org.assertj.core.api.Assertions.assertThat
@ -26,7 +26,7 @@ import kotlin.test.assertTrue
class ClientRPCInfrastructureTests : AbstractRPCTest() {
// TODO: Test that timeouts work
private fun RPCDriverExposedDSLInterface.testProxy(): TestOps {
private fun RPCDriverDSL.testProxy(): TestOps {
return testProxy<TestOps>(TestOpsImpl()).ops
}

View File

@ -1,15 +1,15 @@
package net.corda.client.rpc
import net.corda.client.rpc.internal.RPCClientConfiguration
import net.corda.core.messaging.RPCOps
import net.corda.core.utilities.millis
import net.corda.core.crypto.random63BitValue
import net.corda.core.internal.concurrent.fork
import net.corda.core.internal.concurrent.transpose
import net.corda.core.messaging.RPCOps
import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.millis
import net.corda.node.services.messaging.RPCServerConfiguration
import net.corda.testing.internal.RPCDriverExposedDSLInterface
import net.corda.testing.internal.RPCDriverDSL
import net.corda.testing.internal.rpcDriver
import net.corda.testing.internal.testThreadFactory
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet
@ -20,7 +20,10 @@ import org.junit.runners.Parameterized
import rx.Observable
import rx.subjects.UnicastSubject
import java.util.*
import java.util.concurrent.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executor
import java.util.concurrent.Executors
@RunWith(Parameterized::class)
class RPCConcurrencyTests : AbstractRPCTest() {
@ -84,7 +87,7 @@ class RPCConcurrencyTests : AbstractRPCTest() {
}
}
private fun RPCDriverExposedDSLInterface.testProxy(): TestProxy<TestOps> {
private fun RPCDriverDSL.testProxy(): TestProxy<TestOps> {
return testProxy<TestOps>(
TestOpsImpl(pool),
clientConfiguration = RPCClientConfiguration.default.copy(

View File

@ -5,14 +5,14 @@ import net.corda.client.rpc.internal.RPCClientConfiguration
import net.corda.core.messaging.RPCOps
import net.corda.core.utilities.minutes
import net.corda.core.utilities.seconds
import net.corda.testing.internal.performance.div
import net.corda.node.services.messaging.RPCServerConfiguration
import net.corda.testing.internal.RPCDriverExposedDSLInterface
import net.corda.testing.measure
import net.corda.testing.internal.RPCDriverDSL
import net.corda.testing.internal.performance.div
import net.corda.testing.internal.performance.startPublishingFixedRateInjector
import net.corda.testing.internal.performance.startReporter
import net.corda.testing.internal.performance.startTightLoopInjector
import net.corda.testing.internal.rpcDriver
import net.corda.testing.measure
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@ -42,7 +42,7 @@ class RPCPerformanceTests : AbstractRPCTest() {
}
}
private fun RPCDriverExposedDSLInterface.testProxy(
private fun RPCDriverDSL.testProxy(
clientConfiguration: RPCClientConfiguration,
serverConfiguration: RPCServerConfiguration
): TestProxy<TestOps> {

View File

@ -1,24 +1,19 @@
package net.corda.client.rpc
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.RPCOps
import net.corda.node.services.Permissions.Companion.invokeRpc
import net.corda.node.services.messaging.rpcContext
import net.corda.nodeapi.internal.config.User
import net.corda.testing.internal.RPCDriverExposedDSLInterface
import net.corda.testing.internal.RPCDriverDSL
import net.corda.testing.internal.rpcDriver
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import kotlin.reflect.KVisibility
import kotlin.reflect.full.declaredMemberFunctions
import kotlin.test.assertFailsWith
@RunWith(Parameterized::class)
class RPCPermissionsTests : AbstractRPCTest() {
companion object {
const val DUMMY_FLOW = "StartFlow.net.corda.flows.DummyFlow"
const val OTHER_FLOW = "StartFlow.net.corda.flows.OtherFlow"
const val ALL_ALLOWED = "ALL"
}
@ -26,18 +21,27 @@ class RPCPermissionsTests : AbstractRPCTest() {
* RPC operation.
*/
interface TestOps : RPCOps {
fun validatePermission(str: String)
fun validatePermission(method: String, target: String? = null)
}
class TestOpsImpl : TestOps {
override val protocolVersion = 1
override fun validatePermission(str: String) { rpcContext().requirePermission(str) }
override fun validatePermission(method: String, target: String?) {
val authorized = if (target == null) {
rpcContext().isPermitted(method)
} else {
rpcContext().isPermitted(method, target)
}
if (!authorized) {
throw PermissionException("RPC user not authorized")
}
}
}
/**
* Create an RPC proxy for the given user.
*/
private fun RPCDriverExposedDSLInterface.testProxyFor(rpcUser: User) = testProxy<TestOps>(TestOpsImpl(), rpcUser).ops
private fun RPCDriverDSL.testProxyFor(rpcUser: User) = testProxy<TestOps>(TestOpsImpl(), rpcUser).ops
private fun userOf(name: String, permissions: Set<String>) = User(name, "password", permissions)
@ -46,9 +50,9 @@ class RPCPermissionsTests : AbstractRPCTest() {
rpcDriver {
val emptyUser = userOf("empty", emptySet())
val proxy = testProxyFor(emptyUser)
assertFailsWith(PermissionException::class,
"User ${emptyUser.username} should not be allowed to use $DUMMY_FLOW.",
{ proxy.validatePermission(DUMMY_FLOW) })
assertNotAllowed {
proxy.validatePermission("startFlowDynamic", "net.corda.flows.DummyFlow")
}
}
}
@ -57,7 +61,8 @@ class RPCPermissionsTests : AbstractRPCTest() {
rpcDriver {
val adminUser = userOf("admin", setOf(ALL_ALLOWED))
val proxy = testProxyFor(adminUser)
proxy.validatePermission(DUMMY_FLOW)
proxy.validatePermission("startFlowDynamic", "net.corda.flows.DummyFlow")
proxy.validatePermission("startTrackedFlowDynamic", "net.corda.flows.DummyFlow")
}
}
@ -66,7 +71,8 @@ class RPCPermissionsTests : AbstractRPCTest() {
rpcDriver {
val joeUser = userOf("joe", setOf(DUMMY_FLOW))
val proxy = testProxyFor(joeUser)
proxy.validatePermission(DUMMY_FLOW)
proxy.validatePermission("startFlowDynamic", "net.corda.flows.DummyFlow")
proxy.validatePermission("startTrackedFlowDynamic", "net.corda.flows.DummyFlow")
}
}
@ -75,36 +81,46 @@ class RPCPermissionsTests : AbstractRPCTest() {
rpcDriver {
val joeUser = userOf("joe", setOf(DUMMY_FLOW))
val proxy = testProxyFor(joeUser)
assertFailsWith(PermissionException::class,
"User ${joeUser.username} should not be allowed to use $OTHER_FLOW",
{ proxy.validatePermission(OTHER_FLOW) })
}
}
@Test
fun `check ALL is implemented the correct way round`() {
rpcDriver {
val joeUser = userOf("joe", setOf(DUMMY_FLOW))
val proxy = testProxyFor(joeUser)
assertFailsWith(PermissionException::class,
"Permission $ALL_ALLOWED should not do anything for User ${joeUser.username}",
{ proxy.validatePermission(ALL_ALLOWED) })
}
}
@Test
fun `fine grained permissions are enforced`() {
val allPermissions = CordaRPCOps::class.declaredMemberFunctions.filter { it.visibility == KVisibility.PUBLIC }.map { invokeRpc(it) }
allPermissions.forEach { permission ->
rpcDriver {
val user = userOf("Mark", setOf(permission))
val proxy = testProxyFor(user)
proxy.validatePermission(permission)
(allPermissions - permission).forEach { notOwnedPermission ->
assertFailsWith(PermissionException::class, { proxy.validatePermission(notOwnedPermission) })
}
assertNotAllowed {
proxy.validatePermission("startFlowDynamic", "net.corda.flows.OtherFlow")
}
assertNotAllowed {
proxy.validatePermission("startTrackedFlowDynamic", "net.corda.flows.OtherFlow")
}
}
}
@Test
fun `joe user is not allowed to call other RPC methods`() {
rpcDriver {
val joeUser = userOf("joe", setOf(DUMMY_FLOW))
val proxy = testProxyFor(joeUser)
assertNotAllowed {
proxy.validatePermission("nodeInfo")
}
assertNotAllowed {
proxy.validatePermission("networkMapFeed")
}
}
}
@Test
fun `checking invokeRpc permissions entitlements`() {
rpcDriver {
val joeUser = userOf("joe", setOf("InvokeRpc.networkMapFeed"))
val proxy = testProxyFor(joeUser)
assertNotAllowed {
proxy.validatePermission("nodeInfo")
}
assertNotAllowed {
proxy.validatePermission("startTrackedFlowDynamic", "net.corda.flows.OtherFlow")
}
proxy.validatePermission("networkMapFeed")
}
}
private fun assertNotAllowed(action: () -> Unit) {
assertFailsWith(PermissionException::class, "User should not be allowed to perform this action.", action)
}
}