A Companion Guide to Fabric CA Operation Guide

Introduction

As a permissioned blockchain platform, Hyperledger Fabric requires all entities, whether it is a network component or a user (client) using the platform, to be identified. This identification is implemented through digital certificates, and an infrastructure for certificate issuance and management is needed.

While one can use third-party to bring up this infrastructure, Fabric CA provides a handy way, and it generates the appropriate format required in Hyperledger Fabric system.

There is a good tutorial in readthedoc, Fabric CA Operation Guide. It creates a typical setup and provides very detailed step-by-step with explanation. I keep hearing from readers saying that there are some challenges when following this guide. As a result, I came up with this companion guide, and rearrange things into clearer steps with illustration. During the lab we make certain observations at various points to get a bigger picture. Meanwhile I also fix some naming inconsistency and update the configuration files in order to work better. Hope this is helpful when you are working on this tutorial.

Tutorial Overview

The whole setup is summarized in this.

  • Three organizations, org0 is the orderer organization, org1 and org2 are the peer organizations
  • org0 comes with one orderer (orderer1-org0) serving ordering service in Solo
  • In each peer organizations (org1 and org2) there are two peers (peer1-orgx, peer2-orgx)
  • There is an admin user (admin-orgx) for each organization

For our reference, here is the overall picture. We will explain the last column immediately in the next part.

Image for post
Image for post
Summary of organizations
Image for post
Image for post
Entities to be enrolled in this tutorial network

If we see the setup from CA perspective, there are four CAs in this tutorial

  • TLS-CA: the CA issuing TLS server certificates for network components (orderer and peers) for the whole network for. This certification is for TLS communication only, and note related to identity in this fabric network.
  • RCA-ORGx (x=0, 1, 2): It is the Root CA for identities in each organization. On one side it issues the required certificates to the components and users. On the other side it represents the organization (in MSP way) when forming a fabric network.

The last column is for quick reference. We will see these directories later in the tutorial.

Image for post
Image for post
Summary of CAs used in this tutorial
Image for post
Image for post

Once the certificate issuance is complete and fabric network setup is done, these CAs are not required in daily operation. They are not participating in joining channels, deploying chaincode, invoking chaincode functions, etc. They are needed only when new components (add one more orderer or one more peer) or new users (add more client applications) are joining the setup and new certificates are generated.

Here is the overall flow of this tutorial (Note: this just shows a sequence of tasks, and the steps shown here are not the steps shown in the tutorial.)

  1. Bring up four CAs, each of which as a Fabric-CA-Server running in a container.
  2. Use Fabric-CA-Client in localhost to interact with these CAs. For each CA, enrol a registrar, and start entity registration of all organizations according to our tutorial design..
  3. For each organization, use Fabric-CA-Client to enroll entities registered in 2. Now we have all crypto material required.
  4. Place the resulting crypto material in appropriate directories, which will be mapped in those components (orderer and peer) defined in docker-compose file.
  5. Prepare the MSP directory for each organization, which is needed when creating fabric networks.
  6. Bring up the five containers (one orderer, four peers) and two CLI containers.
  7. Create channel and join peers to channel
  8. Deploy chaincode and observe the attribute-based access control (ABAC) feature in chaincode.

There are two configuration files: a docker-compose file (docker-compose.yaml) and a channel artifacts file (configtx.yaml).

The docker-compose.yaml is modified and updated to reflect the change. The original file is here.

Here is the configuration for generating channel artifacts (configtx.yaml). The original file is here. No change in the file except fixing the indent.

We create /tmp/hyperledger to keep all the material generated during the whole tutorial. We are using Fabric-CA-Client in localhost to perform all the certificate generation. The result is all kept inside the subdirectories of /tmp/hyperledger. We will see four subdirectories tls-ca, org0, org1, org2 over the course, and take a look at what is inside the directories during the tutorial.

Meanwhile the directories are being used for two purposes.

Mapped to network components

If we take a look on network components (orderers or peers), we will see the volume mapping. Take peer1-org1 as an example.

Image for post
Image for post
extract from docker-compose.yaml, showing peer1-org1

From volumes we see the whole directory /tmp/hyperledger/org1/peer1 of localhost will be seen in /tmp/hyperledger/org1/peer1 of peer1-org1 container, and those materials inside this directory will be used as identity (MSP) and TLS related material. Similar can be seen in other network components.

Configuration forming the consortium network

In our setup, these three organizations are forming a consortium network. They are represented by their membership service provider (MSP). We take a look at the configuration file (extracted).

Image for post
Image for post
extract from configtx.yaml, showing the MSP of all organizations in the fabric network

As a result, after we complete the enrollment, we will put up correct certificates to form these directories /tmp/hyperledger/orgx/msp. There are specific requirements in structure and we will see them in the tutorial.

Understand Fabric-CA-Server

As the tutorial involves a lot of Fabric CA Server, let’s first take a look how things are working inside.

Here we pick RCA-ORG1 as an example. The docker compose file for RCA-ORG1 is like this.

Image for post
Image for post
extract from docker-compose.yaml, showing rca-org1

According to this setup, we learn

  • The home for this Fabric-CA-Server is mapped to /tmp/hyperledger/org1/ca/crypto of the localhost. During the tutorial we seldom go into the containers. Instead we can inspect and refer material from the localhost.
  • The CA is defined with bootstrap credential. In this CA it is rca-org1-admin:rca-org1-adminpw. This is being used when we use a Fabric-CA-Client to enrol an admin (registrar).
  • TLS is enabled. With this, after the CA is up and running, it will issue a TLS server certificate. It is only used for accessing this RCA-ORG1, and not part of TLS of network components. And do not mix this with the TLS-CA as TLS-CA is for TLS server certificates of network components of organizations.

Now we just bring up this container and make an observation.

Bring up the RCA-ORG1 container.

Image for post
Image for post

Here is an illustration of RCA-ORG1, with those components of our interests.

Image for post
Image for post
Zoom in a typical CA running as a Fabric-CA-Server

Observe directory structure (localhost). We see a directory /tmp/hyperledger/org1/ca/crypto in my localhost, which is the server home for Fabric-CA-Server of RCA-ORG1.

Image for post
Image for post
Server home directory of RCA-ORG1 (Fabric-CA-Server)

For our interest, we first locate the two certificates in this directory (ca-cert.pem and tls-cert.pem). We take a look at the subject and issuer of each certificate.

Image for post
Image for post

The certificate ca-cert.pem is the identity Root CA certificate for org1 (the top one in our diagram). It is the self-signed certificate (issuer =subject). All certificates issued and signed by Root CA (by RCA’s private key) can be verified by this certificate.

Another certificate tls-cert.pem is issued by the RCA (see the issuer). This is the bottom one in our diagram. This is a TLS server certificate only for TLS communication to this RCA. Concretely, when a client accesses the RCA-ORG1, RCA-ORG1 will present this server certificate to the client. The client will use the issuer (that is, the Root CA certificate) to verify this server certificate, and confirm the client is talking to the right server (RCA-ORG1), and the communication between the client and RCA-ORG1 is encrypted.

We can also locate the private keys (secret keys) corresponding to these two certificates. They are stored in msp/keystore.

Image for post
Image for post

We see two here. By a quick check we know which corresponds to which (the method is to deduce the public key from the private key, and compare it with the public key in certificates).

This private key (647e…) is for ca-cert.pem

Image for post
Image for post
Matching the private key and the certificate (resulting same public key)

And this private key (526e…) is for tls-cert.pem

Image for post
Image for post
Matching the private key and the certificate (resulting same public key)

Finally, we also see a database (sqlite3). This database keeps tracking all upcoming entity registration and enrollment. Note that the bootstrap ID and secret is also placed in the database, as a registered entity. We will take a look at the flow in the tutorial.

Tutorial Detail

As you have seen in the readthedoc, the whole process involves a lot of commands. In this guide we will break them and then group them into a sequence of shell scripts. Some rearrangement is made in order to make the flow logical. We will make some observations and highlights.

It is just my practice to put it under fabric-samples/. It can be anywhere. Just make sure you have PATH including the fabric-samples/bin/ directory

Copy the two configuration files: docker-compose.yaml and configtx.yaml. Over the tutorial, just place the script file in guide/ and execute it.

In case any time we wish to reset everything and begin from Step 1, we can reset the network through

Then you can begin with Step 1 again.

Script: 1_ca-tls.sh

