FabricCA的基本概念與用法講解

說(shuō)明

Hyperledger Fabric CA是Hyperledger Fabric的證書(shū)授權(quán)中心,支持:

添加用戶(hù)、或者對(duì)接LDAP
簽發(fā)注冊(cè)證書(shū)
證書(shū)的更新和撤銷(xiāo)

概覽

如下圖所示,fabric-ca可以對(duì)接ldap,或者mysql、pgsql數(shù)據(jù)庫(kù)。

通過(guò)fabric-ca client或者fabric-ca的sdk獲得證書(shū)后,就可以用這些證書(shū)訪問(wèn)Peer。

編譯安裝

$ go get -u github.com/hyperledger/fabric-ca
$ cd $GOPATH/src/github.com/hyperledger/fabric-ca
$ make fabric-ca-server
$ make fabric-ca-client
$ ls bin/
fabric-ca-client  fabric-ca-server

fabric-ca-server初始化

mkdir -p /opt/app/fabric-ca/client
cp $GOPATH/src/github.com/hyperledger/fabric-ca/bin/fabric-ca-client /opt/app/fabric-ca/client/
ln -s /opt/app/fabric-ca/client/fabric-ca-client  /usr/bin/fabric-ca-client

mkdir -p /opt/app/fabric-ca/server
cp $GOPATH/src/github.com/hyperledger/fabric-ca/bin/fabric-ca-server /opt/app/fabric-ca/server/
cd /opt/app/fabric-ca/server

初始化,可以使用ldap、mysql、postgresql,或者本地sqlite,默認(rèn)sqlite:

./fabric-ca-server init -b admin:pass

如果啟動(dòng)的是中間CA,用-u指定上級(jí)CA:

./fabric-ca-server start -b admin:adminpw -u http://<enrollmentID>:<secret>@<parentserver>:<parentport>

如果直接作為RootCA,后面兩個(gè)參數(shù)表示允許刪除聯(lián)盟和用戶(hù):

./fabric-ca-server start -b admin:pass --cfg.affiliations.allowremove  --cfg.identities.allowremove

初始化后,會(huì)在當(dāng)前目錄生成以下文件:

ca-cert.pem  fabric-ca-server-config.yaml  fabric-ca-server.db  msp/

fabric-ca-server-config.yaml是fabric-ca-server的配置文件。

其中ca-cert.pem是一個(gè)自簽署的證書(shū):

$ openssl verify -CAfile ca-cert.pem ca-cert.pem
ca-cert.pem: OK

這個(gè)證書(shū)是根據(jù)fabric-ca-server-config.yaml中的csr生成的:

csr:
   cn: fabric-ca-server
   names:
      - C: US
        ST: "North Carolina"
        L:
        O: Hyperledger
        OU: Fabric
   hosts:
     - 10-39-0-121
     - localhost
   ca:
      expiry: 131400h
      pathlength: 1

可以用下面的命令查看:

openssl x509 -in ca-cert.pem  -text

如果要生成被其它CA簽署的證書(shū),使用-u指定上一級(jí)CA:

-u <parent-fabric-ca-server-URL>

URL格式:
    <scheme>://<enrollmentID>:<secret>@<host>:<port>

如果要簽署已經(jīng)準(zhǔn)備好的key,需要用ca.certfileca.keyfile指定:

ca:
  # Name of this CA
  name:
  # Key file (is only used to import a private key into BCCSP)
  keyfile:
  # Certificate file (default: ca-cert.pem)
  certfile:
  # Chain file
  chainfile:

msp/keystore中存放的BCCSP (BlockChain Crypto Service Provider)中用到的key:

bccsp:
    default: SW
    sw:
        hash: SHA2
        security: 256
        filekeystore:
            # The directory used for the software file-based keystore
            keystore: msp/keystore

還可以通過(guò)指定-cacount生成多個(gè)CA:

fabric-ca-server start -b admin:adminpw --cacount 2

以及指定多個(gè)cafiles:

fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-config.yaml --cafiles ca/ca2/fabric-ca-config.yaml

每個(gè)cafiles格式如下:

ca:
# Name of this CA
name: <CANAME>

csr:
  cn: <COMMONNAME>

