Implementing and Updating Access Control Lists for Hyperledger Fabric
Learn how to implement Access Control in Hyperledger Fabric project and update it dynamically.
This is an extensive guide for Hyperledger Fabric ACLs at the config level. Hyperledger Fabric is currently the most popular permissioned blockchain framework in the business world.
This tutorial is divided into two parts.
- Understanding and Implementing Access Control List for Hyperledger Fabric.
- Updating the Access Control List(or any other configuration) from channel configuration dynamically.
We will implement policy based Access Control on a channel administration level in this tutorial. We will discuss default ACLs present in the fabric, how they’re formatted and how they can be overwritten.
Prerequisites
- Understanding of different components of Hyperledger Fabric.
https://hyperledger-fabric.readthedocs.io/en/release-1.4/fabric_model.html - Basic understanding of Hyperledger Fabric transaction workflow.
https://hyperledger-fabric.readthedocs.io/en/release-1.4/txflow.html - Installation of Hyperldger Fabric docker images and prerequisites for Fabric.
https://hyperledger-fabric.readthedocs.io/en/release-1.4/prereqs.html
https://hyperledger-fabric.readthedocs.io/en/release-1.4/install.html
Understanding and Implementing ACLs
To keep this article succinct, I will quickly state what has been clearly explained in the Fabric Read the docs.
Users interact with Fabric by targeting a user chaincode, system chaincode, or an events stream source. As such, these endpoints are considered “resources” on which access control should be exercised.
Application developers need to be aware of these resources and the default policies associated with them.
There are 2 types of policies we will be using in this.
- Signature Policies
These policies identify specific users who must sign in order for a policy to be satisfied.
Policies:
MyPolicy:
Type: Signature
Rule: “Org1.Peer OR Org2.Peer”
Signature policies support arbitrary combinations of AND
, OR
, and NOutOf
, allowing the construction of extremely powerful rules like: “An admin of org A and two other admins, or 11 of 20 org admins”.
2. Implicit Meta Policies
These Implicit Meta policies aggregate the results of policies deeper into the configuration hierarchy that ultimately defined by the Signature policies. They support default rules like “A majority of the organization admins”. These policies use a different but still very simple syntax as compared to Signature
policies: <ALL|ANY|MAJORITY> <sub_policy>
.
Here’s an example of an ImplicitMeta
policy structure:
Policies:
AnotherPolicy:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Access control defaults exist inside configtx.yaml
, the file that configtxgen
uses to build channel configurations.
Sample configtx.yaml file.
In this file, you can see from
line 35, Signature Policies are defined
line 194, ImplicitMeta Policies are defined
and from line 131, ACLs are defined.
These are ACLs are currently defined on the system chaincode’s functions.
Read this to understand more on system chaincodes and their respective functions.
Enough of theory now.
Now I will show a bit of code and new policy changes I made while testing ACLs
Let’s edit the Application: ACLs
section inside configtx.yaml
to change peer/Propose
from this:
peer/Propose: /Channel/Application/Writers
To this:
peer/Propose: /Channel/Application/MyPolicy
where MyPolicy
is defined as:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
MyPolicy:
Type: Signature
Rule: "OR('Org1MSP.client')"
Here MyPolicy
says only the Client has the right to perform the task.
Don’t forget to generate and update new CA and admin certificates.
Let’s run and try to invoke chaincode from Org1Client.
Now with Org2Client
As we can clearly see from the logs, peer/propose
(invocation of function) cannot be done via the ORG2 client.
Updating the Access Control List from configuration (or any other configuration) dynamically.
Access control can be updated one of two ways, either by editing configtx.yaml
itself, which will propagate the ACL change to any new channels or by updating access control in the channel configuration of a particular channel. We will update the access in the channel configuration of our channel.
You must have a network running before implementing the below steps.
- Access the cli
There is a cli Docker container created automatically, it is a command line interface to control the nodes.
docker exec -it cli bash
Then, set up environment variables used by some programs:
export CHANNEL_NAME=mychannel
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
You could just copy all of them, then paste to your terminal and press “enter”.
2. Fetch the current channel configurations for mychannel — output: config_block.pb, which is a block file
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
3. Transform the config_block.pb configurations to an understandable JSON file — output: config.json
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json
4. Make a copy of config.json to modified_config.json, which we will modify it according to what we need to update
cp config.json modified_config.json
5. Install vim for the modification of the JSON file
vim is a famous editing tool in Linux.
sudo apt-get update -y
sudo apt-get install vim -y
6. Modify configurations in modified_config.json
vim modified_config.json
We will change the MyPolicy description from Org1MSP to Org2MSP.
- Press “/” to start searching text
- Type “MyPolicy”
3. Now, Press “i” to enter insert mode in vim (thus we can start editing), after pressing, you should see that there is “ — Insert — ” on the left bottom of the terminal
4. Change Org1MSP to Org2MSP.
5. Then, press “esc” to exit insert mode of vim
6. Press “shift + :”, type “wq!”, and press “enter”. You should now leave vim and the modification is saved.
7. Transform modified_config.json to a block file — output: modified_config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
8. Transform config.json to a block file — output: config.pb
configtxlator proto_encode --input config.json --type common.Config --output config.pb
9. Compute the difference between modified_config.pb and config.pb — output: diff_config.pb
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output diff_config.pb
10. Transform the diff_config.pb configurations to an understandable JSON file — output: diff_config.json
configtxlator proto_decode --input diff_config.pb --type common.ConfigUpdate | jq . > diff_config.json
11. Add envelope text in diff_config.json — output: diff_config_envelope.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat diff_config.json)'}}}' | jq . > diff_config_envelope.json
12. Transform diff_config_envelope.json to a block file — output: diff_config_envelope.pb
configtxlator proto_encode --input diff_config_envelope.json --type common.Envelope --output diff_config_envelope.pb
13. Sign diff_config_envelope.pb as Org1 admin (depending on policy)
In step 1, under “Access the Cli”, our cli is representing Peer0 in Org1 via environment variables.
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
Now, we do signing:
peer channel signconfigtx -f diff_config_envelope.pb
If you are careful enough, you should observe that the file size of diff_config_envelope.pb before signing is smaller than that after signing.
And it is okay to sign multiple times, let’s try it yourself.
14. Sign diff_config_envelope.pb as Org2 admin
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
Now, we do signing from Org2
peer channel signconfigtx -f diff_config_envelope.pb
When we make changes in ACLs all the organization admins need to sign the changes before updating it.
15. Send channel update transaction
It is time to update the channel!
peer channel update -f diff_config_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
Let’s check the results by invoking the function again from both clients
Invoking from Org1 Client
Invoking from Org2 Client
As you can see, now only the client of Org2 can invoke the chaincode.
To practice on fabric-samples first-network with the node SDK, you can clone my repo.
https://github.com/aditya520/fabric_node_first_network
FUTURE STEPS
Next, I will try to bring ACLs to user chaincode functions which can give us more flexibility.
Resources
2. https://github.com/hyperledger/fabric/blob/release-1.2/sampleconfig/configtx.yaml
3. https://hyperledger-fabric.readthedocs.io/en/release-1.4/channel_update_tutorial.html
4. https://medium.com/coinmonks/hyperledger-fabric-updating-channel-configs-45082a5dc9b2
Thanks, Reasdom for giving us consolidated codes and points for updating the config file.