93 lines
3.5 KiB
Go
93 lines
3.5 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package endorsement
|
|
|
|
import (
|
|
"github.com/hyperledger/fabric-protos-go/peer"
|
|
"github.com/hyperledger/fabric/common/policies"
|
|
"github.com/hyperledger/fabric/gossip/api"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
func principalsFromCollectionConfig(ccp *peer.CollectionConfigPackage) (principalSetsByCollectionName, error) {
|
|
principalSetsByCollections := make(principalSetsByCollectionName)
|
|
if ccp == nil {
|
|
return principalSetsByCollections, nil
|
|
}
|
|
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 *peer.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
|
|
}
|