117 lines
3.2 KiB
Go
117 lines
3.2 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package cauthdsl
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
cb "github.com/hyperledger/fabric-protos-go/common"
|
|
"github.com/hyperledger/fabric/common/policies"
|
|
"github.com/hyperledger/fabric/msp"
|
|
"github.com/hyperledger/fabric/protoutil"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type provider struct {
|
|
deserializer msp.IdentityDeserializer
|
|
}
|
|
|
|
// NewPolicyProvider provides a policy generator for cauthdsl type policies
|
|
func NewPolicyProvider(deserializer msp.IdentityDeserializer) policies.Provider {
|
|
return &provider{
|
|
deserializer: deserializer,
|
|
}
|
|
}
|
|
|
|
// NewPolicy creates a new policy based on the policy bytes
|
|
func (pr *provider) NewPolicy(data []byte) (policies.Policy, proto.Message, error) {
|
|
sigPolicy := &cb.SignaturePolicyEnvelope{}
|
|
if err := proto.Unmarshal(data, sigPolicy); err != nil {
|
|
return nil, nil, fmt.Errorf("Error unmarshalling to SignaturePolicy: %s", err)
|
|
}
|
|
|
|
if sigPolicy.Version != 0 {
|
|
return nil, nil, fmt.Errorf("This evaluator only understands messages of version 0, but version was %d", sigPolicy.Version)
|
|
}
|
|
|
|
compiled, err := compile(sigPolicy.Rule, sigPolicy.Identities)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
return &policy{
|
|
evaluator: compiled,
|
|
deserializer: pr.deserializer,
|
|
signaturePolicyEnvelope: sigPolicy,
|
|
}, sigPolicy, nil
|
|
}
|
|
|
|
// EnvelopeBasedPolicyProvider allows to create a new policy from SignaturePolicyEnvelope struct instead of []byte
|
|
type EnvelopeBasedPolicyProvider struct {
|
|
Deserializer msp.IdentityDeserializer
|
|
}
|
|
|
|
// NewPolicy creates a new policy from the policy envelope
|
|
func (pp *EnvelopeBasedPolicyProvider) NewPolicy(sigPolicy *cb.SignaturePolicyEnvelope) (policies.Policy, error) {
|
|
if sigPolicy == nil {
|
|
return nil, errors.New("invalid arguments")
|
|
}
|
|
|
|
compiled, err := compile(sigPolicy.Rule, sigPolicy.Identities)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &policy{
|
|
evaluator: compiled,
|
|
deserializer: pp.Deserializer,
|
|
signaturePolicyEnvelope: sigPolicy,
|
|
}, nil
|
|
}
|
|
|
|
type policy struct {
|
|
signaturePolicyEnvelope *cb.SignaturePolicyEnvelope
|
|
evaluator func([]msp.Identity, []bool) bool
|
|
deserializer msp.IdentityDeserializer
|
|
}
|
|
|
|
// EvaluateSignedData takes a set of SignedData and evaluates whether
|
|
// 1) the signatures are valid over the related message
|
|
// 2) the signing identities satisfy the policy
|
|
func (p *policy) EvaluateSignedData(signatureSet []*protoutil.SignedData) error {
|
|
if p == nil {
|
|
return errors.New("no such policy")
|
|
}
|
|
|
|
ids := policies.SignatureSetToValidIdentities(signatureSet, p.deserializer)
|
|
|
|
return p.EvaluateIdentities(ids)
|
|
}
|
|
|
|
// EvaluateIdentities takes an array of identities and evaluates whether
|
|
// they satisfy the policy
|
|
func (p *policy) EvaluateIdentities(identities []msp.Identity) error {
|
|
if p == nil {
|
|
return fmt.Errorf("No such policy")
|
|
}
|
|
|
|
ok := p.evaluator(identities, make([]bool, len(identities)))
|
|
if !ok {
|
|
return errors.New("signature set did not satisfy policy")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (p *policy) Convert() (*cb.SignaturePolicyEnvelope, error) {
|
|
if p.signaturePolicyEnvelope == nil {
|
|
return nil, errors.New("nil policy field")
|
|
}
|
|
|
|
return p.signaturePolicyEnvelope, nil
|
|
}
|