前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >超级账本(Hyperledger Fabric)之权限管理浅析

超级账本(Hyperledger Fabric)之权限管理浅析

原创
作者头像
qudamahcui
发布2018-09-13 16:04:23
6.2K6
发布2018-09-13 16:04:23
举报

超级账本(Hyperledger Fabric)之权限管理浅析

超级账本是联盟链的代表,而其相对于共链(例如比特币,以太坊)一个较大的区别在于其强大的角色管理和权限把控上,本文主要介绍其角色管理和权限把控的一些核心机制。

证书生成

证书认证是超级账本中权限管理体系的最基础的机制,而所有证书的生成超级账本提供了一个工具cryptogen用于根据配置文件生成一套证书,并且将这些证书组织为peer和orderer两个核心组件可以直接使用的形式。

配置文件

Cryptogen的配置文件demo如下

#################################################################

OrdererOrgs: #用于orderer 组件使用的组织信息

- Name: Orderer #orderermsp的名称

Domain: example.com #orderer 的域名后缀

CA: #CA信息,不用关注,照着填写即可

Country: US

Province: California

Locality: San Francisco

Specs: #orderer域名前缀,和Domain一起组成了域名用于tls认证使用

- Hostname: orderer

PeerOrgs: #用于peer 组件使用的组织信息

- Name: Org1 #组织名称

Domain: org1.example.com #组织域名

CA:

Country: US

Province: California

Locality: San Francisco

Template: #组织内参与个体的个数

Count: 2

Users: #组织内除了管理员用户外的其他用户个数

Count: 1

- Name: Org2

Domain: org2.example.com

CA:

Country: US

Province: California

Locality: San Francisco

Template:

Count: 2

Users:

Count: 1

###########################################################################

上面的配置文件定义了一个orderer和两个组织(org1和org2),而每一个组织有两个参与方(template/count=2),同时每一个组织有一个普通用户(users/count=1)和一个管理员。其中域名的信息是为了生成tls证书,不用太关注。

生成工具

将上面的配置文件另存为crypto-config.yaml,然后运行

./cryptogen generate --config=./crypto-config.yaml --output ./crypto-config

其中cryptogen是超级账本源码自带的一个工具,编译方式是找到Fabric的目录,使用命令行:

Make build/bin/cryptogen

编译后,cryptogen存放在Fabric目录的build/bin目录下

参数—config代表了配置文件的路径

参数—output代表了生成的一套证书存放的位置

生成结果

命令运行后生成的目录结构如下

其中ordererOrganizations目录对应的是配置文件中的OrdererOrgs一节,而peerOrganizations目录对应的是PeerOrgs一节。ordererOrganizations/example.com、peerOrganizations/org1.example.com、peerOrganizations/org2.example.com这三个目录分别代表了三个机构,orderer机构一般是虚拟的,或者是超然的,是orderer节点的配置,而每一个机构都有两个根证书,一个用于功能性证书的签发,一个用于tls机制证书的签发,tls机制网上有比较成熟的资料,本文不过多介绍,只关注功能性证书。

每一个组织一般有这些目录

Ca

存放了一个功能性证书的根证书,和它对应的私钥。这个证书用于签发组织内所有非tls证书。

Tlsca

tls类证书的根证书,不关注

Users

代表所有的用户,这个一般是用于通过命令行cli节点连接Fabric网络时证明自己身份的,Admin代表是这个组织的管理员,而User代表的是组织的成员

Msp

存放了管理员证书admincerts,根证书cacerts,tls根证书tlscacerts 三类证书的拷贝,但是只有证书没有私钥,这个目录目前笔者没有发现在实际应用中的用途。

Orderers/peers目录

存放的一般是orderer.example.com或者peer0.org2.example.com

其中msp和tls两个目录直接用于orderer或者对应的peer节点启动的配置。Msp一般存放了功能性证书如下:

