github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/policy/policy.go (about) 1 /* 2 Copyright hechain. 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 "github.com/hechain20/hechain/common/flogging" 14 "github.com/hechain20/hechain/common/policies" 15 "github.com/hechain20/hechain/msp" 16 "github.com/hechain20/hechain/protoutil" 17 pb "github.com/hyperledger/fabric-protos-go/peer" 18 ) 19 20 var logger = flogging.MustGetLogger("policy") 21 22 // PolicyChecker offers methods to check a signed proposal against a specific policy 23 // defined in a channel or not. 24 type PolicyChecker interface { 25 // CheckPolicy checks that the passed signed proposal is valid with the respect to 26 // passed policy on the passed channel. 27 // If no channel is passed, CheckPolicyNoChannel is invoked directly. 28 CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal) error 29 30 // CheckPolicyBySignedData checks that the passed signed data is valid with the respect to 31 // passed policy on the passed channel. 32 // If no channel is passed, the method will fail. 33 CheckPolicyBySignedData(channelID, policyName string, sd []*protoutil.SignedData) error 34 35 // CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to 36 // passed policy on the local MSP. 37 CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error 38 39 // CheckPolicyNoChannelBySignedData checks that the passed signed data is valid with the respect to 40 // passed policy on the local MSP. 41 CheckPolicyNoChannelBySignedData(policyName string, signedData []*protoutil.SignedData) error 42 } 43 44 type policyChecker struct { 45 channelPolicyManagerGetter policies.ChannelPolicyManagerGetter 46 localMSP msp.IdentityDeserializer 47 principalGetter MSPPrincipalGetter 48 } 49 50 // NewPolicyChecker creates a new instance of PolicyChecker 51 func NewPolicyChecker(channelPolicyManagerGetter policies.ChannelPolicyManagerGetter, localMSP msp.MSP) PolicyChecker { 52 return &policyChecker{ 53 channelPolicyManagerGetter: channelPolicyManagerGetter, 54 localMSP: localMSP, 55 principalGetter: &localMSPPrincipalGetter{localMSP: localMSP}, 56 } 57 } 58 59 // CheckPolicy checks that the passed signed proposal is valid with the respect to 60 // passed policy on the passed channel. 61 func (p *policyChecker) CheckPolicy(channelID, policyName string, signedProp *pb.SignedProposal) error { 62 if channelID == "" { 63 return p.CheckPolicyNoChannel(policyName, signedProp) 64 } 65 66 if policyName == "" { 67 return fmt.Errorf("Invalid policy name during check policy on channel [%s]. Name must be different from nil.", channelID) 68 } 69 70 if signedProp == nil { 71 return fmt.Errorf("Invalid signed proposal during check policy on channel [%s] with policy [%s]", channelID, policyName) 72 } 73 74 // Get Policy 75 policyManager := p.channelPolicyManagerGetter.Manager(channelID) 76 if policyManager == nil { 77 return fmt.Errorf("Failed to get policy manager for channel [%s]", channelID) 78 } 79 80 // Prepare SignedData 81 proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes) 82 if err != nil { 83 return fmt.Errorf("Failing extracting proposal during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err) 84 } 85 86 header, err := protoutil.UnmarshalHeader(proposal.Header) 87 if err != nil { 88 return fmt.Errorf("Failing extracting header during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err) 89 } 90 91 shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader) 92 if err != nil { 93 return fmt.Errorf("Invalid Proposal's SignatureHeader during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err) 94 } 95 96 sd := []*protoutil.SignedData{{ 97 Data: signedProp.ProposalBytes, 98 Identity: shdr.Creator, 99 Signature: signedProp.Signature, 100 }} 101 102 return p.CheckPolicyBySignedData(channelID, policyName, sd) 103 } 104 105 // CheckPolicyNoChannel checks that the passed signed proposal is valid with the respect to 106 // passed policy on the local MSP. 107 func (p *policyChecker) CheckPolicyNoChannel(policyName string, signedProp *pb.SignedProposal) error { 108 if policyName == "" { 109 return errors.New("Invalid policy name during channelless check policy. Name must be different from nil.") 110 } 111 112 if signedProp == nil { 113 return fmt.Errorf("Invalid signed proposal during channelless check policy with policy [%s]", policyName) 114 } 115 116 proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes) 117 if err != nil { 118 return fmt.Errorf("Failing extracting proposal during channelless check policy with policy [%s]: [%s]", policyName, err) 119 } 120 121 header, err := protoutil.UnmarshalHeader(proposal.Header) 122 if err != nil { 123 return fmt.Errorf("Failing extracting header during channelless check policy with policy [%s]: [%s]", policyName, err) 124 } 125 126 shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader) 127 if err != nil { 128 return fmt.Errorf("Invalid Proposal's SignatureHeader during channelless check policy with policy [%s]: [%s]", policyName, err) 129 } 130 131 // Deserialize proposal's creator with the local MSP 132 id, err := p.localMSP.DeserializeIdentity(shdr.Creator) 133 if err != nil { 134 logger.Warnw("Failed deserializing proposal creator during channelless check policy", "error", err, "policyName", policyName, "identity", protoutil.LogMessageForSerializedIdentity(shdr.Creator)) 135 return fmt.Errorf("Failed deserializing proposal creator during channelless check policy with policy [%s]: [%s]", policyName, err) 136 } 137 138 // Load MSPPrincipal for policy 139 principal, err := p.principalGetter.Get(policyName) 140 if err != nil { 141 return fmt.Errorf("Failed getting local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err) 142 } 143 144 // Verify that proposal's creator satisfies the principal 145 err = id.SatisfiesPrincipal(principal) 146 if err != nil { 147 logger.Warnw("Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy", "error", err, "policyName", policyName, "requiredPrincipal", principal, "signingIdentity", protoutil.LogMessageForSerializedIdentity(shdr.Creator)) 148 return fmt.Errorf("Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err) 149 } 150 151 // Verify the signature 152 return id.Verify(signedProp.ProposalBytes, signedProp.Signature) 153 } 154 155 // CheckPolicyBySignedData checks that the passed signed data is valid with the respect to 156 // passed policy on the passed channel. 157 func (p *policyChecker) CheckPolicyBySignedData(channelID, policyName string, sd []*protoutil.SignedData) error { 158 if channelID == "" { 159 return errors.New("Invalid channel ID name during check policy on signed data. Name must be different from nil.") 160 } 161 162 if policyName == "" { 163 return fmt.Errorf("Invalid policy name during check policy on signed data on channel [%s]. Name must be different from nil.", channelID) 164 } 165 166 if sd == nil { 167 return fmt.Errorf("Invalid signed data during check policy on channel [%s] with policy [%s]", channelID, policyName) 168 } 169 170 // Get Policy 171 policyManager := p.channelPolicyManagerGetter.Manager(channelID) 172 if policyManager == nil { 173 return fmt.Errorf("Failed to get policy manager for channel [%s]", channelID) 174 } 175 176 // Recall that get policy always returns a policy object 177 policy, _ := policyManager.GetPolicy(policyName) 178 179 // Evaluate the policy 180 err := policy.EvaluateSignedData(sd) 181 if err != nil { 182 logger.Warnw("Failed evaluating policy on signed data", "error", err, "policyName", policyName, "identities", protoutil.LogMessageForSerializedIdentities(sd)) 183 return fmt.Errorf("Failed evaluating policy on signed data during check policy on channel [%s] with policy [%s]: [%s]", channelID, policyName, err) 184 } 185 186 return nil 187 } 188 189 // CheckPolicyNoChannelBySignedData checks that the passed signed data are valid with the respect to 190 // passed policy on the local MSP. 191 func (p *policyChecker) CheckPolicyNoChannelBySignedData(policyName string, signedData []*protoutil.SignedData) error { 192 if policyName == "" { 193 return errors.New("invalid policy name during channelless check policy. Name must be different from nil.") 194 } 195 196 if len(signedData) == 0 { 197 return fmt.Errorf("no signed data during channelless check policy with policy [%s]", policyName) 198 } 199 200 for _, data := range signedData { 201 // Deserialize identity with the local MSP 202 id, err := p.localMSP.DeserializeIdentity(data.Identity) 203 if err != nil { 204 logger.Warnw("Failed deserializing signed data identity during channelless check policy", "error", err, "policyName", policyName, "identity", protoutil.LogMessageForSerializedIdentity(data.Identity)) 205 return fmt.Errorf("failed deserializing signed data identity during channelless check policy with policy [%s]: [%s]", policyName, err) 206 } 207 208 // Load MSPPrincipal for policy 209 principal, err := p.principalGetter.Get(policyName) 210 if err != nil { 211 return fmt.Errorf("failed getting local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err) 212 } 213 214 // Verify that proposal's creator satisfies the principal 215 err = id.SatisfiesPrincipal(principal) 216 if err != nil { 217 logger.Warnw("failed verifying that the signed data identity satisfies local MSP principal during channelless check policy", "error", err, "policyName", policyName, "requiredPrincipal", principal, "identity", protoutil.LogMessageForSerializedIdentity(data.Identity)) 218 return fmt.Errorf("failed verifying that the signed data identity satisfies local MSP principal during channelless check policy with policy [%s]: [%s]", policyName, err) 219 } 220 221 // Verify the signature 222 if err = id.Verify(data.Data, data.Signature); err != nil { 223 return err 224 } 225 } 226 227 return nil 228 }