github.com/true-sqn/fabric@v2.1.1+incompatible/core/policy/application.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policy
     8  
     9  import (
    10  	"github.com/golang/protobuf/proto"
    11  	"github.com/hyperledger/fabric-protos-go/common"
    12  	"github.com/hyperledger/fabric-protos-go/peer"
    13  	"github.com/hyperledger/fabric/common/cauthdsl"
    14  	"github.com/hyperledger/fabric/common/policies"
    15  	"github.com/hyperledger/fabric/msp"
    16  	"github.com/hyperledger/fabric/protoutil"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  //go:generate mockery -dir . -name Policy -case underscore -output mocks/
    21  
    22  // Policy is the local interface that used to generate mocks for foreign interface.
    23  type Policy interface {
    24  	policies.Policy
    25  }
    26  
    27  //go:generate mockery -dir . -name ChannelPolicyManagerGetter -case underscore -output mocks/
    28  
    29  // ChannelPolicyManagerGetter is the local interface that used to generate mocks for foreign interface.
    30  type ChannelPolicyManagerGetter interface {
    31  	policies.ChannelPolicyManagerGetter
    32  }
    33  
    34  //go:generate mockery -dir . -name PolicyManager -case underscore -output mocks/
    35  
    36  // PolicyManager is the local interface that used to generate mocks for foreign interface.
    37  type PolicyManager interface {
    38  	policies.Manager
    39  }
    40  
    41  //go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/
    42  
    43  // IdentityDeserializer is the local interface that used to generate mocks for foreign interface.
    44  type IdentityDeserializer interface {
    45  	msp.IdentityDeserializer
    46  }
    47  
    48  //go:generate mockery -dir . -name Identity -case underscore -output mocks/
    49  
    50  // Identity is the local interface that used to generate mocks for foreign interface.
    51  type Identity interface {
    52  	msp.Identity
    53  }
    54  
    55  //go:generate mockery -dir . -name ChannelPolicyReferenceProvider -case underscore -output mocks/
    56  //go:generate mockery -dir . -name SignaturePolicyProvider -case underscore -output mocks/
    57  
    58  // SignaturePolicyProvider provides the backing implementation of a policy.
    59  type SignaturePolicyProvider interface {
    60  	// NewPolicy creates a new policy based on the policy bytes.
    61  	NewPolicy(signaturePolicy *common.SignaturePolicyEnvelope) (policies.Policy, error)
    62  }
    63  
    64  // ChannelPolicyReferenceProvider is used to determine if a set of signature is valid and complies with a policy.
    65  type ChannelPolicyReferenceProvider interface {
    66  	// NewPolicy creates a new policy based on the policy bytes.
    67  	NewPolicy(channelConfigPolicyReference string) (policies.Policy, error)
    68  }
    69  
    70  type ApplicationPolicyEvaluator struct {
    71  	signaturePolicyProvider        SignaturePolicyProvider
    72  	channelPolicyReferenceProvider ChannelPolicyReferenceProvider
    73  }
    74  
    75  // Manager defines functions to interface with the policy manager of a channel
    76  type Manager interface {
    77  	// GetPolicy returns a policy and true if it was the policy requested, or false if it is the default policy
    78  	GetPolicy(id string) (policies.Policy, bool)
    79  }
    80  
    81  type ChannelPolicyReferenceProviderImpl struct {
    82  	Manager
    83  }
    84  
    85  func (c *ChannelPolicyReferenceProviderImpl) NewPolicy(channelConfigPolicyReference string) (policies.Policy, error) {
    86  	p, ok := c.GetPolicy(channelConfigPolicyReference)
    87  	if !ok {
    88  		return nil, errors.Errorf("failed to retrieve policy for reference %s", channelConfigPolicyReference)
    89  	}
    90  
    91  	return p, nil
    92  }
    93  
    94  // dynamicPolicyManager implements a policy manager that
    95  // always acts on the latest config for this channel
    96  type dynamicPolicyManager struct {
    97  	channelPolicyManagerGetter policies.ChannelPolicyManagerGetter
    98  	channelID                  string
    99  }
   100  
   101  func (d *dynamicPolicyManager) GetPolicy(id string) (policies.Policy, bool) {
   102  	mgr := d.channelPolicyManagerGetter.Manager(d.channelID)
   103  	if mgr == nil {
   104  		// this will never happen - if we are here we
   105  		// managed to retrieve the policy manager for
   106  		// this channel once, and so by the way the
   107  		// channel config is managed, we cannot fail.
   108  		panic("programming error")
   109  	}
   110  
   111  	return mgr.GetPolicy(id)
   112  }
   113  
   114  // New returns an evaluator for application policies
   115  func New(deserializer msp.IdentityDeserializer, channel string, channelPolicyManagerGetter policies.ChannelPolicyManagerGetter) (*ApplicationPolicyEvaluator, error) {
   116  	mgr := channelPolicyManagerGetter.Manager(channel)
   117  	if mgr == nil {
   118  		return nil, errors.Errorf("failed to retrieve policy manager for channel %s", channel)
   119  	}
   120  
   121  	return &ApplicationPolicyEvaluator{
   122  		signaturePolicyProvider: &cauthdsl.EnvelopeBasedPolicyProvider{Deserializer: deserializer},
   123  		channelPolicyReferenceProvider: &ChannelPolicyReferenceProviderImpl{Manager: &dynamicPolicyManager{
   124  			channelID:                  channel,
   125  			channelPolicyManagerGetter: channelPolicyManagerGetter,
   126  		}},
   127  	}, nil
   128  }
   129  
   130  func (a *ApplicationPolicyEvaluator) evaluateSignaturePolicy(signaturePolicy *common.SignaturePolicyEnvelope, signatureSet []*protoutil.SignedData) error {
   131  	p, err := a.signaturePolicyProvider.NewPolicy(signaturePolicy)
   132  	if err != nil {
   133  		return errors.WithMessage(err, "could not create evaluator for signature policy")
   134  	}
   135  
   136  	return p.EvaluateSignedData(signatureSet)
   137  }
   138  
   139  func (a *ApplicationPolicyEvaluator) evaluateChannelConfigPolicyReference(channelConfigPolicyReference string, signatureSet []*protoutil.SignedData) error {
   140  	p, err := a.channelPolicyReferenceProvider.NewPolicy(channelConfigPolicyReference)
   141  	if err != nil {
   142  		return errors.WithMessage(err, "could not create evaluator for channel reference policy")
   143  	}
   144  
   145  	return p.EvaluateSignedData(signatureSet)
   146  }
   147  
   148  func (a *ApplicationPolicyEvaluator) Evaluate(policyBytes []byte, signatureSet []*protoutil.SignedData) error {
   149  	p := &peer.ApplicationPolicy{}
   150  	err := proto.Unmarshal(policyBytes, p)
   151  	if err != nil {
   152  		return errors.Wrap(err, "failed to unmarshal ApplicationPolicy bytes")
   153  	}
   154  
   155  	switch policy := p.Type.(type) {
   156  	case *peer.ApplicationPolicy_SignaturePolicy:
   157  		return a.evaluateSignaturePolicy(policy.SignaturePolicy, signatureSet)
   158  	case *peer.ApplicationPolicy_ChannelConfigPolicyReference:
   159  		return a.evaluateChannelConfigPolicyReference(policy.ChannelConfigPolicyReference, signatureSet)
   160  	default:
   161  		return errors.Errorf("unsupported policy type %T", policy)
   162  	}
   163  }