一:簡介
在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:使用鏡像啓動
- 進入到$GOPATH/src/github.com/hyperledger/fabric-ca/docker/server目錄下然後對docker-compose.yaml文件進行編輯。
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/*
7:註冊org2.example.com的管理員[email protected]
爲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 <nil>}
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