当前位置:首页 » 区块链精品文章 » 正文

3.5 策略管理和访问控制

1949 人参与  2018年10月15日 11:04  分类 : 区块链精品文章  评论

在Hyperledger Fabric 1.0中,较多的地方都使用策略进行管理,它是一种权限管理的方法,包括交易背书策略、链码的实例化策略、通道管理策略等。

3.5.1 策略定义及其类型

策略定义了一些规则,验证签名数据是否符合定义的条件,结果为TRUE或者FALSE。策略的定义如下:


type Policy struct {
   Type  int32  // 策略的类型
   Value []byte // 策略的内容
}


策略的类型有两种。

1)SignaturePolicy:在基于验证签名策略的基础上,支持条件AND、OR、NOutOf的任意组 合,其中的NOutOf指的是满足m个条件中的n个就表示满足策略(m≥n)。比如 OR(Org1.Admin,NOutOf(2,Org2.Member))表示Org1的管理员或者两个Org2的成员签名都满足策略。

2)ImplicitMetaPolicy:隐含的元策略,是在SignaturePolicy之上的策略,支持大多数的组织管理员这种策略,只适用于通道管理策略。

SignaturePolicy实际只有两种类型,SignedBy和NOutOf,其他的,比如AND和OR都会转换成NOutOf类型。其定义如下:


type SignaturePolicy struct {
   // 支持的类型有:
   // *SignaturePolicy_SignedBy,验证单个签名是否正确
   // *SignaturePolicy_NOutOf_,验证是否有n个签名都正确
   Type isSignaturePolicy_Type `protobuf_oneof:"Type"`
}


ImplicitMetaPolicy是递归策略的定义方法,名称中的Implicit说明规则是由子策略生成的,Meta说明策略依赖其他策略的验证结果。


type ImplicitMetaPolicy struct {
   SubPolicy string                   // 子策略的名称
   Rule      ImplicitMetaPolicy_Rule  // 策略的规则
}


策略的规则支持3种形式:

·ImplicitMetaPolicy_ANY:任意一个子规则成立就满足策略;

·ImplicitMetaPolicy_ALL:全部子规则都成立才满足策略;

·ImplicitMetaPolicy_MAJORITY:大多数的子规则成立就满足策略。

特别说明ImplicitMetaPolicy_MAJORITY需要满足子规则数的计算方法:


threshold = len(subPolicies)/2 + 1


比如一共有3个子策略,需要至少2个子策略成立才能满足策略。如果总共有4个子策略,需要至少3个子策略成立才能满足策略。如果没有子策略,默认是满足的。

策略的内容可以有多种,下面分别来看几种策略:交易背书策略、链码实例化策略和通道管理策略。

3.5.2 交易背书策略

交易背书策略是对交易进行背书的规则,是跟通道和链码相关的,在链码实例化的时候指定。在链码调用的时候,需要从背书节点收集足够的签名背书,只有通过背书策略的交易才是有效的。这是通过应用程序和背书节点之间的交互来完成的,这在前面的交易流程里已经介绍过了。

1.交易背书策略的验证

背书是由一组签名组成的,每个Peer节点接收到区块时,都能根据交易的内容本地验证背书是否符合背书策略,不需要和其他节点交互。验证交易背书的基本原则是:

1)所有的背书都是有效的,验证消息用有效的证书进行正确的签名;

2)满足背书策略的有效背书数量,转化为NOutOf格式进行比较;

3)背书是期望的背书节点签名的,在背书策略中指定了哪些组织和角色是有效的背书节点。

如何来实现这几个原则的呢?我们先从背书签名的命令行语法开始,背书签名的语法AND和OR都可以转为NOutOf:

·AND(A,B)可以转换为NOutOf(1,A,B);

·OR(A,B)可以转换为NOutOf(2,A,B)。

我们主要来看下NOutOf如何实现,背书策略的定义如下:


type SignaturePolicyEnvelope struct {
   Version    int32                    // 背书策略版本,默认都是0
   Rule       *SignaturePolicy         // 背书策略规则:签名策略
   Identities []*common1.MSPPrincipal  // 背书策略主体:MSP主体签名
}


其中,MSP主体(Principal)是基于MSP的身份标识的,有如下几种类型。

1)MSPPrincipal_ROLE:基于MSP角色的验证方法,目前只有admin和member两种。

2)MSPPrincipal_ORGANIZATION_UNIT:基于部门的验证方法,同一个MSP中的不同部门。

