diff --git a/docs/source/endorsement-policies.rst b/docs/source/endorsement-policies.rst index bad1a18458b..dde70f654c1 100644 --- a/docs/source/endorsement-policies.rst +++ b/docs/source/endorsement-policies.rst @@ -17,29 +17,35 @@ of endorsements and that they are from the expected sources (both of these are specified in the endorsement policy). The endorsements are also checked to make sure they're valid (i.e., that they are valid signatures from valid certificates). -Two ways to require endorsement -------------------------------- +Multiple ways to require endorsement +------------------------------------ By default, endorsement policies are specified in the chaincode definition, which is agreed to by channel members and then committed to a channel (that is, one endorsement policy covers all of the state associated with a chaincode). -However, there are cases where it may be necessary for a particular state (a -particular key-value pair, in other words) to have a different endorsement policy. -This **state-based endorsement** allows the default chaincode-level endorsement -policies to be overridden by a different policy for the specified keys. +For private data collections, you can also specify an endorsement policy +at the private data collection level, which would override the chaincode +level endorsement policy for any keys in the private data collection, thereby +further restricting which organizations can write to a private data collection. -To illustrate the circumstances in which these two types of endorsement policies +Finally, there are cases where it may be necessary for a particular public +channel state or private data collection state (a particular key-value pair, +in other words) to have a different endorsement policy. +This **state-based endorsement** allows the chaincode-level or collection-level +endorsement policies to be overridden by a different policy for the specified keys. + +To illustrate the circumstances in which the various types of endorsement policies might be used, consider a channel on which cars are being exchanged. The "creation" --- also known as "issuance" -- of a car as an asset that can be traded (putting the key-value pair that represents it into the world state, in other words) would have to satisfy the chaincode-level endorsement policy. To see how to set a chaincode-level endorsement policy, check out the section below. -If the car requires a specific endorsement policy, it can be defined either when -the car is created or afterwards. There are a number of reasons why it might -be necessary or preferable to set a state-specific endorsement policy. The car -might have historical importance or value that makes it necessary to have the +If the key representing the car requires a specific endorsement policy, it can be +defined either when the car is created or afterwards. There are a number of reasons +why it might be necessary or preferable to set a state-specific endorsement policy. The +car might have historical importance or value that makes it necessary to have the endorsement of a licensed appraiser. Also, the owner of the car (if they're a member of the channel) might also want to ensure that their peer signs off on a transaction. In both cases, **an endorsement policy is required for a particular @@ -116,8 +122,8 @@ that they can be written to be updated automatically with channel membership. If you specify an endorsement policy using the ``—-signature-policy`` flag or the SDK, you will need to update the policy when organizations join or leave the -channel. A new organization added to the channel after instantiation will be -able to query a chaincode (provided the query has appropriate authorization as +channel. A new organization added to the channel after the chaincode has been defined +will be able to query a chaincode (provided the query has appropriate authorization as defined by channel policies and any application level checks enforced by the chaincode) but will not be able to execute or endorse the chaincode. Only organizations listed in the endorsement policy syntax will be able sign @@ -162,14 +168,39 @@ For example: 'Org2.member'), AND('Org1.member', 'Org3.member'), AND('Org2.member', 'Org3.member'))``. +Setting collection-level endorsement policies +--------------------------------------------- +Similar to chaincode-level endorsement policies, when you approve and commit +a chaincode definition, you can also specify the chaincode's private data collections +and corresponding collection-level endorsement policies. If a collection-level +endorsement policy is set, transactions that write to a private data collection +key will require that the specified organization peers have endorsed the transaction. + +You can use collection-level endorsement policies to restrict which organization +peers can write to the private data collection key namespace, for example to +ensure that non-authorized organizations cannot write to a collection, and to +have confidence that any state in a private data collection has been endorsed +by the required collection organization(s). + +The collection-level endorsement policy may be less restrictive or more restrictive +than the chaincode-level endorsement policy and the collection's private data +distribution policy. For example a majority of organizations may be required +to endorse a chaincode transaction, but a specific organization may be required +to endorse a transaction that includes a key in a specific collection. + +The syntax for collection-level endorsement policies exactly matches the syntax +for chaincode-level endorsement policies --- in the collection configuration +you can specify an ``endorsementPolicy`` with either a ``signaturePolicy`` or +``channelConfigPolicy``. For more details see :doc:`private-data-arch`. + .. _key-level-endorsement: Setting key-level endorsement policies -------------------------------------- -Setting regular chaincode-level endorsement policies is tied to the lifecycle of -the corresponding chaincode. They can only be set or modified when instantiating -or upgrading the corresponding chaincode on a channel. +Setting regular chaincode-level or collection-level endorsement policies is tied to +the lifecycle of the corresponding chaincode. They can only be set or modified when +defining the chaincode on a channel. In contrast, key-level endorsement policies can be set and modified in a more granular fashion from within a chaincode. The modification is part of the @@ -234,29 +265,29 @@ At commit time, setting a value of a key is no different from setting the endorsement policy of a key --- both update the state of the key and are validated based on the same rules. -+---------------------+-----------------------------+--------------------------+ -| Validation | no validation parameter set | validation parameter set | -+=====================+=============================+==========================+ -| modify value | check chaincode ep | check key-level ep | -+---------------------+-----------------------------+--------------------------+ -| modify key-level ep | check chaincode ep | check key-level ep | -+---------------------+-----------------------------+--------------------------+ ++---------------------+------------------------------------+--------------------------+ +| Validation | no validation parameter set | validation parameter set | ++=====================+====================================+==========================+ +| modify value | check chaincode or collection ep | check key-level ep | ++---------------------+------------------------------------+--------------------------+ +| modify key-level ep | check chaincode or collection ep | check key-level ep | ++---------------------+------------------------------------+--------------------------+ As we discussed above, if a key is modified and no key-level endorsement policy -is present, the chaincode-level endorsement policy applies by default. This is -also true when a key-level endorsement policy is set for a key for the first time +is present, the chaincode-level or collection-level endorsement policy applies by default. +This is also true when a key-level endorsement policy is set for a key for the first time --- the new key-level endorsement policy must first be endorsed according to the -pre-existing chaincode-level endorsement policy. +pre-existing chaincode-level or collection-level endorsement policy. If a key is modified and a key-level endorsement policy is present, the key-level -endorsement policy overrides the chaincode-level endorsement policy. In practice, -this means that the key-level endorsement policy can be either less restrictive -or more restrictive than the chaincode-level endorsement policy. Because the -chaincode-level endorsement policy must be satisfied in order to set a key-level -endorsement policy for the first time, no trust assumptions have been violated. +endorsement policy overrides the chaincode-level or collection-level endorsement policy. +In practice, this means that the key-level endorsement policy can be either less restrictive +or more restrictive than the chaincode-level or collection-level endorsement policies. +Because the chaincode-level or collection-level endorsement policy must be satisfied in order +to set a key-level endorsement policy for the first time, no trust assumptions have been violated. If a key's endorsement policy is removed (set to nil), the chaincode-level -endorsement policy becomes the default again. +or collection-level endorsement policy becomes the default again. If a transaction modifies multiple keys with different associated key-level endorsement policies, all of these policies need to be satisfied in order diff --git a/docs/source/peer_event_services.rst b/docs/source/peer_event_services.rst index 6288a7bc080..823a8c2ffc9 100644 --- a/docs/source/peer_event_services.rst +++ b/docs/source/peer_event_services.rst @@ -10,7 +10,7 @@ ledger, regardless of the channel to which that block pertained, and it was only accessible to members of the organization running the eventing peer (i.e., the one being connected to for events). -Starting with v1.1, there are two new services which provide events. These services use an +Starting with v1.1, there are new services which provide events. These services use an entirely different design to provide events on a per-channel basis. This means that registration for events occurs at the level of the channel instead of the peer, allowing for fine-grained control over access to the peer's data. Requests to @@ -28,6 +28,12 @@ This service sends entire blocks that have been committed to the ledger. If any events were set by a chaincode, these can be found within the ``ChaincodeActionPayload`` of the block. +* ``DeliverWithPrivateData`` + +This service sends the same data as the ``Deliver`` service, and additionally +includes any private data from collections that the client's organization is +authorized to access. + * ``DeliverFiltered`` This service sends "filtered" blocks, minimal sets of information about blocks @@ -42,7 +48,7 @@ any events were set by a chaincode, these can be found within the How to register for events -------------------------- -Registration for events from either service is done by sending an envelope +Registration for events is done by sending an envelope containing a deliver seek info message to the peer that contains the desired start and stop positions, the seek behavior (block until ready or fail if not ready). There are helper variables ``SeekOldest`` and ``SeekNewest`` that can be used to @@ -53,7 +59,7 @@ include a stop position of ``MAXINT64``. .. note:: If mutual TLS is enabled on the peer, the TLS certificate hash must be set in the envelope's channel header. -By default, both services use the Channel Readers policy to determine whether +By default, the event services use the Channel Readers policy to determine whether to authorize requesting clients for events. Overview of deliver response messages @@ -63,11 +69,12 @@ The event services send back ``DeliverResponse`` messages. Each message contains one of the following: - * status -- HTTP status code. Both services will return the appropriate failure + * status -- HTTP status code. Each of the services will return the appropriate failure code if any failure occurs; otherwise, it will return ``200 - SUCCESS`` once the service has completed sending all information requested by the ``SeekInfo`` message. * block -- returned only by the ``Deliver`` service. + * block and private data -- returned only by the ``DeliverWithPrivateData`` service. * filtered block -- returned only by the ``DeliverFiltered`` service. A filtered block contains: diff --git a/docs/source/private-data-arch.rst b/docs/source/private-data-arch.rst index 5342f26556e..e525cd09a4b 100644 --- a/docs/source/private-data-arch.rst +++ b/docs/source/private-data-arch.rst @@ -72,11 +72,29 @@ Collection definitions are composed of the following properties: * ``memberOnlyRead``: a value of ``true`` indicates that peers automatically enforce that only clients belonging to one of the collection member organizations are allowed read access to private data. If a client from a non-member org - attempts to execute a chaincode function that performs a read of a private data, + attempts to execute a chaincode function that performs a read of a private data key, the chaincode invocation is terminated with an error. Utilize a value of ``false`` if you would like to encode more granular access control within individual chaincode functions. +* ``memberOnlyWrite``: a value of ``true`` indicates that peers automatically + enforce that only clients belonging to one of the collection member organizations + are allowed to write private data from chaincode. If a client from a non-member org + attempts to execute a chaincode function that performs a write on a private data key, + the chaincode invocation is terminated with an error. Utilize a value of + ``false`` if you would like to encode more granular access control within + individual chaincode functions, for example you may want certain clients + from non-member organization to be able to create private data in a certain + collection. + +* ``endorsementPolicy``: An optional endorsement policy to utilize for the + collection that overrides the chaincode level endorsement policy. A + collection level endorsement policy may be specified in the form of a + ``signaturePolicy`` or may be a ``channelConfigPolicy`` reference to + an existing policy from the channel configuration. The ``endorsementPolicy`` + may be the same as the collection distribution ``policy``, or may require + fewer or additional organization peers. + Here is a sample collection definition JSON file, containing an array of two collection definitions: @@ -89,7 +107,8 @@ collection definitions: "requiredPeerCount": 0, "maxPeerCount": 3, "blockToLive":1000000, - "memberOnlyRead": true + "memberOnlyRead": true, + "memberOnlyWrite": true }, { "name": "collectionMarblePrivateDetails", @@ -97,7 +116,11 @@ collection definitions: "requiredPeerCount": 0, "maxPeerCount": 3, "blockToLive":3, - "memberOnlyRead": true + "memberOnlyRead": true, + "memberOnlyWrite":true, + "endorsementPolicy": { + "signaturePolicy": "OR('Org1MSP.member')" + } } ] @@ -106,9 +129,13 @@ This example uses the organizations from the BYFN sample network, ``Org1`` and organizations to the private data. This is a typical configuration when the chaincode data needs to remain private from the ordering service nodes. However, the policy in the ``collectionMarblePrivateDetails`` definition restricts access -to a subset of organizations in the channel (in this case ``Org1`` ). In a real -scenario, there would be many organizations in the channel, with two or more -organizations in each collection sharing private data between them. +to a subset of organizations in the channel (in this case ``Org1`` ). Additionally, +writing to this collection requires endorsement from a ``Org1`` peer, even +though the chaincode level endorsement policy may require endorsement from +``Org1`` or ``Org2``. And since "memberOnlyWrite" is true, only clients from +``Org1`` may invoke chaincode that writes to the private data collection. +In this way you can control which organizations are entrusted to write to certain +private data collections. Private data dissemination -------------------------- @@ -183,6 +210,28 @@ along with the data in the chaincode APIs, for example A single chaincode can reference multiple collections. +Referencing implicit collections from chaincode +----------------------------------------------- + +Starting in v2.0, an implicit private data collection can be used for each +organization in a channel, so that you don't have to define collections if you'd +like to utilize per-organization collections. Each org-specific implicit collection +has a distribution policy and endorsement policy of the matching organization. +You can therefore utilize implicit collections for use cases where you'd like +to ensure that a specific organization has written to a collection key namespace. +The v2.0 chaincode lifecycle uses implicit collections to track which organizations +have approved a chaincode definition. Similarly, you can use implicit collections +in application chaincode to track which organizations have approved or voted +for some change in state. + +To write and read an implicit private data collection key, in the ``PutPrivateData`` +and ``GetPrivateData`` chaincode APIs, specify the collection parameter as +``"_implicit_org_"``, for example ``"_implicit_org_Org1MSP"``. + +.. note:: Application defined collection names are not allowed to start with an underscore, + therefore there is no chance for an implicit collection name to collide + with an application defined collection name. + How to pass private data in a chaincode proposal ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -213,15 +262,16 @@ Access control for private data Until version 1.3, access control to private data based on collection membership was enforced for peers only. Access control based on the organization of the chaincode proposal submitter was required to be encoded in chaincode logic. -Starting in v1.4 a collection configuration option ``memberOnlyRead`` can -automatically enforce access control based on the organization of the chaincode -proposal submitter. For more information about collection +Collection configuration options ``memberOnlyRead`` (since version v1.4) and +``memberOnlyWrite`` (since version v2.0) can automatically enforce that the chaincode +proposal submitter must be from a collection member in order to read or write +private data keys. For more information about collection configuration definitions and how to set them, refer back to the `Private data collection definition`_ section of this topic. .. note:: If you would like more granular access control, you can set - ``memberOnlyRead`` to false. You can then apply your own access - control logic in chaincode, for example by calling the GetCreator() + ``memberOnlyRead`` and ``memberOnlyWrite`` to false. You can then apply your + own access control logic in chaincode, for example by calling the GetCreator() chaincode API or using the client identity `chaincode library `__ . @@ -288,22 +338,22 @@ configurable number blocks by using the peer’s Updating a collection definition ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To update a collection definition or add a new collection, you can upgrade -the chaincode to a new version and pass the new collection configuration -in the chaincode upgrade transaction, for example using the ``--collections-config`` -flag if using the CLI. If a collection configuration is specified during the -chaincode upgrade, a definition for each of the existing collections must be +To update a collection definition or add a new collection, you can update +the chaincode definition and pass the new collection configuration +in the chaincode approve and commit transactions, for example using the ``--collections-config`` +flag if using the CLI. If a collection configuration is specified when updating +the chaincode definition, a definition for each of the existing collections must be included. -When upgrading a chaincode, you can add new private data collections, +When updating a chaincode definition, you can add new private data collections, and update existing private data collections, for example to add new members to an existing collection or change one of the collection definition properties. Note that you cannot update the collection name or the blockToLive property, since a consistent blockToLive is required regardless of a peer's block height. -Collection updates becomes effective when a peer commits the block that -contains the chaincode upgrade transaction. Note that collections cannot be +Collection updates becomes effective when a peer commits the block with the updated +chaincode definition. Note that collections cannot be deleted, as there may be prior private data hashes on the channel’s blockchain that cannot be removed.