目錄結(jié)構(gòu)可以如下:

--<Server Home>
  |--ca
    |--ca1
      |-- fabric-ca-config.yaml
    |--ca2
      |-- fabric-ca-config.yaml

生成fabric-ca管理員的憑證

生成第一個(gè)用戶(hù)的憑證:

export FABRIC_CA_CLIENT_HOME=/opt/app/fabric-ca/clients/admin
mkdir -p $FABRIC_CA_CLIENT_HOME
fabric-ca-client enroll -u http://admin:pass@localhost:7054

或者:

fabric-ca-client enroll -u http://admin:pass@localhost:7054 -H `pwd`

/opt/app/fabric-ca/clients/admin可以看到生成了以下文件:

fabric-ca-client-config.yaml  msp/

其中fabric-ca-client-config.yaml是一個(gè)默認(rèn)的配置文件,msp/中存放的是相關(guān)的證書(shū)。

msp/
|-- cacerts
|   -- localhost-7054.pem
|-- intermediatecerts
|   -- localhost-7054.pem
|-- keystore
|   -- a17c01f53b037cbf51ad76f2a95684e6b2a4b8371e0b247949805af8035bf50e_sk
-- signcerts
    -- cert.pem

之后就可以通過(guò)msp目錄中的證書(shū),訪問(wèn)fabric-ca,不需要在輸入密碼。

查看聯(lián)盟成員

fabric-ca默認(rèn)注冊(cè)了幾個(gè)聯(lián)盟,可以用affiliation list查看:

$ fabric-ca-client affiliation list
2018/04/28 14:59:55 [INFO] 127.0.0.1:38094 GET /affiliations 200 0 "OK"
affiliation: .
   affiliation: org1
      affiliation: org1.department1
      affiliation: org1.department2
   affiliation: org2
      affiliation: org2.department1

添加/刪除聯(lián)盟成員,也是通過(guò)這個(gè)命令進(jìn)行:

fabric-ca-client affiliation add another
fabric-ca-client affiliation add another.sub

新增加的聯(lián)盟成員如下:

[root@10-39-0-121 admin]# fabric-ca-client affiliation list
2018/04/28 15:03:42 [INFO] 127.0.0.1:38104 GET /affiliations 201 0 "OK"
affiliation: .
   affiliation: org1
      affiliation: org1.department1
      affiliation: org1.department2
   affiliation: org2
      affiliation: org2.department1
   affiliation: another
      affiliation: another.sub1

默認(rèn)是禁止刪除聯(lián)盟,如果需要開(kāi)啟,需要在啟動(dòng)fabric-ca-server時(shí)傳入?yún)?shù)--cfg.affiliations.allowremove:

./fabric-ca-server start -b  admin:pass  --cfg.affiliations.allowremove

然后可以刪除:

fabric-ca-client affiliation remove another.sub1

如果聯(lián)盟下還有聯(lián)盟,可以加上參數(shù)-force級(jí)聯(lián)刪除。

注冊(cè)新用戶(hù)

例如注冊(cè)一個(gè)名為admin2的用戶(hù),先指定要使用的用戶(hù)的client目錄:

$ export FABRIC_CA_CLIENT_HOME=/opt/app/fabric-ca/clients/admin

也可以用-H參數(shù)指定:

$ fabric-ca-client -H /opt/app/fabric-ca/clients/admin  <其它參數(shù)...>

注冊(cè)新用戶(hù)的命令如下:

$ fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,admin=true:ecert'
2018/04/28 10:20:42 [INFO] Configuration file location: /opt/app/fabric-ca/clients/admin/fabric-ca-client-config.yaml
2018/04/28 10:20:42 [INFO] 127.0.0.1:38036 POST /register 201 0 "OK"
Password: wvkpvMzLsjPz

新用戶(hù)注冊(cè)后,會(huì)自動(dòng)為新用戶(hù)生成一個(gè)密碼,新用戶(hù)需要使用這個(gè)密碼,生成自己的憑證,就像第一個(gè)用戶(hù)那樣。

為新注冊(cè)的用戶(hù)admin2準(zhǔn)備一個(gè)目錄,注意要使用一個(gè)新的目錄,防止與其它用戶(hù)混淆:

