|
|
@ -17,6 +17,7 @@ import (
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/golang/groupcache/lru"
|
|
|
|
"github.com/golang/groupcache/lru"
|
|
|
|
|
|
|
|
"github.com/golang/groupcache/singleflight"
|
|
|
|
_log "github.com/sirupsen/logrus"
|
|
|
|
_log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
@ -32,7 +33,9 @@ type CA struct {
|
|
|
|
rsa.PrivateKey
|
|
|
|
rsa.PrivateKey
|
|
|
|
RootCert x509.Certificate
|
|
|
|
RootCert x509.Certificate
|
|
|
|
StorePath string
|
|
|
|
StorePath string
|
|
|
|
|
|
|
|
|
|
|
|
cache *lru.Cache
|
|
|
|
cache *lru.Cache
|
|
|
|
|
|
|
|
group *singleflight.Group
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewCA(path string) (*CA, error) {
|
|
|
|
func NewCA(path string) (*CA, error) {
|
|
|
@ -44,6 +47,7 @@ func NewCA(path string) (*CA, error) {
|
|
|
|
ca := &CA{
|
|
|
|
ca := &CA{
|
|
|
|
StorePath: storePath,
|
|
|
|
StorePath: storePath,
|
|
|
|
cache: lru.New(100),
|
|
|
|
cache: lru.New(100),
|
|
|
|
|
|
|
|
group: new(singleflight.Group),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if err := ca.load(); err != nil {
|
|
|
|
if err := ca.load(); err != nil {
|
|
|
@ -242,20 +246,28 @@ func (ca *CA) saveCert() error {
|
|
|
|
|
|
|
|
|
|
|
|
func (ca *CA) GetCert(commonName string) (*tls.Certificate, error) {
|
|
|
|
func (ca *CA) GetCert(commonName string) (*tls.Certificate, error) {
|
|
|
|
if val, ok := ca.cache.Get(commonName); ok {
|
|
|
|
if val, ok := ca.cache.Get(commonName); ok {
|
|
|
|
|
|
|
|
log.WithField("commonName", commonName).Debug("GetCert")
|
|
|
|
return val.(*tls.Certificate), nil
|
|
|
|
return val.(*tls.Certificate), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val, err := ca.group.Do(commonName, func() (interface{}, error) {
|
|
|
|
cert, err := ca.DummyCert(commonName)
|
|
|
|
cert, err := ca.DummyCert(commonName)
|
|
|
|
if err != nil {
|
|
|
|
if err == nil {
|
|
|
|
|
|
|
|
ca.cache.Add(commonName, cert)
|
|
|
|
|
|
|
|
}
|
|
|
|
return cert, err
|
|
|
|
return cert, err
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ca.cache.Add(commonName, cert)
|
|
|
|
return val.(*tls.Certificate), nil
|
|
|
|
return cert, err
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: 是否应该支持多个 SubjectAltName
|
|
|
|
// TODO: 是否应该支持多个 SubjectAltName
|
|
|
|
func (ca *CA) DummyCert(commonName string) (*tls.Certificate, error) {
|
|
|
|
func (ca *CA) DummyCert(commonName string) (*tls.Certificate, error) {
|
|
|
|
|
|
|
|
log.WithField("commonName", commonName).Debug("DummyCert")
|
|
|
|
template := &x509.Certificate{
|
|
|
|
template := &x509.Certificate{
|
|
|
|
SerialNumber: big.NewInt(time.Now().UnixNano() / 100000),
|
|
|
|
SerialNumber: big.NewInt(time.Now().UnixNano() / 100000),
|
|
|
|
Subject: pkix.Name{
|
|
|
|
Subject: pkix.Name{
|
|
|
|