Flexible and convenient package for access control to chaincode methods in HyperLedger Fabric.
go get github.com/IceTweak/hyperaccImportant: The package uses HyperLedger Fabric v2 API:
github.com/hyperledger/fabric-chaincode-go/v2github.com/hyperledger/fabric-contract-api-go/v2github.com/hyperledger/fabric-protos-go-apiv2
- Role-based access check (role attribute)
- MSPID check
- Organizational Unit (OU) check
- Support for administrators and clients based on
hf.Type - Rule combinations (AND/OR/NOT)
- Custom rules
- Simple and intuitive API
package main
import (
"github.com/hyperledger/fabric-contract-api-go/v2/contractapi"
"github.com/IceTweak/hyperacc"
)
type MyContract struct {
contractapi.Contract
}
func (c *MyContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, value string) error {
// Access check: only "manager" role
if err := hyperacc.CheckAccess(ctx, hyperacc.RequireRole("manager")); err != nil {
return err
}
// Asset creation logic
return ctx.GetStub().PutState(id, []byte(value))
}func (c *MyContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error {
// Only administrators can delete assets
if err := hyperacc.CheckAccess(ctx, hyperacc.RequireHLFAdmin()); err != nil {
return err
}
return ctx.GetStub().DelState(id)
}func (c *MyContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (string, error) {
// Access for manager, viewer or auditor
if err := hyperacc.CheckAccess(ctx,
hyperacc.RequireAnyRole("manager", "viewer", "auditor"),
); err != nil {
return "", err
}
data, err := ctx.GetStub().GetState(id)
return string(data), err
}func (c *MyContract) OrgSpecificMethod(ctx contractapi.TransactionContextInterface) error {
// Access only for specific organization
if err := hyperacc.CheckAccess(ctx,
hyperacc.RequireMSPID("Org1MSP"),
); err != nil {
return err
}
// Method logic
return nil
}func (c *MyContract) DepartmentMethod(ctx contractapi.TransactionContextInterface) error {
// Access only for users from OU "department1"
if err := hyperacc.CheckAccess(ctx,
hyperacc.RequireOU("department1"),
); err != nil {
return err
}
// Method logic
return nil
}func (c *MyContract) SensitiveOperation(ctx contractapi.TransactionContextInterface) error {
// Must be manager AND from Org1MSP
if err := hyperacc.CheckAccess(ctx,
hyperacc.And(
hyperacc.RequireRole("manager"),
hyperacc.RequireMSPID("Org1MSP"),
),
); err != nil {
return err
}
// Operation logic
return nil
}func (c *MyContract) MultiOrgMethod(ctx contractapi.TransactionContextInterface) error {
// Access for multiple organizations
if err := hyperacc.CheckAccess(ctx,
hyperacc.Or(
hyperacc.RequireMSPID("Org1MSP"),
hyperacc.RequireMSPID("Org2MSP"),
hyperacc.RequireMSPID("Org3MSP"),
),
); err != nil {
return err
}
// Method logic
return nil
}func (c *MyContract) ComplexAccess(ctx contractapi.TransactionContextInterface) error {
// (admin OR (manager AND Org1MSP)) AND NOT department2
if err := hyperacc.CheckAccess(ctx,
hyperacc.And(
hyperacc.Or(
hyperacc.RequireHLFAdmin(),
hyperacc.And(
hyperacc.RequireRole("manager"),
hyperacc.RequireMSPID("Org1MSP"),
),
),
hyperacc.Not(
hyperacc.RequireOU("department2"),
),
),
); err != nil {
return err
}
// Method logic
return nil
}func (c *MyContract) CustomAccessMethod(ctx contractapi.TransactionContextInterface) error {
// Custom rule based on function
customRule := hyperacc.Custom("business-hours", func(ctx contractapi.TransactionContextInterface) error {
stub := ctx.GetStub()
timestamp, err := stub.GetTxTimestamp()
if err != nil {
return err
}
hour := timestamp.AsTime().Hour()
if hour < 9 || hour > 18 {
return fmt.Errorf("operation only allowed during business hours (9-18)")
}
return nil
})
if err := hyperacc.CheckAccess(ctx, customRule); err != nil {
return err
}
// Method logic
return nil
}type MyContract struct {
contractapi.Contract
}
func (c *MyContract) Init(ctx contractapi.TransactionContextInterface) error {
return nil
}
func (c *MyContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, value string) error {
// Create access control object
ac := hyperacc.New(
hyperacc.RequireRole("manager"),
hyperacc.RequireMSPID("Org1MSP"),
)
// Access check
if err := ac.Check(ctx); err != nil {
return err
}
// Asset creation logic
return ctx.GetStub().PutState(id, []byte(value))
}RequireRole(role string)- requires specific roleRequireAnyRole(roles ...string)- requires one of the roles
RequireMSPID(mspid string)- requires specific MSPIDRequireAnyMSPID(mspids ...string)- requires one of the MSPIDsRequireOU(ou string)- requires specific Organizational UnitRequireAnyOU(ous ...string)- requires one of the OUs
And(rules ...Rule)- all rules must passOr(rules ...Rule)- at least one rule must passNot(rule Rule)- inverts the rule result
Custom(name string, checkFunc func(...) error)- creates custom ruleAlwaysDeny(message string)- always denies access
New(rules ...Rule)- creates new hyperacc objectCheckAccess(stub, rules...)- checks access (helper function)(ha *hyperacc).Check(stub)- checks all rules in the object
func (c *MyContract) SomeMethod(ctx contractapi.TransactionContextInterface) error {
err := hyperacc.CheckAccess(ctx, hyperacc.RequireRole("manager"))
if err != nil {
// Check error type
if accErr, ok := hyperacc.AsAccessError(err); ok {
// Special handling for access denial
return fmt.Errorf("unauthorized: %w", err)
}
return err
}
// Method is accessible
return nil
}func (c *SupplyChainContract) CreateShipment(ctx contractapi.TransactionContextInterface,
shipmentID string, data string) error {
// Only manufacturer from Org1MSP can create shipments
if err := hyperacc.CheckAccess(ctx,
hyperacc.And(
hyperacc.RequireRole("manufacturer"),
hyperacc.RequireMSPID("Org1MSP"),
),
); err != nil {
return err
}
return ctx.GetStub().PutState(shipmentID, []byte(data))
}
func (c *SupplyChainContract) ReceiveShipment(ctx contractapi.TransactionContextInterface,
shipmentID string) error {
// Only distributor or retailer can receive shipments
if err := hyperacc.CheckAccess(ctx,
hyperacc.RequireAnyRole("distributor", "retailer"),
); err != nil {
return err
}
// Shipment receiving logic
return nil
}
func (c *SupplyChainContract) AuditShipment(ctx contractapi.TransactionContextInterface,
shipmentID string) (string, error) {
// Auditors from any organization or administrators
if err := hyperacc.CheckAccess(ctx,
hyperacc.Or(
hyperacc.RequireRole("auditor"),
hyperacc.RequireAdmin(),
),
); err != nil {
return "", err
}
data, err := ctx.GetStub().GetState(shipmentID)
return string(data), err
}func (c *FinanceContract) TransferFunds(ctx contractapi.TransactionContextInterface,
from, to string, amount int) error {
// Only managers from financial departments of banks
if err := hyperacc.CheckAccess(ctx,
hyperacc.And(
hyperacc.RequireRole("finance-manager"),
hyperacc.RequireOU("finance"),
hyperacc.RequireAnyMSPID("BankAMSP", "BankBMSP"),
),
); err != nil {
return err
}
// Fund transfer logic
return nil
}
func (c *FinanceContract) ApproveTransaction(ctx contractapi.TransactionContextInterface,
txID string) error {
// Only compliance officers or administrators
if err := hyperacc.CheckAccess(ctx,
hyperacc.Or(
hyperacc.RequireRole("compliance-officer"),
hyperacc.RequireAdmin(),
),
); err != nil {
return err
}
// Transaction approval logic
return nil
}- Go 1.21+
- HyperLedger Fabric 2.x+
- fabric-chaincode-go/v2
- fabric-contract-api-go/v2
- fabric-protos-go-apiv2
- README.md - Main documentation and examples
- API Reference - Complete API documentation
- CHANGELOG.md - Change history
Complete chaincode example using hyperacc is available in examples/asset-contract.
-
π Open issue
-
π¬ Start discussion
- Time-based policy support
- Integration with external authentication systems
- Advanced audit capabilities
- Dynamic rule support from ledger
See open issues for a complete list of proposed features and known issues.
This project is licensed under the MIT License - see the LICENSE file for details.
If you use this project in research or publications, please cite:
@software{hyperacc,
author = {Roman Savoschik [github.com/IceTweak]},
title = {Access control for HyperLedger Fabric Go chaincodes},
year = {2026},
url = {https://github.com/IceTweak/hyperacc}
}