github.com/defanghe/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 }