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  }