145 lines
4.1 KiB
Go
145 lines
4.1 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package policies
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
cb "github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric/msp"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
type ImplicitMetaPolicy struct {
|
|
Threshold int
|
|
SubPolicies []Policy
|
|
|
|
// Only used for logging
|
|
managers map[string]*ManagerImpl
|
|
SubPolicyName string
|
|
}
|
|
|
|
// NewPolicy creates a new policy based on the policy bytes
|
|
func NewImplicitMetaPolicy(data []byte, managers map[string]*ManagerImpl) (*ImplicitMetaPolicy, error) {
|
|
definition := &cb.ImplicitMetaPolicy{}
|
|
if err := proto.Unmarshal(data, definition); err != nil {
|
|
return nil, fmt.Errorf("Error unmarshalling to ImplicitMetaPolicy: %s", err)
|
|
}
|
|
|
|
subPolicies := make([]Policy, len(managers))
|
|
|
|
i := 0
|
|
for _, manager := range managers {
|
|
subPolicies[i], _ = manager.GetPolicy(definition.SubPolicy)
|
|
i++
|
|
}
|
|
|
|
var threshold int
|
|
|
|
switch definition.Rule {
|
|
case cb.ImplicitMetaPolicy_ANY:
|
|
threshold = 1
|
|
case cb.ImplicitMetaPolicy_ALL:
|
|
threshold = len(subPolicies)
|
|
case cb.ImplicitMetaPolicy_MAJORITY:
|
|
threshold = len(subPolicies)/2 + 1
|
|
}
|
|
|
|
// In the special case that there are no policies, consider 0 to be a majority or any
|
|
if len(subPolicies) == 0 {
|
|
threshold = 0
|
|
}
|
|
|
|
return &ImplicitMetaPolicy{
|
|
SubPolicies: subPolicies,
|
|
Threshold: threshold,
|
|
managers: managers,
|
|
SubPolicyName: definition.SubPolicy,
|
|
}, nil
|
|
}
|
|
|
|
// EvaluateSignedData takes a set of SignedData and evaluates whether this set of signatures satisfies the policy
|
|
func (imp *ImplicitMetaPolicy) EvaluateSignedData(signatureSet []*protoutil.SignedData) error {
|
|
logger.Debugf("This is an implicit meta policy, it will trigger other policy evaluations, whose failures may be benign")
|
|
remaining := imp.Threshold
|
|
|
|
defer func() {
|
|
if remaining != 0 {
|
|
// This log message may be large and expensive to construct, so worth checking the log level
|
|
if logger.IsEnabledFor(zapcore.DebugLevel) {
|
|
var b bytes.Buffer
|
|
b.WriteString(fmt.Sprintf("Evaluation Failed: Only %d policies were satisfied, but needed %d of [ ", imp.Threshold-remaining, imp.Threshold))
|
|
for m := range imp.managers {
|
|
b.WriteString(m)
|
|
b.WriteString("/")
|
|
b.WriteString(imp.SubPolicyName)
|
|
b.WriteString(" ")
|
|
}
|
|
b.WriteString("]")
|
|
logger.Debugf(b.String())
|
|
}
|
|
}
|
|
}()
|
|
|
|
for _, policy := range imp.SubPolicies {
|
|
if policy.EvaluateSignedData(signatureSet) == nil {
|
|
remaining--
|
|
if remaining == 0 {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
if remaining == 0 {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("implicit policy evaluation failed - %d sub-policies were satisfied, but this policy requires %d of the '%s' sub-policies to be satisfied", (imp.Threshold - remaining), imp.Threshold, imp.SubPolicyName)
|
|
}
|
|
|
|
// EvaluateIdentities takes an array of identities and evaluates whether
|
|
// they satisfy the policy
|
|
func (imp *ImplicitMetaPolicy) EvaluateIdentities(identities []msp.Identity) error {
|
|
logger.Debugf("This is an implicit meta policy, it will trigger other policy evaluations, whose failures may be benign")
|
|
remaining := imp.Threshold
|
|
|
|
defer func() {
|
|
// This log message may be large and expensive to construct, so worth checking the log level
|
|
if remaining == 0 {
|
|
return
|
|
}
|
|
if !logger.IsEnabledFor(zapcore.DebugLevel) {
|
|
return
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
b.WriteString(fmt.Sprintf("Evaluation Failed: Only %d policies were satisfied, but needed %d of [ ", imp.Threshold-remaining, imp.Threshold))
|
|
for m := range imp.managers {
|
|
b.WriteString(m)
|
|
b.WriteString("/")
|
|
b.WriteString(imp.SubPolicyName)
|
|
b.WriteString(" ")
|
|
}
|
|
b.WriteString("]")
|
|
logger.Debugf(b.String())
|
|
}()
|
|
|
|
for _, policy := range imp.SubPolicies {
|
|
if policy.EvaluateIdentities(identities) == nil {
|
|
remaining--
|
|
if remaining == 0 {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
if remaining == 0 {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("implicit policy evaluation failed - %d sub-policies were satisfied, but this policy requires %d of the '%s' sub-policies to be satisfied", (imp.Threshold - remaining), imp.Threshold, imp.SubPolicyName)
|
|
}
|