hyperacc

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: MIT Imports: 6 Imported by: 0

README ΒΆ

Go Reference Go Report Card Go Version CI Release

πŸ” hyperacc

Flexible and convenient package for access control to chaincode methods in HyperLedger Fabric.

Table of Contents


Installation

go get github.com/IceTweak/hyperacc

Important: The package uses HyperLedger Fabric v2 API:

  • github.com/hyperledger/fabric-chaincode-go/v2
  • github.com/hyperledger/fabric-contract-api-go/v2
  • github.com/hyperledger/fabric-protos-go-apiv2

Main Features

  • βœ… 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

Quick Start

Simple role check
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))
}
Administrator check
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)
}
Multiple roles check (OR)
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
}
MSPID check
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
}
Organizational Unit check
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
}

Rule combinations

AND - all rules must pass
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
}
OR - at least one rule must pass
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
}
Complex combinations
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
}

Custom rules

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
}

Usage with hyperacc object

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))
}

API Reference

Role-based rules
  • RequireRole(role string) - requires specific role
  • RequireAnyRole(roles ...string) - requires one of the roles
Organization-based rules
  • RequireMSPID(mspid string) - requires specific MSPID
  • RequireAnyMSPID(mspids ...string) - requires one of the MSPIDs
  • RequireOU(ou string) - requires specific Organizational Unit
  • RequireAnyOU(ous ...string) - requires one of the OUs
Combinators
  • And(rules ...Rule) - all rules must pass
  • Or(rules ...Rule) - at least one rule must pass
  • Not(rule Rule) - inverts the rule result
Custom rules
  • Custom(name string, checkFunc func(...) error) - creates custom rule
  • AlwaysDeny(message string) - always denies access
Main functions
  • New(rules ...Rule) - creates new hyperacc object
  • CheckAccess(stub, rules...) - checks access (helper function)
  • (ha *hyperacc).Check(stub) - checks all rules in the object

Error handling

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
}

Real-world scenario examples

Supply Chain contract
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
}
Financial contract
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
}

Requirements

  • Go 1.21+
  • HyperLedger Fabric 2.x+
  • fabric-chaincode-go/v2
  • fabric-contract-api-go/v2
  • fabric-protos-go-apiv2

Documentation

πŸ“– Main documentation
πŸ”„ Migration and updates

Examples

Complete chaincode example using hyperacc is available in examples/asset-contract.

Support

Roadmap

  • 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.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Citation

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}
}

Made with ❀️ for the HyperLedger Fabric community

Documentation ΒΆ

Index ΒΆ

Constants ΒΆ

This section is empty.

Variables ΒΆ

This section is empty.

Functions ΒΆ

func CheckAccess ΒΆ

func CheckAccess(ctx contractapi.TransactionContextInterface, rules ...Rule) error

CheckAccess helper function for access checking

func HasAttribute ΒΆ

func HasAttribute(ctx contractapi.TransactionContextInterface, attrName string) (bool, error)

HasAttribute checks if the caller has an attribute

func LogAccessDenied ΒΆ

func LogAccessDenied(ctx contractapi.TransactionContextInterface, err error)

LogAccessDenied logs access denial Automatically determines if the error is an access denial error

func New ΒΆ

func New(rules ...Rule) *controller

New creates a new instance of controller

Types ΒΆ

type AccessError ΒΆ

type AccessError struct {
	Reason string
	Cause  error
}

func AsAccessError ΒΆ

func AsAccessError(err error) (*AccessError, bool)

func NewAccessError ΒΆ

func NewAccessError(reason string) *AccessError

func WrapAccessError ΒΆ

func WrapAccessError(reason string, cause error) *AccessError

func (*AccessError) Error ΒΆ

func (e *AccessError) Error() string

func (*AccessError) Unwrap ΒΆ

func (e *AccessError) Unwrap() error

type AlwaysDenyRule ΒΆ

type AlwaysDenyRule struct {
	// contains filtered or unexported fields
}

AlwaysDenyRule always denies access

func AlwaysDeny ΒΆ

func AlwaysDeny(message string) *AlwaysDenyRule

AlwaysDeny creates a rule that always denies access

func (*AlwaysDenyRule) Check ΒΆ

Check always returns an error (access denied)

type AndRule ΒΆ

type AndRule struct {
	// contains filtered or unexported fields
}

AndRule combines multiple rules with AND logic (all must pass)

func And ΒΆ

func And(rules ...Rule) *AndRule

And creates a rule that requires all nested rules to pass

func (*AndRule) Check ΒΆ

Check checks all rules (all must pass)

type AnyMSPIDRule ΒΆ

type AnyMSPIDRule struct {
	// contains filtered or unexported fields
}

AnyMSPIDRule checks for one of the specified MSPIDs

func RequireAnyMSPID ΒΆ

func RequireAnyMSPID(mspids ...string) *AnyMSPIDRule

RequireAnyMSPID creates a rule to check for one of the MSPIDs

func (*AnyMSPIDRule) Check ΒΆ

Check checks if the caller has one of the MSPIDs

type AnyOURule ΒΆ

type AnyOURule struct {
	// contains filtered or unexported fields
}

