Skip to content

Commit

Permalink
Merge branch 'master' into shams-master-merge-081217
Browse files Browse the repository at this point in the history
# Conflicts:
#	node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/internal/DriverDSLImpl.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt
#	testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/DemoRunner.kt
#	verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt
  • Loading branch information
shamsasari committed Dec 11, 2017
2 parents 41bfd7a + da38e6f commit d6054e4
Show file tree
Hide file tree
Showing 75 changed files with 1,899 additions and 494 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ buildscript {
ext.jackson_version = '2.9.2'
ext.jetty_version = '9.4.7.v20170914'
ext.jersey_version = '2.25'
ext.jolokia_version = '2.0.0-M3'
ext.jolokia_version = '1.3.7'
ext.assertj_version = '3.8.0'
ext.slf4j_version = '1.7.25'
ext.log4j_version = '2.9.1'
Expand All @@ -49,6 +49,7 @@ buildscript {
ext.beanutils_version = '1.9.3'
ext.crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e'
ext.jsr305_version = constants.getProperty("jsr305Version")
ext.shiro_version = '1.4.0'
ext.artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion')

// Update 121 is required for ObjectInputFilter and at time of writing 131 was latest:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ class RPCStabilityTests {
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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
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.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"
}

/*
* 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")
}
}
}

/**
Expand All @@ -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")
}
}
}

Expand All @@ -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")
}
}

Expand All @@ -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")
}
}

Expand All @@ -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) })
assertNotAllowed {
proxy.validatePermission("startFlowDynamic", "net.corda.flows.OtherFlow")
}
assertNotAllowed {
proxy.validatePermission("startTrackedFlowDynamic", "net.corda.flows.OtherFlow")
}
}
}

@Test
fun `check ALL is implemented the correct way round`() {
fun `joe user is not allowed to call other RPC methods`() {
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) })
assertNotAllowed {
proxy.validatePermission("nodeInfo")
}
assertNotAllowed {
proxy.validatePermission("networkMapFeed")
}
}
}

@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) })
}
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)
}
}
23 changes: 5 additions & 18 deletions config/dev/jolokia-access.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>

<!-- an all powerful policy file -->
<restrict>
<http>
<method>post</method>
Expand All @@ -8,23 +8,10 @@

<commands>
<command>read</command>
<command>write</command>
<command>exec</command>
<command>list</command>
<command>search</command>
<command>version</command>
</commands>

<!-- allow anyone to force a garbage collection -->
<allow>
<mbean>
<name>java.lang:type=Memory</name>
<operation>gc</operation>
</mbean>
</allow>

<!-- in case we ever end up using c3pio connection pooling, this example from the docs prevents the password being exported -->
<deny>
<mbean>
<name>com.mchange.v2.c3p0:type=PooledDataSource,*</name>
<attribute>properties</attribute>
</mbean>
</deny>

</restrict>
24 changes: 24 additions & 0 deletions config/prod/jolokia-access.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Jolokia agent and MBean access policy based security -->
<!-- TODO: review these settings before production deployment -->
<restrict>
<!-- IP based restrictions -->
<remote>
<!-- IP address, a host name, or a netmask given in CIDR format (e.g. "10.0.0.0/16" for all clients coming from the 10.0 network). -->
<host>127.0.0.1</host>
<host>localhost</host>
</remote>
<!-- commands for which access is granted: read, write, exec, list, search, version -->
<commands>
<command>version</command>
<command>read</command>
</commands>
<!-- MBean access and deny restrictions -->
<!-- HTTP method restrictions: get, post -->
<http>
<method>get</method>
</http>
<!-- Cross-Origin Resource Sharing (CORS) restrictions
(by default, allow cross origin access from any host)
-->
</restrict>
Binary file modified docs/source/_static/corda-cheat-sheet.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
Contract Constraints
====================
API: Contract Constraints
=========================

A basic understanding of contract key concepts, which can be found :doc:`here </key-concepts-contracts>`,
is required reading for this page.

Transaction states specify a constraint over the contract that will be used to verify it. For a transaction to be
valid, the verify() function associated with each state must run successfully. However, for this to be secure, it is
not sufficient to specify the verify() function by name as there may exist multiple different implementations with the
same method signature and enclosing class. Contract constraints solve this problem by allowing a contract developer to
constrain which verify() functions out of the universe of implementations can be used.
(ie the universe is everything that matches the signature and contract constraints restricts this universe to a subset.)
valid, the ``verify`` function associated with each state must run successfully. However, for this to be secure, it is
not sufficient to specify the ``verify`` function by name as there may exist multiple different implementations with
the same method signature and enclosing class. Contract constraints solve this problem by allowing a contract developer
to constrain which ``verify`` functions out of the universe of implementations can be used (i.e. the universe is
everything that matches the signature and contract constraints restricts this universe to a subset).

A typical constraint is the hash of the CorDapp JAR that contains the contract and states but will in future releases
include constraints that require specific signers of the JAR, or both the signer and the hash. Constraints can be
Expand All @@ -20,12 +20,13 @@ constructs a ``TransactionState`` without specifying the constraint parameter a
(``AutomaticHashConstraint``) is used. This default will be automatically resolved to a specific
``HashAttachmentConstraint`` that contains the hash of the attachment which contains the contract of that
``TransactionState``. This automatic resolution occurs when a ``TransactionBuilder`` is converted to a
``WireTransaction``. This reduces the boilerplate involved in finding a specific hash constraint when building a transaction.
``WireTransaction``. This reduces the boilerplate involved in finding a specific hash constraint when building a
transaction.

It is possible to specify the constraint explicitly with any other class that implements the ``AttachmentConstraint``
interface. To specify a hash manually the ``HashAttachmentConstraint`` can be used and to not provide any constraint
the ``AlwaysAcceptAttachmentConstraint`` can be used - though this is intended for testing only. An example below
shows how to construct a ``TransactionState`` with an explicitly specified hash constraint from within a flow;
shows how to construct a ``TransactionState`` with an explicitly specified hash constraint from within a flow:

.. sourcecode:: java

Expand All @@ -42,23 +43,22 @@ shows how to construct a ``TransactionState`` with an explicitly specified hash
LedgerTransaction ltx = wtx.toLedgerTransaction(serviceHub)
ltx.verify() // Verifies both the attachment constraints and contracts


This mechanism exists both for integrity and security reasons. It is important not to verify against the wrong contract,
which could happen if the wrong version of the contract is attached. More importantly when resolving transaction chains
there will, in a future release, be attachments loaded from the network into the attachment sandbox that are used
to verify the transaction chain. Ensuring the attachment used is the correct one ensures that the verification will
not be tamperable by providing a fake contract.
to verify the transaction chain. Ensuring the attachment used is the correct one ensures that the verification is
tamper-proof by providing a fake contract.

CorDapps as attachments
-----------------------

CorDapp JARs (:doc:`cordapp-overview`) that are installed to the node and contain classes implementing the ``Contract``
interface are automatically loaded into the ``AttachmentStorage`` of a node at startup.

After CorDapps are loaded into the attachment store the node creates a link between contract classes and the
attachment that they were loaded from. This makes it possible to find the attachment for any given contract.
This is how the automatic resolution of attachments is done by the ``TransactionBuilder`` and how, when verifying
the constraints and contracts, attachments are associated with their respective contracts.
After CorDapps are loaded into the attachment store the node creates a link between contract classes and the attachment
that they were loaded from. This makes it possible to find the attachment for any given contract. This is how the
automatic resolution of attachments is done by the ``TransactionBuilder`` and how, when verifying the constraints and
contracts, attachments are associated with their respective contracts.

Implementations
---------------
Expand Down Expand Up @@ -95,7 +95,7 @@ to specify JAR URLs in the case that the CorDapp(s) involved in testing already
MockNetwork/MockNode
********************

The most simple way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to use the
The simplest way to ensure that a vanilla instance of a MockNode generates the correct CorDapps is to use the
``cordappPackages`` constructor parameter (Kotlin) or the ``setCordappPackages`` method on ``MockNetworkParameters`` (Java)
when creating the MockNetwork. This will cause the ``AbstractNode`` to use the named packages as sources for CorDapps. All files
within those packages will be zipped into a JAR and added to the attachment store and loaded as CorDapps by the
Expand Down
3 changes: 3 additions & 0 deletions docs/source/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ from the previous milestone release.

UNRELEASED
----------
* Exporting additional JMX metrics (artemis, hibernate statistics) and loading Jolokia agent at JVM startup when using
DriverDSL and/or cordformation node runner.

* Removed confusing property database.initDatabase, enabling its guarded behaviour with the dev-mode.
In devMode Hibernate will try to create or update database schemas, otherwise it will expect relevant schemas to be present
in the database (pre configured via DDL scripts or equivalent), and validate these are correct.
Expand Down
2 changes: 1 addition & 1 deletion docs/source/cheat-sheet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ Cheat sheet
A "cheat sheet" summarizing the key Corda types. A PDF version is downloadable `here`_.

.. image:: resources/cheatsheet.jpg
:width: 700px
:width: 700px

.. _`here`: _static/corda-cheat-sheet.pdf
1 change: 1 addition & 0 deletions docs/source/corda-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The following are the core APIs that are used in the development of CorDapps:
api-states
api-persistence
api-contracts
api-contract-constraints
api-vault-query
api-transactions
api-flows
Expand Down
7 changes: 5 additions & 2 deletions docs/source/corda-configuration-file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ path to the node's base directory.
:serverNameTablePrefix: Prefix string to apply to all the database tables. The default is no prefix.
:transactionIsolationLevel: Transaction isolation level as defined by the ``TRANSACTION_`` constants in
``java.sql.Connection``, but without the "TRANSACTION_" prefix. Defaults to REPEATABLE_READ.
:exportHibernateJMXStatistics: Whether to export Hibernate JMX statistics (caution: expensive run-time overhead)

:dataSourceProperties: This section is used to configure the jdbc connection and database driver used for the nodes persistence.
Currently the defaults in ``/node/src/main/resources/reference.conf`` are as shown in the first example. This is currently
Expand Down Expand Up @@ -163,7 +164,9 @@ path to the node's base directory.
Each should be a string. Only the JARs in the directories are added, not the directories themselves. This is useful
for including JDBC drivers and the like. e.g. ``jarDirs = [ 'lib' ]``

:sshd: If provided, node will start internal SSH server which will provide a management shell. It uses the same credentials
and permissions as RPC subsystem. It has one required parameter.
:sshd: If provided, node will start internal SSH server which will provide a management shell. It uses the same credentials and permissions as RPC subsystem. It has one required parameter.

:port: The port to start SSH server on

:exportJMXTo: If set to ``http``, will enable JMX metrics reporting via the Jolokia HTTP/JSON agent.
Default Jolokia access url is http://127.0.0.1:7005/jolokia/
1 change: 1 addition & 0 deletions docs/source/corda-nodes-index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Corda nodes
corda-configuration-file
clientrpc
shell
node-auth-config
node-database
node-administration
out-of-process-verification
Loading

0 comments on commit d6054e4

Please sign in to comment.