fabric 使用 fabric-ca 服务

  • 准备部分

首先需要用户从github上download fabric-ca 的工程代码

cd $GOPATH/src/github.com/hyperledger
git clone https://github.com/hyperledger/fabric-ca.git

然后对它进行编译,在编译时,会需要安装 goimports 命令,貌似目前关于golang的相关内容都被“东方神秘力量”所限制,请读者们自行科学上网。

cd fabric-ca
make

在编译过程中,可能会在test 部分遇到错误,但是没有关系,因为用不到,我们只需要将 fabric-ca-client 编译出来即可。

  • 部署环境

让我们还是以e2e_cli 做例子给大家介绍如何部署ca以及使用它来创建用户。

在启动fabric 服务的 network_setup.sh 脚本中,默认是使用 docker-compose-cli.yaml 配置文件启动 docker 镜像的,将 COMPOSE_FILE 变量修改为使用 docker-compose-e2e.yaml 配置文件启动docker 镜像

#COMPOSE_FILE=docker-compose-cli.yaml
COMPOSE_FILE_COUCH=docker-compose-couch.yaml
COMPOSE_FILE=docker-compose-e2e.yaml

在 hyperledger fabric 1.0.5 分布式部署 (五)介绍的 generateArtifacts.sh 脚本,在其 replacePrivateKey 函数中,会将 docker-compose-e2e-template.yaml 配置文件拷贝一个名叫 docker-compose-e2e.yaml 的文件,并且将 cryptogen 生成的相关私钥和证书信息替换 docker-compose-e2e.yaml 其中的内容。

所以我们还需要将 docker-compose-e2e-template.yaml 配置进行修改,修改后内容如下

version: ''

services:
ca0:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org1
- FABRIC_CA_SERVER_TLS_ENABLED=false
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
- FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY
ports:
- "7054:7054"
command: sh -c '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/CA1_PRIVATE_KEY -b admin:adminpw -d'
volumes:
- ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
container_name: ca_peerOrg1 ca1:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org2
- FABRIC_CA_SERVER_TLS_ENABLED=false
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem
- FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY
ports:
- "8054:7054"
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY -b admin:adminpw -d'
volumes:
- ./crypto-config/peerOrganizations/org2.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
container_name: ca_peerOrg2 orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org1.example.com peer1.org1.example.com:
container_name: peer1.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org1.example.com peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org2.example.com peer1.org2.example.com:
container_name: peer1.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer1.org2.example.com cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=DEBUG
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
volumes:
- /var/run/:/host/var/run/
- ../chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com

ca0 和 ca1 两个镜像的环境变量 FABRIC_CA_SERVER_TLS_ENABLED 必须要设置为 false ,否则后续连接ca server 时会报错以下错误

