FabricCA机制详解
Fabric CA机制详解
Fabric CA项目是超级账本Fabric内的MemberService组件, 对网络内各个实体的身份证书的管理。
Fabric CA概述
Fabric 基于PKI 认证体系实现了:
- 身份认证,或者从 LDAP(轻量目录访问协议) 中获取注册信息;
- 发行担保证书 ECerts (Enrollment Certificates);
- 发行交易证书 TCerts (Transaction Certificates),保障 Hyperledger Fabric 区域链交易平台上的信息匿名性和不可追踪性;
- 证书更新和撤销。
有两种方式可以与Fabric CA服务器交互:
- 使用Fabric CA客户端
- 使用某种特定开发语言的Farbic SDK
所有与Fabric CA服务器的通信都是 使用REST API。详情参考:fabric-ca/swagger/swagger-fabric-ca.json文件
Fabric CA客户端或SDK可能连接到Fabric CA服务器集群 中的一个服务器,这一点可以查看上图的右上部分。客户端将请求提交给HA代理访问 端结点,HA代理进行负载均衡,并将客户端的请求路由给fabric-ca-server集群中的 某一成员服务器。
一个服务器可能包含多个CA,每个CA可能是根CA或者中间CA。
安装及命令分析
前置条件
Go环境
安装好libtool 和 libtdhl-dev 包
克隆Fabric CA项目到本地,选择版本
1
2git clone https://github.com/hyperledger/fabric-ca.git
git checkout v1.5.0此处需要注意,网上大部分教程为1.4版本。1.5版本fabric-ca项目目录已发生变化。
在
fabric-ca/bin
目录下有fabric-ca-server
和fabric-ca-client
工具类对CA服务端进行初始化
1
fabric-ca-server init -b admin:adminpw
初始化后在目录下生成
- msp:包含keystore,CA服务器的私钥
- ca-cert.pem:CA服务器的证书
- fabric-ca-server.db:CA默认使用的嵌入型数据库 SQLite
- fabric-ca-server-config.yaml:CA服务端的配置文件
用户的注册过程分为登记(register)和注册(enroll)两步,注册操作需要拿到登记密码才能完成,且用户的登记需要有一个登记员用户。所以首先需要注册我们在启动时设置的管理员用户(admin的登记密码在启动时已设置),然后用这个admin用户来完成其他用户的登记操作。
Fabric CA CLI
- Fabric CA server 命令,具体使用请参考:
1 | Hyperledger Fabric Certificate Authority Server |
- Fabric CA client 命令,具体使用请参考:https://hyperledger-fabric-ca.readthedocs.io/en/latest/clientcli.html
Fabric CA 配置
Fabric CA 有三种设置配置的方法(优先级由高到低):
CLI 参数
环境变量
配置文件
以下内容中,将演示如何改配置文件,但是配置文件的设置会被环境变量及CLI参数覆盖。
如下是client的配置文件:
Fabric CA Server 命令分析
在启动服务器前要先初始化它。这个过程会产生一份默认的配置文件,然后你可以检查并修改。
Fabric CA服务器的home目录是这样决定的:
如果设置了 FABRIC_CA_SERVER_HOME 环境变量, 则就取它的值
否则就取 FABRIC_CA_HOME 的值
否则就取 CA_CFG_PATH 的值
否则就用当前的工作目录
在本章节中, 我们假设已经设置了环境变量 FABRIC_CA_HOME 为 $HOME/fabric-ca/server。
下面的指令假设你已经将配置文件放在了服务器的home目录下。
fabric-ca-server命令主要负责启动一个CA服务, 包括init和start两个子命令
初始化CA服务器
用以下语句初始化CA服务器:
fabric-ca-server init -b admin:adminpw
当LDAP被禁用时,就必须要有这个 -b (代表“启动身份”bootstrap identity) 选项。 启动服务器必须要有启动身份; 这个身份就是管理员身份。
生成的配置文件fabric-ca-server-config.yaml类似下图:
配置文件里可以配置证书签名请求域 (Certificate Signing Request简称CSR),以下就是一个CSR域的示例。
以上所有字段都对应了X.509证书的字段,即调用 fabric-ca-server init
生成的证书字段。 这个CSR的域设置效果等同于配置中的 ca.certfile (证书) 和 ca.keyfile (密钥)两个配置域的组合。 配置了CSR域就是用这些信息自己给自己签名,ca.certfile和ca.keyfile是用这两个文件自签名。
字段解释如下:
cn 证书名Common Name
O 组织名organization name
OU 组织单元organizational unit
L 位置location or city
ST 州state
C 国家country
如果要配置CSR,就要把 ca.certfile 和 ca-keyfile 对应的文件删了。(官方默认是ca-cert.pem和ca-key.pem) 然后重新运行一下 fabric-ca-server init -b admin:adminpw
fabric-ca-server init
命令会生成一个自签名证书。
如果你要指定 CA 签名证书 和 key 文件, 你就得把文件放到 ca.certfile 和 ca.keyfile 的指定路径下。
文件必须是PEM格式且不可加密。此处摘抄一句英文原文:
Both files must be PEM-encoded and must not be encrypted.
CA签名证书必须以 ——-BEGIN CERTIFICATE——- 开头。 key 文件必须以 ——-BEGIN PRIVATE KEY——- 开头,而不是——-BEGIN ENCRYPTED PRIVATE KEY——-。
启动CA服务器
用以下命令启动CA服务器:
fabric-ca-server start -b
:
第一次启动时,如果服务器未初始化,则会先进行初始化。
在初始化期间,如果发现 ca-cert.pem 和 ca-key.pem 不存在,则会先生成,如果配置文件不存在也会生成默认的配置文件。
除非你用的是LDAP,否则你必须要先有一个预先注册好的bootstrap身份信息用来注册和登记其他身份信息。 用 -b 选项来指定bootstrap身份。
如果要让服务器监听 https 而不是 http,则需要设置 tls.enabled 为 true。
要限制同一个 secret (或 password) 的登记使用次数,需要给 registry.maxenrollments 配置项设置一个值。 如果设置为1, 则每个 enrollment ID只能被登记一次,如果设置为 -1, 则secret的登记使用次数不做限制。 默认值是-1。 如果设置为0, 则所有的身份或者是注册进来的身份都不能被登记了。
启动后,CA服务器监听端口是 7054。
总结: 先初始化,再读取配置文件,如果是Root CA就自己给自己创建证书和秘钥,如果不是就读取证书文件和秘钥文件的信息。最后启动网络服务监听端口信息。
Fabric CA Client
使用Fabric CA Client 的命令连接 server。
准备工作
请将配置文件放home目录下后,完成以下过程。
enroll the bootstrap identity
CA的账号概念是:先注册identity,它带有一个enrollment id,然后可以enroll具体的账号,可以在csr里指定属性。
一个账号的生命周期如下图所示:
(注:register字面的意思是注册,注册就是主体向 CA 自我介绍的过程;enroll字面的意思是登记,就是最终实体进行证书申请并从 CA 接收证书的过程)
从创建超级管理员到注册用户过程如下:
bootstrap identity即超级管理员identity,注册是在ca-server初始化时完成的(用-b 选项指定enrollment ID和密码)。
client端配置好CSR,并enroll了超级管理员identity到home目录下的msp
client去向CA register user的identity,CA认可client的msp,client去向CA enroll 刚才user的msp。
根据需要自定义client home目录下配置文件中的CSR部分,其中
csr.cn
必须设置为bootstrap identity的enrollment ID。然后运行 fabric-ca-client enroll 命令去enroll一个identity。例如, 以下命令会enroll一个ID是 admin 密码是 adminpw 的identity, 其调用的是运行在本地的监听7054端口的Fabric CA 服务器。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client enroll -u http://admin:adminpw@localhost:7054
enroll命令会存储一个登录证书(ECert),相对应的私钥,还有CA证书链PEM文件。这些存储在Fabric CA客户端的msp目录的子目录下,你会看到信息提示PEM存储在哪里。
注册一个新身份
只有已经enroll了的身份才能发起register的请求,而且必须有相应的权限来注册想要注册的身份类型。
特别地,注册时Fabric CA服务端做两项权限检查:
- 注册发起者的“hf.Registrar.Roles”属性中必须有请求注册的类型。举个例子,如果发起者的“hf.Registrar.Roles”属性的值为“peer,app,user”,那么他能注册的类型为peer,app和user,不能注册orderer。
- 发起者的affiliation(部门)必须与他请求注册的身份的affiliation相同,或者是所请求注affiliation的前缀。举个例子,一个affiliation为“a.b”的发起者,可以注册一个affiliation为“a.b.c”的身份,但是不能注册一个affiliation为“a.c”的身份。
- —id.type参数必须是是server端配置文件fabric-ca-server-config.yaml里hf.Registrar.Roles属性值里的一个。
下面的命令使用admin身份的凭证来注册一个新的身份,登录ID是“admin2”,类型为“user”,affiliation为“org1.department1”,还有“hf.Revoker”属性为“true”。
1
2
3 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
密码会被打印出来,登录这个新注册的身份的时候,需要用到这个密码。这允许一个管理员注册身份,然后把这个身份的ID和密码给别人来登陆。
举个例子,假设配置文件包含下面的内容:
1 | id: |
下面的命令会注册一个新的身份,id为admin3,其他的内容会从配置文件中读取出来。包括:类型“user”,affiliation “org1.department1”,还有两个属性,“hf.Revoker”和“anotherAttrName”。
1 | export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin |
接下来,让我们注册一个节点身份,下面内容会在登陆节点的时候用到。下面的命令注册了一个peer1身份,在这里我们选择指明自己的密码,而不是由服务器生成。
1 | export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin |
登录一个节点
现在你成功地注册了一个节点身份,你可以用ID和密码登陆。下面的命令登陆peer1。记得在“-M”选项下更改为你自己的MSP目录,MSP目录是由节点的core.yaml里的“mspConfigPath”指定的。
1 | export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1 |
从另一个Fabric CA服务器获得CA证书链
通常,MSP目录的ca证书目录必须包含证书链,代表这个节点所有信任的信任中心。
fabric-ca-client getcacerts
命令用于从其他Fabric CA服务器实例获取这些证书链。
举个例子,下面的命令会在本地启动第二个Fabric CA服务器,监听7055端口,命名为“CA2“。这代表两个由不同成员管理的分开的信任中心。
1 | export FABRIC_CA_SERVER_HOME=$HOME/ca2 |
下面的命令会把CA2的证书链安装进peer1的MSP目录。
1 | export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1 |
重新登陆一个身份
假设你的登陆证书快过期了,你可以重新登陆来替换你的登陆证书(ECert)。
1 | export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1 |
撤销一个证书或身份
身份和证书都能被撤销。撤销一个身份会撤销该身份拥有的所有证书,该身份也不能再获得新的证书。撤销一个证书会使该证书失效。
为了撤销一个证书或身份,发起者必须有hf.Revoker属性。发起者只能撤销与自己的affiliation相同的证书或身份,或者发起者的affiliation是被撤销者的affiliation的前缀。
举个例子,一个“orgs.org1”的发起者只能撤销orgs.org1或者orgs.org1.department1的身份,而不能撤销orgs.org2的身份。
下面的命令撤销一个身份。将来所有发自该身份的请求都会被Fabric CA服务器拒收。
1 | fabric-ca-client revoke -e <enrollment_id> -r <reason> |
除此之外,还有很多理由可以撤销一个身份或证书。
启用TLS
首先修改CA客户端配置在fabric-ca-client-config.yaml
中。
1 | tls: |
certfiles是该客户端信任的根证书集合。一般这都会是Fabric CA服务端根目录下的ca-cert.pem。
只有在服务器配置了双向TLS的情况下,client选项才需要。
Fabric SDK
使用Fabric SDK 连接 server。
参考https://hyperledgercn.github.io/hyperledgerDocs/sdk_java_zh/
深入剖析
初始化Server服务
启动过程使用默认的配置文件fabric-ca-server-config.yaml
,如果当前路径下没有会生成默认模板。在启动过程中会创建这个自我认证的身份admin
方便后面操作。
1 | fabric-ca-server start -b admin:adminpw |
命令执行完成后生成如下4个文件:
- server配置文件
${FABRIC_CA_SERVER_HOME}/fabric-ca-server-config.yaml - server内部存储数据库文件
${FABRIC_CA_SERVER_HOME}/fabric-ca-server.db - 自我认证身份的证书文件
${FABRIC_CA_SERVER_HOME}/ca-cert.pem - 自我认证身份的私钥(private key)文件${FABRIC_CA_SERVER_HOME}/msp/keystore/27554ec70fe8a2707c0a74ba5d6ecb36a0a4d565871c4f050ed93d662849560d_sk
其中${FABRIC_CA_SERVER_HOME}/fabric-ca-server.db是一个sqlite文件,包含三个表:
1 | 1. table affiliations |
可以通过fabric ca client命令获取CA信息
1 | fabric-ca-client getcainfo -u http://admin:adminpw@localhost:7054 |
其等同于 POST 请求 http://localhost:7054/cainfo
1 | $ curl -i -uadmin:adminpw -X POST -H "Content-type:application/json" http://localhost:7054/cainfo |
自证管理员身份认证
我们是启动CA服务时,设置了一个初始的admin账户,用于后面的各种操作。所以我们得先用这个账户去登录CA服务器。
1 | fabric-ca-client enroll -u http://admin:adminpw@localhost:7054 |
命令执行完之后生成如下4个文件:
- client配置文件
${FABRIC_CA_CLIENT_HOME}/fabric-ca-client-config.yaml - CA根证书文件
${FABRIC_CA_CLIENT_HOME}/msp/cacerts/localhost-7054.pem
这个文件其实就是server端的自我认证身份的证书文件,与${FABRIC_CA_SERVER_HOME}/ca-cert.pem一致 - client证书文件
${FABRIC_CA_CLIENT_HOME}/msp/signcerts/cert.pem - client私钥(private key)文件
${FABRIC_CA_CLIENT_HOME}/msp/keystore/338dc8051e6aa74bcbc1ee7da17afb735e0d8c1291f0a6b6d98bfce605a774ba_sk
再看server端数据库的变化,可以看到表certificates里面多了一条记录:
1 | 1. certificates |
实际上这个pem的内容就是client的证书文件,即${FABRIC_CA_CLIENT_HOME}/msp/signcerts/cert.pem一致。
登记普通角色身份(register)
我们使用 admin 的身份及其配套证书,登记了一个名称为 “tester”、类型为 “user”、组织关系为 “org1.department1”、”hf.Revoker” 属性为 “true” 的新角色
1 | fabric-ca-client register --id.name tester --id.secret testpasswd --id.type user --id.affiliation org1.department1 --id.attrs hf.Revoker=true |
再看server端数据库的变化,可以看到表users里面多了一条记录。
1 | 1. table users |
认证普通角色身份(enroll)
完成身份登记之后需要做认证。
1 | fabric-ca-client enroll -u http://tester:testpasswd@localhost:7054 |
与自证时相同,认证过程会生成本地文件,包括client配置文件,client证书文件,client私钥文件,和根证书文件。同时在server端会把client的证书写入数据库表certificates中。
总结登记(register)和认证(enroll)的功能
总结起来,登记身份和认证身份分别完成的功能是:
- 登记register身份用来登记一个身份
它需要提供待登记身份的身份信息,包含用户名,密码,类型,组织关系,等属性。
实施登记的人,还需要有登记的权限,例如初始的自证管理员,或其他管理员身份。
登记过程不会生成本地文件,但是会往server的数据库表users中插入一条数据。 - 认证enroll身份用来认证一个前面已经登记过的身份
它需要提供登记时身份的名字和密码;实施认证不需要认证的权利。
认证过程会生成本地文件,包括client配置文件,client证书文件,client私钥文件,和根证书文件。
同时在server端会把client的证书写入数据库表certificates中。
参考资料:
https://hyperledgercn.github.io/hyperledgerDocs/ca-setup_zh/
Fabric CA指南 - 简书 (jianshu.com)