1 Star 0 Fork 0

陈文甲 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
policy.go 9.13 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package policies
import (
"fmt"
"strings"
"github.com/hyperledger/fabric/common/flogging"
cb "github.com/hyperledger/fabric/protos/common"
"go.uber.org/zap/zapcore"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/protos/msp"
"github.com/pkg/errors"
)
const (
// Path separator is used to separate policy names in paths
PathSeparator = "/"
// ChannelPrefix is used in the path of standard channel policy managers
ChannelPrefix = "Channel"
// ApplicationPrefix is used in the path of standard application policy paths
ApplicationPrefix = "Application"
// OrdererPrefix is used in the path of standard orderer policy paths
OrdererPrefix = "Orderer"
// ChannelReaders is the label for the channel's readers policy (encompassing both orderer and application readers)
ChannelReaders = PathSeparator + ChannelPrefix + PathSeparator + "Readers"
// ChannelWriters is the label for the channel's writers policy (encompassing both orderer and application writers)
ChannelWriters = PathSeparator + ChannelPrefix + PathSeparator + "Writers"
// ChannelApplicationReaders is the label for the channel's application readers policy
ChannelApplicationReaders = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Readers"
// ChannelApplicationWriters is the label for the channel's application writers policy
ChannelApplicationWriters = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Writers"
// ChannelApplicationAdmins is the label for the channel's application admin policy
ChannelApplicationAdmins = PathSeparator + ChannelPrefix + PathSeparator + ApplicationPrefix + PathSeparator + "Admins"
// BlockValidation is the label for the policy which should validate the block signatures for the channel
BlockValidation = PathSeparator + ChannelPrefix + PathSeparator + OrdererPrefix + PathSeparator + "BlockValidation"
)
var logger = flogging.MustGetLogger("policies")
// PrincipalSet is a collection of MSPPrincipals
type PrincipalSet []*msp.MSPPrincipal
// PrincipalSets aggregates PrincipalSets
type PrincipalSets []PrincipalSet
// ContainingOnly returns PrincipalSets that contain only principals of the given predicate
func (psSets PrincipalSets) ContainingOnly(f func(*msp.MSPPrincipal) bool) PrincipalSets {
var res PrincipalSets
for _, set := range psSets {
if !set.ContainingOnly(f) {
continue
}
res = append(res, set)
}
return res
}
// ContainingOnly returns whether the given PrincipalSet contains only Principals
// that satisfy the given predicate
func (ps PrincipalSet) ContainingOnly(f func(*msp.MSPPrincipal) bool) bool {
for _, principal := range ps {
if !f(principal) {
return false
}
}
return true
}
// UniqueSet returns a histogram that is induced by the PrincipalSet
func (ps PrincipalSet) UniqueSet() map[*msp.MSPPrincipal]int {
// Create a histogram that holds the MSPPrincipals and counts them
histogram := make(map[struct {
cls int32
principal string
}]int)
// Now, populate the histogram
for _, principal := range ps {
key := struct {
cls int32
principal string
}{
cls: int32(principal.PrincipalClassification),
principal: string(principal.Principal),
}
histogram[key]++
}
// Finally, convert to a histogram of MSPPrincipal pointers
res := make(map[*msp.MSPPrincipal]int)
for principal, count := range histogram {
res[&msp.MSPPrincipal{
PrincipalClassification: msp.MSPPrincipal_Classification(principal.cls),
Principal: []byte(principal.principal),
}] = count
}
return res
}
// Policy is used to determine if a signature is valid
type Policy interface {
// Evaluate takes a set of SignedData and evaluates whether this set of signatures satisfies the policy
Evaluate(signatureSet []*cb.SignedData) error
}
// InquireablePolicy is a Policy that one can inquire
type InquireablePolicy interface {
// SatisfiedBy returns a slice of PrincipalSets that each of them
// satisfies the policy.
SatisfiedBy() []PrincipalSet
}
// Manager is a read only subset of the policy ManagerImpl
type Manager interface {
// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default policy
GetPolicy(id string) (Policy, bool)
// Manager returns the sub-policy manager for a given path and whether it exists
Manager(path []string) (Manager, bool)
}
// Provider provides the backing implementation of a policy
type Provider interface {
// NewPolicy creates a new policy based on the policy bytes
NewPolicy(data []byte) (Policy, proto.Message, error)
}
// ChannelPolicyManagerGetter is a support interface
// to get access to the policy manager of a given channel
type ChannelPolicyManagerGetter interface {
// Returns the policy manager associated to the passed channel
// and true if it was the manager requested, or false if it is the default manager
Manager(channelID string) (Manager, bool)
}
// ManagerImpl is an implementation of Manager and configtx.ConfigHandler
// In general, it should only be referenced as an Impl for the configtx.ConfigManager
type ManagerImpl struct {
path string // The group level path
policies map[string]Policy
managers map[string]*ManagerImpl
}
// NewManagerImpl creates a new ManagerImpl with the given CryptoHelper
func NewManagerImpl(path string, providers map[int32]Provider, root *cb.ConfigGroup) (*ManagerImpl, error) {
var err error
_, ok := providers[int32(cb.Policy_IMPLICIT_META)]
if ok {
logger.Panicf("ImplicitMetaPolicy type must be provider by the policy manager")
}
managers := make(map[string]*ManagerImpl)
for groupName, group := range root.Groups {
managers[groupName], err = NewManagerImpl(path+PathSeparator+groupName, providers, group)
if err != nil {
return nil, err
}
}
policies := make(map[string]Policy)
for policyName, configPolicy := range root.Policies {
policy := configPolicy.Policy
if policy == nil {
return nil, fmt.Errorf("policy %s at path %s was nil", policyName, path)
}
var cPolicy Policy
if policy.Type == int32(cb.Policy_IMPLICIT_META) {
imp, err := newImplicitMetaPolicy(policy.Value, managers)
if err != nil {
return nil, errors.Wrapf(err, "implicit policy %s at path %s did not compile", policyName, path)
}
cPolicy = imp
} else {
provider, ok := providers[int32(policy.Type)]
if !ok {
return nil, fmt.Errorf("policy %s at path %s has unknown policy type: %v", policyName, path, policy.Type)
}
var err error
cPolicy, _, err = provider.NewPolicy(policy.Value)
if err != nil {
return nil, errors.Wrapf(err, "policy %s at path %s did not compile", policyName, path)
}
}
policies[policyName] = cPolicy
logger.Debugf("Proposed new policy %s for %s", policyName, path)
}
for groupName, manager := range managers {
for policyName, policy := range manager.policies {
policies[groupName+PathSeparator+policyName] = policy
}
}
return &ManagerImpl{
path: path,
policies: policies,
managers: managers,
}, nil
}
type rejectPolicy string
func (rp rejectPolicy) Evaluate(signedData []*cb.SignedData) error {
return fmt.Errorf("No such policy: '%s'", rp)
}
// Manager returns the sub-policy manager for a given path and whether it exists
func (pm *ManagerImpl) Manager(path []string) (Manager, bool) {
logger.Debugf("Manager %s looking up path %v", pm.path, path)
for manager := range pm.managers {
logger.Debugf("Manager %s has managers %s", pm.path, manager)
}
if len(path) == 0 {
return pm, true
}
m, ok := pm.managers[path[0]]
if !ok {
return nil, false
}
return m.Manager(path[1:])
}
type policyLogger struct {
policy Policy
policyName string
}
func (pl *policyLogger) Evaluate(signatureSet []*cb.SignedData) error {
if logger.IsEnabledFor(zapcore.DebugLevel) {
logger.Debugf("== Evaluating %T Policy %s ==", pl.policy, pl.policyName)
defer logger.Debugf("== Done Evaluating %T Policy %s", pl.policy, pl.policyName)
}
err := pl.policy.Evaluate(signatureSet)
if err != nil {
logger.Debugf("Signature set did not satisfy policy %s", pl.policyName)
} else {
logger.Debugf("Signature set satisfies policy %s", pl.policyName)
}
return err
}
// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default reject policy
func (pm *ManagerImpl) GetPolicy(id string) (Policy, bool) {
if id == "" {
logger.Errorf("Returning dummy reject all policy because no policy ID supplied")
return rejectPolicy(id), false
}
var relpath string
if strings.HasPrefix(id, PathSeparator) {
if !strings.HasPrefix(id, PathSeparator+pm.path) {
logger.Debugf("Requested absolute policy %s from %s, returning rejectAll", id, pm.path)
return rejectPolicy(id), false
}
// strip off the leading slash, the path, and the trailing slash
relpath = id[1+len(pm.path)+1:]
} else {
relpath = id
}
policy, ok := pm.policies[relpath]
if !ok {
logger.Debugf("Returning dummy reject all policy because %s could not be found in %s/%s", id, pm.path, relpath)
return rejectPolicy(relpath), false
}
return &policyLogger{
policy: policy,
policyName: PathSeparator + pm.path + PathSeparator + relpath,
}, true
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/venjia/fabric.git
git@gitee.com:venjia/fabric.git
venjia
fabric
fabric
v1.3.0-rc1

搜索帮助

344bd9b3 5694891 D2dac590 5694891