Admincerts存放了本peer对应的组织的管理员证书和users下的admin证书是一个,只是这里只有证书没有私钥。这个是用于后面验证访问peer节点的cli(用户使用的命令行)的身份是否是该组织的管理员。

Cacerts 存放了本组织根证书的拷贝,用于验证所有的本组织的证书是否合法。

Signcerts和keyStore两个目录是配套的证书和私钥,用于peer节点对交易做签名,供别的节点(orderer或者别的peer)验证,以证明交易的合法性。这个证书是peer节点独有的,用于证明peer节点(代表这个机器或者节点,区别于user代表的是实际人)的身份。

其中有几个重点需要关注:

1、每一个组织都有一个自己的根证书,各个组织的根证书互相独立。

2、每一个组织有两类实体,一类是代表人的user,一类是代表机器或者节点的peer

3、每一个组织的用户user分成管理员Admin和普通用户

4、Peer节点存放的是根证书、管理员证书、以及代表自己的证书,只有代表自己的证书有私钥,根证书和管理员证书是没有私钥的,仅仅是为了验证别人的身份

证书验证

证书验证

这里的证书验证是指,证明证书本身是否合法,以及使用这个证书签名的数据是否合法两个部分。

首先是证书合法,证书合法需要两个信息一个是证书对应的组织id,一个是证书本身。

验证过程为

其次是验证交易数据是否合法,其实交易包含三部分,一部分就是组织ID+证书,一部分就是交易数据,第三部分是使用证书给交易数据打的签名

交易的验证就是通过证书验证交易数据是否合法,验证过程如下

策略验证

除了证书本身的验证,超级账本还引入了策略验证,策略验证可以认为是多证书验证。是Fabric权限管理的基础。如创建通道需要同时两个组织都同意才可以,也就是需要两个组织的User都签名,那么这个策略就需要验证两个单证书是否合法。

策略分三种

1、n of m策略

这种策略指的是必须符合m个策略中的n个策略策略验证才算通过,n of m 策略可以嵌套 n of m 策略、meta策略、以及原子策略,比如创建链码需要 三个组织中有两个以上组织认可才算通过,就是一个2 of 3 策略。

"Policy": {

"PolicyType": "1",

"Policy": {

"version": 0,

"rule": {

"nOutOf": {

"n": 1,

"rules": [

{

"signedBy": 0

}

]

}

},

"identities": [

{

"principalClassification": "ROLE",

"principal": "CgpPcmRlcmVyTVNQEAE="

}

]

}

}

这个例子代表了一个1 of n的策略

2、meta策略

这种策略指的是子(组织中的)策略集合必须满足一定规则才可以通过。一般有三种形式:

1)ANY 子策略集合中的任意一个策略满足就为通过

2)MAJORITY 子策略集合中的半数以上策略满足就为通过

3)ALL 子策略集合中的所有策略满足才算通过

"Policy": {

"PolicyType": "3",

"Policy": {

"subPolicy": "Readers",

"rule": "ANY"

}

}

这个例子代表了,只需要满足一个子组织中的Readers策略就算是通过。

3、原子策略

原子策略是直接对应证书验证的策略,有三种形式

1)ROLE形式,ROLE形式又分为Admin和member两种,前者验证证书是否是某个组织的admin证书,后者只需要检查证书对应的组织id和预期的组织一致就可以

2)IDENTITY形式,代表了证书必须是和预期的证书是一个证书,二进制match

3)ORGANIZATION_UNIT形式,代表证书信息中的org信息必须是预期内的(这个和证书信息本身有关,虽然也是组织但是和上文谈到的组织id不是一个概念)

原子策略一般被嵌套在n of m策略或者meta策略内部使用,也可以单独使用

策略一般通过路径定位,比如channel/Readers 定位到的是通道读权限对应的策略。

系统配置

配置结构

上文中提到的策略等是以配置的形式存放在区块中的,而配置的结构是一个嵌套的结构,每一层叫做一个配置Group,每一个Group包含三个子结构

