引言
Fabric CA项目是超级账本Fabric内的MemberService组件, 对网络内各个实体的身份证书的管理, 它提供的功能有:
1. 身份认证,或者从 LDAP(轻量目录访问协议) 中获取注册信息;
2. 发行担保证书 ECerts (Enrollment Certificates);
3. 发行交易证书 TCerts (Transaction Certificates),保障 Hyperledger Fabric 区域链交易平台上的信息匿名性和不可追踪性;
4. 证书更新和撤销。
Fabric CA 属于典型的 CS (Client and Server) 架构,官方代码库:https://github.com/hyperledger/fabric-ca 。
Fabric CA采用Go语言进行编写。
本文主要参考:https://hyperledger-fabric-ca.readthedocs.io/en/latest/users-guide.html#getting-started
一. 概述
上图展现了 Fabric CA 服务端是如何参与到 Hyperledger Fabric 整体架构中去的。
与 Fabric CA 服务端交互的方式有如下两种:
1. 通过 Fabric CA 客户端
2. 使用Fabric SDK
与 Fabric CA 服务端的所有通信,都是通过 REST API 进行的。详情可查看 fabric-ca/swagger/swagger-fabric-ca.json 处的 swagger 文档中的 REST API 部分。
如前图所示,Fabric CA 客户端或 SDK 的请求首先会到达 Fabric CA 集群前端的高可用负载均衡服务端,实际的 CA 服务由后端的某台Fabric CA 服务端提供。同一集群中的所有 Fabric CA 服务端共享相同的后端数据库(或 LDAP)集群,以确保证书和身份的一致性。
二. 安装
2.1 前提条件
1. 安装好 Go 1.10.x
2. 正确设置 `GOPATH`环境变量
3. 安装好libtool 和 libtdhl-dev 包
在Ubuntu上安装libtool:
# sudo apt install libtool libltdl-dev
安装 fabric-ca-server 与 fabric-ca-client 两个终端命令行工具。
# go get -u github.com/hyperledger/fabric-ca/cmd/...
2.2 启动服务端:本地环境
如下所示,将按默认配置启动 Fabric CA 服务端,-b 选项用于指定管理员的账号与密码。
# fabric-ca-server start -b admin:adminpw
默认将在当前目录创建一个名为 fabric-ca-server-config.yaml 的配置文件,该文件的存储位置也可以另行指定。
2.3 启动服务端:Docker 环境
也可以选择在 Docker 环境下运行服务端,如下将创建并通过 docker-compose 启动服务端
# cd $GOPATH/src/github.com/hyperledger/fabric-ca
# make docker
# cd docker/server
# docker-compose up -d
名为 hyperledger/fabric-ca 的 docker 镜像中包含了 fabric-ca-server 与 fabric-ca-client 命令行工具。
三. 使用Fabric CA CLI
至此,Fabric CA的环境已搭建完毕。可以使用相关命令进行操作,具体包括两部分:
1 Fabric CA server 命令,具体使用请参考:https://hyperledger-fabric-ca.readthedocs.io/en/latest/servercli.html
2 Fabric CA client 命令,具体使用请参考:https://hyperledger-fabric-ca.readthedocs.io/en/latest/clientcli.html
四. 配置方法及其优先级
Fabric CA 有三种设置配置的方法(优先级由高到低): :
1. CLI 参数
2. 环境变量
3. 配置文件
以下内容中,将演示如何改配置文件,但是配置文件的设置会被环境变量及CLI参数覆盖。
如下是client的配置文件:
下面的环境变量将会覆盖上面的配置:
export FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE=cert2.pem
下面这个CLI参数能覆盖配置文件和环境变量:
fabric-ca-client enroll --tls.client.certfile cert3.pem
fabric-ca-server服务器也一样, 只不过环境变量名不是以 FABIRC_CA_CLIENT 开头,而是FABRIC_CA_SERVER 。
五. Fabric CA 服务器
在启动服务器前要先初始化它。这个过程会产生一份默认的配置文件,然后你可以检查并修改。
Fabric CA服务器的home目录是这样决定的:
1 如果设置了 FABRIC_CA_SERVER_HOME 环境变量, 则就取它的值
2 否则就取 FABRIC_CA_HOME 的值
3 否则就取 CA_CFG_PATH 的值
4 否则就用当前的工作目录
在本章节中, 我们假设已经设置了环境变量 FABRIC_CA_HOME 为$HOME/fabric-ca/server。
下面的指令假设你已经将配置文件放在了服务器的home目录下。
5.1 服务端命令剖析
fabric-ca-server命令主要负责启动一个CA服务, 包括init和start两个子命令
用以下语句初始化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-----。
5.2 启动服务器
用以下命令启动CA服务器:
fabric-ca-server start -b <admin>:<adminpw>
第一次启动时,如果服务器未初始化,则会先进行初始化。
在初始化期间,如果发现 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。
六. Fabric CA 客户端
6.1 准备工作
本节讲述如何使用fabric-ca-client的命令。
首先,要先确定Fabric CA client的home目录,其决定顺序如下:
命令行 -home 选项
环境变量 FABRIC_CA_CLIENT_HOME
环境变量 FABRIC_CA_HOME
环境变量 CA_CFG_PATH
$HOME/.fabric-ca-client
请将配置文件放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命令会生成一份enrollment 证书 (ECert), 以及对应的私钥文件和CA根证书 PEM 文件 ,保存在Fabric CA client的 msp 子目录下。 提示信息里会告诉你保存到哪个目录。
6.2 注册一个新identity
发起注册请求的身份必须是已经登记(enroll)过的,同时也必须有权限去注册要注册的相应类型的身份。
在register期间,CA server会做两个授权检查:
调用者要register的身份必须是其“hf.Registrar.Roles”属性中所指明的身份中的一个。 例如调用者的“hf.Registrar.Roles”属性值为“peer,app,user”,那么他不能register orderer类型的identity。
调用者identity的从属关系必须等于要register时候的从属关系的前缀。 例如,一个调用者的从属关系是“a.b”,
那么他可以register一个拥有”a.b.c”的identity, 但不能是“a.c”。
下文的命令用admin identity去register一个新的identity,他的enrollment id是admin2, 类型是user,从属关系是org1.department1,hf.Revoker属性的值为true,foo属性的值为bar。
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.attrs 'hf.Revoker=true,foo=bar'
CA server会返回一个密码,用于这个identity去enroll。 也允许一个管理员去register一个identity, 然后将这个identity对应的enrollment ID和密码给其他人去enroll。
如果设置 maxenrollments 为 0 或者不设置则其默认值为 CA的 最大 enrollment 值。 这个注册用户的最大enroll值不能超过CA的最大enroll值, 比如CA的最大值设置为是5,则所有注册的身份只能小于等于 5, 而且也不能设置为 -1 (无限enroll).
下面我们注册一个 peer1 用户,注意这里我们指定了密码,而不是让命令为我们生成一个默认密码。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client register --id.name peer1 --id.type peer --id.affiliation org1.department1 --id.secret peer1p
6.3 Enroll一个 Peer identity
注册好身份后就可以enroll,enroll需要使用刚才注册的enrollmentID和密码(比如上节例子里的 password )。这个enroll和enroll bootstrap身份有点像,只不过我们这里还用到了 “-M” 选项 用于指定生成 MSP (Membership Service Provider) 目录结构。
以下是enroll一个 peer1。 确保 “-M” 指定的目录为你的 peer的 MSP 目录, 要与peer的core.yaml文件里设置的 ‘mspConfigPath’ 值要保持一致。 你也可以设置 FABRIC_CA_CLIENT_HOME 为你的 peer的home目录。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
fabric-ca-client enroll -u http://peer1:peer1pw@localhost:7054 -M $FABRIC_CA_CLIENT_HOME/msp
enroll一个orderer也类似,只不过-M指定的是orderer.yaml里的 ‘LocalMSPDir’ 。
6.4 重新enroll一个identity
假设你的证书到期了,就需要用以下命令重新enroll一份了
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
fabric-ca-client reenroll
6.5 撤销一个证书或一个identity
撤销一个identity会撤销他的所有证书,并阻止他再得到新的证书,撤销一个证书只是使一个证书无效。 撤销者的从属关系是orgs.org1可以撤销从属关系是orgs.org1和orgs.org1.department1的identity,但不能撤销orgs.org1的identity。
例子:bootstrap admin这个超级用户可以撤销**peer1**这个身份
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client revoke -e peer1
6.6 客户端命令剖析
fabric-ca-client命令可以与服务端进行交互, 包括五个子命令:
enroll: 登录获取ECert
getcacert: 获取CA服务的证书链
reenroll: 再次登录
register: 注册用户实体
revoke: 吊销签发的实体证书
6.6.1 enroll命令
向服务端申请签发ECert证书并将文件保存至本地
$ fabric-ca-client enroll -u http://admin:pass@localhost:7054
6.6.2 getcacert命令
向服务端申请根证书信息并保存至本地主配置目录的msp/cacerts路径下
$ fabric-ca-client getcacert -u http://admin:pass@localhost:7054
证书命名格式为: 服务器主机名-CA实例名.pem
6.6.3 reenroll命令
利用本地配置信息再次执行enroll过程, 生成新的签名证书材料
$ fabric-ca-client reenroll
6.6.4 register命令
执行注册新用户实体的客户端必须已经通过登记认证, 并且拥有足够的权限(所注册用户的hf.Registrar.Roles和affiliation都不能超出调用者属性)来进行注册
$ fabric-ca-client register --id.name jack --id.type user --id.affiliation org1.department1 --id.attrs'"hf.Registrar.Roles=peer,user"'--id.attrs'hf.Revoker=true'--id.secret jackpw
6.6.5 revoke命令
吊销指定的证书或指定实体相关的所有证书. 执行revoke命令的客户端身份必须拥有足够的权限(hf.Revoker为true, 并且被吊销者机构不能超出吊销者机构的范围)
$ fabric-ca-client revoke -e "jack" -r "affiliationchange"
-e: 指定吊销用户
-r: 指定吊销原因