AnyOURule checks for one of the specified OUs

func RequireAnyOU ΒΆ

func RequireAnyOU(ous ...string) *AnyOURule

RequireAnyOU creates a rule to check for one of the OUs

func (*AnyOURule) Check ΒΆ

Check checks if the caller has one of the OUs

type AnyRoleRule ΒΆ

type AnyRoleRule struct {
	// contains filtered or unexported fields
}

AnyRoleRule checks for one of the specified roles

func RequireAnyRole ΒΆ

func RequireAnyRole(roles ...string) *AnyRoleRule

RequireAnyRole creates a rule to check for one of the roles

func (*AnyRoleRule) Check ΒΆ

Check checks if the caller has one of the roles

type AttributeRule ΒΆ

type AttributeRule struct {
	// contains filtered or unexported fields
}

AttributeRule checks for the presence and value of an arbitrary attribute

func RequireAttribute ΒΆ

func RequireAttribute(name, value string) *AttributeRule

RequireAttribute creates a rule to check an attribute

func (*AttributeRule) Check ΒΆ

Check checks the attribute

type CallerInfo ΒΆ

type CallerInfo struct {
	MSPID string
	ID    string
	Role  string
	OUs   []string
}

CallerInfo contains information about the caller

func GetCallerInfo ΒΆ

GetCallerInfo gets information about the current caller

type CustomRule ΒΆ

type CustomRule struct {
	// contains filtered or unexported fields
}

CustomRule allows creating custom rules using a function

func Custom ΒΆ

func Custom(name string, checkFunc func(ctx contractapi.TransactionContextInterface) error) *CustomRule

Custom creates a custom rule based on a function

func (*CustomRule) Check ΒΆ

Check executes the custom check function

type HasAttributeRule ΒΆ

type HasAttributeRule struct {
	// contains filtered or unexported fields
}

HasAttributeRule checks only for the presence of an attribute (value is not important)

func RequireHasAttribute ΒΆ

func RequireHasAttribute(name string) *HasAttributeRule

RequireHasAttribute creates a rule to check for the presence of an attribute

func (*HasAttributeRule) Check ΒΆ

Check checks for the presence of an attribute

type IsHLFAdmintRule ΒΆ

type IsHLFAdmintRule struct{}

IsHLFAdmintRule checks if the caller is an administrator in the HyperLedger Fabric network

func RequireHLFAdmin ΒΆ

func RequireHLFAdmin() *IsHLFAdmintRule

RequireHLFAdmin creates a rule to check that the caller is an administrator

func (*IsHLFAdmintRule) Check ΒΆ

Check checks the caller type

type IsHLFClientRule ΒΆ

type IsHLFClientRule struct{}

IsHLFClientRule checks if the caller is a client in the HyperLedger Fabric network

func RequireHLFClient ΒΆ

func RequireHLFClient() *IsHLFClientRule

RequireHLFClient creates a rule to check that the caller is a client

func (*IsHLFClientRule) Check ΒΆ

Check checks the caller type

type MSPIDRule ΒΆ

type MSPIDRule struct {
	// contains filtered or unexported fields
}

MSPIDRule checks the caller's MSPID

func RequireMSPID ΒΆ

func RequireMSPID(mspid string) *MSPIDRule

RequireMSPID creates a rule to check for a specific MSPID

func (*MSPIDRule) Check ΒΆ

Check checks the caller's MSPID

type Middleware ΒΆ

type Middleware func(ctx contractapi.TransactionContextInterface) error

Middleware function for integration with various frameworks

func CreateMiddleware ΒΆ

func CreateMiddleware(rules ...Rule) Middleware

CreateMiddleware creates a middleware function from rules

type NotRule ΒΆ

type NotRule struct {
	// contains filtered or unexported fields
}

NotRule inverts a rule

func Not ΒΆ

func Not(rule Rule) *NotRule

Not creates a rule that inverts the result of a nested rule

func (*NotRule) Check ΒΆ

Check inverts the result of rule checking

type OURule ΒΆ

type OURule struct {
	// contains filtered or unexported fields
}

OURule checks the caller's Organizational Unit

func RequireOU ΒΆ

func RequireOU(ou string) *OURule

RequireOU creates a rule to check for a specific OU

func (*OURule) Check ΒΆ

Check checks the caller's OU

type OrRule ΒΆ

type OrRule struct {
	// contains filtered or unexported fields
}

OrRule combines multiple rules with OR logic (at least one must pass)

func Or ΒΆ

func Or(rules ...Rule) *OrRule

Or creates a rule that requires at least one nested rule to pass

func (*OrRule) Check ΒΆ

Check checks rules (at least one must pass)

type RoleRule ΒΆ

type RoleRule struct {
	// contains filtered or unexported fields
}

RoleRule checks for a specific role

func RequireRole ΒΆ

func RequireRole(role string) *RoleRule

RequireRole creates a rule to check for a specific role

func (*RoleRule) Check ΒΆ

Check checks if the caller has the role

type Rule ΒΆ

type Rule interface {
	Check(ctx contractapi.TransactionContextInterface) error
}

Rule interface for access rules

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL