github.com/ewagmig/fabric@v2.1.1+incompatible/core/policy/policy.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package policy
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  
    13  	pb "github.com/hyperledger/fabric-protos-go/peer"
    14  	"github.com/hyperledger/fabric/common/policies"
    15  	"github.com/hyperledger/fabric/msp"
    16  	"github.com/hyperledger/fabric/msp/mgmt"
    17  	"github.com/hyperledger/fabric/protoutil"
    18  )
    19  
    20  // PolicyChecker offers methods to check a signed proposal against a specific policy
    21  // defined in a channel or not.
    22  type PolicyChecker interface {
    23  	// CheckPolicy checks that the passed signed proposal is valid with the respect to
    24  	// passed policy on the passed channel.
    25  	// If no channel is passed, CheckPolicyNoChannel is invoked directly.
    26  	CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal) error
    27  
    28  	// CheckPolicyBySignedData checks that the passed signed data is valid with the respect to
    29  	// passed policy on the passed channel.
    30  	// If no channel is passed, the method will fail.
    31  	CheckPolicyBySignedData(channelID, policyName string, sd []*protoutil.SignedData) error
    32  
    33  	// CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to
    34  	// passed policy on the local MSP.
    35  	CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error
    36  }
    37  
    38  type policyChecker struct {
    39  	channelPolicyManagerGetter policies.ChannelPolicyManagerGetter
    40  	localMSP                   msp.IdentityDeserializer
    41  	principalGetter            mgmt.MSPPrincipalGetter
    42  }
    43  
    44  // NewPolicyChecker creates a new instance of PolicyChecker
    45  func NewPolicyChecker(channelPolicyManagerGetter policies.ChannelPolicyManagerGetter, localMSP msp.IdentityDeserializer, principalGetter mgmt.MSPPrincipalGetter) PolicyChecker {
    46  	return &policyChecker{channelPolicyManagerGetter, localMSP, principalGetter}
    47  }
    48  
    49  // CheckPolicy checks that the passed signed proposal is valid with the respect to
    50  // passed policy on the passed channel.
    51  func (p *policyChecker) CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal) error {
    52  	if channelID == "" {
    53  		return p.CheckPolicyNoChannel(policyName, signedProp)
    54  	}
    55  
    56  	if policyName == "" {
    57  		return fmt.Errorf("Invalid policy name during check policy on channel [%s]. Name must be different from nil.", channelID)
    58  	}
    59  
    60  	if signedProp == nil {
    61  		return fmt.Errorf("Invalid signed proposal during check policy on channel [%s] with policy [%s]", channelID, policyName)
    62  	}
    63  
    64  	// Get Policy
    65  	policyManager := p.channelPolicyManagerGetter.Manager(channelID)
    66  	if policyManager == nil {
    67  		return fmt.Errorf("Failed to get policy manager for channel [%s]", channelID)
    68  	}
    69  
    70  	// Prepare SignedData
    71  	proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes)
    72  	if err != nil {
    73  		return fmt.Errorf("Failing extracting proposal during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
    74  	}
    75  
    76  	header, err := protoutil.UnmarshalHeader(proposal.Header)
    77  	if err != nil {
    78  		return fmt.Errorf("Failing extracting header during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
    79  	}
    80  
    81  	shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader)
    82  	if err != nil {
    83  		return fmt.Errorf("Invalid Proposal's SignatureHeader during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
    84  	}
    85  
    86  	sd := []*protoutil.SignedData{{
    87  		Data:      signedProp.ProposalBytes,
    88  		Identity:  shdr.Creator,
    89  		Signature: signedProp.Signature,
    90  	}}
    91  
    92  	return p.CheckPolicyBySignedData(channelID, policyName, sd)
    93  }
    94  
    95  // CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to
    96  // passed policy on the local MSP.
    97  func (p *policyChecker) CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error {
    98  	if policyName == "" {
    99  		return errors.New("Invalid policy name during channelless check policy. Name must be different from nil.")
   100  	}
   101  
   102  	if signedProp == nil {
   103  		return fmt.Errorf("Invalid signed proposal during channelless check policy with policy [%s]", policyName)
   104  	}
   105  
   106  	proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes)
   107  	if err != nil {
   108  		return fmt.Errorf("Failing extracting proposal during channelless check policy with policy [%s]: [%s]", policyName, err)
   109  	}
   110  
   111  	header, err := protoutil.UnmarshalHeader(proposal.Header)
   112  	if err != nil {
   113  		return fmt.Errorf("Failing extracting header during channelless check policy with policy [%s]: [%s]", policyName, err)
   114  	}
   115  
   116  	shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader)
   117  	if err != nil {
   118  		return fmt.Errorf("Invalid Proposal's SignatureHeader during channelless check policy with policy [%s]: [%s]", policyName, err)
   119  	}
   120  
   121  	// Deserialize proposal's creator with the local MSP
   122  	id, err := p.localMSP.DeserializeIdentity(shdr.Creator)
   123  	if err != nil {
   124  		return fmt.Errorf("Failed deserializing proposal creator during channelless check policy with policy [%s]: [%s]", policyName, err)
   125  	}
   126  
   127  	// Load MSPPrincipal for policy
   128  	principal, err := p.principalGetter.Get(policyName)
   129  	if err != nil {
   130  		return fmt.Errorf("Failed getting local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err)
   131  	}
   132  
   133  	// Verify that proposal's creator satisfies the principal
   134  	err = id.SatisfiesPrincipal(principal)
   135  	if err != nil {
   136  		return fmt.Errorf("Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err)
   137  	}
   138  
   139  	// Verify the signature
   140  	return id.Verify(signedProp.ProposalBytes, signedProp.Signature)
   141  }
   142  
   143  // CheckPolicyBySignedData checks that the passed signed data is valid with the respect to
   144  // passed policy on the passed channel.
   145  func (p *policyChecker) CheckPolicyBySignedData(channelID, policyName string, sd []*protoutil.SignedData) error {
   146  	if channelID == "" {
   147  		return errors.New("Invalid channel ID name during check policy on signed data. Name must be different from nil.")
   148  	}
   149  
   150  	if policyName == "" {
   151  		return fmt.Errorf("Invalid policy name during check policy on signed data on channel [%s]. Name must be different from nil.", channelID)
   152  	}
   153  
   154  	if sd == nil {
   155  		return fmt.Errorf("Invalid signed data during check policy on channel [%s] with policy [%s]", channelID, policyName)
   156  	}
   157  
   158  	// Get Policy
   159  	policyManager := p.channelPolicyManagerGetter.Manager(channelID)
   160  	if policyManager == nil {
   161  		return fmt.Errorf("Failed to get policy manager for channel [%s]", channelID)
   162  	}
   163  
   164  	// Recall that get policy always returns a policy object
   165  	policy, _ := policyManager.GetPolicy(policyName)
   166  
   167  	// Evaluate the policy
   168  	err := policy.EvaluateSignedData(sd)
   169  	if err != nil {
   170  		return fmt.Errorf("Failed evaluating policy on signed data during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err)
   171  	}
   172  
   173  	return nil
   174  }