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