1、groups 存放的是子group

2、policies 存放的是这个group对应的策略

3、values 存放的是这个group对应的实际配置信息

一个通道的初始区块的json形式如下图

其中values不用过多解释,一般以key value的形式存放了一些配置如下图

其中HashingAlgorithm代表的是系统使用的hash算法是sha256

Policies一般存放Admins、Readers和Writers三种策略

Admins一般代表了管理员权限,Readers一般代表了读权限,Writers代表了写权限

Groups一般是一些子组织,也就是路径定位中的子路径,比如组织1的完整路径为

Channel/Application/Org1MSP

细心的读者可能会发现配置中基本所有的项(无论value policy还是group)都有一个mod_policy的项,这个代表的是修改这个配置需要的权限,一般是一个字符串,比如/Channel/Orderer/Admins代表了一个绝对路径,而"mod_policy":"Admins"代表了一个相对路径,前者代表的是找Channel下的Orderer下的policy的Admins节点来作为最终的策略;后者代表的是在本Group中找到Policy的admins节点作为最终的策略。

上文中提到的三种策略类型对应的json如下

1)n of m策略

2)meta策略

其中sub_policy 中的Readers代表了一个相对路径,代表了用所有子group中的Readers策略作为meta策略的策略集合。如果没有特殊说明就是ANY类型

3)原子策略

通道配置

通道配置一般可以通过如下方式获取

1)获取到通道最新的配置区块

CORE_PEER_LOCALMSPID="OrdererMSP"

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp

peer channel fetch config newconfig -o orderer.example.com:7050 -c "businesschannel"

其中CORE_PEER_LOCALMSPID和CORE_PEER_MSPCONFIGPATH是代表了组织ID和msp目录的两个环境变量

Newconfig代表了取回来的区块的本地存放文件名

Businesschannel 代表了通道的名称

2)将通道区块转换成json

2.1)./configtxlator start --hostname="0.0.0.0" --port 7059 运行一个解析器的服务端

2.2)curl -X POST --data-binary @newconfig http://127.0.0.1:7059/protolator/decode/common.Block > ./newconfig.json 解码区块为json,其中newconfig是刚刚取回来本地的配置区块,newconfg.json是要转换后的文件

3)将配置单独拿出来

jq .data.data[0].payload.data.config newconfig.json > newconfig_config.json

其中newconfig.json是第二步中转换的json,newconfig_config.json是纯配置文件

最后得到的配置读者可以自行研究,和上文中的配置结构对应着看会比较清楚

关键策略

经过上文的一些描述,希望读者可以了解到权限管理的基本概念和实现方式,本节主要讲解一些权限中一些重要的权限。另外需要提前解释的是身份证明是通过运行命令行时候配置CORE_PEER_LOCALMSPID和CORE_PEER_MSPCONFIGPATH两个环境变量完成的,一个代表组织ID一个代表证书。

通道创建策略

本策略是在使用channel create命令时需要审核的策略,对应的配置位置是orderer初始区块的channel/Consortiumms/SampleConsortium/Values/ChannelCreationPolicy节点内

这里如果看源码可能会有一个困惑,这个策略是怎么应用的呢?

这是一个巧妙的设计

在func (ml *multiLedger) NewChannelConfig(通过名字搜函数)中有一个设置applicationGroup.ModPolicy = config.ChannelCreationPolicyKey 也就是修改application需要有ChannelCreationPolicyKey权限,而从systemchannel也就是系统初始区块构造出来的配置是没有applicationGroup的

但是通道创建的时候会有对application修改的writeset(创建通道其实就是对系统配置的修改,然后拼装成了一个新的配置区块)

Write Set:

{

"Channel": {

"Values": {

"Consortium": {

"Version": "0",

"ModPolicy": "",

"Value": {

"name": "SampleConsortium"

}

}

},

也就是创建通道时候要修改application这个group,而这个group的ModPolicy被设置成了channel/Consortiumms/SampleConsortium/Values/ChannelCreationPolicy

加入通道策略

必须是localmsp的admin权限,也就是想加入通道必须配置msp为和peer相同组织的admin证书。

验证代码是在cscc/configure.go invoke函数的

if err = e.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp) policy获取是 localMSPPrincipalGetter ,localMSP代表的就是本组织的,对应的是peer加载的时候配置的msp目录里的admin和根证书

更新配置策略

更新配置策略一般对应的是要更新的配置的ModPolicy对应的策略,如更新Org1的锚点需要Org1的admin证书

链码安装策略

链码安装也就是peer chaincode install 这个命令需要的是本组织(localmsp)的admin权限这个是在代码中写死的

验证在

func (lscc *LifeCycleSysCC) Invoke(stub shim.ChaincodeStubInterface)

lscc.policyChecker.CheckPolicyNoChannel(mgmt.Admins, sp)

链码部署策略

链码部署有两种权限验证方式

1、通过peer chaincode package的方式打包链码并且安装的话会有一个-i的参数可以指定部署的策略,如:

peer chaincode package -n “testcc” -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -v 1.0 -s -S -i "AND ('Org1MSP.admin')" ccpack.out

其中“testcc” 是链码名称,"AND ('Org1MSP.admin')"代表了部署需要Org1的admin证书签名

生成的ccpack.out 可以通过peer chaincode install ccpack.out 直接安装

Ps:这个功能只有咋v1.0.6这个tag后的代码才有

2、如果普通的直接通过peer chaincode install 命令安装的则需要通道的admin权限,如:

peer chaincode install -n “testcc” -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

这两种机制的区分是在

func (lscc *LifeCycleSysCC) executeDeploy(stub shim.ChaincodeStubInterface, chainname string, depSpec []byte, policy []byte, escc []byte, vscc []byte)

func (lscc *LifeCycleSysCC) getInstantiationPolicy

这个调用链路上有体现

链码更新策略

链码更新策略和链码部署策略一致

链码调用策略

链码调用策略写死在代码中的,需要的是通道的writes策略

代码调用链条是

func (e *Endorser) ProcessProposal(ctx context.Context, signedProp *pb.SignedProposal)

func (e *Endorser) checkACL(signedProp *pb.SignedProposal, chdr *common.ChannelHeader, shdr *common.SignatureHeader, hdrext *pb.ChaincodeHeaderExtension)

e.policyChecker.CheckPolicy(chdr.ChannelId, policies.ChannelApplicationWriters, signedProp)

->func (p *policyChecker) CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal)

链码背书策略

链码背书策略是在链码部署的时候指定的一个参数,如:

peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n $CC_NAME -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

其中-P "OR ('Org1MSP.member','Org2MSP.member')"制定了链码的背书策略,这里也就是需要org1 或者org2 的成员背书

验证的代码链条为

func (v *txValidator) Validate

func (v *vsccValidatorImpl) VSCCValidateTx

func (v *vsccValidatorImpl) GetInfoForValidate

func (vscc *ValidatorOneValidSignature) Invoke

注意这个policy的验证是在区块生成好验证的,为啥不是在执行链码的时候就验证呢?

原因是执行链码时候还没有拿到验证需要的背书签名,只有获取够签名才能验证,而执行链码是在背书的时候进行的,执行后才能拿到背书签名,所以是在验证区块的时候验证,如果验证失败就不入库。这也是Fabric区别于以太坊和比特币的一个很重要的细节,Fabric是无论交易是否合法都写入了区块链,而以太坊和比特币只写入合法的交易。

事件监听策略

事件监听的策略是需要localmsp的member权限,这个也是写死在代码中的,验证的函数是func validateEventMessage(signedEvt *pb.SignedEvent)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 超级账本(Hyperledger Fabric)之权限管理浅析
    • 证书生成
      • 证书验证
        • 系统配置
          • 关键策略
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档