3)MSPPrincipal_IDENTITY:基于某个具体身份证书的验证方法,验证签名是否有效。

MSPPrincipal的定义如下:


type MSPPrincipal struct {
   PrincipalClassification MSPPrincipal_Classification // MSP的类型
   Principal []byte                // 根据MSP的类型不同,实体有不同的内容
}


根据不同的MSP类型,主体是不同的。

(1)基于MSP角色的验证

当PrincipalClassification是MSPPrincipal_ROLE时,主体存储的内容如下:


type MSPRole struct {
   // MSP标识符
   MspIdentifier string
   // MSP角色:可选值是MSPRole_MEMBER和MSPRole_ADMIN
   Role MSPRole_MSPRoleType
}


不同角色的验证方法如下:

1)MSPRole_MEMBER:验证是否为同一个MSP的有效签名;

2)MSPRole_ADMIN:验证签名者是否是MSP设置好的admin成员。

(2)基于部门的验证

当PrincipalClassification是MSPPrincipal_ORGANIZATION_UNIT时,主体存储的内容如下:


type OrganizationUnit struct {
   // MSP标识符
   MspIdentifier string
   // 组织部门标识符
   OrganizationalUnitIdentifier string
   // 证书标识符:信任证书链和组织部门信息的哈希
   CertifiersIdentifier []byte
}


验证过程的步骤是:

·验证是否为相同的MSP;

·验证是否是有效的证书;

·验证组织部门信息是否匹配。

(3)基于身份证书的验证

当PrincipalClassification是MSPPrincipal_IDENTITY时,主体存储的内容如下:


type identity struct {
   // 身份标识符,包含MSP标识符和身份编号
   id *IdentityIdentifier
   // 身份的数字证书,包含了对公钥的签名
   cert *x509.Certificate
   // 身份的公钥
   pk bccsp.Key
   // 身份的MSP信息
   msp *bccspmsp
}


这样验证MSP是否是有效证书就可以了。

2.命令行的背书策略语法

在命令行里,可以用一种简单的语言,根据主体的布尔表达式来表示策略。主体是用MSP来表示的,用来验证签名者的 标识和签名者在MSP里的角色。目前支持两种角色:member和admin。主体的表示方法是MSP.ROLE,其中MSP是MSP的标识,ROLE可 以是memeber也可以是admin。这都是有效的主体:Org0.admin表示由MSP标识Org0的任何一个管理员,Org1.memeber表 示由MSP标识Org1的任何一个成员。

其语法是:EXPR(E[,E...]),其中EXPR可以是AND也可以是OR,E可以为一个主体,也可以为嵌套的EXPR。比如:

1)AND('Org1.member','Org2.member','Org3.member')要求3个MSP标识Org1、Org2和Org3,其中每个MSP都有1个成员有1个签名;

2)OR('Org1.member','Org2.member')要求2个MSP标识Org1、Org2,其中任何1个成员有1个签名;

3)OR('Org1.member',AND('Org2.member','Org3.member'))要求MSP标识Org1的成员有1个签名,或者MSP标识Org2和Org3的成员都有1个签名。

目前在命令行的语法中,背书策略只支持AND和OR两种,并不支持更为复杂的NOutOf。这部分的设计在后续内 容中也会有调整。SDK对背书策略都会转换成NOutOf语法,不过不是所有的SDK都支持。比如目前fabric-sdk-go提供的默认接口不支持 NOutOf语法,但其内部是支持的,稍加改动很容易就能支持。详细可以参考cauthdsl_builder.go文件。

3.给链码指定背书策略

背书策略可以在部署的时候用-P参数指定,后面是具体的背书策略。比如:


peer chaincode deploy -C testchainid -n mycc -p github.com/hyperledger/fabric/
examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a","100","b","200"]}’
-P "AND('Org1.member', 'Org2.member')"


这个命令在链testchainid上部署链码mycc,背书策略是AND('Org1.member','Org2.member')。如果命令行里没有指定策略,那么默认的背书策略要求MSP标识DEFAULT成员的一个签名。

3.5.3 链码实例化策略

链码实例化策略是用来验证是否有权限进行链码实例化和链码升级的。链码实例化策略是在对链码打包和签名的时候指定的,如果没有指定实例化策略,默认是通道的管理员才能实例化。


