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.
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.
Simple Asset Chaincode
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.
Deploy SACC onto Basic Network
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"]}'
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"]}'
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"]}'
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.
Inside CLI Container
Let’s take a look on the environment variable setup in CLI container.
docker exec cli env
We see CORE_PEER_MSPCONFIGPATH is set, pointing to [email protected]/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"]}'
Beside Admin, it also comes with another identity: [email protected]. We can see the users defined inside Org1.
docker exec cli ls crypto/peerOrganizations/org1.example.com/users
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/[email protected]/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/[email protected]/msp" cli peer chaincode invoke -n sacc -C mychannel -c '{"Args":["get", "a"]}'
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.
Inside Docker-Compose 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/[email protected]/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.
Inside ./crypto-config directory
Here is our directory structure of ./crypto-config in our localhost.
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 ([email protected]) and the Issuer (CN=ca.org1.example.com) information.
Here is the one for User1’s certificate. We see the same Issuer (CN=ca.org1.example.com).
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.
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.
Modify SACC-AC Code
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 != "[email protected]" {
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.
Deploy SACC-AC onto Basic Network
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"]}'
Invoke SACC-AC Chaincode
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/[email protected]/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/[email protected]/msp" cli peer chaincode invoke -n sacc-ac -C mychannel -c '{"Args":["set", "a", "500"]}'
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"]}'
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.
This article has been published from a wire agency feed without modifications to the text. Only the headline has been changed.