export FABRIC_CA_CLIENT_HOME=/opt/app/fabric-ca/clients/admin2
mkdir -p $FABRIC_CA_CLIENT_HOME

然后生成憑證:

fabric-ca-client enroll -u http://admin2:wvkpvMzLsjPz@localhost:7054

之后可以看到新的目錄中也生成了fabric-ca-client-config.yamlmsp/,這是admin2用戶(hù)的憑證:

$ tree admin2/
admin2/
|-- fabric-ca-client-config.yaml
-- msp
    |-- cacerts
    |   -- localhost-7054.pem
    |-- intermediatecerts
    |   -- localhost-7054.pem
    |-- keystore
    |   -- 6732d8d3802384c8935aa7174930975ba6141b6d4bc419e6ccbe5f4d76db58f0_sk
    -- signcerts
        -- cert.pem

用戶(hù)的屬性

在注冊(cè)admin2的時(shí)候,指定了這樣一些屬性--id.attrs 'hf.Revoker=true,admin=true:ecert'

fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,admin=true:ecert'

這些屬性是一定要了解的,以hf.開(kāi)頭的屬性,是fabric-ca的內(nèi)置屬性:

hf.Registrar.Roles            List        List of roles that the registrar is allowed to manage
hf.Registrar.DelegateRoles    List        List of roles that the registrar is allowed to give to a registree for its ‘hf.Registrar.Roles’ attribute
hf.Registrar.Attributes       List        List of attributes that registrar is allowed to register
hf.GenCRL                     Boolean     Identity is able to generate CRL if attribute value is true
hf.Revoker                    Boolean     Identity is able to revoke a user and/or certificates if attribute value is true
hf.AffiliationMgr             Boolean     Identity is able to manage affiliations if attribute value is true
hf.IntermediateCA             Boolean     Identity is able to enroll as an intermediate CA if attribute value is true

這些屬性表示的是用戶(hù)是否擁有相關(guān)的權(quán)限:

hf.Registrar.Roles該用戶(hù)可以增加的新用戶(hù)類(lèi)型,用戶(hù)類(lèi)型都有:client、orderer、peer、user。

hf.Registrar.DelegateRoles該用戶(hù)可以設(shè)置的新用戶(hù)的hf.Registrar.Roles屬性。

hf.Registrar.Attributes該用戶(hù)可以為新用戶(hù)設(shè)置的保留屬性和自定義屬性。

hf.GenCRL該用戶(hù)是否可以獲取CRL列表,已經(jīng)撤銷(xiāo)的證書(shū)列表。

hf.Revoker該用戶(hù)是否能夠撤銷(xiāo)其它用戶(hù)。

hf.AffiliationMgr該用戶(hù)是否可以管理聯(lián)盟。

hf.IntermediateCA該用戶(hù)是否可以作為中間CA。

除了這些以hf.開(kāi)頭的屬性外,還可以自定義屬性,例如下面的admin=true:

fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 \
--id.attrs 'hf.Revoker=true,admin=true:ecert'

用戶(hù)自定義的屬性可以寫(xiě)入到用戶(hù)的憑證中,在合約中可以獲取發(fā)起請(qǐng)求的用戶(hù)屬性,根據(jù)用戶(hù)屬性決定用戶(hù)是否由操作權(quán)限。

參考HyplerLedger FabricCA ABAC,HyperLedger Fabric Chaincode ABAC給出一個(gè)使用ABAC的chaincode:

...
"github.com/hyperledger/fabric/core/chaincode/lib/cid"
...

err := cid.AssertAttributeValue(stub, "abac.init", "true")
if err != nil {
    return shim.Error(err.Error())
}
...

cid的使用說(shuō)明見(jiàn): HyperLedger Fabric: Client Identity Chaincode Library

cid(Client Identity)中提供下面的方法:

+AssertAttributeValue(stub ChaincodeStubInterface, attrName, attrValue string) : error
+GetAttributeValue(stub ChaincodeStubInterface, attrName string) : string, bool, error
+GetID(stub ChaincodeStubInterface) : string, error
+GetMSPID(stub ChaincodeStubInterface) : string, error
+GetX509Certificate(stub ChaincodeStubInterface) : *x509.Certificate, error
+New(stub ChaincodeStubInterface) : ClientIdentity, error

