go_study/fabric-main/docs/source/policies.rst

398 lines
13 KiB
ReStructuredText

Policies in Hyperledger Fabric
==============================
Configuration for a Hyperledger Fabric blockchain network is managed by
policies. These policies generally reside in the channel configuration.
The primary purpose of this document is to explain how policies are
defined in and interact with the channel configuration. However,
policies may also be specified in some other places, such as chaincodes,
so this information may be of interest outside the scope of channel
configuration.
What is a Policy?
-----------------
At its most basic level, a policy is a function which accepts as input a
set of signed data and evaluates successfully, or returns an error
because some aspect of the signed data did not satisfy the policy.
More concretely, policies test whether the signer or signers of some
data meet some condition required for those signatures to be considered
'valid'. This is useful for determining that the correct parties have
agreed to a transaction, or change.
For example a policy may define any of the following:
* Administrators from 2 out 5 possible different organizations must sign.
* Any member from any organization must sign.
* Two specific certificates must both sign.
Of course these are only examples, and other more powerful rules can be
constructed.
Policy Types
------------
There are presently two different types of policies implemented:
1. **SignaturePolicy**: This policy type is the most powerful, and
specifies the policy as a combination of evaluation rules for MSP
Principals. It supports arbitrary combinations of *AND*, *OR*, and
*NOutOf*, allowing the construction of extremely powerful rules like:
"An admin of org A and 2 other admins, or 11 of 20 org admins".
2. **ImplicitMetaPolicy**: This policy type is less flexible than
SignaturePolicy, and is only valid in the context of configuration.
It aggregates the result of evaluating policies deeper in the
configuration hierarchy, which are ultimately defined by
SignaturePolicies. It supports good default rules like "A majority of
the organization admin policies".
Policies are encoded in a ``common.Policy`` message as defined in
``fabric-protos/common/policies.proto``. They are defined by the
following message:
::
message Policy {
enum PolicyType {
UNKNOWN = 0; // Reserved to check for proper initialization
SIGNATURE = 1;
MSP = 2;
IMPLICIT_META = 3;
}
int32 type = 1; // For outside implementors, consider the first 1000 types reserved, otherwise one of PolicyType
bytes policy = 2;
}
To encode the policy, simply pick the policy type of either
``SIGNATURE`` or ``IMPLICIT_META``, set it to the ``type`` field, and
marshal the corresponding policy implementation proto to ``policy``.
Configuration and Policies
--------------------------
The channel configuration is expressed as a hierarchy of configuration
groups, each of which has a set of values and policies associated with
them. For a validly configured application channel with two application
organizations and one ordering organization, the configuration looks
minimally as follows:
::
Channel:
Policies:
Readers
Writers
Admins
Groups:
Orderer:
Policies:
Readers
Writers
Admins
Groups:
OrderingOrganization1:
Policies:
Readers
Writers
Admins
Application:
Policies:
Readers
-----------> Writers
Admins
Groups:
ApplicationOrganization1:
Policies:
Readers
Writers
Admins
ApplicationOrganization2:
Policies:
Readers
Writers
Admins
Consider the Writers policy referred to with the ``------->`` mark in
the above example. This policy may be referred to by the shorthand
notation ``/Channel/Application/Writers``. Note that the elements
resembling directory components are group names, while the last
component resembling a file basename is the policy name.
Different components of the system will refer to these policy names. For
instance, to call ``Deliver`` on the orderer, the signature on the
request must satisfy the ``/Channel/Readers`` policy. However, to gossip
a block to a peer will require that the ``/Channel/Application/Readers``
policy be satisfied.
By setting these different policies, the system can be configured with
rich access controls.
Constructing a SignaturePolicy
------------------------------
As with all policies, the SignaturePolicy is expressed as protobuf.
::
message SignaturePolicyEnvelope {
int32 version = 1;
SignaturePolicy policy = 2;
repeated MSPPrincipal identities = 3;
}
message SignaturePolicy {
message NOutOf {
int32 N = 1;
repeated SignaturePolicy policies = 2;
}
oneof Type {
int32 signed_by = 1;
NOutOf n_out_of = 2;
}
}
The outer ``SignaturePolicyEnvelope`` defines a version (currently only
``0`` is supported), a set of identities expressed as
``MSPPrincipal``\ s , and a ``policy`` which defines the policy rule,
referencing the ``identities`` by index. For more details on how to
specify MSP Principals, see the MSP Principals section.
The ``SignaturePolicy`` is a recursive data structure which either
represents a single signature requirement from a specific
``MSPPrincipal``, or a collection of ``SignaturePolicy``\ s, requiring
that ``N`` of them are satisfied.
For example:
::
SignaturePolicyEnvelope{
version: 0,
policy: SignaturePolicy{
n_out_of: NOutOf{
N: 2,
policies: [
SignaturePolicy{ signed_by: 0 },
SignaturePolicy{ signed_by: 1 },
],
},
},
identities: [mspP1, mspP2],
}
This defines a signature policy over MSP Principals ``mspP1`` and
``mspP2``. It requires both that there is a signature satisfying
``mspP1`` and a signature satisfying ``mspP2``.
As another more complex example:
::
SignaturePolicyEnvelope{
version: 0,
policy: SignaturePolicy{
n_out_of: NOutOf{
N: 2,
policies: [
SignaturePolicy{ signed_by: 0 },
SignaturePolicy{
n_out_of: NOutOf{
N: 1,
policies: [
SignaturePolicy{ signed_by: 1 },
SignaturePolicy{ signed_by: 2 },
],
},
},
],
},
},
identities: [mspP1, mspP2, mspP3],
}
This defines a signature policy over MSP Principals ``mspP1``,
``mspP2``, and ``mspP3``. It requires one signature which satisfies
``mspP1``, and another signature which either satisfies ``mspP2`` or
``mspP3``.
Hopefully it is clear that complicated and relatively arbitrary logic
may be expressed using the SignaturePolicy policy type. For code which
constructs signature policies, consult
``fabric/common/cauthdsl/cauthdsl_builder.go``.
---------
**Limitations**: When evaluating a signature policy against a signature set,
signatures are 'consumed', in the order in which they appear, regardless of
whether they satisfy multiple policy principals.
For example. Consider a policy which requires
::
2 of [org1.Member, org1.Admin]
The naive intent of this policy is to require that both an admin, and a member
sign. For the signature set
::
[org1.MemberSignature, org1.AdminSignature]
the policy evaluates to true, just as expected. However, consider the
signature set
::
[org1.AdminSignature, org1.MemberSignature]
This signature set does not satisfy the policy. This failure is because when
``org1.AdminSignature`` satisfies the ``org1.Member`` role it is considered
'consumed' by the ``org1.Member`` requirement. Because the ``org1.Admin``
principal cannot be satisfied by the ``org1.MemberSignature``, the policy
evaluates to false.
To avoid this pitfall, identities should be specified from most privileged to
least privileged in the policy identities specification, and signatures should
be ordered from least privileged to most privileged in the signature set.
MSP Principals
--------------
The MSP Principal is a generalized notion of cryptographic identity.
Although the MSP framework is designed to work with types of
cryptography other than X.509, for the purposes of this document, the
discussion will assume that the underlying MSP implementation is the
default MSP type, based on X.509 cryptography.
An MSP Principal is defined in ``fabric-protos/msp_principal.proto`` as
follows:
::
message MSPPrincipal {
enum Classification {
ROLE = 0;
ORGANIZATION_UNIT = 1;
IDENTITY = 2;
}
Classification principal_classification = 1;
bytes principal = 2;
}
The ``principal_classification`` must be set to either ``ROLE`` or
``IDENTITY``. The ``ORGANIZATIONAL_UNIT`` is at the time of this writing
not implemented.
In the case of ``IDENTITY`` the ``principal`` field is set to the bytes
of a certificate literal.
However, more commonly the ``ROLE`` type is used, as it allows the
principal to match many different certs issued by the MSP's certificate
authority.
In the case of ``ROLE``, the ``principal`` is a marshaled ``MSPRole``
message defined as follows:
::
message MSPRole {
string msp_identifier = 1;
enum MSPRoleType {
MEMBER = 0; // Represents an MSP Member
ADMIN = 1; // Represents an MSP Admin
CLIENT = 2; // Represents an MSP Client
PEER = 3; // Represents an MSP Peer
}
MSPRoleType role = 2;
}
The ``msp_identifier`` is set to the ID of the MSP (as defined by the
``MSPConfig`` proto in the channel configuration for an org) which will
evaluate the signature, and the ``Role`` is set to either ``MEMBER``,
``ADMIN``, ``CLIENT`` or ``PEER``. In particular:
1. ``MEMBER`` matches any certificate issued by the MSP.
2. ``ADMIN`` matches certificates enumerated as admin in the MSP definition.
3. ``CLIENT`` (``PEER``) matches certificates that carry the client (peer) Organizational unit.
(see `MSP Documentation <http://hyperledger-fabric.readthedocs.io/en/{BRANCH_DOC}/msp.html>`_)
Constructing an ImplicitMetaPolicy
----------------------------------
The ``ImplicitMetaPolicy`` is only validly defined in the context of
channel configuration. It is ``Implicit`` because it is constructed
implicitly based on the current configuration, and it is ``Meta``
because its evaluation is not against MSP principals, but rather against
other policies. It is defined in ``fabric-protos/common/policies.proto``
as follows:
::
message ImplicitMetaPolicy {
enum Rule {
ANY = 0; // Requires any of the sub-policies be satisfied, if no sub-policies exist, always returns true
ALL = 1; // Requires all of the sub-policies be satisfied
MAJORITY = 2; // Requires a strict majority (greater than half) of the sub-policies be satisfied
}
string sub_policy = 1;
Rule rule = 2;
}
For example, consider a policy defined at ``/Channel/Readers`` as
::
ImplicitMetaPolicy{
rule: ANY,
sub_policy: "foo",
}
This policy will implicitly select the sub-groups of ``/Channel``, in
this case, ``Application`` and ``Orderer``, and retrieve the policy of
name ``foo``, to give the policies ``/Channel/Application/foo`` and
``/Channel/Orderer/foo``. Then, when the policy is evaluated, it will
check to see if ``ANY`` of those two policies evaluate without error.
Had the rule been ``ALL`` it would require both.
Consider another policy defined at ``/Channel/Application/Writers``
where there are 3 application orgs defined, ``OrgA``, ``OrgB``, and
``OrgC``.
::
ImplicitMetaPolicy{
rule: MAJORITY,
sub_policy: "bar",
}
In this case, the policies collected would be
``/Channel/Application/OrgA/bar``, ``/Channel/Application/OrgB/bar``,
and ``/Channel/Application/OrgC/bar``. Because the rule requires a
``MAJORITY``, this policy will require that 2 of the three
organization's ``bar`` policies are satisfied.
Policy Defaults
---------------
The ``configtxgen`` tool uses policies which must be specified explicitly in configtx.yaml.
Note that policies higher in the hierarchy are all defined as
``ImplicitMetaPolicy``\ s while leaf nodes necessarily are defined as
``SignaturePolicy``\ s. This set of defaults works nicely because the
``ImplicitMetaPolicies`` do not need to be redefined as the number of
organizations change, and the individual organizations may pick their
own rules and thresholds for what is means to be a Reader, Writer, and
Admin.
.. Licensed under Creative Commons Attribution 4.0 International License
https://creativecommons.org/licenses/by/4.0/