Hyperledger Fabric中的身份Identity

身份是许可区块链平台的一个重要特征。在Hyperledger Fabric中,需要在访问结构网络之前识别每个组件。身份Identity由X.509数字证书表示。当与结构网络交互时,该actor指定并呈现数字证书,并且结构网络基于该策略接受或拒绝。

Hyperledger Fabric中有关于身份的很好的描述。链接在这里

在典型情况下,向用户提供具有与该用户相关联的适当信息的数字证书。只要该数字证书由结构网络信任的证书颁发机构颁发,用户的操作将由结构网络接受和处理。

使用加密工具生成加密信息时可以创建数字证书,或者更常见的是,通过在证书颁发机构上注册和注册生成数字证书。

在本文中,我们首先运行基本网络并在其上部署Simple Asset Chaincode。通过检查容器设置和链代码操作,我们将看到在链代码调用期间如何呈现身份。最后,我们引入客户端身份链代码库来捕获用户的身份并基于主题执行访问控制。

这不是身份和会员服务提供商(MSP)的完整指南。尽管如此,我们可以通过Hyperledger Fabric平台中的部署更加了解身份。

设置:基本网络上的简单资产链接

我们从最简单的链代码和结构网络开始。这里我们使用Simple Asset Chaincode和Basic Network。

基本网络

这是最简单的设置,适合快速演示。我们可以通过简单地运行脚本./start.sh来启动基本网络:

1
2
cd fabric-samples/basic-network
./start.sh

脚本完成后,我们会看到一个结构网络,它带有Org1的OrdererPeer和Certificate Authority(CA),以及作为Peer节点的世界状态数据库的CouchDB

除了基础设施之外,还创建了一个通道mychannel,并且对等节点已经与mychannel连接。

SACC

Simple Asset Chaincode(SACC)也有fabric示例。它提供了在分类帐中存储资产的基本功能。资产由键值对表示。当首先在通道中实例化链码时,需要初始键值。稍后可以使用get/set命令调用链代码,以获取密钥的值或为现有密钥设置新的键值或新值。你可以在这里参考SACC

将SACC部署到基本网络

请注意,链代码本身不包含任何结构网络和通道信息。 我们需要将链码部署到我们的基本网络和mychannel上。

我们使用CLI来促进链代码安装和实例化。

1
2
3
docker-compose -f docker-compose.yml up -d cli
docker exec cli peer chaincode install -n sacc -v 0 -p github.com/sacc
docker exec cli peer chaincode instantiate -n sacc -v 0 -C mychannel -c '{"Args":["a", "100"]}'

现在我们可以检查分类帐中a的值。

1
docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'

我们可以设置另一个值并再次获得结果。SACC按预期在我们的基本网络中运行良好。

1
2
docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["set", "a", "500"]}'
docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'

事情进展顺利。现在我们将注意力转移到身份部分。

在Fabric网络中查看身份

如上所述,作为许可的区块链平台,我们期望结构网络中的每个交易都由识别的用户发起。如果我们重新审视我们已经完成的工作,我们似乎永远不会涉及任何身份:我们只从CLI发出命令对等链代码。

实际上,CLI扮演的角色是在发出命令时向结构网络提供身份信息。

在CLI容器内

我们来看一下CLI容器中的环境变量设置。

1
docker exec cli env

我们看到CORE_PEER_MSPCONFIGPATH已设置,指向Admin@org1.example.com/msp。这是我们使用CLI启动到结构网络的任何交易时使用的标识。

我们可以通过将此变量设置为空来进行测试。链代码调用失败,访问被拒绝。

1
docker exec -e "CORE_PEER_MSPCONFIGPATH=" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'

除了Admin之外,它还带有另一个标识:User1@org1.example.com。我们可以看到Org1中定义的用户。

1
docker exec cli ls crypto/peerOrganizations/org1.example.com/users

如果我们使用此标识调用链代码(覆盖此变量),我们也会得到结果。

1
2
docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["set", "a", "300"]}'
docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}

到目前为止,我们知道链代码调用(以及所有链代码操作)需要身份。在CLI中,它是通过环境变量完成的。但这些身份来自哪里? 我们进一步移动并查看配置文件。

在Docker-Compose文件中

CLI容器从docker-compose文件实例化。以下是有关CLI的docker-compose文件的一部分。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=info
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
- CORE_CHAINCODE_KEEPALIVE=10
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
networks:
- basic

我们在这里看到:

  • 此处设置环境变量CORE_PEER_MSPCONFIGPATH。CLI容器运行后,我们已经拥有此默认标识。
  • 身份信息保存在容器内的/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto目录中,该目录是从我们的localhost上的./crypto-config映射的卷。

因此,我们将查看localhost中的./crypto-config

在./crypto-config目录中

这是我们localhost中的./crypto-config的目录结构。

我们在org1.example.com/users中看到AdminUser1都已定义。这些是CLI中链代码调用中使用的标识。

在msp中,我们看到了keystoresigncerts目录。密钥库保留签名密钥(私钥),signcerts保留包含与私钥关联的公钥的证书。

这是管理员证书截获的。我们看到主题(CN = Admin@org1.example.com)和发行人(CN = ca.org1.example.com)信息。

这是User1证书的一个。我们看到相同的Issuer(CN = ca.org1.example.com)。

Fabric网络接受两个证书,因为它们都由结构网络信任的同一Issuer颁发。

最后,我们还看到了颁发者的证书。它是Org1的CA.

这是一个自签名证书(Issuer = Subject)。这通常用于演示目的。 在现实生活中,它通常来自企业认证机构或一些可信赖的第三方。

我们的最后一个问题是:这些证书来自哪里?如前所述,数字证书可以通过加密工具和证书颁发机构的注册获得。在基本网络中,此crypto-config目录已预先填充。整个目录结构使用bin/cryptogen和配置文件crypto-config.yaml构建。虽然在基本网络中运行CA,但我们不需要访问CA. 额外的User1证书足以进行演示。

这是配置文件crypto-config.yaml(删除所有注释)

1
2
3
4
5
6
7
8
9
10
11
12
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
Template:
Count: 1
Users:
Count: 1

在此配置文件中,Users Count 1表示除Admin之外,还会生成新的用户标识(表示为User1)。这就是我们在Org1中看到Admin和User1的原因。

同样,这种加密信息是通过加密工具创建的。如果所需的用户身份数量是已知的并且是静态的,则可能已经足够好了。如果在运行cryptogen之后需要更多用户证书,或者我们需要自定义某些属性,我们可以使用为Org1部署的CA。

当我们从用户角度与结构网络交互时,我们几乎发现了与身份相关的任何事情。我们现在看到如何根据证书主题应用访问控制。

Chaincode中的访问控制

在链代码级别实施访问控制的方法是通过Hyperledger Fabric提供的库:Client Identity Chaincode Library

导入后,此库提供了获取链代码调用程序信息的方法,例如ID,MSPID和X509。除了X509中的基本信息之外,该库还提供了一种在生成X509数字证书时读取属性的方法。

出于演示目的,我正在创建一个名为sacc-ac(SACC访问控制)的新链代码。此代码从另一个链代码chaincode/abac复制。我利用abac中已安装的所有必需软件包。为了保持一致性和简单性,我使用SACC覆盖原始的abac.go(abac.go使用chaincode_example02)。

1
2
3
4
5
cd fabric-samples/chaincode
cp -r abac/ sacc-ac/
cp sacc/sacc.go sacc-ac/go/sacc-ac.go
cd sacc-ac/go
rm abac.go

为了演示,我修改了函数set(),以便只有Admin可以设置一个新值,而其他人(如User1)则不能。

修改SACC-AC代码

这是修改后的SACC(sacc-ac.go)。仅显示修改部分。

import部分

1
2
3
4
5
6
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim/ext/cid"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)

set()部分

1
2
3
4
5
6
7
8
9
10
11
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {

// only Admin can set value
x509, _ := cid.GetX509Certificate(stub)
if x509.Subject.CommonName != "Admin@org1.example.com" {
return "", fmt.Errorf("Only Admin can set new value.")
}
...
original code
...
}

这两个更新是在原始的sacc.go链代码上完成的。

cid库已导入。请注意,该库已包含在vendor目录中。

set()中我们使用cid.GetX509Certificate()方法提取x509证书,在x509中我们提取Subject.CommonName(CN)。我们通过检查CN是否为Admin来强制执行访问控制,并且将返回非Admin用户并显示错误消息。

将SACC-AC部署到基础网络

和以前一样,我们安装并实例化链码。我们的链码现在称为sacc-ac

1
2
docker exec cli peer chaincode install -n sacc-ac -v 0 -p github.com/sacc-ac/go
docker exec cli peer chaincode instantiate -n sacc-ac -v 0 -C mychannel -c '{"Args":["a", "100"]}'

调用SACC-AC Chaincode

我们首先使用User1(设置环境变量)来获取值,然后设置值。

1
2
docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["get", "a"]}'
docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["set", "a", "500"]}'

请注意,User1可以获取值,但不能在链代码中为每个访问控制设置任何值。如果我们再次尝试使用Admin(默认值是使用Admin),

1
docker exec cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["set", "a", "500"]}'

调用成功。带主题的访问控制效果很好。

总结

通过Basic Network和Simple Asset Chaincode,我们了解了Hyperledger Fabric中的身份。Hyperledger Fabric网络和链代码上的每个活动都需要身份,以X.509数字证书的形式呈现。只要发布者CA受到结构网络的信任,就接受并处理该活动。使用客户端身份链代码库,我们然后修改了SACC并包含基于主题公共名称的访问控制。这证明了如何在链代码级别强制执行访问控制。

======================================================================

如果你想学习区块链并在Blockchain Technologies建立职业生涯,那么请查看我们分享的一些以太坊、比特币、EOS、Fabric等区块链相关的交互式在线编程实战教程:

  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • c#比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。
  • EOS入门教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
  • 深入浅出玩转EOS钱包开发,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。
  • Hyperledger Fabric 区块链开发详解,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。
  • Hyperledger Fabric java 区块链开发详解,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。
  • tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。

汇智网原创翻译,转载请标明出处。这里是Hyperledger Fabric中的身份Identity