一、Fabric CA 概述
Fabric Server 端由一个服务器集群组成,以树形架构组织 CA Server 节点,包含一个 Root 节点和多个中间节点。每个 CA 要么是根 CA,要么是中间 CA。每个中间 CA 都有一个父 CA,它要么是根 CA,要么是另一个中间 CA。
可以通过 Client 或 SDK 与服务器集群中的 CA 服务器进行交互。客户端首先路由到 HA 代理,由代理进行负载均衡,将客户端连接至某一服务器的集群成员。
包括前端的一个高可用的代理服务器,连接着若干个 CA Server 集群,这些集群将数据共同存放在同一个数据服务器上。数据库可能是 MySQL、LDAP、PostgresSQL 或者 SQLite(集群环境中不推荐使用 SQLite)。
集群中的所有 CA 服务器都共享相同的数据库,以跟踪身份和证书。如果配置了 LDAP,则将标识信息保存在 LDAP 中而不是数据库中。
二、开始使用
(一)先决条件
1. 安装 Go 1.9+
2. 设置正确的 GOPATH 路径,虚拟主机 GOPATH:/home/greedystar/goapps
按照官方推荐的路径结构,源码会在 GOPATH/src/ github.com/hyperledger/目录下
3. 安装 libtool 和 libtdhl-dev
Ubuntu 安装命令:sudo apt install libtool libltdl-dev
注意:在 MacOSX 上没有必要使用 libtdhl-dev
(二)安装 Fabric-ca
官方建议:
go get -ugithub.com/hyperledger/fabric-ca/cmd/...
注意:上面的命令将在$GOPATH/bin 中安装 fabric-ca-server 和 fabric-ca-client 二进制文件,并克隆 fabric-ca源码到$GOPATH/src/github.com/hyperledger/fabric-ca/目录下,但在启动 server 服务时会提示错误:panic: Version is not setfor fabric-ca library,原因是 fabric-ca 1.1.0 版本在运行时会调用 lib/metadta/version.go,其中的 version 变量在初始化启动时默认没有赋值,因此可以通过编译二进制文件时指定版本,命令如下:
go get -v-ldflags "-X github.com/hyperledger/fabric-ca/lib/metadata.Version=1.1.0"github.com/hyperledger/fabric-ca/cmd/...
注意:如果已经克隆了 fabric-ca 仓库,请确保在运行“go get”命令之前已经在主分支上了。
配置 fabric-ca-server 和 client 的命令行路径
export GOPATH=/home/greedystar/apps
export GOROOT=/usr/local/go
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
安装成功后可通过 fabric-ca-server version 查看版本如下图所示:
(三)启动服务方式
1. Docker 启动
进入$GOPATH/src/github.com/hyperledger/fabric-ca/docker/server 编辑 docker-compose.yml,更改镜像版本为本地 fabric-ca 镜像版本,下图红框部分。
在 docker-compose.yml 文件所在目录中打开终端,执行命令:docker-compose up –d
此命令首先会拉取 docker-compse.yml 中配置的 fabric-ca 镜像,然后启动 fabric-ca-server 实例,由于我使用的是本地镜像,因此此命令不会去拉取镜像,只会启动 ca 服务器实例。
2. 原生命令启动
使用缺省设置启动 fabric-ca-server,命令如下:
fabric-ca-server start -b admin:adminpw
三、Fabric CA Server
(一)初始化 Server
命令:fabric-ca-server init -badmin:adminpw
-b 选项提供了引导管理员的注册 ID 和密钥;如果配置文件中 LDAP 没有启用“ldap.enabled”设置,那么这是必需的(LDAP 是轻量目录访问协议,英文全称是 Lightweight Directory Access Protocol,是一种以树状的层次结构来存储数据的协议)
执行命令后在当前目录生成如下图所示的结构的文件。
ca-cert.pem 为生成的证书文件,通过 openssl 命令查看证书内容,命令如下:
openssl x509 –inca-cert.pen –inform pem –noout -text
fabric-ca-config.yaml 为生成的默认配置文件,如果需要自定义配置,可以使用–config xx-config.yaml 来进行启动配置。也可设置 FABRIC_CA_SERVER_HOME 环境变量,在该环境变量所指向的目录下配置 fabric-ca-server-config.yaml(默认寻找的配置文件,如无则创建默认配置文件),并在该目录下启动 Server,则 Server 便会使用当前目录下的配置文件。
fabric-ca-server.db 为存储发放证书信息的 sqlite3 数据库。
msp/keystore 存储的即为 keyfile(官方文档中所描述的 ca-key.pem)
Server 配置文件中可以配置一个证书签名请求(CSR),如下所示(字段的具体含义会在配置文件部分说明):
如果需要自定义 CSR 的属性,那么就需要自定义 server 配置文件,并删除掉配置文件中 ca.certfile 和 ca.keyfile 节点指向的文件,然后重新执行初始化命令。
fabric-ca-server init 命令会生成一个自签名的 CA 证书,除非提供-u <parent-fabric-ca-server-URL> 选项。如果提供了-u 选项,此服务器的 CA 证书将由其父 Server 节点进行签名。为了保证得到父节点的认证权限,<parent-fabric-ca-server-URL>的格式必须遵从<scheme>://<enrollmentID>:<secret>@<host>:<port>
如:fabric-ca-server init-u http://admin:adminpw@localhost:7054
如果想要 CA Server 使用个人提供的签名证书和私钥签名,则必须修改配置文件中的 ca.certfile 和 ca.keyfile,且证书和私钥签名必须是 pem 格式编码的文件。
可以通过自定义 CSR 来生成支持 ECDSA 和 RSA 的 X.509 证书和密钥。以下是一个椭圆曲线数字签名算法(ECDSA)的设置,采用的曲线是 prime256v1,签名算法是 ecdsa-with-SHA256。
对算法和密钥长度的选择出于对安全的考量。
ECDSA 提供以下选项:
size | ASN1 OID | Signature Algorithm |
256 | prime256v1 | ecdsa-with-SHA256 |
384 | secp384r1 | ecdsa-with-SHA384 |
521 | secp384r1 | ecdsa-with-SHA521 |
RSA 提供以下选项:
size | Modulus (bits) | Signature Algorithm |
2048 | 2048 | sha256WithRSAEncryption |
4096 | 2096 | sha512WithRSAEncryption |
(二)启动 Server
命令:fabric-ca-server start -b<admin>:<adminpw>
如果Fabric CA server 没有被初始化,则会首先初始化 Server,初始化详情请参考上一小节。
如果Fabric CA server 没有启用 LDAP,那么必须在命令中携带-b 选项并指定至少一个引导用户。
如果想要Fabric CA server 在 https 协议监听,那么就需要将 tls.enabled 设置为 true。
启动成功后,Fabric CA server 默认在 7054 端口监听(可在配置文件中配置)。
(三)配置数据库
Fabric CA 默认使用 SQLite 数据库,这是一种嵌入式的文件数据库,如果需要将在集群中部署 Fabric CA,那么就需要使用 PostgreSQL 或者 MySQL 数据库,支持的最低版本如下:
PostgreSQL: 9.5.5
MySQL: 5.7
1. PostgreSQL
下面的示例用于配置 PostgreSQL 数据库的链接,可以添加到 Fabric CA Server 的配置文件中使之生效,更具体的字段介绍可以参考https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
db:
type: postgres
datasource: host=localhost port=5432 user=Username password=Password dbname=fabric_ca sslmode=verify-full
sslmode 字段设置了 SSL 认证的具体配置,如下表所示
sslmode | 描述 |
disable | 禁用 SSL |
require | Always SSL (跳过验证) |
verify-ca | Always SSL (验证 Server 提供的证书是否由可信 CA 签名) |
verify-full | 与 verify-ca 相同,验证 Server 提供的证书是否由可信 CA 签名且 Server 的主机名与证书中的主机名匹配 |
如果要使用 TLS,那么必须设置 CA server 配置文件中的 db.tls 属性,如果在 PostgreSQL 服务器中启用了 SSL 客户端认证,那么必须在 Server 配置文件中的 db.tls.client 字段指定客户端的证书和密钥文件,如下:
db:
...
tls:
enabled: true
certfiles:
- db-server-cert.pem
client:
certfile: db-client-cert.pem
keyfile: db-client-key.pem
certfiles:PEM 编码的可信根证书文件列表
certfile 和 keyfile:PEM 编码的证书和密钥文件,用来保证 CA server 和 PostgreSQL server 的安全通信。
在 PostgreSQL 服务器上配置 SSL 的基本步骤:
1. 在 postgresql.conf 中,取消 SSLd 的注释并设置为“ON”(SSL= ON)
2. 在 PostgreSQL 数据目录中放置证书和密钥文件。
用于生成自签名证书的指令:https://www.postgresql.org/docs/9.5/static/ssl-tcp.html
注意:自签名证书用于测试,不应用于生产环境中。
PostgreSQL 服务器 – 需要客户端证书
1. 将您信任的证书颁发机构(CAS)的证书放置在 PostgreSQL 数据目录中的文件 root.crt 中
2. 在 postgresql.conf 中,设置“ssl_ca_file”以指向客户端的根证书(CA 证书)
3. 在 pg_hba.conf 中的 appropriate hostssl line,设置 clientcert 参数为 1
有关在 PostgreSQL 服务器上配置 SSL 的更多细节,请参阅以下 PostgreSQL 文档:https://www.postgresql.org/docs/9.4/static/libpq-ssl.html
2. MySQL
下面的示例用于配置 MySQL 数据库的链接,可以添加到 Fabric CA Server 的配置文件中使之生效,更具体的字段介绍可以参考https://dev.mysql.com/doc/refman/5.7/en/identifiers.html
db:
type: mysql
datasource: root:rootpw@tcp(localhost:3306)/fabric_ca?parseTime=true&tls=custom
使用 MySQL 需要 MySQL Server 允许接受’0000-00-00’为有效的日期,需要在 my.cnf 中找到配置选项 sql_mode,并且删除 NO_ZERO_DATE,并重启服务器。
更多的使用版本配置请参考https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html
如果要使用 TLS,请参考上一节的配置。
在 MySQL 服务器上配置 SSL 的基本步骤
打开或创建服务器的 my.cnf 文件,在[mysqld] 部分增加如下代码或取消如下代码的注释。应该指向 MySql 服务器的密钥和证书,以及根 CA 证书。
[mysqld] ssl-ca=ca-cert.pem ssl-cert=server-cert.pem ssl-key=server-key.pem
可以通过以下命令查询配置是否生效:
mysql> SHOW GLOBAL VARIABLES LIKE ‘have_%ssl’;
应当可以看到下表结果
variable_name | Value |
have_openssl | YES |
have_ssl | YES |
在 MySQL 服务器端 SSL 配置完成之后,下一步是创建一个有特权通过 SSL 接入 MySQL 服务器的用户。
mysql> GRANT ALL PRIVILEGES ON . TO ‘ssluser’@’%’ IDENTIFIED BY ‘password’ REQUIRE SSL; mysql> FLUSH PRIVILEGES
如果想要使用户从一个特定的 IP 地址访问 MySQL Server,可以把“%”变为特定的 IP 地址。
MySQL 服务器 – 需要客户端证书
安全连接的选项和用于服务器端的选项是相似的
– ssl-ca 识别 CA 证书,如果用到,必须和服务器端用相同的证书。
– ssl-cert 识别 MySQL 服务器的证书。
– ssl-key 识别 MySQL 服务器的私钥。
假设你想要用一个账户来连接,这个账户没有特殊的加密要求或是被一个包括 REQUIRE SSL 的 GRANT statement 创建的,启动 MySQL 服务至少需要-ssl-cert 和-ssl-key 选项。然后在服务设置文件中设置 db.tls.certfiles 属性并启动 CA 服务。
为了要求一个客户端证书也是被指定的,创建一个用 REQUIRE X509 选项的账户。然后客户端也必须明确客户端密钥和证书文件;否则,MySQL server 将会拒绝连接。为了给 CA server 指定客户端密钥和证书文件,设置 db.tls.client.certfile 和 db.tls.client.keyfile
(四)配置 LDAP
CA Server 可以从 LDAP Server 中读取进行配置
特别地,CA Server 可以连接到 LDAP Server 做如下事情:
– 在登记前认证身份
– 检索用于认证的身份属性
修改 CA Server 配置文件的 LDAP 部分来配置 CA Server 连接 LDAP Server
ldap:
enabled: false
url: <scheme>://<adminDN>:<pass>@<host>:<port>/<base>
userfilter: <filter>
attribute:
names: <LDAPAttrs>
converters:
- name: <fcaAttrName>
value: <fcaExpr>
maps:
<mapName>:
- name: <from>
value: <to>
- scheme: LDAP 或 LDAPS 中的一个。
- adminDN:admin 用户的名字。
- pass:admin 用户的密码。
- host:LDAP 服务器的 hostname 或 IP 地址。
- port:可选的端口号,ldap 默认的端口号是389,ldaps 默认的端口号是636。
- base:LDAP 树的根,用来搜索。
- filter:登录名的过滤器,例如:(uid=%s)用来搜索用用户名登陆的用户,(email=%s)用来搜索用邮箱登陆的用户。
当 LDAP 被配置好之后,登记过程如下:
– CA client 或 client SDK 发送一个 enrollment 请求,这个请求带一个 basic authorization header
– CA server 接收了这个 enrollment 请求,对 authorization header 中的 identity name 和 password 进行解码,用配置文件中的“userfilter”来从 identity name 中查找 DN(Distinquished Name),然后用 identity 的密码请求一个 LDAP bind,如果 LDAP bind 成功了,enrollment 过程就被授权了,可以执行了。
(五)配置多个 CAs
Fabric-ca-server 默认包含一个 CA,可以通过 cafiles 或 cacount 配置选项来增加其他的 CA,每一个 CA 都有他自己的 home 目录。
1. cacount
cacount 可以方便的创建多个附加 CAs,他们的 home directory 和 server directory 相关,如下所示:
-- <Server Home>
|--ca
|--ca1
|--ca2
如下命令来启动 2 个附加 CAs:
fabric-ca-server start -b admin:admin --cacount 2
2. cafiles
为每个要启动的 CA 配置 CA 配置文件。每个配置文件必须有唯一的 CA 名称和通用名称(CN),否则服务器将无法启动,因为这些名称必须是唯一的。CA 配置文件将重写任何默认 CA 配置,CA 配置文件中的任何缺失选项将由默认 CA 的值替换。
配置的优先级如下:
– CA Configuration file(自定义配置文件)
– Default CA CLI flags (默认命令选项)
– Default CA Environment variables(默认 CA 环境变量)
– Default CA Configuration file(默认配置文件)
一个 CA 的配置文件至少包括下述内容:
ca:
# Name of this CA
name: <CANAME>
csr:
cn: <COMMONNAME>
可以设置文档结构如下:
--<Server Home>
|--ca
|--ca1
|-- fabric-ca-config.yaml
|--ca2
|-- fabric-ca-config.yaml
如下命令可以启动两个自定义配置的 CA 实例:
fabric-ca-server start -b admin:admin --cafiles ca/ca1/fabric-ca-config.yaml --cafiles ca/ca2/fabric-ca-config.yaml
四、Fabric CA Client
(一)登记引导身份
fabric-ca-client enroll 命令用于登记身份,如下命令在本地 7054 端口监听的 Server 登记了 Id 为 admin,密码为 adminpw 的引导身份(未指定-u 选项即为登记引导身份)
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client enroll -u http://admin:adminpw@localhost:7054
(二)注册新身份
进行注册身份请求的身份首先需要进行登录,并且拥有注册此类别身份的权限。
Fabric CA server 制定了如下 3 种权限检验规则:
1. 注册者必须拥有 hf.Registrar.Roles 属性,其中的一个值与被注册身份的类型相同。例如注册 User 身份,则注册者的 hf.Registrar.Roles 属性中必须包含 User 值。
2. 注册者的组织关系必须与被注册身份相同或者是被注册身份组织关系的前缀。例如注册者组织关系为 a.b,则被注册身份可以为 a.b 或 a.b.*。
3. 注册者可以注册带有属性的用户,当且仅当满足如下情况:
- 注册者可以注册以“hf”为前缀的 Fabric CA 保留属性,注册者拥有保留属性且取值必须是 hf.Registrar.Attributes 属性中的值。如果属性是类型列表,则被注册的属性的值必须等于或是注册者具有的值的子集。如果属性为布尔类型,则注册者只有在该属性值为“true”时才能注册该属性。
- 注册非“hf”前缀的自定义属性,要求注册者拥有 hf.Registrar.Attributes 属性和值或属性和模式表达式。如果注册者有 hf.Registrar.Attributes=ad*,那么注册者可以从身份添加或删除的属性就是以“ad”为前缀的属性。
- 如果请求的属性名是以 hf 为前缀的保留属性,则会进行额外的检查,以查看该属性值是否为注册者相同属性值的子集。例如注册者的属性值为“A.B.*,X.Y.Z”,那么请求 A.B.C 是有效的,请求 A.C.B 是无效的。
下表列出了可以为身份注册的所有预置属性。注:属性的名称是区分大小写的
属性名 | 类型 | 描述 |
hf.Registrar.Roles | List | 注册者可以管理的角色列表 |
hf.Registrar.DelegateRoles | List | 注册者可以授予被注册身份 hf.Registrar.Roles 属性的角色列表 |
hf.Registrar.Attributes | List | 注册者允许注册的属性列表 |
hf.GenCRL | Boolean | 如果 true 则身份可以生成 CRL |
hf.Revoker | Boolean | 如果 true 则身份可以撤销用户或证书 |
hf.AffiliationMgr | Boolean | 如果 true 则身份可以管理组织关系 |
hf.IntermediateCA | Boolean | 如果 true 则身份可以登记中间 CA Server |
注意:在注册身份时若提供属性为列表,且列表中存在重复的属性名,则以最后一个为准。
下述命令以 admin 身份证书注册了一个 id 为 admin2,组织关系为 org1.department1 的用户,并提供了 hf.Revoker 的保留属性和 admin 的自定义属性(:exert 表示该属性名和值会插入到登记证书中)
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client register --id.name admin2 --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,admin=true:ecert'
可以将多个属性指定为-id.attrs 选项的一部分,每个属性必须逗号分隔。对于包含逗号的属性值,属性必须封装在双引号中。见下面的例子。
fabric-ca-client register -d --id.name admin2 --id.affiliation org1.department1 --id.attrs '"hf.Registrar.Roles=peer,user",hf.Revoker=true'
fabric-ca-client register -d --id.name admin2 --id.affiliation org1.department1 --id.attrs '"hf.Registrar.Roles=peer,user"' --id.attrs hf.Revoker=true
可以通过修改配置文件为字段提供默认值,如下命令从命令行提供了 name 字段,其余字段在配置文件中读取。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/admin
fabric-ca-client register --id.name admin3
可以通过–id.secret peerpw 提供密码。
(三)登记身份
命令如下,-M 选项表示填充 MSP(成员服务提供商)目录结构。
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
Fabric CA Server 发出的所有注册证书都有组织关系,规则如下:
1. OU 层次结构的根等于身份类型。
2. 为身份标识的每个组件添加了 OU。
例如,一个身份的类型为节点,它属于 dept1.team1,那么它的 OU 层次结构为(从叶到根)OU=team1 OU=dept1 OU=peer
(四)从其他 CA 服务器获取 CA 证书链
通常,msp 目录的 cacerts 目录必须包含 CA 颁发的证书链,代表节点的所有可信根证书。
fabric-ca-client getcacerts 命令即是用于从其他 Fabric CA 服务器实例获取证书链。
例如,下面命令将启动另一个 Fabric CA 服务器,名称为 CA2,在本地主机上监听 7055 端口,这表示区块链上的另一个可信根证书。
export FABRIC_CA_SERVER_HOME=$HOME/ca2
fabric-ca-server start -b admin:ca2pw -p 7055 -n CA2
下面的命令将会安装 CA2 的证书链到 peer1 的 msp 目录下。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
fabric-ca-client getcacert -u http://localhost:7055 -M $FABRIC_CA_CLIENT_HOME/msp
默认情况下,Fabric CA 服务器以子代为先的顺序返回 CA 证书链,这意味着链中的每个 CA 证书后面跟着它的颁发者 CA 证书。如果需要以相反的顺序返回 CA 证书链,那么将环境变量 CA_CHAIN_PARENT_FIRST 设置为 true,并重新启动 FabricCA 服务器,客户端将适当地处理顺序。
(五)重新登记身份
假设证书即将过期,可以通过如下命令重新登记身份。
export FABRIC_CA_CLIENT_HOME=$HOME/fabric-ca/clients/peer1
fabric-ca-client reenroll
(六)撤销证书或身份
为了撤销证书或身份,调用身份必须具有 hf.Revoker 和 hf.Registrar.Roles 属性。调用身份只能撤销证书或与调用身份组织关系相同和匹配前缀的身份。此外,撤消者只能撤销在撤消者的 hf.Registrar.Roles 角色属性中列出的类型的身份。
下面的命令禁用身份并撤销与该身份相关联的所有证书。Fabric CA Server 接收到的所有该身份的请求都将被拒绝。
fabric-ca-client revoke -e <enrollment_id> -r <reason>
reason 选项的具体取值请参考:
http://hyperledger-fabric-ca.readthedocs.io/en/release-1.1/users-guide.html#reenrolling-an-identity
fabric-ca-clientrevoke -e peer1 –gencrl
-gencrl 会生成 CRL 并存储在<msp folder>/crls/crl.pem
(七)通过命令生成 CRL
任何拥有 hf.GenCRL 属性的身份都可以创建一个 CRL,该 CRL 包含在某一段期间被撤销的所有证书的序列号。创建的 CRL 存储在<msp 文件夹> /crl/crl.pem 文件中。
export FABRIC_CA_CLIENT_HOME=~/clientconfig
fabric-ca-client gencrl -M ~/msp
上述命令将创建包含所有被撤销的证书(过期和未过期)的 CRL,并将 CRL 存储在~/msp/crl/crl.pem 文件中。
export FABRIC_CA_CLIENT_HOME=~/clientconfig
fabric-ca-client gencrl --caname "" --revokedafter 2017-09-13T16:39:57-08:00 --revokedbefore 2017-09-21T16:39:57-08:00 -M ~/msp
上述命令将创建一个 CRL,包含所有在 2017-09-13T16:39:57-08:00 之后撤销的(由–revokedafter 指定)和 2017-09-21T16:39:57-08:00 之前撤销的(由-revokedbefore 指定)的证书(过期和未过期),并将 CRL 存储在~/msp/crl/crl.pem 中。
-caname 标志表示生成 CRL 请求发送到的 CA 名字,此命令会将请求发送至默认 CA。
export FABRIC_CA_CLIENT_HOME=~/clientconfig
fabric-ca-client gencrl --expireafter 2017-09-13T16:39:57-08:00 --expirebefore 2018-09-13T16:39:57-08:00 --revokedafter 2017-09-13T16:39:57-08:00 --revokedbefore 2017-09-21T16:39:57-08:00 -M ~/msp
gencrl 命令还接受-expireafter 和-expirebefore 选项,用于为撤销的证书指定超时时间范围,如上述命令所示。
(八)基于属性的访问控制
访问控制决策可以由基于身份属性的链码(和由 Hyperledger Fabric 运行时)来实现,称为基于属性的访问控制,简称 ABAC。
为了使这成为可能,身份的注册证书(ECert)可以包含一个或多个属性名称和值。然后链码提取属性值来进行访问控制决策。
有两种方法获得具有属性的注册证书:
1. 注册身份时,可以指定为身份颁发的注册证书应默认包含的属性。此行为可以在注册时重写,但这对于建立默认行为非常有用,如果注册发生在您的应用程序之外,则不需要任何应用程序更改。
当用户在注册时没有明确地请求属性时,“:ecert”后缀会导致 app1Admin 属性默认插入 user 的注册证书中。
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'
2. 登记身份时,可以显式请求将一个或多个属性添加到证书中。对于所请求的每个属性,可以指定属性是否是可选的。如果不需要请求,并且身份不具有属性,则会发生错误。
如在命令中指定了 address,但身份中不具有该属性则会报错。
fabric-ca-client enroll -u http://user1:user1pw@localhost:7054 --enrollment.attrs "email,phone:opt"
下表显示了每个身份自动注册的三个属性
属性名 | 属性值 |
hf.EnrollmentID | The enrollment ID of the identity |
hf.Type | The type of the identity |
hf.Affiliation | The affiliation of the identity |
若要将任何上述属性默认添加到证书中,必须显式地使用“:ecert”注册属性,如下命令所示:
fabric-ca-clientregister --id.name user1 --id.secret user1pw --id.type user --id.affiliationorg1 --id.attrs 'hf.Affiliation=org1:ecert'
(九)动态服务器配置更新
动态对 CA Server 进行配置更新,无需重启 Server。本节中的所有命令都要求首先通过执行 fabric-ca-client enroll 命令进行登记。
1. 使用 fabric-ca-client 命令动态更新身份
如果客户端身份不满足以下所有情况,则会发生授权失败:
(1)客户端身份必须具有“hf.Registrar.Roles”属性,该属性值是具有逗号分隔的列表,其中一个属性值与被更新的身份类型相同。例如,如果 Client 身份的“hf.Registrar.Roles”属性取值为“client,peer”,则 Client 可以更新 client 和 peer 类型的身份,而不能更新 orderer。
(2)客户端身份的归属关系必须等同或匹配被更新身份的归属关系前缀。例如,客户端归属于 a.b,则其可以更新归属于 a.b.c 的身份,但不能更新归属于 a.c 的身份。如果一个身份需要根关联,那么更新请求应该指定“.”用于关联,并且客户端也必须具有根关联。
2. 获取身份信息
fabric-ca-client identity list --id user1
fabric-ca-client identity list
3. 添加身份
有两种方法添加身份,如下所示:
fabric-ca-client identity add user1 --json '{"secret": "user1pw", "type": "user", "affiliation": "org1", "max_enrollments": 1, "attrs": [{"name": "hf.Revoker", "value": "true"}]}'
fabric-ca-client identity add user1 --secret user1pw --type user --affiliation . --maxenrollments 1 --attrs hf.Revoker=true
下表列出了身份的所有字段以及它们是否是必需的或可选的,以及它们可能具有的任何默认值。
Fields | Required | Default Value |
ID | Yes | |
Secret | No | |
Affiliation | No | Caller’s Affiliation |
Type | No | client |
Maxenrollments | No | 0 |
Attributes | No |
4. 修改身份
有两种方法可以用来修改身份信息,一种是通过 json 字符串,另一种是直接使用选项标识。
如下命令通过 json 对 user1 的多个信息进行了修改:
fabric-ca-client identity modify user1 --json '{"secret": "newPassword", "affiliation": ".", "attrs": [{"name": "hf.Regisrar.Roles", "value": "peer,client"},{"name": "hf.Revoker", "value": "true"}]}'
如下命令直接使用选项标识修改身份信息:
fabric-ca-client identity modify user1 --secret newsecret
fabric-ca-client identity modify user1 --affiliation org2
fabric-ca-client identity modify user1 --type peer
fabric-ca-client identity modify user1 --maxenrollments -2 // -2表示使用 CA 的最大登记设置
fabric-ca-client identity modify user1 --secret newpass --type peer
5. 移除身份
下面命令删除身份 user1,并撤消与 user1 身份相关联的任何证书。
fabric-ca-client identity remove user1
注意:在默认情况下,Fabric CA 服务器是禁用身份的删除的,但可以通过设置–cfg.identities.allowremove 选项启动 Fabric CA 服务器启用。
6. 添加组织关系
要求 client 满足:
(1)client 身份必须拥有 hf.AffiliationMgr 属性,且取值为 true
(2)client 身份的归属关系必须在被更新的层次之上,如 client 归属于 a.b,则 client 可添加 a.b.*归属关系
命令 : fabric-ca-client affiliation add org1.dept1
7. 修改组织关系
要求 client 满足:
(1)client 身份必须拥有 hf.AffiliationMgr 属性,且取值为 true
(2)client 身份的归属关系必须在被更新的层次之上
(3)如果修改的组织关系需要级联修改身份信息,那么 client 身份必须拥有修改身份信息的权限
如下命令将 org2 的名字修改为 org3,若需要级联修改身份信息,则会报错
fabric-ca-client affiliation modify org2 --name org3
添加—force 选项即可级联修改身份信息
fabric-ca-client affiliation modify org1 --name org2 --force
8. 移除组织关系
要求 client 满足:参考7.修改组织关系
如下命令将会移除 org2,同时移除其子组织关系,但若存在需要级联移除的身份,则会报错
fabric-ca-client affiliation remove org2
添加—force 选项即可级联删除身份信息
fabric-ca-client affiliation remove org2 --force
注意:在默认情况下,Fabric CA 服务器是禁用身份的删除的,但可以通过设置–cfg. affiliations.allowremove 选项启动 FabricCA 服务器启用。
9. 列举组织关系信息
要求 client 满足:参考 6.添加组织关系,如下命令列出特定组织关系的信息
fabric-ca-client affiliation list --affiliation org2.dept1
如下命令列出全部组织关系的信息,但需要具有相应的权限
fabric-ca-client affiliation list
(十)指定特定的 CA 实例
当服务器运行多个 CA 实例时,请求可以指向特定的 CA。默认情况下,如果在客户端请求中没有指定 CA 名称,则请求将指向服务器上的默认 CA。可以在客户端命令的命令行上指定 CA 名称,如下所示:
fabric-ca-client enroll -u http://admin:adminpw@localhost:7054 --caname <caname>
(十一)启动中间 CA
为了创建中间 CA 的签名证书,中间 CA 必须以与 fabric-ca-client 相同的方式向一个父 CA 进行登记。通过使用-U 选项来指定父 CA 的 URL、登记 ID 和密码。此中间 CA 必须具有 hf.IntermediateCA 属性且取值为 true。待颁发证书的 CN 会设置为注册的 ID。如果中间 CA 试图显式指定 CN 值,则会发生错误。
fabric-ca-server start -b admin:adminpw -u http://<enrollmentID>:<secret>@<parentserver>:<parentport>
五、证书格式
通过 openssl 命令查看证书内容
openssl x509 –inca-cert.pen –inform pem –noout –text
数字认证证书是记录了一个群体一系列属性的证件。最常见的数字认证证书是遵守 X.509 标准的证书。X.509 标准允许将群体的身份详细信息编码。
下图的数字认证证书是一个 SUBJECT 由(C=US, ST=NorthCarolina, O=Hyperledger, OU=Fabric, CN=fabric-ca-server)的属性构成。fabric-ca-server(注册的身份的名称,无实际意义,下称该身份)的证书就是他的身份证,提供了能证明该身份是他自己的关键事实。
一个数字认证证书描绘了该身份,该身份是这个证书对应的 subject。这个数字认证证书也包括了许多其他的信息,该身份的公钥在他的数字认证证书中,而私钥却不在里面(私钥必须保密)。
该身份的所有属性特征都可以通过数学加密的方式记录,所以篡改证书信息会使证书无效。该身份可以携带他的证书来证明他的身份,只要其它群体信任向该身份颁发证书的机构(CA)。只要 CA 确保了私有信息的安全,就可以确保该身份的证书没有被篡改。
六、Fabric-CA-Client 配置文件
#############################################################################
# fabric-ca-client 命令配置文件.
#############################################################################
# URL of the Fabric-ca-server (default: http://localhost:7054)
url: http://localhost:7054
# Membership Service Provider (MSP) 目录
# 配置 MSP 目录在客户端用户登记 peer 或 drderer 的时候很有用,这可以使得登记结构以
# MSP 所期望的格式存储
mspdir: msp
#############################################################################
# TLS(安全传输层协议)部分 用于保证 socket 连接的安全
# certfiles - PEM-编码的可信任的根证书文件列表
# client:
# certfile - PEM-编码的证书文件(需提供:当服务器启动了对客户端的身份验证)
# keyfile - PEM-编码的私钥文件(需提供:当服务器启动了对客户端的身份验证)
#############################################################################
tls:
certfiles:
client:
certfile:
keyfile:
#############################################################################
# CSR 部分,用于为登记证书编码生成证书签名请求
#
# cn – 用于 CAs 决定为谁生成证书
# serialnumber – 序列号属性,将作为证书的一部分。例如,某一公司拥有证书颁发机构,其希# 望将员工的工号包含在证书中。
# 注意:这里的 serialnumber 与 Server 配置的 serialnumber 不一样,此处序列号将作为证书# 的一部分
# names - name 对象列表,每个 name 对象都至少包含"C", "L", "O", "ST"中的一个值(或者# 任意组合)
# "C": 国家
# "L": 地区或直辖市(如城市或城镇名称)
# "O": 组织
# "OU": 组织单位(如拥有密钥的部门),也可以用来作为 DBS 的名称。
# "ST": 州或省
# 注意:OU 或 OUs 是根据身份类型和所属组织关系来设置的,Ous 根据如下规则计算登录
# OU=<type>, OU=<affiliationRoot>, ...,OU=<affiliationLeaf>
# 例如:从属于 org1.dept2.team3 的 client 进行登录,则 Ous 为:OU=client, OU=org1,
# OU=dept2, OU=team3
# hosts – 该证书有效的主机名列表
#############################################################################
csr:
cn: admin
serialnumber:
names:
- C: US
ST: North Carolina
L:
O: Hyperledger
OU: Fabric
hosts:
- home
#############################################################################
# id 部分用于向 fabric-ca-server 注册一个新的身份
#
# name – 身份的唯一名称
# type – 注册的身份类型 (e.g. 'peer, app, user')
# affiliation – 身份的组织关系
# maxenrollments –secret(??密码??)可以用来登记的最大次数
# -1:无限制 0:使用 CA 的最大登记值
# attributes – 身份的 name/value 属性列表
#############################################################################
id:
name:
type:
affiliation:
maxenrollments: 0
attributes:
# - name:
# value:
#############################################################################
# enrollment 部分用于向 fabric-ca server 登记一个身份
# profile -颁发证书时使用的签名配置文件的名称
# label -在 HSM(高速存储器)操作中使用的标签
#############################################################################
enrollment:
profile:
label:
#############################################################################
# 要连接的 fabric-ca-server 名
#############################################################################
caname:
#############################################################################
# BCCSP (BlockChain Crypto Service Provider) 部分允许选择使用的加密实现库
#############################################################################
bccsp:
default: SW
sw:
hash: SHA2
security: 256
filekeystore:
# 存储密钥的目录
keystore: msp/keystore
七、Fabric-CA-Server 配置文件
#############################################################################
# fabric-ca-server 命令配置文件
#############################################################################
# 配置文件版本
version: 1.1.0
# 服务器监听端口 (default: 7054)
port: 7054
# 开启调试日志 (default: false)
debug: false
# 证书吊销列表大小限制,单位:字节(default: 512000)
crlsizelimit: 512000
#############################################################################
# Server 监听端口的安全传输层协议(TLS)
# type - 客户端认证支持如下类型:NoClientCert, RequestClientCert,
# RequireAnyClientCert, VerifyClientCertIfGiven, RequireAndVerifyClientCert.
# certfiles – 根证书列表,用于 Server 验证 Client 证书
#############################################################################
tls:
# 启用 TLS (default: false)
enabled: false
certfile:
keyfile:
clientauth:
type: noclientcert
certfiles:
#############################################################################
# CA 部分包含与 CA 相关的信息
# name – CA 在区块链网络中唯一的名称
# keyfile – 密钥文件,只用于将私钥导入 BCCSP
# certfile – 证书文件
# keyfile 和 certfile 用于办法注册证书(ECert)和交易证书(TCert)
# chainfile - (如果存在)包含被此 CA 信任的证书链,通常链中第一个证书为 root CA 的证书
##############################################################################
ca:
name:
keyfile:
certfile:
chainfile:
#############################################################################
# 指定生成的 CRL 的到期时间,将此属性指定的小时数添加到 UTC 时间,结果时间用于设置 CRL
# 的下一个更新日期。
#############################################################################
crl:
expiry: 24h
#############################################################################
# registry 部分控制着 Server 如何做以下两件事:
# 1) 包含 username 和 password(也叫作 enrollment ID 和 secret)的登记验证请求
# 2) 一旦经过身份验证,就可以检索出身份的 name/value 属性对,Server 可将属性对随机
# 加入到用于区块链交易问题的交易证书(Tcerts)中,这些属性对于在 chaincode 中进行
# 访问控制决策非常有用。
# 两个主要的配置选项:
# 1) fabric-ca-server 作为登记处.
# 如果 ldap 部分的 ldap.enabled 为 false,则 fabric-ca-server 作为登记处
# 2) LDAP server 作为登记处
# 如果 ldap 部分的 ldap.enabled 为 true,则 LDAP server 作为登记处,也就是说 registry
# 部分被忽略
# 在这种情况下,fabric-ca-server 调用 LDAP 服务器来执行登记任务
#############################################################################
registry:
# password/secret 可以重复使用进行登记的次数,默认:-1,即无限制
maxenrollments: -1
# 包含身份信息
identities:
- name: admin
pass: admin
type: client
affiliation: ""
attrs:
hf.Registrar.Roles: "peer,orderer,client,user"
hf.Registrar.DelegateRoles: "peer,orderer,client,user"
hf.Revoker: true
hf.IntermediateCA: true
hf.GenCRL: true
hf.Registrar.Attributes: "*"
hf.AffiliationMgr: true
#############################################################################
# Database section
# 支持数据库: "sqlite3", "postgres", and "mysql".
# 数据源的取值依赖于数据库类型
# 如果是"sqlite3",则数据源取值为用户数据库存储的文件名,由于"sqlite3"是一个嵌入
# 式的数据库,因此如果想在集群服务器上运行 fabric-ca-server,那么必须选择"postgres"
# 或"mysql"
#############################################################################
db:
type: sqlite3
datasource: fabric-ca-server.db
tls:
enabled: false
certfiles:
client:
certfile:
keyfile:
#############################################################################
# LDAP section
# 如果开启 LDAP,那么 fabric-ca-server 将调用 LDAP 处理:
# 1) 为登记请求认证 enrollmentID and secret (username and password)
# 2) 获取身份属性
#############################################################################
ldap:
# 如果启用, 那么 registry 部分将会被忽略. (default: false)
enabled: false
# The URL of the LDAP server
url: ldap://<adminDN>:<adminPassword>@<host>:<port>/<base>
# 客户端连接 LDAP server 的 TLS 配置
tls:
certfiles:
client:
certfile:
keyfile:
# 属性相关的配置,从 LDAP 条目映射到 Fabric CA 属性。
attribute:
# 'names'是一个字符串数组,包含从 LDAP 服务器请求的 LDAP 身份条目的 LDAP 属性名
names: ['uid','member']
# 'converters' 用于将 LDAP 条目转换为 fabric CA 属性
# 如下将表达式< attr("uid") =~ "revoker*">( LDAP 的 uid 属性是否由'revoker'开头) 的值转换为 fabric CA 属性"hf.Revoker"
# converters:
# - name: hf.Revoker
# value: attr("uid") =~ "revoker*"
converters:
- name:
value:
# The 'maps' 用于在'converters'中对属性进行映射
# 假设属性'member'的值为'dn1', 'dn2', and 'dn3'. 对于如下配置
# converters:
# - name: hf.Registrar.Roles
# value: map(attr("member"),"groups")
# maps:
# groups:
# - name: dn1
# value: peer
# - name: dn2
# value: client
# 用户的'hf.Registrar.Roles'取值将为"peer,client,dn3".
# 因为 maps 中将 dn1,dn2 分别映射为 peer、client
maps:
groups:
- name:
value:
#############################################################################
# Affiliations section. Fabric CA Server 可以使用本节指定的从属关系进行引导
# 从属关系本质上是分层的,例如:
# businessunit1:
# department1:
# - team1
# businessunit2:
# - department2
# - department3
# 注意:从属关系是区分大小写的,除了 Server 配置文件中指定的非叶子从属关系,它们总是
# 存储在小写的情况下(即在 Server 配置文件中配置的从属关系中,叶子结点区分大小写,而
# 非叶子节点自动按小写存储)
#############################################################################
affiliations:
org1:
- department1
- department2
org2:
- department1
#############################################################################
# Signing section 签名部分
#
# default 部分用于签发登记证书,expiry 默认为 8760h(1 年)
#
# profile.ca 用于签发中间 CA 证书,ca.expiry 默认 43800h(5 年)
# 注意:
# isca 为 true 意味着它会颁发 CA 证书.
# maxpathlen 为 0 表示中间 CA 不能发布其他中间 CA 证书,尽管它仍然可以发布最终实
# 体证书
#
# tls 用于签署 TLS 证书请求
# expiry 默认 8760h(1 年)
##############################################################################
signing:
default:
usage:
- digital signature
expiry: 8760h
profiles:
ca:
usage:
- cert sign
- crl sign
expiry: 43800h
caconstraint:
isca: true
maxpathlen: 0
tls:
usage:
- signing
- key encipherment
- server auth
- client auth
- key agreement
expiry: 8760h
###########################################################################
# 证书签名请求(CSR)部分, 控制根 CA 证书的创建
#
# 根 CA 证书的到期时间配置为 ca.expiry 字段,默认值为“131400 小时(15 年)
#
# ca.pathlength 字段用于限制 CA 证书层次结构
# 1)无 pathlength 值意味着不要求限制。
# 2)pathlength:1(根 CA 的默认值)意味着根 CA 可以发布中间 CA 证书,但是这些中间
# CAs 可能不会依次发布其他 CA 证书,尽管它们仍然可以发布最终实体证书。
# 3)pathlength:0(中间 CA 的默认值)意味着它不能发布 CA 证书,尽管它仍然可以发布
# 最终实体证书。
############################################################################
csr:
cn: fabric-ca-server
names:
- C: US
ST: "North Carolina"
L:
O: Hyperledger
OU: Fabric
hosts:
- home
- localhost
ca:
expiry: 131400h
pathlength: 1
#############################################################################
# BCCSP (BlockChain Crypto Service Provider) 部分允许选择使用的加密实现库
#############################################################################
bccsp:
default: SW
sw:
hash: SHA2
security: 256
filekeystore:
# 存储密钥的目录
keystore: msp/keystore
#############################################################################
# Multi CA section
#
# 每个 Fabric CA server 默认包含一个 CA,这一部分用于在一个 Server 上设置多个 CA
#
# 1) --cacount <number-of-CAs>
# 自动生成<number-of-CAs>个非默认的 CA,自动命名"ca1", "ca2", ... "caN",通常
# 用于开发环境快速创建多个 CA
# 2) --cafiles <CA-config-files>
# 对于列表中的每个 CA 配置文件,生成一个单独的签名 CA。该列表中的每个 CA 配置文件可
# 以包含与服务器配置文件中除了端口、调试和 TLS 部分中所有元素相同的元素
# 示例:
# fabric-ca-server start -b admin:adminpw --cacount 2
# fabric-ca-server start -b admin:adminpw --cafiles ca/ca1/fabric-ca-server-
# config.yaml --cafiles ca/ca2/fabric-ca-server-config.yaml
#############################################################################
cacount:
cafiles:
#############################################################################
# Intermediate CA section
#
# 服务器和 CAs 之间的关系如下:
# 1)单个服务器进程可以包含或充当一个或多个 CAS,这是由上面的 Multi CA 部分配置的
# 2)每个 CA 是根 CA 或中间 CA
# 3)每个中间 CA 有一个父 CA,它是根 CA 或另一个中间 CA
#
# 如果设置了 parentserver.url 属性,则这是一个带有指定父 CA 的中间 CA
# parentserver section
# url -父 Server 的 URL
# caname – 父 CA 在服务器内注册的名称
#
# enrollment section 用于通过父 CA 登记中间 CA
# profile -在颁发证书时使用的签名配置文件的名称
# label -用于 HSM 操作的标签
#
# tls section (安全传输层协议)部分 用于保证 socket 连接的安全
# certfiles - PEM-编码的可信任的根证书文件列表
# client:
# certfile - PEM-编码的证书文件(需提供:当服务器启动了对客户端的身份验证)
# keyfile - PEM-编码的私钥文件(需提供:当服务器启动了对客户端的身份验证)
#############################################################################
intermediate:
parentserver:
url:
caname:
enrollment:
hosts:
profile:
label:
tls:
certfiles:
client:
certfile:
keyfile: