Identity in Hyperledger Fabric (Part 1)

Overview

Identity is an important feature of permissioned blockchain platform. In Hyperledger Fabric, each component needs to be identified before accessing the fabric network. The identity is represented by an X.509 digital certificate. When interacting with a fabric network, the actor specifies and presents the digital certificate, and the fabric network accepts or denies based on the policy.

There is a good description about identity in Hyperledger Fabric. Here is the link.

In a typical case, user is given a digital certificate with proper information associated to that user. As far as this digital certificate is issued by a Certificate Authority trusted by the fabric network, the user’s operation will be accepted and processed by the fabric network.

The digital certificate can be created when crypto material is generated with cryptogen tool, or more commonly, generated through registration and enrollment on a Certificate Authority.

In this article, we first run the Basic Network and deploy the Simple Asset Chaincode on it. By inspecting down into the container setup and chaincode operation, we will see how identity is presented during chaincode invocation. Finally we introduce client identity chaincode library to capture the user’s identity and perform access control based on the subject.

It is not a complete guide for identity and membership service provider (MSP). Nevertheless we can understand the identity more through a deployment in Hyperledger Fabric platform.

Setup: Simple Asset Chaincode on Basic Network

We begin with the most simple chaincode and fabric network. Here we are using Simple Asset Chaincode and Basic Network.

It is the simplest setup good for quick demonstration. We can start the basic network by simply running the script ./start.sh.

cd fabric-samples/basic-network
./start.sh

After the script completes, we see a fabric network with an Orderer, a Peer and a Certificate Authority (CA) for Org1, and a CouchDB as the world state database for the Peer node.

Image for post
Image for post
Four containers up and running after start.sh script

Beside the infrastructure, a channel mychannel is also created and the peer node is already joint to mychannel.

Image for post
Image for post
This peer has already joint mychannel

The Simple Asset Chaincode (SACC) also comes in fabric-samples. It provides the very basic functions of storing an asset in the ledger. The asset is represented by a key-value pair. When chaincode is first instantiated in a channel, an initial key-value is required. Later the chaincode can be invoked with “get/set” command, to get the value of a key or set a new key-value or a new value to an existing key. You can refer to the SACC here.

Note that the chaincode itself does not contain any fabric network and channel information. We need to deploy the chaincode onto our Basic Network and mychannel.

We are using CLI to facilitate the chaincode installation and instantiation.

docker-compose -f docker-compose.yml up -d clidocker exec cli peer chaincode install -n sacc -v 0 -p github.com/saccdocker exec cli peer chaincode instantiate -n sacc -v 0 -C mychannel -c '{"Args":["a", "100"]}'
Image for post
Image for post

Now we can check the value of “a” in the ledger.

docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'
Image for post
Image for post

We can set another value and get the result again. The SACC works well in our Basic Network as expected.

docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["set", "a", "500"]}'docker exec cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'
Image for post
Image for post

Things are working well. Now we shift our focus on the identity portion.

Observing Identity in Fabric Network

As mentioned above, as a permissioned blockchain platform, we expect that every transaction in a fabric network is initiated by an identified user. If we revisit what we have been done, it seems we never touch on any identity: we only issue command peer chaincode from CLI.

In fact CLI plays the role to provide the identity information to the fabric network when issuing commands.

Let’s take a look on the environment variable setup in CLI container.

docker exec cli env
Image for post
Image for post
CORE_PEER_MSPCONFIGPATH specifies the identity

We see CORE_PEER_MSPCONFIGPATH is set, pointing to Admin@org1.example.com/msp. This is the identity we use when initiating any transactions to the fabric network using CLI.

We can do a test by setting this variable to nothing. The chaincode invoke fails with access denied.

docker exec -e "CORE_PEER_MSPCONFIGPATH=" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'
Image for post
Image for post
Access denied when no identity is specified

Beside Admin, it also comes with another identity: User1@org1.example.com. We can see the users defined inside Org1.

docker exec cli ls crypto/peerOrganizations/org1.example.com/users
Image for post
Image for post

If we invoke chaincode with this identity (override this variable), we also get the result.

docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["set", "a", "300"]}'docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'
Image for post
Image for post
Chaincode invoke can be done by User1.

So far, we understand that chaincode invocation (and all chaincode operation) requires identity. Inside CLI it is done through environment variable. But where are these identities coming from? We move further and take a look on the configuration file.

The CLI container is instantiated from docker-compose file. Here is the part of docker-compose file about CLI.

cli:
container_name: cli
image: hyperledger/fabric-tools
tty: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- FABRIC_LOGGING_SPEC=info
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
- CORE_CHAINCODE_KEEPALIVE=10
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./../chaincode/:/opt/gopath/src/github.com/
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
networks:
- basic

Here we see

  • The environment variable CORE_PEER_MSPCONFIGPATH is set here. Once the CLI container is running we already have this default identity.
  • The identity information is kept in /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto directory inside the container, which is a volume mapped from ./crypto-config on our localhost.

Therefore we will take a look on the ./crypto-config in our localhost.

Here is our directory structure of ./crypto-config in our localhost.

Image for post
Image for post

We see both Admin and User1 defined inside org1.example.com/users. These are the identities used in chaincode invoke inside CLI.

Inside msp, we see keystore and signcerts directory. Keystore keeps the the signing key (private key) and signcerts keeps the certificate containing the public key associated to the private key.

Here is a truncated capture of Admin’s certificate. We see the Subject (CN=Admin@org1.example.com) and the Issuer (CN=ca.org1.example.com) information.

Image for post
Image for post
Admin’s X509 Certificate

Here is the one for User1’s certificate. We see the same Issuer (CN=ca.org1.example.com).

Image for post
Image for post
User1’s X509 Certificate

Fabric network accepts both certificates as they are both issued by the same Issuer, which the fabric network trusts.

Finally we also see the Issuer’s certificate. It is the CA for Org1.

Image for post
Image for post
CA’s certificate: a self-signed certificate

This is a self-signed certificate (Issuer = Subject). It is common for demonstration purpose. In real life, it usually comes from the enterprise certfiicate authority or some trusted third parties.

Our last question is: where did these certificates come from? As introduced earlier, digital certificates can be obtained through cryptogen tool and enrollment from a Certificate Authority. In Basic Network this crypto-config directory is prepopulated. The whole directory structure is built using bin/cryptogen with configuration file crypto-config.yaml. Although there is a CA running in Basic Network, we do not need to access CA. The additional User1 certificate is good enough for demonstration.

Here is the configuration file crypto-config.yaml (all comments removed)

OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
Template:
Count: 1
Users:
Count: 1

In this configuration file The Users Count 1 means that in addition to Admin, a new user identity (denoted as User1) is generated. That is the reason we see Admin and User1 in Org1.

Again, this crypto material is created through cryptogen tool. It may be good enough if the required amount of user identity are known and static. If we need more user certificates after running the cryptogen, or if we need customize some attributes, we can use the CA deployed for Org1. It will be covered in next article.

We almost discover anything related to identity when we interact with the fabric network from a user perspective. We now see how to apply access control based on the certificate subject.

Access Control in Chaincode

The way to enforce access control at chaincode level is through a library provided by Hyperledger Fabric: Client Identity Chaincode Library (link).

Once imported, this library provides methods to obtain information of the chaincode invoker, such as ID, MSPID and X509. Besides basic information inside X509, the library also provides a way to read attributes which are built in the X509 digital certificate when it is generated.

For demonstration purpose, I am creating a new chaincode called sacc-ac (SACC Access Control). This code is copied from another chaincode chaincode/abac. I leverage all the required packages already installed in abac. To keep consistency and simplicity, I use the SACC to override the original abac.go (abac.go uses chaincode_example02).

cd fabric-samples/chaincode
cp -r abac/ sacc-ac/
cp sacc/sacc.go sacc-ac/go/sacc-ac.go
cd sacc-ac/go
rm abac.go

For demonstration I modify the function set() such that only Admin can set a new value, while others (such as User1) cannot.

Here is the modified SACC (sacc-ac.go). Only the modification part is shown.

import portion

import ("fmt""github.com/hyperledger/fabric/core/chaincode/shim/ext/cid"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)

set() portion

func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {

// only Admin can set value
x509, _ := cid.GetX509Certificate(stub)
if x509.Subject.CommonName != "
Admin@org1.example.com" {
return "", fmt.Errorf("Only Admin can set new value.")
}
...
original code
...
}

The two updates done on the original sacc.go chaincode.

The cid library is imported. Note that the library is already included inside vendor directory.

Inside set() we use cid.GetX509Certificate() method to extract the x509 certificate, and inside x509 we extract the Subject.CommonName (CN). We enforce access control by checking If the CN is Admin or not, and non Admin user will be returned with error message.

As before, we install and instantiate the chaincode. Our chaincode is now called sacc-ac.

docker exec cli peer chaincode install -n sacc-ac -v 0 -p github.com/sacc-ac/godocker exec cli peer chaincode instantiate -n sacc-ac -v 0 -C mychannel -c '{"Args":["a", "100"]}'
Image for post
Image for post

We first use User1 (setting the environment variable) to get the value, and then set the value.

docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["get", "a"]}'docker exec -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["set", "a", "500"]}'
Image for post
Image for post
User1 cannot set a new value.

Note that User1 can get the value but cannot set any value per access control inside the chaincode. If we try again using the Admin (the default value is using Admin),

docker exec cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["set", "a", "500"]}'
Image for post
Image for post

The invoke is successful. The access control with subject works well.

Summary

Through the Basic Network and Simple Asset Chaincode, we understand a bit about identity in Hyperledger Fabric. Each activity on fabric network and chaincode requires identity, presented as X.509 digital certificate. As far as the issuer CA is trusted by fabric network, the activity is accepted and processed. With client identity chaincode library, we then modified the SACC and include the access control based on the subject common name. This demonstrated how access control can be enforced at the chaincode level.

Stay tuned to the next article with Fabric CA and more about the attribute-based access control (ABAC).

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

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store