We will walk through the whole script.

  • First we bring up the TLS-CA container. After the TLS-CA container is up and running, several things happen
  • The TLS-CA home directory is mapped to /tmp/hyperledger/tls-ca/crypto/ of localhost. We can refer to this directory if we are referring any material in the TLS-CA home directory.
  • We are using Fabric-CA-Client (client) in localhost. Two parameters are set for the client.
  • We extract the TLS-CA Root Certificate (tls-cert.pem) and keep it in FABRIC_CA_CLIENT_TLS_CERTFILES. This name is a bit unclear. It is the CA certificate to verify the TLS server certificate from TLS-CA (see above Understand Fabric-CA-Server session about TLS).
  • The home directory is set to /tmp-hyperledger/tls-ca/admin. The crypto material will be kept in this directory.
  • There is a bootstrap ID name (tls-ca-admin) and secret (tls-ca-adminpw) configured in the docker-compose file on TLS-CA (line 10 in docker-compose.yaml). This is an entity registered in the TLS-CA database.
  • We now use Fabric-CA-Client to enroll a registrar on TLS-CA (https://0.0.0.0:7052), with this bootstrap ID name and secret. The result is kept in the home directory, /tmp-hyperledger/tls-ca/admin. This is the identity for a registrar.
  • With this identity, we use Fabric-CA-Client to register the five network components in the network. Each register is done with an ID name, secret (provided in this tutorial, but can be generated by CA) and type.
  • The result is that the TLS-CA database now keeps these five entities information. They are used in later steps when these entities enrol to TLS-CA.

The last line in the script is just for showing the entities registered in TLS-CA database, including the bootstrap tls-ca-admin, and those five components registered in this script.

Image for post
Image for post
Entities registered in the TLS-CA database.

Here is the result after the script is executed.

Image for post
Image for post

We can also take a look at the directory in the localhost. A quick recap

  • tls-ca/crypto/: Directory for Fabric-CA-Server Home of TLS-CA, mapped to localhost.
  • tls-ca/admin/: It is where Fabric-CA-Client stores registrar for TLS-CA in localhost
Image for post
Image for post

Script: 2_rca-org0.sh

The pattern is the same as the TLS-CA in Step 1. Without repeating everything, here we only register two entities: orderer1-org0 and admin-org0. Here is the result of the last command.

Image for post
Image for post
Entities registered in the RCA-ORG0 database.

When we examine the directory, we see org0/ca/. This is similar to what we observe in TLS-CA. Again, the crypto/ is a mapping of Fabric-CA-Server Home directory, and the admin/ is registrar for RCA-ORG0.

Image for post
Image for post

Script 3_rca_org1.sh

Script 4_rca_org2.sh

The result directories are org1/ca/ and org2/ca/, respectively.

Image for post
Image for post

There is a point of difference. When we register admin-org2 in RCA-ORG2, we put an attribute abac.init=true. This will be placed in the certificate when this admin-org2 enrols in the RCA-ORG2. We will examine this when enrollment is made. Meanwhile, admin-org1 does not have this attribute.

The use of this attribute is to link to the demonstration of chaincode. After the network is running, we will deploy chaincode/abac/go. The deployment requires the deployer with this attribute abac.init=true. In Step 11, we will deploy chaincode from both admin-org1 and admin-org2, and we can see that only admin-org2 can deploy but admin-org1 cannot, due to this missing attribute.

Here are the entities registered in each CA database after the four scripts. Note that enrollment is not done yet. In the next steps we enrol those entities in organizations, one by one.

Image for post
Image for post
All entities are registered in the required CAs after the four scripts.

Script 5_enrollOrg0.sh

The purpose of this script is to enrol entities for org0. There are two entities to be enrolled: orderer1-org0 and admin-org0.

We will walk through this script.

  • All the material for org0 will be built under /tmp/hyperledger/org0/.
  • The network component orderer1-org0 will be stored in orderer/, the user admin-org0 in admin/.
  • First we prepare two directories: orderer/assets/ca/ and orderer/assets/tls-ca/, they are holding the CA certificate of RCA-ORG0 and TLS-CA, respectively. We copy the certificates from those mapped volumes of these CA.
  • These two CA certificates are required when accessing RCA-ORG0 and TLS-CA with TLS. and are specified in FABRIC_CA_CLIENT_TLS_CERTFILES during the enrollment.

We start enrolling orderer1-org0, both identity and TLS, and admin-org0 for identity only.

For orderer1-org0,

  • We specify the org0/orderer/ as the Fabric-CA-Client home directory, meaning that the result will be stored in this directory.
  • Identity for orderer1-org0, we specify msp/ to hold the result, and enrol it in RCA-ORG0.
  • TLS for orderer1-org0, we specify tls-msp/ to hold the result, and enrol it in TLS-CA.

For admin-org0,

  • We specify the org0/admin/ as the Fabric-CA-Client home directory, meaning that the result will be stored in this directory.
  • Identity for admin-org0, we specify msp/ to hold the result, and enrol it in RCA-ORG0.

Finally we will create a directory org0/msp/, which includes the following directories and contents. It is used when the fabric network configuration is being built.

  • admincerts/
  • cacerts/
  • tlscacerts/
  • users/

We copy those certificates, and rename when necessary.

After the script is fully executed, we will see some directories in /tmp/hyperledger/org0/.

Image for post
Image for post

For our interests, we will inspect first the org0/orderer/. We see two directories: msp/ and tls-msp/, inside which are the crypto material for orderer1-org0.

Image for post
Image for post

In msp/ it is the identity. The private key is kept in keystore/ and the certificate is in signcert/.

Image for post
Image for post

We first do a matching and make sure the private key matches the public key in the certificate.

Image for post
Image for post

Then we take a look at the certificate, in particular we are interested in the subject and the issuer.

Image for post
Image for post

We see the issuer of this identity certificate is RCA-ORG0, and the subject (owner) of certificate is orderer1-org0, with OU=orderer, which is what we specify in “type” during registration (see Step 2).

Similar directory structure is seen in tls-msp/. Without repeating all steps above, we will take a look at the TLS server certificate, inside tls-msp/signcert/

Image for post
Image for post

We see the issuer of this TLS server certificate is TLS-CA.

Enrollment for orderer1-org0

Image for post
Image for post
Enrollment for orderer1-org0, both identity and TLS server certificate

Certificates issued to orderer1.org0.

Image for post
Image for post
Both RCA-ORG0 and TLS-CA issue certificates for orderer1-org0.

Finally, we take a look at the admin-org0, which is stored in org0/admin/. We see a similar directory structure, and the identity is stored in msp/. From the certificate we can see that it is RCA-ORG0 issuing this certificate.

Image for post
Image for post

Enrollment for admin-org0

Image for post
Image for post
Enrollment for admin-org0, only on identity.

Certificate issued to admin-org0

Image for post
Image for post
RCA-ORG0 issues identity certificate for admin-org0.

Now we have everything for org0.

Finally we have prepared org0/msp/ which is useful when we form the fabric network.

Image for post
Image for post

Script 6_enrollOrg1.sh

The overall flow is largely similar to org0 (Step 5). The only difference is that in org1 we have two peers, peer1-org1 and peer2-org1. The same process is repeated for each peer. We only enrol one admin for org1.

Here is the directory structure of org1 after the script is completely executed.

Image for post
Image for post

We now have peer1/ and peer2/ for the peers, and admin/ for the admin of org1.

Again, without repeating what has been introduced in org0 (Step 5), here we just inspect the certificate of each component and user.

Identity certificate for peer1-org1, peer2-org1 and admin-org1. We see all certificates are issued by RCA-ORG1.

Image for post
Image for post
All identity certificates are issued by RCA-ORG1 for org1.

TLS server certificate for peer1-org1 and peer2-org1. We see all certificates are issued by TLS-CA.

Image for post
Image for post
All TLS certificates are issued by TLS-CA.

Besides, per msp requirement, for peer1/msp/, peer2/msp/ and admin/msp/ we need a admincerts/ directory holding the admin certificate for this organization (see line 62–69 in this script).

Script 7_enrollOrg2.sh

We can see this script is largely the same as the script for org1, except that everything is now applied on org2.

We just repeat the last inspection on the certificates of the two peers peer1-org2 and peer2-org2, and the user admin-org2.

Identity certificate for peer1-org2, peer2-org2 and admin-org2. We see all certificates are issued by RCA-ORG2.

Image for post
Image for post
All identity certificates are issued by RCA-ORG2 for org2.

TLS server certificate for peer1-org2 and peer2-org2. We see all certificates are issued by TLS-CA.

Image for post
Image for post
All TLS certificates are issued by TLS-CA.

In particular, we have admin-org2 with attribute abac.init:true (see Step 4). Here we can see the attributes in the certificate.

Image for post
Image for post

Now we have all identity certificates and TLS server certificates generated for our network. We can now move to the fabric network part, and we will not interact with these CAs unless we need to add more network components (orderers or peers) and/or users.

Here is how the network looks like after all the required crypto material is generated.

Image for post
Image for post
Entities in all organizations obtain the identity certificate, and network components also obtain TLS server certificates.

Script 8_bringUpContainers.sh

Our objective is to bring up all the components, including orderer1-org0, peer1-org1, peer2-org1, peer1-org2 and peer2-org2. Also we have two CLIs, one for a peer organization, for our actions later.

Meanwhile, orderer1-org0 requires the genesis block file (genesis.block) according to the docker-compose.yaml. Therefore we use configtxgen to generate this locally (line 4), and the result is placed in org0/ directory, which is mapped to orderer1-org0. We also generate the channel configuration transaction channel.tx, and also kept in org0/ directory (line 6).

When things are working fine, we will see all these containers up and running.

Image for post
Image for post

From now on we have finished the component level. The remaining part is purely the operation of Hyperledger Fabric. And we do not work with the CAs any more.

We follow the standard way to create and join channels.

First we bring up two CLI: cli-org1 and cli-org2. In these two CLIs, the environment variables are set for org1 and org2. The default target peer is peer1-org1 and peer1-org2, respectively. In case peer2 is needed in the two CLIs, we only set the variable.

For org1 terminal,

For org2 terminal,

First, we need to copy the channel configuration transaction (channel.tx). It is currently in org0/orderer/ directory (see Step 8). Copy it to org1/peer1/assets/. Note that in real life it may be handled out-of-band, but for our tutorial we just copy between mapped volumes between org0/ and org1/.

In localhost,

Use org1 terminal to create channel genesis block

In org1 terminal

Image for post
Image for post

The result is the block file mychannel.block kept in org1/peer1/assets/.

Use org1 terminal to join peer1-org1 and peer2-org1. Note that we temporarily set the variable in order to target the peer command to peer2-org1.

Image for post
Image for post
peer1-org1 and peer2-org1 joined mychannel

We need to copy this mychannel.block to cli-org2. Again we are using the mapped volumes.

In localhost,

Similarly, use org2 terminal to join peer1-org2 and peer2-org2.

In org2 terminal,

Image for post
Image for post
peer1-org2 and peer2-org2 joined mychannel

To check if all the peers have successfully joined the channel, we can check

In org1 terminal,

Image for post
Image for post

In org2 terminal,

Image for post
Image for post

We should get back the same result of the four commands above, meaning that all the peers have the same ledger (blockchain).

With that, all the peers have joined the channel, and we can start working on the chaincode.

We install the chaincode/abac/go to the peers. The chaincode directory is mapped to cli-org1 and cli-org2 in docker-compose file.

In org1 terminal,

Image for post
Image for post

In org2 terminal,

Image for post
Image for post

With chaincode installed in all the peers, we now instantiate chaincode.

Before we instantiate chaincode, we first take a look at the Attribute-Based Access Control (ABAC) in the chaincode/abac/go/abac.go. In the Init() part,

Image for post
Image for post
Init() part of chaincode/abac/go/abac.go

In line 42, the chaincode will extract the client (proposal sender) certificate, and see if attribute abac.init:true is in the certificate. If not, error is returned.

We first instantiate from org1. Remember that admin-org1 does not have the attribute abac.init:true.

In org1 terminal,

Image for post
Image for post
Error when we instantiate chaincode with admin-org1

This error message shows that the instantiation fails due to the missing attribute.

Now we instantiate from org2. Remember that admin-org2 has this attribute (see Step 7)

In org2 terminal,

We see no error, and the instantiation is complete. We will interact with the chaincode functions in the final step of this tutorial.

We first query the current value of a, which should be 100 according to chaincode design and arguments set when chaincode is instantiated.

In org1 terminal,

Image for post
Image for post

In org2 terminal,

Image for post
Image for post

Now invoke chaincode function in org1 terminal

Note: invoking chaincode can also be done on org2 terminal. Just change the TLS certificate with the right path (i.e. org2 instead of org1).

Image for post
Image for post

After chaincode function invoked, we query the value of a again in all the peers. All should be updated to 90.

In org1 terminal,

Image for post
Image for post

In org2 terminal,

Image for post
Image for post

We get back the correct result. The network is running properly.

This is the end of the tutorial.

Summary

We have built a typical fabric network, with all crypto material generated by Fabric CA Server. By carefully design and proper process, we have all entities acquiring identity certificates from CA of each organization, while all network components acquiring TLS server certificates from a single TLS CA for all organizations in this network. We also use a chaincode with intelligence in checking identity to show how to control access based on the attributes inside a certificate.

This is a heavy article, matching the original lengthy operation guide. By breaking them into steps, I hope you now have a clearer picture about how to use Fabric CA to build your own network design.

Written by

Happy to share what I learn on blockchain. Visit http://www.ledgertech.biz/kcarticles.html for my works. or reach me on https://www.linkedin.com/in/ktam1/.

Get the Medium app