Add KV datastore
Signed-off-by: Emile Vauge <emile@vauge.com>
This commit is contained in:
parent
38b62d4ae3
commit
5a0440d6f8
21 changed files with 498 additions and 46 deletions
81
acme/acme.go
81
acme/acme.go
|
@ -173,6 +173,7 @@ type ACME struct {
|
|||
storageLock sync.RWMutex
|
||||
client *acme.Client
|
||||
account *Account
|
||||
defaultCertificate *tls.Certificate
|
||||
}
|
||||
|
||||
//Domains parse []Domain
|
||||
|
@ -216,28 +217,50 @@ type Domain struct {
|
|||
SANs []string
|
||||
}
|
||||
|
||||
// CreateConfig creates a tls.config from using ACME configuration
|
||||
func (a *ACME) CreateConfig(tlsConfig *tls.Config, CheckOnDemandDomain func(domain string) bool) error {
|
||||
func (a *ACME) init() error {
|
||||
if len(a.Store) == 0 {
|
||||
a.Store = a.StorageFile
|
||||
}
|
||||
acme.Logger = fmtlog.New(ioutil.Discard, "", 0)
|
||||
|
||||
if len(a.StorageFile) == 0 {
|
||||
return errors.New("Empty StorageFile, please provide a filename for certs storage")
|
||||
}
|
||||
|
||||
log.Debugf("Generating default certificate...")
|
||||
if len(tlsConfig.Certificates) == 0 {
|
||||
// no certificates in TLS config, so we add a default one
|
||||
cert, err := generateDefaultCertificate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsConfig.Certificates = append(tlsConfig.Certificates, *cert)
|
||||
// no certificates in TLS config, so we add a default one
|
||||
cert, err := generateDefaultCertificate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.defaultCertificate = cert
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateClusterConfig creates a tls.config from using ACME configuration
|
||||
func (a *ACME) CreateClusterConfig(tlsConfig *tls.Config, CheckOnDemandDomain func(domain string) bool) error {
|
||||
err := a.init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.Store) == 0 {
|
||||
return errors.New("Empty Store, please provide a filename/key for certs storage")
|
||||
}
|
||||
tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateLocalConfig creates a tls.config from using ACME configuration
|
||||
func (a *ACME) CreateLocalConfig(tlsConfig *tls.Config, CheckOnDemandDomain func(domain string) bool) error {
|
||||
err := a.init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.Store) == 0 {
|
||||
return errors.New("Empty Store, please provide a filename/key for certs storage")
|
||||
}
|
||||
tlsConfig.Certificates = append(tlsConfig.Certificates, *a.defaultCertificate)
|
||||
|
||||
var needRegister bool
|
||||
var err error
|
||||
|
||||
// if certificates in storage, load them
|
||||
if fileInfo, err := os.Stat(a.StorageFile); err == nil && fileInfo.Size() != 0 {
|
||||
if fileInfo, fileErr := os.Stat(a.Store); fileErr == nil && fileInfo.Size() != 0 {
|
||||
log.Infof("Loading ACME certificates...")
|
||||
// load account
|
||||
a.account, err = a.loadAccount(a)
|
||||
|
@ -265,7 +288,10 @@ func (a *ACME) CreateConfig(tlsConfig *tls.Config, CheckOnDemandDomain func(doma
|
|||
}
|
||||
a.client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.DNS01})
|
||||
wrapperChallengeProvider := newWrapperChallengeProvider()
|
||||
a.client.SetChallengeProvider(acme.TLSSNI01, wrapperChallengeProvider)
|
||||
err = client.SetChallengeProvider(acme.TLSSNI01, wrapperChallengeProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if needRegister {
|
||||
// New users will need to register; be sure to save it
|
||||
|
@ -322,12 +348,9 @@ func (a *ACME) CreateConfig(tlsConfig *tls.Config, CheckOnDemandDomain func(doma
|
|||
|
||||
ticker := time.NewTicker(24 * time.Hour)
|
||||
safe.Go(func() {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if err := a.renewCertificates(a.client); err != nil {
|
||||
log.Errorf("Error renewing ACME certificate %+v: %s", a.account, err.Error())
|
||||
}
|
||||
for range ticker.C {
|
||||
if err := a.renewCertificates(client, account); err != nil {
|
||||
log.Errorf("Error renewing ACME certificate %+v: %s", account, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,22 +493,22 @@ func (a *ACME) LoadCertificateForDomains(domains []string) {
|
|||
func (a *ACME) loadAccount(acmeConfig *ACME) (*Account, error) {
|
||||
a.storageLock.RLock()
|
||||
defer a.storageLock.RUnlock()
|
||||
Account := Account{
|
||||
account := Account{
|
||||
DomainsCertificate: DomainsCertificates{},
|
||||
}
|
||||
file, err := ioutil.ReadFile(acmeConfig.StorageFile)
|
||||
file, err := ioutil.ReadFile(acmeConfig.Store)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(file, &Account); err != nil {
|
||||
if err := json.Unmarshal(file, &account); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = Account.DomainsCertificate.init()
|
||||
err = account.DomainsCertificate.init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Infof("Loaded ACME config from storage %s", acmeConfig.StorageFile)
|
||||
return &Account, nil
|
||||
log.Infof("Loaded ACME config from store %s", acmeConfig.Store)
|
||||
return &account, nil
|
||||
}
|
||||
|
||||
func (a *ACME) saveAccount() error {
|
||||
|
@ -496,7 +519,7 @@ func (a *ACME) saveAccount() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(a.StorageFile, data, 0600)
|
||||
return ioutil.WriteFile(a.Store, data, 0600)
|
||||
}
|
||||
|
||||
func (a *ACME) getDomainsCertificates(client *acme.Client, domains []string) (*Certificate, error) {
|
||||
|
|
|
@ -8,18 +8,20 @@ import (
|
|||
"github.com/xenolf/lego/acme"
|
||||
)
|
||||
|
||||
type wrapperChallengeProvider struct {
|
||||
var _ acme.ChallengeProvider = (*inMemoryChallengeProvider)(nil)
|
||||
|
||||
type inMemoryChallengeProvider struct {
|
||||
challengeCerts map[string]*tls.Certificate
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
func newWrapperChallengeProvider() *wrapperChallengeProvider {
|
||||
return &wrapperChallengeProvider{
|
||||
func newWrapperChallengeProvider() *inMemoryChallengeProvider {
|
||||
return &inMemoryChallengeProvider{
|
||||
challengeCerts: map[string]*tls.Certificate{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *wrapperChallengeProvider) getCertificate(domain string) (cert *tls.Certificate, exists bool) {
|
||||
func (c *inMemoryChallengeProvider) getCertificate(domain string) (cert *tls.Certificate, exists bool) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
if cert, ok := c.challengeCerts[domain]; ok {
|
||||
|
@ -28,7 +30,7 @@ func (c *wrapperChallengeProvider) getCertificate(domain string) (cert *tls.Cert
|
|||
return nil, false
|
||||
}
|
||||
|
||||
func (c *wrapperChallengeProvider) Present(domain, token, keyAuth string) error {
|
||||
func (c *inMemoryChallengeProvider) Present(domain, token, keyAuth string) error {
|
||||
cert, _, err := acme.TLSSNI01ChallengeCert(keyAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -45,10 +47,9 @@ func (c *wrapperChallengeProvider) Present(domain, token, keyAuth string) error
|
|||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (c *wrapperChallengeProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
func (c *inMemoryChallengeProvider) CleanUp(domain, token, keyAuth string) error {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
delete(c.challengeCerts, domain)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue