This article takes Fabric 1.4.6 as an example to briefly introduce the issue of cryptogen and Fabric CA certificate interoperability. Enabling a test network in the most efficient way is to run in the Fabric first-network
of ./byfn.sh up
(version 2.0.0 use more than test-network
replaced first-network
, similar to the method used here, do not speak). However, when using the script, the cryptogen
tool is used to generate the identity by default , but the number of accounts (certificates) generated by the tool is fixed. Although you can change crypto-config.yaml
the settings in, change the number of additional users to a number greater than 1. But this change happens before the network is started, once the network is started, it cannot be changed. Therefore, we still need a mechanism to dynamically add users, and here it is CA's turn to appear.
To prepare, install the official original Fabric 1.4.6, Fabric Samples 1.4.6 and Fabric CA 1.4.2 according to the official documents Install Samples, Binaries, and Docker Images .
Tips: You can also write your own scripts, use CA directly instead of cryptogen to generate the identity and then start the network (see fabric-samples version 2.0.0 and above), so that there will be no intercommunication issues. But this article is mainly to talk about intercommunication, so we still use Fabric 1.4.6 version.
1. Start the test network and CA
To use the CA issuing identity, you need to start the CA server. You can start it manually with a command, or you can use a byfn.sh
script to start a docker container. We use a script to minimize the work.
Switch to the fabric-samples
following first-network
directory and run the following script:
./byfn.sh down
./byfn.sh up -a
The -a
option here is to start a CA at the same time when starting the network, see byfn.sh
the introduction at the beginning of the script for details.
After the network deployment is completed, there will be a prompt. At this time, let's check the running container:
➜ fabric-samples git:(337f82c) ✗ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
63334fdbdd15 dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 43 minutes ago Up 43 minutes dev-peer0.org2.example.com-mycc-1.0
7e2df103a97c dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 46 minutes ago Up 46 minutes dev-peer0.org1.example.com-mycc-1.0
27c9e9e18e16 dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab "chaincode -peer.add…" 15 hours ago Exited (0) 55 minutes ago dev-peer1.org2.example.com-mycc-1.0
3f4f0dbc9c9e hyperledger/fabric-tools:latest "/bin/bash" 15 hours ago Up 55 minutes cli
fb080f3a877c hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 15 hours ago Up 55 minutes 0.0.0.0:7054->7054/tcp ca_peerOrg1
98be2c8c32b7 hyperledger/fabric-peer:latest "peer node start" 15 hours ago Up 55 minutes 0.0.0.0:7051->7051/tcp peer0.org1.example.com
3f36dbf02ed1 hyperledger/fabric-peer:latest "peer node start" 15 hours ago Up 55 minutes 0.0.0.0:8051->8051/tcp peer1.org1.example.com
789e6006049a hyperledger/fabric-orderer:latest "orderer" 15 hours ago Up 55 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
1a4e27bc675f hyperledger/fabric-peer:latest "peer node start" 15 hours ago Up 55 minutes 0.0.0.0:10051->10051/tcp peer1.org2.example.com
7f4adb26061e hyperledger/fabric-ca:latest "sh -c 'fabric-ca-se…" 15 hours ago Up 55 minutes 7054/tcp, 0.0.0.0:8054->8054/tcp ca_peerOrg2
87c6b79f7292 hyperledger/fabric-peer:latest "peer node start" 15 hours ago Up 55 minutes 0.0.0.0:9051->9051/tcp peer0.org2.example.com
➜ fabric-samples git:(337f82c) ✗
From NAMES
that we can see, we start the CA server container two organizations, ports, respectively 7054
, and 8054
the corresponding org1 and org2. The work of this article is to use the CA of org1 to add a User2.
Let's take a look at the directory structure of the corresponding part after the identity is generated, mainly for User1:
you can see that we have generated an organization administrator Admin and a user User1, now let us generate a user without restarting the network User2.
2. Establish Fabric CA client
For convenience, we will operate in the fabric-samples directory. Run the following command to switch to the fabric-samples
directory and create a working directory:
cd ..
mkdir fabric_ca_test
cd fabric_ca_test
cp ../bin/fabric-ca-client ./
You can see that we fabric-ca-client
copied this Fabric CA client tool to this directory. Because TLS is enabled by default when the script starts the CA, we need the TLS certificate of the CA Server. In first-network
the directory of docker-compose-ca.yaml
you you can see the certificate path:
- FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
. Note that this is a virtual directory, and the real directory is volumes
mapped in:
volumes:
- ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
Here, according to the format of the certificate, it can be seen that the domain name of the CA is: ca.org1.example.com.
An environment variable that needs to be noted here is set to - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/${BYFN_CA1_PRIVATE_KEY}
. It sets the private key of Fabric CA Server to the private key cryptogen
generated by the tool. If the private key is the same, the generated certificates are consistent. This is the prerequisite for the interoperability of certificates generated by different tools.
Run the following command to copy this TLS certificate:
mkdir tls-root-cert
cp ../first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem tls-root-cert/tls-ca-cert.pem
As you can see, we have also renamed the file for convenience.
Now that we have the client and TLS certificate, we can request the CA Server to issue the identity.
3. Issuing CA to guide users
The first step in issuing an identity is to issue a guide user (equivalent to a CA administrator, not an organization administrator). The account password of the guide user is determined when the CA Server is started. See docker-compose-ca.yaml
the startup command in:
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/${BYFN_CA1_PRIVATE_KEY} -b admin:adminpw -d'
For specific CA usage, you can read the official document , which is not explained here. As you can see from the above command, the username admin
and password of the leading user are adminpw
.
Mentioned earlier, CA's domain name: ca.org1.example.com, because we are here not no server-side configuration files, you can not use localhost
, you also need /etc/hosts
to add one 127.0.0.1
to ca.org1.example.com
the resolution.
Run the following command to issue guide users:
export FABRIC_CA_CLIENT_HOME=$PWD
./fabric-ca-client enroll -u https://admin:[email protected]:7054 --tls.certfiles tls-root-cert/tls-ca-cert.pem --csr.hosts localhost --mspdir admin/msp
You will get similar output:
2020/08/22 12:05:43 [INFO] Created a default configuration file at /Users/likai/fabric/fabric-samples/fabric_ca_test/fabric-ca-client-config.yaml
2020/08/22 12:05:43 [INFO] TLS Enabled
2020/08/22 12:05:43 [INFO] generating key: &{
A:ecdsa S:256}
2020/08/22 12:05:43 [INFO] encoded CSR
2020/08/22 12:05:43 [INFO] Stored client certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/signcerts/cert.pem
2020/08/22 12:05:43 [INFO] Stored root CA certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/cacerts/ca-org1-example-com-7054.pem
2020/08/22 12:05:43 [INFO] Stored Issuer public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/IssuerPublicKey
2020/08/22 12:05:43 [INFO] Stored Issuer revocation public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/admin/msp/IssuerRevocationPublicKey
Indicates that the guide user is successfully issued, and the relevant information is located in the admin/msp
directory.
Four, use guide users to register and issue User2
1. Registration
You must register before issuing an identity. Run the following command to register:
./fabric-ca-client register --id.name User2 --id.secret User2pw --tls.certfiles tls-root-cert/tls-ca-cert.pem --mspdir admin/msp/
There will be output similar to the following:
2020/08/22 12:09:39 [INFO] Configuration file location: /Users/likai/fabric/fabric-samples/fabric_ca_test/fabric-ca-client-config.yaml
2020/08/22 12:09:39 [INFO] TLS Enabled
2020/08/22 12:09:39 [INFO] TLS Enabled
Password: User2pw
2. Issue
Use the username and password just registered to issue the identity:
./fabric-ca-client enroll -u https://User2:[email protected]:7054 --tls.certfiles tls-root-cert/tls-ca-cert.pem --csr.hosts localhost --mspdir users/User2/msp
There will be output similar to the following:
2020/08/22 12:13:13 [INFO] TLS Enabled
2020/08/22 12:13:13 [INFO] generating key: &{
A:ecdsa S:256}
2020/08/22 12:13:13 [INFO] encoded CSR
2020/08/22 12:13:13 [INFO] Stored client certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/signcerts/cert.pem
2020/08/22 12:13:13 [INFO] Stored root CA certificate at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/cacerts/ca-org1-example-com-7054.pem
2020/08/22 12:13:13 [INFO] Stored Issuer public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/IssuerPublicKey
2020/08/22 12:13:13 [INFO] Stored Issuer revocation public key at /Users/likai/fabric/fabric-samples/fabric_ca_test/users/User2/msp/IssuerRevocationPublicKey
We can use the tree
command to view the directory structure just generated:
tree users/User2/
The resulting structure is as follows:
users/User2/
└── msp
├── IssuerPublicKey
├── IssuerRevocationPublicKey
├── cacerts
│ └── ca-org1-example-com-7054.pem
├── keystore
│ └── 6f097b265f17e3bcab411a9ea3e328c62e851f9948ad4af7298d4e57535cb471_sk
├── signcerts
│ └── cert.pem
└── user
5 directories, 5 files
Our User2 has been generated. At this time, you can compare the directory structure of User1 in vscode and find that there are still some differences. Our next step is to copy the newly issued User2 certificate and key to first-network
the corresponding directory structure in.
Five, add User2 tofirst-network
Run the following command to copy the directory structure of User1 to User2:
cd ../first-network/crypto-config/peerOrganizations/org1.example.com/users/
mkdir [email protected]
cd [email protected]
cp -r ../[email protected]/tls ./
cp -r ../[email protected]/msp ./
rm -f msp/keystore/*
Choose y here, delete User1's key, and then run:
rm -f msp/signcerts/*
Also select y to delete User1's certificate.
We copy User2's key and certificate:
cp ../../../../../../fabric_ca_test/users/User2/msp/keystore/* msp/keystore/
cp ../../../../../../fabric_ca_test/users/User2/msp/signcerts/cert.pem msp/signcerts/[email protected]
Finally, we copy the CA root certificate of User2 (can be omitted)
cp ../../../../../../fabric_ca_test/users/User2/msp/cacerts/ca-org1-example-com-7054.pem msp/cacerts/ca.org1.example.com-cert.pem
Why can it be omitted here, because the target file already exists, it is copied from User1. Because we have two ways cryptogen
and Fabric CA
use the same private key, so the trusted root certificate must be the same, otherwise there is no way to communicate. Interested readers can check whether the contents of the last copied source file and target file are exactly the same. If they are inconsistent, it will indicate what went wrong.
At this point, our new user User2
has successfully released.
Here is a pit that the author encountered, that is, when registering User2, do not specify --id.type
it, client
just let it default to .
Six, test
The test is a little more complicated here and involves the application of fabric-sdk-go. But here is an article for reference: Use fabric-sdk-go to manipulate chain codes . You can Admin
replace the places used in the source code (not in the configuration file) with User1
and User2
test. Here the author wrote a simple test file main.go
, but the go mod init
reader needs to get the configuration file by himself.
package main
import (
"fmt"
"log"
"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)
const (
org1CfgPath = "./config.yaml"
ChannelID = "mychannel"
peer0Org1 = "peer0.org1.example.com"
peer0Org2 = "peer0.org2.example.com"
)
func main() {
sdk, err := fabsdk.New(config.FromFile(org1CfgPath))
if err != nil {
log.Panicf("failed to create fabric sdk: %s", err)
}
ccp := sdk.ChannelContext(ChannelID, fabsdk.WithUser("User2"))
cc, err := channel.New(ccp)
if err != nil {
log.Panicf("failed to create channel client: %s", err)
}
fmt.Println("channel init over")
query(cc)
// execute(cc)
// time.Sleep(5 * time.Second)
// query(cc)
}
func query(cc *channel.Client) {
// new channel request for query
req := channel.Request{
ChaincodeID: "mycc",
Fcn: "query",
Args: packArgs([]string{
"a"}),
}
// send request and handle response
reqPeers := channel.WithTargetEndpoints(peer0Org1)
response, err := cc.Query(req, reqPeers)
if err != nil {
fmt.Printf("failed to query chaincode: %s\n", err)
}
if len(response.Payload) > 0 {
fmt.Printf("chaincode query success,the value is %s\n", string(response.Payload))
}
}
func execute(cc *channel.Client) {
args := packArgs([]string{
"a", "b", "10"})
req := channel.Request{
ChaincodeID: "mycc",
Fcn: "invoke",
Args: args,
}
peers := []string{
peer0Org1, peer0Org2}
reqPeers := channel.WithTargetEndpoints(peers...)
response, err := cc.Execute(req, reqPeers)
if err != nil {
fmt.Printf("failed to Execute chaincode: %s\n", err)
}
fmt.Printf("Execute chaincode success,txId:%s\n", response.TransactionID)
}
func packArgs(paras []string) [][]byte {
var args [][]byte
for _, k := range paras {
args = append(args, []byte(k))
}
return args
}
We can replace ccp := sdk.ChannelContext(ChannelID, fabsdk.WithUser("User2"))
the "User2" in the middle with "User1" or "Admin", and it will work.
run:
go run main.go
Will get results similar to the following
channel init over
chaincode query success,the value is 90
The commented out code is used to execute the chain code, and interested readers can uncomment it and test it.
Well, the test is complete, and the newly generated users using CA can be used directly without changing the network.
Welcome everyone to point out the problems in the article or leave a message for discussion.