github.com/pvitto98/fabric@v2.1.1+incompatible/core/aclmgmt/resourceprovider.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package aclmgmt 8 9 import ( 10 "fmt" 11 12 "github.com/hyperledger/fabric-protos-go/common" 13 pb "github.com/hyperledger/fabric-protos-go/peer" 14 "github.com/hyperledger/fabric/common/channelconfig" 15 "github.com/hyperledger/fabric/protoutil" 16 ) 17 18 //--------- errors --------- 19 20 //PolicyNotFound cache for resource 21 type PolicyNotFound string 22 23 func (e PolicyNotFound) Error() string { 24 return fmt.Sprintf("policy %s not found", string(e)) 25 } 26 27 //InvalidIdInfo 28 type InvalidIdInfo string 29 30 func (e InvalidIdInfo) Error() string { 31 return fmt.Sprintf("Invalid id for policy [%s]", string(e)) 32 } 33 34 //---------- policyEvaluator ------ 35 36 //policyEvalutor interface provides the interfaces for policy evaluation 37 type policyEvaluator interface { 38 PolicyRefForAPI(resName string) string 39 Evaluate(polName string, id []*protoutil.SignedData) error 40 } 41 42 //policyEvaluatorImpl implements policyEvaluator 43 type policyEvaluatorImpl struct { 44 bundle channelconfig.Resources 45 } 46 47 func (pe *policyEvaluatorImpl) PolicyRefForAPI(resName string) string { 48 app, exists := pe.bundle.ApplicationConfig() 49 if !exists { 50 return "" 51 } 52 53 pm := app.APIPolicyMapper() 54 if pm == nil { 55 return "" 56 } 57 58 return pm.PolicyRefForAPI(resName) 59 } 60 61 func (pe *policyEvaluatorImpl) Evaluate(polName string, sd []*protoutil.SignedData) error { 62 policy, ok := pe.bundle.PolicyManager().GetPolicy(polName) 63 if !ok { 64 return PolicyNotFound(polName) 65 } 66 67 return policy.EvaluateSignedData(sd) 68 } 69 70 //------ resourcePolicyProvider ---------- 71 72 //aclmgmtPolicyProvider is the interface implemented by resource based ACL. 73 type aclmgmtPolicyProvider interface { 74 //GetPolicyName returns policy name given resource name 75 GetPolicyName(resName string) string 76 77 //CheckACL backs ACLProvider interface 78 CheckACL(polName string, idinfo interface{}) error 79 } 80 81 //aclmgmtPolicyProviderImpl holds the bytes from state of the ledger 82 type aclmgmtPolicyProviderImpl struct { 83 pEvaluator policyEvaluator 84 } 85 86 //GetPolicyName returns the policy name given the resource string 87 func (rp *aclmgmtPolicyProviderImpl) GetPolicyName(resName string) string { 88 return rp.pEvaluator.PolicyRefForAPI(resName) 89 } 90 91 //CheckACL implements AClProvider's CheckACL interface so it can be registered 92 //as a provider with aclmgmt 93 func (rp *aclmgmtPolicyProviderImpl) CheckACL(polName string, idinfo interface{}) error { 94 aclLogger.Debugf("acl check(%s)", polName) 95 96 //we will implement other identifiers. In the end we just need a SignedData 97 var sd []*protoutil.SignedData 98 switch idinfo := idinfo.(type) { 99 case *pb.SignedProposal: 100 signedProp := idinfo 101 proposal, err := protoutil.UnmarshalProposal(signedProp.ProposalBytes) 102 if err != nil { 103 return fmt.Errorf("Failing extracting proposal during check policy with policy [%s]: [%s]", polName, err) 104 } 105 106 header, err := protoutil.UnmarshalHeader(proposal.Header) 107 if err != nil { 108 return fmt.Errorf("Failing extracting header during check policy [%s]: [%s]", polName, err) 109 } 110 111 shdr, err := protoutil.UnmarshalSignatureHeader(header.SignatureHeader) 112 if err != nil { 113 return fmt.Errorf("Invalid Proposal's SignatureHeader during check policy [%s]: [%s]", polName, err) 114 } 115 116 sd = []*protoutil.SignedData{{ 117 Data: signedProp.ProposalBytes, 118 Identity: shdr.Creator, 119 Signature: signedProp.Signature, 120 }} 121 122 case *common.Envelope: 123 var err error 124 sd, err = protoutil.EnvelopeAsSignedData(idinfo) 125 if err != nil { 126 return err 127 } 128 129 default: 130 return InvalidIdInfo(polName) 131 } 132 133 err := rp.pEvaluator.Evaluate(polName, sd) 134 if err != nil { 135 return fmt.Errorf("failed evaluating policy on signed data during check policy [%s]: [%s]", polName, err) 136 } 137 138 return nil 139 } 140 141 //-------- resource provider - entry point API used by aclmgmtimpl for doing resource based ACL ---------- 142 143 //resource getter gets channelconfig.Resources given channel ID 144 type ResourceGetter func(channelID string) channelconfig.Resources 145 146 //resource provider that uses the resource configuration information to provide ACL support 147 type resourceProvider struct { 148 //resource getter 149 resGetter ResourceGetter 150 151 //default provider to be used for undefined resources 152 defaultProvider defaultACLProvider 153 } 154 155 //create a new resourceProvider 156 func newResourceProvider(rg ResourceGetter, defprov defaultACLProvider) *resourceProvider { 157 return &resourceProvider{rg, defprov} 158 } 159 160 func (rp *resourceProvider) enforceDefaultBehavior(resName string, channelID string, idinfo interface{}) bool { 161 // we currently enforce using p types if defined. In future we will allow p types 162 // to be overridden through peer configuration 163 return rp.defaultProvider.IsPtypePolicy(resName) 164 } 165 166 //CheckACL implements the ACL 167 func (rp *resourceProvider) CheckACL(resName string, channelID string, idinfo interface{}) error { 168 if !rp.enforceDefaultBehavior(resName, channelID, idinfo) { 169 resCfg := rp.resGetter(channelID) 170 171 if resCfg != nil { 172 pp := &aclmgmtPolicyProviderImpl{&policyEvaluatorImpl{resCfg}} 173 policyName := pp.GetPolicyName(resName) 174 if policyName != "" { 175 aclLogger.Debugf("acl policy %s found in config for resource %s", policyName, resName) 176 return pp.CheckACL(policyName, idinfo) 177 } 178 aclLogger.Debugf("acl policy not found in config for resource %s", resName) 179 } 180 } 181 182 return rp.defaultProvider.CheckACL(resName, channelID, idinfo) 183 }