Error: POST failure [Post http://localhost:7054/enroll: malformed HTTP response "\x15\x03\x01\x00\x02\x02\x16"]; not sending
POST http://localhost:7054/enroll

用户可以像以前没有ca 服务一样,通过 network_setup.sh 脚本启动整个 fabric 服务

./network_setup.sh up mychannel  couchdb ;

然后查看一下docker 镜像起来了哪些 docker ps

CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED             STATUS              PORTS                                                                       NAMES
7da99a56c176 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.a..." hours ago Up hours dev-peer0.org1.example.com-mycc-1.0
4a29b3322e06 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.a..." hours ago Up hours dev-peer0.org2.example.com-mycc-1.0
380421da2c99 hyperledger/fabric-tools "/bin/bash -c './s..." hours ago Up hours cli
98e1cb275d00 hyperledger/fabric-peer "peer node start" hours ago Up hours 0.0.0.0:->/tcp, 0.0.0.0:->/tcp, 0.0.0.0:->/tcp peer0.org2.example.com
f17f8c1dfd7d hyperledger/fabric-peer "peer node start" hours ago Up hours 0.0.0.0:->/tcp, 0.0.0.0:->/tcp, 0.0.0.0:->/tcp peer1.org2.example.com
7f1fbc2539f1 hyperledger/fabric-peer "peer node start" hours ago Up hours 0.0.0.0:->/tcp, 0.0.0.0:->/tcp, 0.0.0.0:->/tcp peer1.org1.example.com
44edc4b5557b hyperledger/fabric-peer "peer node start" hours ago Up hours 0.0.0.0:-->-/tcp peer0.org1.example.com
f0f688da1e7e hyperledger/fabric-couchdb "tini -- /docker-e..." hours ago Up hours /tcp, /tcp, 0.0.0.0:->/tcp couchdb1
48030f9de76c hyperledger/fabric-couchdb "tini -- /docker-e..." hours ago Up hours /tcp, /tcp, 0.0.0.0:->/tcp couchdb0
46acc883badc hyperledger/fabric-ca "sh -c 'fabric-ca-..." hours ago Up hours 0.0.0.0:->/tcp ca_peerOrg2
e67e62547da0 hyperledger/fabric-ca "sh -c 'fabric-ca-..." hours ago Up hours 0.0.0.0:->/tcp ca_peerOrg1
92b9a19e7a4b hyperledger/fabric-orderer "orderer" hours ago Up hours 0.0.0.0:->/tcp orderer.example.com
005c18e53da3 hyperledger/fabric-couchdb "tini -- /docker-e..." hours ago Up hours /tcp, /tcp, 0.0.0.0:->/tcp couchdb2
ecb4de206d3e hyperledger/fabric-couchdb "tini -- /docker-e..." hours ago Up hours /tcp, /tcp, 0.0.0.0:->/tcp couchdb3

用户可以看到分别启动了两个 ca server 服务,并且分别对应 Org1MSP 、 Org2MSP 两个机构。

让我们重写切换一下路径,并且设置一下环境变量,让后续生成的相关文件落在该目录

cd /opt/gopath/src/github.com/hyperledger/fabric-ca/bin
mkdir -p /root/ca
export FABRIC_CA_CLIENT_HOME=/root/ca

然后使用 fabric-ca-client 去连接 ca server。

注意 admin:adminpw 代表的是ca server 的管理员用户名和密码,7054 端口对应的是配置了 Org1MSP 的ca server,8054 端口则是配置了 Org2MSP 的ca server。

执行以下命令后,将会在 /root/ca 目录上主动创建 fabric-ca-client-config.yaml 文件和 msp 目录

./fabric-ca-client enroll -u http://admin:adminpw@localhost:7054

向ca server 注册一个新的用户,名字叫 test, 密码为 test123

./fabric-ca-client register --id.name test --id.type user --id.affiliation org1.department1 --id.attrs 'hf.Revoker=true,foo=bar' --id.secret 'test123'

然后生成 test 用户的相关私钥和证书

./fabric-ca-client enroll -u http://test:test123@localhost:7054 -M $FABRIC_CA_CLIENT_HOME/testmsp --tls.certfiles "/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"

为了后续使用,我们还要再做一些辅助动作

mkdir /root/ca/testmsp/admincerts
cp /root/ca/testmsp/signcerts/cert.pem /root/ca/testmsp/admincerts/
  • 是原生的用户查询数据

在之前的博客中,作者向读者演示如何查询fabric 中的数据,都是通过docker-compose 启动一个临时的cli 镜像来执行peer 命令,那么按照客户端和服务端的连接关系,peer 命令应该在任何机器上执行都是可行的。

在作者查阅了相关的配置文件和脚本后,整理出以下关键环境变量,主要是设计该客户端在连接 peer 节点时,应该采用哪些证书和私钥进行加密通讯。

以下命令将设置client 连接 peer0.org1.example.com:7051 服务,并且使用 peer0.org1.example.com 节点的私钥和证书。

export CORE_PEER_TLS_ROOTCERT_FILE="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" ; \
export CORE_PEER_LOCALMSPID="Org1MSP" ; \
export CORE_PEER_TLS_ENABLED=true ; \
export CORE_PEER_MSPCONFIGPATH="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" ; \
export CORE_PEER_ADDRESS="peer0.org1.example.com:7051" ;
# CORE_PEER_TLS_KEY_FILE 变量貌似用不上
# export CORE_PEER_TLS_KEY_FILE="/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key" ; \

宿主的peer 可执行程序在 /opt/gopath/src/github.com/hyperledger/fabric/release/linux-amd64/bin 目录,切换到该目录后执行

./peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
  • 使用新创建的test 用户进行测试

如果用户希望使用刚才 fabric-ca-client 命令创建的test 用户,则只需要修改 CORE_PEER_MSPCONFIGPATH 环境变量即可

export CORE_PEER_MSPCONFIGPATH="/root/ca/testmsp" ;

再次使用peer 执行查询命令,查询正常。

./peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

同理,如果需要peer 执行 invoke 命令,则像过去一样执行就ok 了

./peer chaincode invoke -o orderer.example.com:  --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  -C mychannel -n mycc -c '{"Args":["invoke","a","b","20"]}'
  • 权限思考

不知道读者在看到这里时,是否有反思过,fabric 区块链是如何做到读、写权限分开的。

在环境变量设置上,是使用了peer 节点的私钥和证书,此时peer 的命令可以直接从区块链中读取数据。

而在执行 invoke 命令时,则需要加上 --tls 和 --cafile 参数,并且还需要指定 orderer 的私钥。

所以按照作者的理解,fabric 区块链的数据写入,必须要同时拥有 orderer 的私钥和 peer 节点的私钥、证书,而读取,则只要拥有peer 节点的私钥和证书即可。

  • 在chaincode 中获取用户的名字

根据 http://www.cnblogs.com/studyzy/p/7482451.html 博客的介绍,我们可以编写一段测试的chaincode 来获得执行peer 命令的用户名

chaincode 代码

package main

import (
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"fmt"
"encoding/pem"
"crypto/x509"
"bytes"
) type SimpleChaincode struct {
} func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
} func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
fmt.Println("invoke is running " + function)
if function == "cert" {//自定义函数名称
return t.testCertificate(stub, args)//定义调用的函数
}
return shim.Error("Received unknown function invocation")
}
func (t *SimpleChaincode) testCertificate(stub shim.ChaincodeStubInterface, args []string) pb.Response{
creatorByte,_:= stub.GetCreator()
certStart := bytes.IndexAny(creatorByte, "-----")// Devin:I don't know why sometimes -----BEGIN is invalid, so I use -----
if certStart == - {
fmt.Errorf("No certificate found")
}
certText := creatorByte[certStart:]
bl, _ := pem.Decode(certText)
if bl == nil {
fmt.Errorf("Could not decode the PEM structure")
}
fmt.Println(string(certText))
cert, err := x509.ParseCertificate(bl.Bytes)
if err != nil {
fmt.Errorf("ParseCertificate failed")
}
fmt.Println(cert)
uname:=cert.Subject.CommonName
fmt.Println("Name:"+uname)
return shim.Success([]byte("Called testCertificate "+uname))
}

如果使用原生的配置执行

./peer chaincode query -C mychannel -n mycc --logging-level CRITICAL -c '{"Args":["cert"]}'

输出

Query Result: Called testCertificate Admin@org1.example.com

如果使用test 用户执行,则会输出

Query Result: Called testCertificate test

参考博客:

http://www.cnblogs.com/studyzy/p/7482451.html

hyperledger fabric 1.0.5 分布式部署 (七)的更多相关文章

  1. hyperledger fabric 1.0.5 分布式部署 (八)

    gdb debug peer 程序 在开始我们从 github 上download 下来的源码包,实际上已经包含了可执行的 peer 程序,但是该程序是使用 release 方式编译的,并不支持gdb ...

  2. hyperledger fabric 1.0.5 分布式部署 (六)

    如何在相同的peer 节点上创建多个 channel 作者在hyperledger fabric 1.0.5 分布式部署 (五)已经向读者们介绍了一个简单的fabric 的部署流程,那么根据上一篇博客 ...

  3. hyperledger fabric 1.0.5 分布式部署 (五)

    梳理fabric e2e_cli 测试程序的具体步骤 作者在 hyperledger fabric 1.0.5 分布式部署 (一)中给读者们介绍了如何从零开始部署一个测试的 demo 环境,如果细心的 ...

  4. hyperledger fabric 1.0.5 分布式部署 (四)

    chaincode 的开发 作者在hyperledger fabric 1.0.5 分布式部署 (三)中向读者介绍了如何开发fabric 的chaincode,那么实际上chaincode 还有其他的 ...

  5. hyperledger fabric 1.0.5 分布式部署 (二)

    环境:2台 ubuntu 16.04 角色列表 角色 IP地址 宿主端口 docker端口  peer0.org1.example.com  47.93.249.250  7051  7051  pe ...

  6. hyperledger fabric 1.0.5 分布式部署 (三)

    本篇博客主要是向读者介绍 fabric 在部署时的一些细节,还有作者自己学习过程中的心得. 初始化相关密钥的程序,实际上是一个shell脚本,并且结构特别简单 generateArtifacts.sh ...

  7. hyperledger fabric 1.0.5 分布式部署 (一)

    环境是个人虚拟机ubuntu 16.04 64 位版本 前期用户需要先安装好:gcc.g++.git 软件 安装 golang 首先给环境安装一个 go 语言环境,版本最好在1.8 以上 golang ...

  8. hyperledger fabric 1.0.5 分布式部署 (九)

    linux 使用vim.ctags 配置fabric 源码阅读环境 首先需要安装 ctags,作者使用apt-get 来安装的,安装的版本是5.9 apt-get install ctags 5.9 ...

  9. Hyperledger Fabric 1.0 从零开始(十三)——orderer分布式方案

    简述 在搭建HyperLedger Fabric环境的过程中,我们会用到一个configtx.yaml文件(可参考Hyperledger Fabric 1.0 从零开始(八)——Fabric多节点集群 ...

随机推荐

  1. 为编译器的实现者提供一个精确的定义:ANSI C

    编译器的实现 常用C++编译器推荐_w3cschool https://www.w3cschool.cn/cpp/cpp-zxm72ps8.html 常用C++编译器推荐 由 Alma 创建, 最后一 ...

  2. spring boot 使用redis 及redis工具类

    1-添加maven依赖 2-添加redis配置 3-工具类 1-添加maven依赖 实际上是封装了jedis <!-- redis 依赖--> <dependency> < ...

  3. vue定义全局变量和全局方法

    一.全局引入文件 1.先定义共用组件 common.vue <script type="text/javascript"> // 定义一些公共的属性和方法 const ...

  4. HDU2586 How far away? —— 倍增LCA

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Ot ...

  5. Yii的缓存机制之动态缓存

    当整个页面被缓存,但只有小部分区域需要根据不同的条件设置不同的信息.(例如商品的详细页面的缓存中用户名是动态的)这里就需要设置动态缓存. 首先在被缓存的模板中使用renderDynamic进行动态渲染 ...

  6. JavaWeb学习总结(三)response与request

    一.response response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse.在客户端发出每个请求时,服务器 ...

  7. DDD领域驱动之干货 (一)

    说道DDD不得不说传统的架构与DDD的架构区别. 传统的架构不外乎就是三层,而在这三层里面又不断的细分,始终没有达到想要的效果,那么为什么当时还是采用三层. 当然在DDD没有提出的时候三层是大多数人的 ...

  8. [SCOI 2014] 方伯伯的玉米田

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=3594 [算法] 首先有一个结论 : 每次选择的区间右端点一定是n 根据这个结论 , ...

  9. C语言解释器的实现--存储结构(一)

    目录: 1. 内存池 2. 栈 3. Hash表 1.内存池  在一些小的程序里,没什么必要添加内存管理模块在里面.但是对于比较复杂的代码,如果需要很多的内存操作,那么加入自己的内存管理是有必要的.至 ...

  10. salt api

    #!/usr/bin/env python # -*- coding:utf8 -*- # __author__ = '北方姆Q' import requests import json from d ...