一:简介
在e2e_cli的例子中,所有用到的证书和私钥都是由cryptogen这个工具根据crypto-config.yaml而生成的。但是在实际的生产环境中,我们需要给每个org都建立自己的CA,用来管理本org的用户。本次是以e2e_cli为例子,然后手动的生成所有的证书和私钥,并进行手动的执行例子进行验证。
二:环境准备
1:linux环境(我的是vmware虚拟机, ubuntu16.04)
Go 1.9+ GOPATH环境变量安装成功
Libtool和libtdhl-dev需要安装
(ubuntu:sudo apt install libtool libltdl-dev)
2:可以成功执行e2e_cli例子(这是基本,毕竟在上面进行验证)
3:安装fabric-ca-server和fabric-ca-client的可执行文件到$GOPATH/bin目录下
(go get -u github.com/hyperledger/fabric-ca/cmd/...)
我是直接进行复制的,这样下不下来。
三:生成根CA的证书
生成自签CA证书有两种形式:通过可执行文件和镜像,下面进行分别的说明:
1:命令行形式
执行fabric-ca-server start -b admin:adminpw
-b选项为引导管理员提供注册ID和密码; 如果LDAP未启用“ldap.enabled”设置,则这是必需的。如果服务器以前没有被初始化init,它将在第一次启动时自行初始化。 在初始化期间,如果服务器尚不存在,服务器将生成ca-cert.pem和ca-key.pem文件(msp文件夹下),并且如果该文件不存在,还会创建一个默认配置文件fabric-ca-server-config.yaml。
注意:
(1):首先可以通过fabric-ca-server init进行初始化,创建证书和私钥以及配置文件,也可以直接进行start,第一次start时会自动执行init的操作。
(2):这种操作产生的根证书是自签的。可以进行验证:(openssl verify -CAfile ca-cert.pem ca-cert.pem 返回ok)
(3):证书可以通过openssl x509 -in ca-cert.pem -text进行查看。
2:使用镜像启动
fabric-ca-server:
image: hyperledger/fabric-ca:x86_64-1.0.0-beta
container_name: fabric-ca-server
ports:
- "7054:7054"
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
volumes:
- "./fabric-ca-server:/etc/hyperledger/fabric-ca-server"
command: sh -c 'fabric-ca-server start -b admin:adminpw'
(注意:自己的ca image的版本根据自己机器中的进行修改)
2. 然后执行 docker-compose up -d 启动容器。
( fabric-ca docker 镜像包含了fabric-ca-server和fabric-ca-client两部分。然后会在该目录下生成自签的CA证书和密钥以及fabric ca server的配置文件。)
如果不想自签,使用自己准备的证书和密钥,可以通过下面三种方式进行指定。
1:配置文件
如果需要CSR的自定义值,则可以自定义配置文件,修改ca.certfile和ca.keyfile配置项指定的文件,然后再次运行fabric-ca-server init -b admin:adminpw命令。
2:命令行
fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${PRIVATE_KEY} -b admin:adminpw -d
Fabric CA Server启动的时候,带了3个重要的参数:ca.certfile 指定了CA的根证书,ca.keyfile 指定了接下来给新用户签发证书时的私钥。另外就是-b参数,指定了CA Client连接CA Server时使用的用户名密码。其中证书和密钥两个文件都必须是PEM编码的,并且不得加密。更具体地说,CA证书文件的内容必须以----- BEGIN CERTIFICATE -----开头,并且密钥文件的内容必须以----- BEGIN PRIVATE KEY -----开头,而不是-----开始加密私钥-----。
3:镜像
docker-compose.yaml文件中的 command: sh -c 'fabric-ca-server start -b admin:adminpw'命令行修改为 fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/${PRIVATE_KEY} -b admin:adminpw -d
四:对应e2e_cli生成对应的证书
1:结构分析
我们的目的是生成对应的证书然后使得e2e_cli能够顺利的跑起来。
我们可以使用下面的部署方式:
这里做了简化,只部署了一个Fabric-CA作为rootCA。
将创建一个由两个组织org1.example.com和org2.example.com组成的的联盟。
另外还有一个组织example.com用来部署orderer。
example.com部署了一个solo模式的orderer。(多个orderer的部署方式,其实是一样的)
orderer.example.com
org1.example.com部署了两个peer:
peer0.org1.example.com
peer1.org1.example.com
org2.example.com部署了两个个peer:
peer0.org2.example.com
peer1.org2.example.com
每个组织都要有一个Admin用户,每个组件(peer/orderer)也需要一个账号,因此需要通过fabric-ca创建8个用户:
example.com: [email protected] orderer.example.com
org1.example.com: [email protected] peer0.org1.example.com peer1.org1.example.com
org2.example.com: [email protected] peer0.org2.example.com peer1.org2.example.com
这里只创建了Admin用户,普通用户的创建方式相同,只是普通用户的证书不需要添加到目标组件的admincerts目录中。
2:生成fabric-ca admin的凭证
在/opt/gopath/bin下面执行:mkdir fabric-ca-files 生成fabric-ca admin的凭证,用-H参数指定client目录:
mkdir -p `pwd`/fabric-ca-files/admin
fabric-ca-client enroll -u http://admin:pass@localhost:7054 -H `pwd`/fabric-ca-files/admin
这时候/opt/gopath/bin/fabric-ca-files下面有一个admin的文件夹(里面是管理员的证书和私钥等信息):
3:创建联盟
通过上面的启动,会默认创建两个组织:
melly@melly-virtual-machine:/opt/gopath/bin$ sudo ./fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation list
(这是fabric-ca-server配置文件中默认的配置,可以在配置文件上进行修改)
但是通过我们的结构分析,这种联盟以及名称不是我们需要的,我们需要进行修改。首先将其删除:
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation remove --force org1
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation remove --force org2
然后创建我们需要的联盟:
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation add com
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation add com.example
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation add com.example.org1
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation add com.example.org2
创建联盟如下:
fabric-ca-client -H `pwd`/fabric-ca-files/admin affiliation list
4:为每个联盟创建msp,将根证书放入到对应的位置
mkdir -p ./fabric-ca-files/example.com/msp
fabric-ca-client getcacert -M `pwd`/fabric-ca-files/example.com/msp //-M需要指定绝对路径
命令执行结束后,会在fabric-ca-files/example.com/msp得到文件:
$ tree fabric-ca-files/example.com/msp/
example.com/msp/
|-- cacerts
| `-- localhost-7054.pem
|-- intermediatecerts
| `-- localhost-7054.pem
|-- keystore
`-- signcerts
注意:getcacert得到msp目录中只有CA证书。这里是用getcacert为每个组织准备需要的ca文件,在生成创始块的时候会用到!
用同样的方式分别为org1和org2进行操作:
mkdir -p fabric-ca-files/org1.example.com/msp
fabric-ca-client getcacert -M `pwd`/fabric-ca-files/org1.example.com/msp
mkdir -p ./fabric-ca-files/org2.example.com/msp
fabric-ca-client getcacert -M `pwd`/fabric-ca-files/org2.example.com/msp
tls在配置文件中设置为false不需要了。
5: 注册example.com的管理员[email protected]
$ fabric-ca-client register --id.name [email protected] --id.type c --id.affiliation "com.example" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert'
$ mkdir -p ./fabric-ca-files/example.com/admin
$ fabric-ca-client enroll -u http://[email protected]:(password)@localhost:7054 -H `pwd`/fabric-ca-files/example.com/admin
$ ls ./fabric-ca-files/example.com/admin fabric-ca-client-config.yaml msp/
这时候可以用[email protected]的身份查看联盟:(可以全部看到)
$ fabric-ca-client affiliation list -H `pwd`/fabric-ca-files/example.com/admin
返回:
affiliation: com
affiliation: com.example
affiliation: com.example.org1
affiliation: com.example.org2
最后需要将[email protected]的证书复制到example.com/msp/admincerts/
$ mkdir fabric-ca-files/example.com/msp/admincerts/
$ cp fabric-ca-files/example.com/admin/msp/signcerts/cert.pem fabric-ca-files/example.com/msp/admincerts/
只有这样,才能具备管理员权限。
6: 注册org1.example.com的管理员Admin@org1.example.com
$ fabric-ca-client register --id.name [email protected] --id.type client --id.affiliation "com.example.org1" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert'
$ fabric-ca-client enroll -u http://[email protected]:password@localhost:7054 -H `pwd`/fabric-ca-files/org1.example.com/admin
只能查看org1和example的联盟。
将[email protected]的证书复制到org1.example.com的msp/admincerts中:
$ mkdir fabric-ca-files/org1.example.com/msp/admincerts/
$ cp fabric-ca-files/org1.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org1.example.com/msp/admincerts/
在[email protected]中也需要创建msp/admincerts目录,通过peer命令操作fabric的时候会要求admincerts存在
$ mkdir fabric-ca-files/org1.example.com/admin/msp/admincerts/
$ cp fabric-ca-files/org1.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org1.example.com/admin/msp/admincerts/
另外,这里没有使用中间CA,将intermediatecerts中的空文件删除,否则peer会提示Warning
$ rm fabric-ca-files/org1.example.com/admin/msp/intermediatecerts/*
为org2.example.com的管理员[email protected]准备一个目录:
$ mkdir -p ./fabric-ca-files/org2.example.com/admin
$ fabric-ca-client register --id.name [email protected] --id.type client --id.affiliation "com.example.org2" --id.attrs '"hf.Registrar.Roles=client,orderer,peer,user","hf.Registrar.DelegateRoles=client,orderer,peer,user",hf.Registrar.Attributes=*,hf.GenCRL=true,hf.Revoker=true,hf.AffiliationMgr=true,hf.IntermediateCA=true,role=admin:ecert'
$ fabric-ca-client enroll -u http://[email protected]:password@localhost:7054 -H `pwd`/fabric-ca-files/org2.example.com/admin
$ ls ./fabric-ca-files/org2.example.com/admin
fabric-ca-client-config.yaml msp/
$ fabric-ca-client affiliation list -H `pwd`/fabric-ca-files/org2.example.com/admin
返回结果:
affiliation: com
affiliation: com.example
affiliation: com.example.org2
[email protected]只能看到组织com.example.org2。
将[email protected]的证书复制到org2.example.com的msp/admincerts中:
$ mkdir fabric-ca-files/org2.example.com/msp/admincerts/
$ cp fabric-ca-files/org2.example.com/admin/msp/signcerts/cert.pem 、
fabric-ca-files/org2.example.com/msp/admincerts/
在[email protected]中也需要创建msp/admincerts目录,通过peer命令操作fabric的时候会要求admincerts存在:
$ mkdir fabric-ca-files/org2.example.com/admin/msp/admincerts/
$ cp fabric-ca-files/org2.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org2.example.com/admin/msp/admincerts/
另外,这里没有使用中间CA,将intermediatecerts中的空文件删除,否则peer会提示Warning:
$ rm fabric-ca-files/org2.example.com/admin/msp/intermediatecerts/*
8:各个组织分别使用自己的Admin账户创建其它账号
//order
example.com、org1.example.com、org2.example.com三个组织这时候可以分别使用自己的Admin账号创建子账号。
orderer.example.com
使用[email protected]注册账号orderer.example.com。注意这时候指定的目录是fabric-ca-files/example.com/admin/。
$ fabric-ca-client register -H `pwd`/fabric-ca-files/example.com/admin --id.secret=password --id.name orderer.example.com --id.type orderer --id.affiliation "com.example" --id.maxenrollments "0" --id.attrs 'role=orderer:ecert'
$ mkdir ./fabric-ca-files/example.com/orderer
$ fabric-ca-client enroll -u http://orderer.example.com:password@localhost:7054 -H
`pwd`/fabric-ca-files/example.com/orderer
将[email protected]的证书复制到fabric-ca-files/example.com/orderer/msp/admincerts:
$ mkdir fabric-ca-files/example.com/orderer/msp/admincerts
$ cp fabric-ca-files/example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/example.com/orderer/msp/admincerts/
//peer0org1
使用[email protected]注册账号peer0.org1.example.com。这时候指定的目录是fabric-ca-files/org1.example.com/admin/。
$ fabric-ca-client register -H `pwd`/fabric-ca-files/org1.example.com/admin/ --id.secret=password --id.name peer0.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.maxenrollments "0" --id.attrs 'role=peer:ecert'
$ mkdir ./fabric-ca-files/org1.example.com/peer0
$ fabric-ca-client enroll -u http://peer0.org1.example.com:password@localhost:7054 -H `pwd`/fabric-ca-files/org1.example.com/peer0
$ mkdir fabric-ca-files/org1.example.com/peer0/msp/admincerts
$ cp fabric-ca-files/org1.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org1.example.com/peer0/msp/admincerts/
//peer1org1
$ fabric-ca-client register -H `pwd`/fabric-ca-files/org1.example.com/admin --id.secret=password --id.name peer1.org1.example.com --id.type peer --id.affiliation "com.example.org1" --id.maxenrollments "0" --id.attrs 'role=peer:ecert'
$ mkdir ./fabric-ca-files/org1.example.com/peer1
$ fabric-ca-client enroll -u http://peer1.org1.example.com:password@localhost:7054 -H `pwd`/fabric-ca-files/org1.example.com/peer1
$ mkdir fabric-ca-files/org1.example.com/peer1/msp/admincerts
$ cp fabric-ca-files/org1.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org1.example.com/peer1/msp/admincerts/
//peer0org2
$ fabric-ca-client register -H `pwd`/fabric-ca-files/org2.example.com/admin --id.secret=password --id.name peer0.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.maxenrollments "0" --id.attrs 'role=peer:ecert'
$ mkdir ./fabric-ca-files/org2.example.com/peer0
$ fabric-ca-client enroll -u http://peer0.org2.example.com:password@localhost:7054 -H `pwd`/fabric-ca-files/org2.example.com/peer0
$ mkdir fabric-ca-files/org2.example.com/peer0/msp/admincerts
$ cp fabric-ca-files/org2.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org2.example.com/peer0/msp/admincerts/
//peer1org2
$ fabric-ca-client register -H `pwd`/fabric-ca-files/org2.example.com/admin --id.secret=password --id.name peer1.org2.example.com --id.type peer --id.affiliation "com.example.org2" --id.maxenrollments "0" --id.attrs 'role=peer:ecert'
$ mkdir ./fabric-ca-files/org2.example.com/peer1
$ fabric-ca-client enroll -u http://peer1.org2.example.com:password@localhost:7054 -H `pwd`/fabric-ca-files/org2.example.com/peer1
$ mkdir fabric-ca-files/org2.example.com/peer1/msp/admincerts
$ cp fabric-ca-files/org2.example.com/admin/msp/signcerts/cert.pem
fabric-ca-files/org2.example.com/peer1/msp/admincerts/
五:进行替换然后手动执行验证
1:替换
根据原来通过generateArtifacts.sh脚本生成的crypto-config文件夹的结构进行分析,只需要将我们生成的msp更新对应的msp即可:
Example.com的msp
Order的msp
user下的admin的msp
Org1 的msp
Peer0的msp
Peer1的msp
User的admin的msp
Org2的msp
Peer0的msp
Peer1的msp
user的admin的msp
主要操作,删除原crypto-config文件夹中对应的msp,然后从自己生成的/opt/gopath/fabric-ca-files文件夹中进行复制。
2:验证:
1:修改generateArtifacts.sh,注释掉倒数第二第三行:
#generateCerts
#replacePrivateKey
不生成证书和密钥
2:network_start 中down的时候不删除这个存证书和密钥的文件夹
修改为:rm -rf channel-artifacts/*.block channel-artifacts/*.tx
3:直接执行sudo ./network_setup.sh up启动网络
4:手动执行e2e_cli的例子进行:
命令行:
//进入cli容器进行操作
docker exec -it cli bash
export CHANNEL_NAME=mychannel
//创建channel
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx
//peer0.org1.example.com加入channel
peer channel join -b mychannel.block
//peer0.org2.example.com 加入channel
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" peer channel join -b mychannel.block
//anchor peer for Org1 as peer0.org1.example.com
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx
//peer0.org2.example.com
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx
//安装链码
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02/
//初始化链码
peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}'
//进行查询操作
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
//进行交易
peer chaincode invoke -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
如果执行正常,说明证书生成以及替换是正确的。
六:参考文档:
https://www.cnblogs.com/studyzy/p/7482451.html
http://hyperledger-fabric-ca.readthedocs.io/en/latest/
https://blog.csdn.net/lijiaocn/article/details/80261529
七:遇到的问题
1:melly@melly-virtual-machine:/opt/gopath/bin$ sudo ./fabric-ca-client affiliation list
[sudo] melly 的密码:
Error: Failed to parse response: 404 page not found
: invalid character 'p' after top-level value
查看fabric-ca默认注册了几个联盟
查看失败,但是可以去fabric-server的配置文件看即可:(默认如下)
或者:修改路径
sudo ./fabric-ca-client -H /home/melly/.fabric-ca-client/ affiliation list
affiliation: .
affiliation: org2
affiliation: org2.department1
affiliation: org1
affiliation: org1.department1
affiliation: org1.department2
2: [INFO] 127.0.0.1:47924 POST /register 401 42 "Failed to register attribute: Failed to get attribute 'hf.Registrar.Attributes': User does not have attribute 'hf.Registrar.Attributes'"
解决:
如下示例,使用 admin 的身份及其配套证书,登记了一个名称为 "admin2"、类型为 "user"、组织关系为 "org1.department1"、"hf.Revoker" 属性为 "true" 的新角色:
# export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
# fabric-ca-client register --id.name admin2 --id.type user --id.affiliation org1.department1 --id.attr hf.Revoker=true
3:peer create channel
grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: failed to write window update: write tcp 172.20.0.7:57304->172.20.0.3:7050: write: broken pipe"; Reconnecting to {orderer.example.com:7050
Error: Error connecting due to rpc error: code = Unavailable desc = grpc: the connection is unavailable
grpc:Server.Serve未能完成来自“172.20.0.7:48830”的安全握手:tls:第一条记录看起来不像TLS握手
解决:去docker-compse-cli.yaml文件中关闭tls
4:HYPERLEDGER FABRIC网络搭建之network e2ecli_default not found
原因是:
e2e_cli目录是固定的,启动后会创建一个docker network以此为名字,这里是e2e_cli。如果修改该目录,要修 改/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/base目录下的peer-base.yaml
将网络名修改一下:
我的目录是e2e_cli2
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=e2ecli2_default
5:Error: Response from server: Error Code: 20 - Authorization failure
授权失败:
需要重新:授权一下:
export FABRIC_CA_CLIENT_HOME=`pwd`/fabric-ca-files/admin
sudo ./fabric-ca-client enroll -u http://admin:pass@localhost:7054