github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/common/deliver/acl.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package deliver 8 9 import ( 10 "time" 11 12 "github.com/hyperledger/fabric-protos-go/common" 13 "github.com/hyperledger/fabric/protoutil" 14 "github.com/pkg/errors" 15 ) 16 17 // ExpiresAtFunc is used to extract the time at which an identity expires. 18 type ExpiresAtFunc func(identityBytes []byte) time.Time 19 20 // ConfigSequencer provides the sequence number of the current config block. 21 type ConfigSequencer interface { 22 Sequence() uint64 23 } 24 25 // NewSessionAC creates an instance of SessionAccessControl. This constructor will 26 // return an error if a signature header cannot be extracted from the envelope. 27 func NewSessionAC(chain ConfigSequencer, env *common.Envelope, policyChecker PolicyChecker, channelID string, expiresAt ExpiresAtFunc) (*SessionAccessControl, error) { 28 signedData, err := protoutil.EnvelopeAsSignedData(env) 29 if err != nil { 30 return nil, err 31 } 32 33 return &SessionAccessControl{ 34 envelope: env, 35 channelID: channelID, 36 sequencer: chain, 37 policyChecker: policyChecker, 38 sessionEndTime: expiresAt(signedData[0].Identity), 39 }, nil 40 } 41 42 // SessionAccessControl holds access control related data for a common Envelope 43 // that is used to determine if a request is allowed for the identity 44 // associated with the request envelope. 45 type SessionAccessControl struct { 46 sequencer ConfigSequencer 47 policyChecker PolicyChecker 48 channelID string 49 envelope *common.Envelope 50 lastConfigSequence uint64 51 sessionEndTime time.Time 52 usedAtLeastOnce bool 53 } 54 55 // Evaluate uses the PolicyChecker to determine if a request should be allowed. 56 // The decision is cached until the identity expires or the chain configuration 57 // changes. 58 func (ac *SessionAccessControl) Evaluate() error { 59 if !ac.sessionEndTime.IsZero() && time.Now().After(ac.sessionEndTime) { 60 return errors.Errorf("client identity expired %v before", time.Since(ac.sessionEndTime)) 61 } 62 63 policyCheckNeeded := !ac.usedAtLeastOnce 64 65 if currentConfigSequence := ac.sequencer.Sequence(); currentConfigSequence > ac.lastConfigSequence { 66 ac.lastConfigSequence = currentConfigSequence 67 policyCheckNeeded = true 68 } 69 70 if !policyCheckNeeded { 71 return nil 72 } 73 74 ac.usedAtLeastOnce = true 75 return ac.policyChecker.CheckPolicy(ac.envelope, ac.channelID) 76 }