type SignedChaincodeDeploymentSpec struct {
   // 链码部署规范
   ChaincodeDeploymentSpec []byte
   // 链码的实例化策略,结构同背书策略,在实例化的时候验证
   InstantiationPolicy []byte
   // 链码所有者的签名背书列表
   OwnerEndorsements []*Endorsement
}


链码实例化策略的定义和背书策略完全一样,验证方法也相同,只是用途和用法不一样。链码实例化策略是直接从链码打 包中获取的,实例化完成后会将策略存放在链上。在链码实例化和升级的时候会先验证是否符合当前的实例化策略,验证通过才可以更新链码实例化策略。存储在链 上的链码信息结构如下所示:


type ChaincodeData struct {
   // 链码名称
   Name string
   // 链码版本
   Version string
   // 链码的ESCC
   Escc string
   // 链码的VSCC
   Vscc string
   // 链码的背书策略
   Policy []byte
   // 链码的内容:包含链码的名称、版本、链码源码哈希、链码名称和版本的元数据哈希等内容
   // 不包含链码源码
   Data []byte
   // 链码指纹标识,目前没有使用
   Id []byte
   // 链码实例化策略
   InstantiationPolicy []byte
}


链码信息结构ChaincodeData在链上是按链码的名称索引的。

3.5.4 通道管理策略

通道配置是递归定义的:


type ConfigGroup struct {
   Version   uint64                    // 配置版本
   Groups    map[string]*ConfigGroup   // 子配置
   Values    map[string]*ConfigValue   // 配置值
   Policies  map[string]*ConfigPolicy  // 配置策略定义
   ModPolicy string                    // 配置修改策略的名称
}


其中,配置值ConfigValue定义的是一些配置数据,定义如下:


type ConfigValue struct {
   Version   uint64 // 配置版本
   Value     []byte // 配置数据,可以是JSON结构的
   ModPolicy string // 配置修改策略名称
}


比如在通道配置中区块生成间隔BatchTimeout设置的值是“2s”,局部的格式如下:


"BatchTimeout": {
   "mod_policy": "Admins",
   "value": {
       "timeout": "2s"
   }
}


我们再来看最重要的配置策略的定义:


type ConfigPolicy struct {
   Version   uint64  // 配置策略版本
   Policy    *Policy // 配置策略的内容,这在前面已经介绍过
   ModPolicy string  // 配置策略中修改策略的名称
}


从上面的定义中我们可以看到,配置策略是基于SignaturePolicy和ImplicitMetaPolicy的,ModPolicy代表的是修改同级策略用到的策略名称。通道定义了3种配置策略,如表3-1所示。

表3-1 3种配置策略

image.png

1.通道配置的递归定义

我们来看一个简化的通道配置是如何递归定义的。


Channel:
   Policies:
       Readers
       Writers
       Admins
   Groups:
       Orderer:
           Policies:
               Readers
               Writers
               Admins
           Groups:
               OrdereringOrganization1:
                   Policies:
                       Readers
                       Writers
                       Admins
       Application:
           Policies:
               Readers
----------->    Writers
               Admins
           Groups:
               ApplicationOrganization1:
                   Policies:
                       Readers
                       Writers
                       Admins
               ApplicationOrganization2:
                   Policies:
                       Readers
                       Writers
                       Admins


在上面的配置中,最外层是Channel,它定义了通道的子配置和策略定义。Channel的子配置里面定义了 Orderer和Application配置,它们分别是相同的递归定义结构。其中"------->"显示的一行按照层级展开,代表的是 /Channel/Application/Writers。

怎么来使用这些配置策略呢?比如在排序服务节点调用Deliver接口的时候会检查这个节点是否满足/Channel/Readers策略。Peer节点同步区块的时候也会检查是否满足/Channel/Application/Readers策略。

更详细的例子参考第6章的相关内容。

2.通道配置的默认策略

在使用configtxgen工具生成创世区块或者通道配置时,使用的默认策略如表3-2所示。

表3-2 通道配置的默认策略
image.png

来源:我是码农,转载请保留出处和链接!

本文链接:http://www.54manong.com/?id=1082

区块链是什么  

微信号:qq444848023    QQ号:444848023

加入【我是码农】QQ群:864689844(加群验证:我是码农)

<< 上一篇 下一篇 >>

网站分类

标签列表

最近发表

全站首页 | 数据结构 | 区块链| 大数据 | 机器学习 | 物联网和云计算 | 面试笔试

本站资源大部分来自互联网,版权归原作者所有!