github.com/ztalab/ZACA@v0.0.1/pkg/caclient/ocsp_mem_cache.go (about)

     1  package caclient
     2  
     3  import (
     4  	"crypto/x509"
     5  	"encoding/hex"
     6  	"math"
     7  	"sync/atomic"
     8  	"time"
     9  
    10  	"github.com/pkg/errors"
    11  	"golang.org/x/crypto/ocsp"
    12  
    13  	"github.com/ztalab/ZACA/pkg/memorycacher"
    14  	"go.uber.org/zap"
    15  )
    16  
    17  var _ OcspClient = &ocspMemCache{}
    18  
    19  // ocspMemCache ...
    20  type ocspMemCache struct {
    21  	cache   *memorycacher.Cache
    22  	logger  *zap.SugaredLogger
    23  	ocspURL string // ca server + /ocsp
    24  }
    25  
    26  // NewOcspMemCache ...
    27  func NewOcspMemCache(logger *zap.SugaredLogger, ocspAddr string) (OcspClient, error) {
    28  	return &ocspMemCache{
    29  		cache:   memorycacher.New(30*time.Minute, memorycacher.NoExpiration, math.MaxInt64),
    30  		logger:  logger,
    31  		ocspURL: ocspAddr,
    32  	}, nil
    33  }
    34  
    35  // Validate ...
    36  func (of *ocspMemCache) Validate(leaf, issuer *x509.Certificate) (bool, error) {
    37  	if atomic.LoadInt64(&ocspBlockSign) == 1 {
    38  		return false, errors.New("ocsp Request disabled")
    39  	}
    40  	if leaf == nil || issuer == nil {
    41  		return false, errors.New("leaf/issuer Missing parameter")
    42  	}
    43  	lo := of.logger.With("sn", leaf.SerialNumber.String(), "aki", hex.EncodeToString(leaf.AuthorityKeyId), "id", leaf.URIs[0])
    44  	// Cache fetch
    45  	if _, ok := of.cache.Get(leaf.SerialNumber.String()); ok {
    46  		return true, nil
    47  	}
    48  	ocspRequest, err := ocsp.CreateRequest(leaf, issuer, &ocspOpts)
    49  	if err != nil {
    50  		lo.Errorf("ocsp req create err: %s", err)
    51  		return false, errors.Wrap(err, "ocsp req Creation failed")
    52  	}
    53  	getOcspFunc := func() (interface{}, error) {
    54  		return SendOcspRequest(of.ocspURL, ocspRequest, leaf, issuer)
    55  	}
    56  	sgValue, err, _ := sg.Do("ocsp"+leaf.SerialNumber.String(), getOcspFunc)
    57  	if err != nil {
    58  		lo.Errorf("ocsp Request error: %v", err)
    59  		// Here, the authentication fails due to CA server. The request is allowed. Try again next time
    60  		return true, errors.Wrap(err, "ocsp Request error")
    61  	}
    62  	ocspResp, ok := sgValue.(*ocsp.Response)
    63  	if !ok {
    64  		lo.Error("single flight Parsing error")
    65  		return false, errors.New("single flight Parsing error")
    66  	}
    67  	lo.Debugf("Verify OCSP and the results: %v", ocspResp.Status)
    68  	if ocspResp.Status == int(ocsp.Success) {
    69  		of.cache.SetDefault(leaf.SerialNumber.String(), true)
    70  		return true, nil
    71  	}
    72  	lo.Warnf("Certificate OCSP validation invalid")
    73  	return false, errors.New("ocsp Authentication failed and the certificate was revoked")
    74  }
    75  
    76  func (of *ocspMemCache) Reset() {
    77  	of.cache.Flush()
    78  }