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 }