github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/configtx/policies.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package configtx
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"github.com/hellobchain/third_party/hyperledger/fabric-config/configtx/internal/policydsl"
    13  	"strconv"
    14  	"strings"
    15  
    16  	"github.com/golang/protobuf/proto"
    17  	cb "github.com/hyperledger/fabric-protos-go/common"
    18  	mb "github.com/hyperledger/fabric-protos-go/msp"
    19  )
    20  
    21  // getPolicies returns a map of Policy from given map of ConfigPolicy in organization config group.
    22  func getPolicies(policies map[string]*cb.ConfigPolicy) (map[string]Policy, error) {
    23  	p := map[string]Policy{}
    24  
    25  	for name, policy := range policies {
    26  		switch cb.Policy_PolicyType(policy.Policy.Type) {
    27  		case cb.Policy_IMPLICIT_META:
    28  			imp := &cb.ImplicitMetaPolicy{}
    29  			err := proto.Unmarshal(policy.Policy.Value, imp)
    30  			if err != nil {
    31  				return nil, err
    32  			}
    33  
    34  			rule, err := implicitMetaToString(imp)
    35  			if err != nil {
    36  				return nil, err
    37  			}
    38  
    39  			p[name] = Policy{
    40  				Type:      ImplicitMetaPolicyType,
    41  				Rule:      rule,
    42  				ModPolicy: policy.GetModPolicy(),
    43  			}
    44  		case cb.Policy_SIGNATURE:
    45  			sp := &cb.SignaturePolicyEnvelope{}
    46  			err := proto.Unmarshal(policy.Policy.Value, sp)
    47  			if err != nil {
    48  				return nil, err
    49  			}
    50  
    51  			rule, err := signatureMetaToString(sp)
    52  			if err != nil {
    53  				return nil, err
    54  			}
    55  
    56  			p[name] = Policy{
    57  				Type:      SignaturePolicyType,
    58  				Rule:      rule,
    59  				ModPolicy: policy.GetModPolicy(),
    60  			}
    61  		default:
    62  			return nil, fmt.Errorf("unknown policy type: %v", policy.Policy.Type)
    63  		}
    64  	}
    65  
    66  	return p, nil
    67  }
    68  
    69  // implicitMetaToString converts a *cb.ImplicitMetaPolicy to a string representation.
    70  func implicitMetaToString(imp *cb.ImplicitMetaPolicy) (string, error) {
    71  	var args string
    72  
    73  	switch imp.Rule {
    74  	case cb.ImplicitMetaPolicy_ANY:
    75  		args += cb.ImplicitMetaPolicy_ANY.String()
    76  	case cb.ImplicitMetaPolicy_ALL:
    77  		args += cb.ImplicitMetaPolicy_ALL.String()
    78  	case cb.ImplicitMetaPolicy_MAJORITY:
    79  		args += cb.ImplicitMetaPolicy_MAJORITY.String()
    80  	default:
    81  		return "", fmt.Errorf("unknown implicit meta policy rule type %v", imp.Rule)
    82  	}
    83  
    84  	args = args + " " + imp.SubPolicy
    85  
    86  	return args, nil
    87  }
    88  
    89  // signatureMetaToString converts a *cb.SignaturePolicyEnvelope to a string representation.
    90  func signatureMetaToString(sig *cb.SignaturePolicyEnvelope) (string, error) {
    91  	var roles []string
    92  
    93  	for _, id := range sig.Identities {
    94  		role, err := mspPrincipalToString(id)
    95  		if err != nil {
    96  			return "", err
    97  		}
    98  
    99  		roles = append(roles, role)
   100  	}
   101  
   102  	return signaturePolicyToString(sig.Rule, roles)
   103  }
   104  
   105  // mspPrincipalToString converts a *mb.MSPPrincipal to a string representation.
   106  func mspPrincipalToString(principal *mb.MSPPrincipal) (string, error) {
   107  	switch principal.PrincipalClassification {
   108  	case mb.MSPPrincipal_ROLE:
   109  		var res strings.Builder
   110  
   111  		role := &mb.MSPRole{}
   112  
   113  		err := proto.Unmarshal(principal.Principal, role)
   114  		if err != nil {
   115  			return "", err
   116  		}
   117  
   118  		res.WriteString("'")
   119  		res.WriteString(role.MspIdentifier)
   120  		res.WriteString(".")
   121  		res.WriteString(strings.ToLower(role.Role.String()))
   122  		res.WriteString("'")
   123  
   124  		return res.String(), nil
   125  		// TODO: currently fabric only support string to principle convertion for
   126  		// type ROLE. Implement MSPPrinciple to String for types ORGANIZATION_UNIT,
   127  		// IDENTITY, ANONYMITY, and GOMBINED once we have support from fabric.
   128  	case mb.MSPPrincipal_ORGANIZATION_UNIT:
   129  		return "", nil
   130  	case mb.MSPPrincipal_IDENTITY:
   131  		return "", nil
   132  	case mb.MSPPrincipal_ANONYMITY:
   133  		return "", nil
   134  	case mb.MSPPrincipal_COMBINED:
   135  		return "", nil
   136  	default:
   137  		return "", fmt.Errorf("unknown MSP principal classiciation %v", principal.PrincipalClassification)
   138  	}
   139  }
   140  
   141  // signaturePolicyToString recursively converts a *cb.SignaturePolicy to a
   142  // string representation.
   143  func signaturePolicyToString(sig *cb.SignaturePolicy, IDs []string) (string, error) {
   144  	switch sig.Type.(type) {
   145  	case *cb.SignaturePolicy_NOutOf_:
   146  		nOutOf := sig.GetNOutOf()
   147  
   148  		var policies []string
   149  
   150  		var res strings.Builder
   151  
   152  		// get gate values
   153  		gate := policydsl.GateOutOf
   154  		if nOutOf.N == 1 {
   155  			gate = policydsl.GateOr
   156  		}
   157  
   158  		if nOutOf.N == int32(len(nOutOf.Rules)) {
   159  			gate = policydsl.GateAnd
   160  		}
   161  
   162  		if gate == policydsl.GateOutOf {
   163  			policies = append(policies, strconv.Itoa(int(nOutOf.N)))
   164  		}
   165  
   166  		// get subpolicies recursively
   167  		for _, rule := range nOutOf.Rules {
   168  			subPolicy, err := signaturePolicyToString(rule, IDs)
   169  			if err != nil {
   170  				return "", err
   171  			}
   172  
   173  			policies = append(policies, subPolicy)
   174  		}
   175  
   176  		res.WriteString(strings.ToUpper(gate))
   177  		res.WriteString("(")
   178  		res.WriteString(strings.Join(policies, ", "))
   179  		res.WriteString(")")
   180  
   181  		return res.String(), nil
   182  	case *cb.SignaturePolicy_SignedBy:
   183  		return IDs[sig.GetSignedBy()], nil
   184  	default:
   185  		return "", fmt.Errorf("unknown signature policy type %v", sig.Type)
   186  	}
   187  }
   188  
   189  func setPolicies(cg *cb.ConfigGroup, policyMap map[string]Policy) error {
   190  	if policyMap == nil {
   191  		return errors.New("no policies defined")
   192  	}
   193  
   194  	if _, ok := policyMap[AdminsPolicyKey]; !ok {
   195  		return errors.New("no Admins policy defined")
   196  	}
   197  
   198  	if _, ok := policyMap[ReadersPolicyKey]; !ok {
   199  		return errors.New("no Readers policy defined")
   200  	}
   201  
   202  	if _, ok := policyMap[WritersPolicyKey]; !ok {
   203  		return errors.New("no Writers policy defined")
   204  	}
   205  
   206  	cg.Policies = make(map[string]*cb.ConfigPolicy)
   207  	for policyName, policy := range policyMap {
   208  		err := setPolicy(cg, policyName, policy)
   209  		if err != nil {
   210  			return err
   211  		}
   212  	}
   213  
   214  	return nil
   215  }
   216  
   217  func setPolicy(cg *cb.ConfigGroup, policyName string, policy Policy) error {
   218  	if cg.Policies == nil {
   219  		cg.Policies = make(map[string]*cb.ConfigPolicy)
   220  	}
   221  
   222  	switch policy.Type {
   223  	case ImplicitMetaPolicyType:
   224  		imp, err := implicitMetaFromString(policy.Rule)
   225  		if err != nil {
   226  			return fmt.Errorf("invalid implicit meta policy rule: '%s': %v", policy.Rule, err)
   227  		}
   228  
   229  		implicitMetaPolicy, err := proto.Marshal(imp)
   230  		if err != nil {
   231  			return fmt.Errorf("marshaling implicit meta policy: %v", err)
   232  		}
   233  
   234  		if policy.ModPolicy == "" {
   235  			policy.ModPolicy = AdminsPolicyKey
   236  		}
   237  
   238  		cg.Policies[policyName] = &cb.ConfigPolicy{
   239  			ModPolicy: policy.ModPolicy,
   240  			Policy: &cb.Policy{
   241  				Type:  int32(cb.Policy_IMPLICIT_META),
   242  				Value: implicitMetaPolicy,
   243  			},
   244  		}
   245  	case SignaturePolicyType:
   246  		sp, err := policydsl.FromString(policy.Rule)
   247  		if err != nil {
   248  			return fmt.Errorf("invalid signature policy rule: '%s': %v", policy.Rule, err)
   249  		}
   250  
   251  		signaturePolicy, err := proto.Marshal(sp)
   252  		if err != nil {
   253  			return fmt.Errorf("marshaling signature policy: %v", err)
   254  		}
   255  
   256  		if policy.ModPolicy == "" {
   257  			policy.ModPolicy = AdminsPolicyKey
   258  		}
   259  
   260  		cg.Policies[policyName] = &cb.ConfigPolicy{
   261  			ModPolicy: policy.ModPolicy,
   262  			Policy: &cb.Policy{
   263  				Type:  int32(cb.Policy_SIGNATURE),
   264  				Value: signaturePolicy,
   265  			},
   266  		}
   267  	default:
   268  		return fmt.Errorf("unknown policy type: %s", policy.Type)
   269  	}
   270  
   271  	return nil
   272  }
   273  
   274  // removePolicy removes an existing policy from an group key organization.
   275  func removePolicy(configGroup *cb.ConfigGroup, policyName string, policies map[string]Policy) {
   276  	delete(configGroup.Policies, policyName)
   277  }