github.com/yimialmonte/fabric@v2.1.1+incompatible/discovery/endorsement/collection.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package endorsement
     8  
     9  import (
    10  	. "github.com/hyperledger/fabric-protos-go/discovery"
    11  	"github.com/hyperledger/fabric-protos-go/peer"
    12  	"github.com/hyperledger/fabric/common/policies"
    13  	"github.com/hyperledger/fabric/gossip/api"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  func principalsFromCollectionConfig(ccp *peer.CollectionConfigPackage) (principalSetsByCollectionName, error) {
    18  	principalSetsByCollections := make(principalSetsByCollectionName)
    19  	if ccp == nil {
    20  		return principalSetsByCollections, nil
    21  	}
    22  	for _, colConfig := range ccp.Config {
    23  		staticCol := colConfig.GetStaticCollectionConfig()
    24  		if staticCol == nil {
    25  			// Right now we only support static collections, so if we got something else
    26  			// we should refuse to process further
    27  			return nil, errors.Errorf("expected a static collection but got %v instead", colConfig)
    28  		}
    29  		if staticCol.MemberOrgsPolicy == nil {
    30  			return nil, errors.Errorf("MemberOrgsPolicy of %s is nil", staticCol.Name)
    31  		}
    32  		pol := staticCol.MemberOrgsPolicy.GetSignaturePolicy()
    33  		if pol == nil {
    34  			return nil, errors.Errorf("policy of %s is nil", staticCol.Name)
    35  		}
    36  		var principals policies.PrincipalSet
    37  		// We now extract all principals from the policy
    38  		for _, principal := range pol.Identities {
    39  			principals = append(principals, principal)
    40  		}
    41  		principalSetsByCollections[staticCol.Name] = principals
    42  	}
    43  	return principalSetsByCollections, nil
    44  }
    45  
    46  type principalSetsByCollectionName map[string]policies.PrincipalSet
    47  
    48  // toIdentityFilter converts this principalSetsByCollectionName mapping to a filter
    49  // which accepts or rejects identities of peers.
    50  func (psbc principalSetsByCollectionName) toIdentityFilter(channel string, evaluator principalEvaluator, cc *ChaincodeCall) (identityFilter, error) {
    51  	var principalSets policies.PrincipalSets
    52  	for _, col := range cc.CollectionNames {
    53  		// Each collection we're interested in should exist in the principalSetsByCollectionName mapping.
    54  		// Otherwise, we have no way of computing a filter because we can't locate the principals the peer identities
    55  		// need to satisfy.
    56  		principalSet, exists := psbc[col]
    57  		if !exists {
    58  			return nil, errors.Errorf("collection %s doesn't exist in collection config for chaincode %s", col, cc.Name)
    59  		}
    60  		principalSets = append(principalSets, principalSet)
    61  	}
    62  	return filterForPrincipalSets(channel, evaluator, principalSets), nil
    63  }
    64  
    65  // filterForPrincipalSets creates a filter of peer identities out of the given PrincipalSets
    66  func filterForPrincipalSets(channel string, evaluator principalEvaluator, sets policies.PrincipalSets) identityFilter {
    67  	return func(identity api.PeerIdentityType) bool {
    68  		// Iterate over all principal sets and ensure each principal set
    69  		// authorizes the identity.
    70  		for _, principalSet := range sets {
    71  			if !isIdentityAuthorizedByPrincipalSet(channel, evaluator, principalSet, identity) {
    72  				return false
    73  			}
    74  		}
    75  		return true
    76  	}
    77  }
    78  
    79  // isIdentityAuthorizedByPrincipalSet returns whether the given identity satisfies some principal out of the given PrincipalSet
    80  func isIdentityAuthorizedByPrincipalSet(channel string, evaluator principalEvaluator, principalSet policies.PrincipalSet, identity api.PeerIdentityType) bool {
    81  	// We look for a principal which authorizes the identity
    82  	// among all principals in the principalSet
    83  	for _, principal := range principalSet {
    84  		err := evaluator.SatisfiesPrincipal(channel, identity, principal)
    85  		if err != nil {
    86  			continue
    87  		}
    88  		// Else, err is nil, so we found a principal which authorized
    89  		// the given identity.
    90  		return true
    91  	}
    92  	return false
    93  }