▼+ClientIdentity : interface
    [methods]
   +AssertAttributeValue(attrName, attrValue string) : error
   +GetAttributeValue(attrName string) : string, bool, error
   +GetID() : string, error
   +GetMSPID() : string, error
   +GetX509Certificate() : *x509.Certificate, error

“admin=true:ecert”中的ecert的意思是,該屬性會(huì)被自動(dòng)寫(xiě)入到用戶(hù)憑證中(enrollment certificate)。

對(duì)于沒(méi)有注明ecert的屬性,可以在生成用戶(hù)憑證的時(shí)候,例如注冊(cè)了這樣一個(gè)用戶(hù)的時(shí)候:

fabric-ca-client register --id.name user1 --id.secret user1pw --id.type user \
--id.affiliation org1 --id.attrs 'app1Admin=true:ecert,email=user1@gmail.com'

它的屬性email=user1@gmail.com沒(méi)有注明是ecert,在生成憑證的時(shí)候,可以指定下面的屬性:

fabric-ca-client enroll -u http://user1:user1pw@localhost:7054 --enrollment.attrs "email,phone:opt"

app1Admin將被自動(dòng)包含在憑證中;email是被明確指定的,它必須是存在的,否則報(bào)錯(cuò);phone:opt也是明確指定的,opt表示phone屬性可選的,如果沒(méi)有phone屬性不會(huì)報(bào)錯(cuò)。

hf.開(kāi)頭的下面三個(gè)屬性,也會(huì)被自動(dòng)包含在登陸憑證中:

hf.EnrollmentID    The enrollment ID of the identity
hf.Type            The type of the identity
hf.Affiliation     The affiliation of the identity

查看用戶(hù)詳情

可以用fabric-ca-client identity list查看有權(quán)限查看的用戶(hù)的詳情:

$ fabric-ca-client identity list
Name: admin, Type: client, Affiliation: , Max Enrollments: -1, Attributes: [{Name:hf.GenCRL Value:1 ECert:false} {Name:hf.Registrar.Attributes Value:* ECert:false} {Name:hf.AffiliationMgr Value:1 ECert:false} {Name:hf.Registrar.Roles Value:peer,orderer,client,user ECert:false} {Name:hf.Registrar.DelegateRoles Value:peer,orderer,client,user ECert:false} {Name:hf.Revoker Value:1 ECert:false} {Name:hf.IntermediateCA Value:1 ECert:false}]
Name: admin2, Type: client, Affiliation: org1.department1, Max Enrollments: -1, Attributes: [{Name:hf.Revoker Value:true ECert:false} {Name:admin Value:true ECert:true} {Name:hf.EnrollmentID Value:admin2 ECert:true} {Name:hf.Type Value:client ECert:true} {Name:hf.Affiliation Value:org1.department1 ECert:true}]

用戶(hù)的權(quán)利范圍

用戶(hù)的權(quán)利范圍是用聯(lián)盟屬性hf.Affiliation來(lái)控制的。

hf.Affiliation     The affiliation of the identity

聯(lián)盟屬性一個(gè)類(lèi)似”a.b.c”樣式的字符串,最頂層用戶(hù)的該屬性為”.”。

一個(gè)用戶(hù)只能管理平級(jí)以及下級(jí)的用戶(hù)。

例如如果一個(gè)用戶(hù)的hf.Affiliation是”a.b.*“,那么它能管理的用戶(hù)的聯(lián)盟屬性必須以”a.b”開(kāi)頭。

聯(lián)盟屬性可以配置多個(gè),并且支持通配符,例如:

hf.Registrar.Attributes = a.b.*, x.y.z

另外:

一個(gè)用戶(hù)管理它的`hf.Registrar.Roles`屬性中列出用戶(hù)類(lèi)型。
一個(gè)用戶(hù)能夠管理的其它用戶(hù)的屬性,只能是它的`hf.Registrar.Attributes`屬性列出的屬性。
    其中保留屬性,還要求必須是當(dāng)前用戶(hù)擁有的屬性。

后續(xù)的很多操作都受到權(quán)利范圍的約束。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容