Compatibility with refactored lego core

lego commit: 42941ccea6b431ebff203d4cb520991fb7b47951
This commit is contained in:
Matthew Holt 2018-12-10 00:26:09 -07:00
parent bea13a36c8
commit 1f94da1ed1
No known key found for this signature in database
GPG Key ID: 2A349DD577D586A5
11 changed files with 105 additions and 133 deletions

View File

@ -61,10 +61,10 @@ CertMagic - Automatic HTTPS using Let's Encrypt
- [Examples](#examples)
- [Serving HTTP handlers with HTTPS](#serving-http-handlers-with-https)
- [Starting a TLS listener](#starting-a-tls-listener)
- [Getting a tls.Config](#getting-a-tls-config)
- [Getting a tls.Config](#getting-a-tlsconfig)
- [Advanced use](#advanced-use)
- [Wildcard Certificates](#wildcard-certificates)
- [Behind a load balancer (or in a cluster)](#behind-a-load-balancer)
- [Behind a load balancer (or in a cluster)](#behind-a-load-balancer-or-in-a-cluster)
- [The ACME Challenges](#the-acme-challenges)
- [HTTP Challenge](#http-challenge)
- [TLS-ALPN Challenge](#tls-alpn-challenge)
@ -237,7 +237,7 @@ tlsConfig := magic.TLSConfig()
// we can simply set its GetCertificate field and append the
// TLS-ALPN challenge protocol to the NextProtos
myTLSConfig.GetCertificate = magic.GetCertificate
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, acme.ACMETLS1Protocol}
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol}
// the HTTP challenge has to be handled by your HTTP server;
// if you don't have one, you should have disabled it earlier
@ -274,7 +274,7 @@ The default Storage and Sync are implemented using the file system, so mounting
Although Storage and Sync seem closely related, they are, in fact, distinct concepts, although in some cases a Locker may rely on a Storage (such as the default FileSystem ones). Storage is where assets are stored, whereas Sync is what coordinates certificate-related tasks. Storage keeps certificates that are obtained, whereas Sync ensures that a certificate is obtained only once at a time.
See [Storage](#storage) and the associated [godoc](TODO) for more information!
See [Storage](#storage) and the associated [godoc](https://godoc.org/github.com/mholt/certmagic#Storage) for more information!
## The ACME Challenges
@ -284,7 +284,7 @@ If you're using the high-level convenience functions like `HTTPS()`, `Listen()`,
The HTTP and TLS-ALPN challenges are the defaults because they don't require configuration from you, but they require that your server is accessible from external IPs on low ports. If that is not possible in your situation, you can enable the DNS challenge, which will disable the HTTP and TLS-ALPN challenges and use the DNS challenge exclusively.
Only one challenge technically needs to be enabled for things to work, but using multiple is good for reliability in case a challenge is discontinued by the CA. This happened to the TLS-SNI challenge in early 2018—many popular ACME clients such as Traefik and Autocert broke, resulting in downtime for some sites, until new releases were made and patches deployed, because they used only one challenge; Caddy, however—this library's forerunner—was unaffected because it also used the HTTP challenge. If multiple challenges are enabled, they are chosen randomly to help prevent false reliance on a single challenge type.
Technically, only one challenge needs to be enabled for things to work, but using multiple is good for reliability in case a challenge is discontinued by the CA. This happened to the TLS-SNI challenge in early 2018—many popular ACME clients such as Traefik and Autocert broke, resulting in downtime for some sites, until new releases were made and patches deployed, because they used only one challenge; Caddy, however—this library's forerunner—was unaffected because it also used the HTTP challenge. If multiple challenges are enabled, they are chosen randomly to help prevent false reliance on a single challenge type.
### HTTP Challenge
@ -335,7 +335,7 @@ Or make two simple changes to an existing `tls.Config`:
```go
myTLSConfig.GetCertificate = magic.GetCertificate
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, acme.ACMETLS1Protocol}
myTLSConfig.NextProtos = append(myTLSConfig.NextProtos, tlsalpn01.ACMETLS1Protocol}
```
Then just make sure your TLS listener is listening on port 443:
@ -392,7 +392,7 @@ certmagic.OnDemand = &certmagic.OnDemandConfig{MaxObtain: 5}
This allows only 5 certificates to be requested and is the simplest way to enable On-Demand TLS, but is the least recommended. It prevents abuse, but only in the least helpful way.
The [godoc](TODO) describes how to use the other policies, all of which are much-more recommended.
The [godoc](https://godoc.org/github.com/mholt/certmagic#OnDemandConfig) describes how to use the other policies, all of which are much more recommended! :)
If `OnDemand` is set and `Manage()` is called, then the names given to `Manage()` will be whitelisted rather than obtained right away.
@ -405,7 +405,7 @@ By default, CertMagic stores assets on the local file system in `$HOME/.local/sh
The notion of a "cluster" or "fleet" of instances that may be serving the same site and sharing certificates, etc, is tied to storage. Simply, any instances that use the same storage facilities are considered part of the cluster. So if you deploy 100 instances of CertMagic behind a load balancer, they are all part of the same cluster if they share storage. Sharing storage could be mounting a shared folder, or implementing some other distributed storage such as a database server or KV store.
The easiest way to change the storage being used is to set `certmagic.DefaultStorage` to a value that satisfies the [Storage interface](TODO).
The easiest way to change the storage being used is to set `certmagic.DefaultStorage` to a value that satisfies the [Storage interface](https://godoc.org/github.com/mholt/certmagic#Storage).
If you write a Storage or Sync implementation, let us know and we'll add it to the project so people can find it!
@ -423,14 +423,28 @@ Again, if you're needing to do this, you've probably over-complicated your appli
### Can I use some of my own certificates while using CertMagic?
Yes, just call the proper method on the `Config` to cache an "unmanaged certificate": (TODO: godoc links)
Yes, just call the relevant method on the `Config` to add your own certificate to the cache:
- [`CacheUnmanagedCertificatePEMBytes()`](https://godoc.org/github.com/mholt/certmagic#Config.CacheUnmanagedCertificatePEMBytes)
- [`CacheUnmanagedCertificatePEMFile()`](https://godoc.org/github.com/mholt/certmagic#Config.CacheUnmanagedCertificatePEMFile)
- [`CacheUnmanagedTLSCertificate()`](https://godoc.org/github.com/mholt/certmagic#Config.CacheUnmanagedTLSCertificate)
### Does CertMagic obtain SAN certificates?
Technically all certificates these days are SAN certificates because CommonName is deprecated. But if you're asking whether CertMagic issues and manages certificates with multiple SANs, the answer is no. But it does support those, if you provide your own.
Technically all certificates these days are SAN certificates because CommonName is deprecated. But if you're asking whether CertMagic issues and manages certificates with multiple SANs, the answer is no. But it does support serving them, if you provide your own.
### How can I listen on ports 80 and 443? Do I have to run as root?
On Linux, you can use `setcap` to grant your binary the permission to bind low ports:
```bash
$ sudo setcap cap_net_bind_service=+ep /path/to/your/binary
```
and then you will not need to run with root privileges.
## Contributing

View File

@ -77,6 +77,8 @@ func (c Certificate) NeedsRenewal() bool {
// cache, from the TLS storage for managed certificates. It returns a
// copy of the Certificate that was put into the cache.
//
// This is a lower-level method; normally you'll call Manage() instead.
//
// This method is safe for concurrent use.
func (cfg *Config) CacheManagedCertificate(domain string) (Certificate, error) {
certRes, err := cfg.loadCertResource(domain)

View File

@ -27,11 +27,12 @@ import (
"sync/atomic"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/certcrypto"
"github.com/xenolf/lego/challenge"
)
// HTTPS serves mux on domain name using the HTTP and HTTPS
// ports, redirecting all HTTP requests to HTTPS.
// HTTPS serves mux for all domainNames using the HTTP
// and HTTPS ports, redirecting all HTTP requests to HTTPS.
//
// Calling this function signifies your acceptance to
// the CA's Subscriber Agreement and/or Terms of Service.
@ -401,7 +402,7 @@ func isInternal(addr string) bool {
var (
// The endpoint of the directory for the ACME
// CA we are to use
CA = LetsEncryptStagingCA // TODO: make production
CA = LetsEncryptProductionCA
// The email address to use when creating or
// selecting an existing ACME server account
@ -462,11 +463,11 @@ var (
// The DNS provider to use when solving the
// ACME DNS challenge
DNSProvider acme.ChallengeProvider
DNSProvider challenge.Provider
// The type of key to use when generating
// certificates
KeyType = acme.RSA2048
KeyType = certcrypto.RSA2048
// The state needed to operate on-demand TLS
OnDemand *OnDemandConfig

122
client.go
View File

@ -24,7 +24,12 @@ import (
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/certificate"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/http01"
"github.com/xenolf/lego/challenge/tlsalpn01"
"github.com/xenolf/lego/lego"
"github.com/xenolf/lego/registration"
)
// acmeMu ensures that only one ACME challenge occurs at a time.
@ -35,7 +40,7 @@ var acmeMu sync.Mutex
// renew, and revoke certificates with ACME.
type acmeClient struct {
config *Config
acmeClient *acme.Client
acmeClient *lego.Client
}
// listenerAddressInUse returns true if a TCP connection
@ -87,7 +92,10 @@ func (cfg *Config) newACMEClient(interactive bool) (*acmeClient, error) {
client, ok := cfg.acmeClients[clientKey]
if !ok {
// the client facilitates our communication with the CA server
client, err = acme.NewClient(caURL, &leUser, keyType)
legoCfg := lego.NewConfig(&leUser)
legoCfg.CADirURL = caURL
legoCfg.KeyType = keyType
client, err = lego.NewClient(legoCfg)
if err != nil {
cfg.acmeClientsMu.Unlock()
return nil, err
@ -109,9 +117,9 @@ func (cfg *Config) newACMEClient(interactive bool) (*acmeClient, error) {
}
}
reg, err := client.Register(cfg.Agreed)
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: cfg.Agreed})
if err != nil {
return nil, errors.New("registration error: " + err.Error())
return nil, fmt.Errorf("registration error: %v", err)
}
leUser.Registration = reg
@ -149,9 +157,9 @@ func (cfg *Config) newACMEClient(interactive bool) (*acmeClient, error) {
// the challenge cert to our cert cache and serve it up during the
// handshake. As for the default solvers... we are careful to honor the
// listener bind preferences by using cfg.ListenHost.
var httpSolver, alpnSolver acme.ChallengeProvider
httpSolver = acme.NewHTTPProviderServer(cfg.ListenHost, fmt.Sprintf("%d", useHTTPPort))
alpnSolver = acme.NewTLSALPNProviderServer(cfg.ListenHost, fmt.Sprintf("%d", useTLSALPNPort))
var httpSolver, alpnSolver challenge.Provider
httpSolver = http01.NewProviderServer(cfg.ListenHost, fmt.Sprintf("%d", useHTTPPort))
alpnSolver = tlsalpn01.NewProviderServer(cfg.ListenHost, fmt.Sprintf("%d", useTLSALPNPort))
if listenerAddressInUse(net.JoinHostPort(cfg.ListenHost, fmt.Sprintf("%d", useHTTPPort))) {
httpSolver = nil
}
@ -164,30 +172,30 @@ func (cfg *Config) newACMEClient(interactive bool) (*acmeClient, error) {
// in fact, this is required now for successful solving of the HTTP challenge
// if the port is already in use, since we must write the challenge info
// to storage for the HTTPChallengeHandler to solve it successfully
c.acmeClient.SetChallengeProvider(acme.HTTP01, distributedSolver{
c.acmeClient.Challenge.SetHTTP01Provider(distributedSolver{
config: cfg,
providerServer: httpSolver,
})
c.acmeClient.SetChallengeProvider(acme.TLSALPN01, distributedSolver{
c.acmeClient.Challenge.SetTLSALPN01Provider(distributedSolver{
config: cfg,
providerServer: alpnSolver,
})
// disable any challenges that should not be used
var disabledChallenges []acme.Challenge
var disabledChallenges []challenge.Type
if cfg.DisableHTTPChallenge {
disabledChallenges = append(disabledChallenges, acme.HTTP01)
disabledChallenges = append(disabledChallenges, challenge.HTTP01)
}
if cfg.DisableTLSALPNChallenge {
disabledChallenges = append(disabledChallenges, acme.TLSALPN01)
disabledChallenges = append(disabledChallenges, challenge.TLSALPN01)
}
if len(disabledChallenges) > 0 {
c.acmeClient.ExcludeChallenges(disabledChallenges)
c.acmeClient.Challenge.Exclude(disabledChallenges)
}
} else {
// Otherwise, use DNS challenge exclusively
c.acmeClient.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSALPN01})
c.acmeClient.SetChallengeProvider(acme.DNS01, cfg.DNSProvider)
c.acmeClient.Challenge.Exclude([]challenge.Type{challenge.HTTP01, challenge.TLSALPN01})
c.acmeClient.Challenge.SetDNS01Provider(cfg.DNSProvider)
}
return c, nil
@ -227,25 +235,16 @@ func (c *acmeClient) Obtain(name string) error {
}
for attempts := 0; attempts < 2; attempts++ {
namesObtaining.Add([]string{name})
request := certificate.ObtainRequest{
Domains: []string{name},
Bundle: true,
MustStaple: c.config.MustStaple,
}
acmeMu.Lock()
certificate, err := c.acmeClient.ObtainCertificate([]string{name}, true, nil, c.config.MustStaple)
certificate, err := c.acmeClient.Certificate.Obtain(request)
acmeMu.Unlock()
namesObtaining.Remove([]string{name})
if err != nil {
// for a certain kind of error, we can enumerate the error per-domain
if failures, ok := err.(acme.ObtainError); ok && len(failures) > 0 {
var errMsg string // combine all the failures into a single error message
for errDomain, obtainErr := range failures {
if obtainErr == nil {
continue
}
errMsg += fmt.Sprintf("[%s] failed to get certificate: %v\n", errDomain, obtainErr)
}
return errors.New(errMsg)
}
return fmt.Errorf("[%s] failed to obtain certificate: %v", name, err)
return fmt.Errorf("[%s] failed to obtain certificate: %s", name, err)
}
// double-check that we actually got a certificate, in case there's a bug upstream (see issue mholt/caddy#2121)
@ -301,14 +300,12 @@ func (c *acmeClient) Renew(name string) error {
}
// Perform renewal and retry if necessary, but not too many times.
var newCertMeta *acme.CertificateResource
var newCertMeta *certificate.Resource
var success bool
for attempts := 0; attempts < 2; attempts++ {
namesObtaining.Add([]string{name})
acmeMu.Lock()
newCertMeta, err = c.acmeClient.RenewCertificate(certRes, true, c.config.MustStaple)
newCertMeta, err = c.acmeClient.Certificate.Renew(certRes, true, c.config.MustStaple)
acmeMu.Unlock()
namesObtaining.Remove([]string{name})
if err == nil {
// double-check that we actually got a certificate; check a couple fields, just in case
if newCertMeta == nil || newCertMeta.Domain == "" || newCertMeta.Certificate == nil {
@ -348,7 +345,7 @@ func (c *acmeClient) Revoke(name string) error {
return err
}
err = c.acmeClient.RevokeCertificate(certRes.Certificate)
err = c.acmeClient.Certificate.Revoke(certRes.Certificate)
if err != nil {
return err
}
@ -372,54 +369,3 @@ func (c *acmeClient) Revoke(name string) error {
return nil
}
// namesObtaining is a set of hostnames with thread-safe
// methods. A name should be in this set only while this
// package is in the process of obtaining a certificate
// for the name. ACME challenges that are received for
// names which are not in this set were not initiated by
// this package and probably should not be handled by
// this package.
var namesObtaining = nameCoordinator{names: make(map[string]struct{})}
type nameCoordinator struct {
names map[string]struct{}
mu sync.RWMutex
}
// Add adds names to c. It is safe for concurrent use.
func (c *nameCoordinator) Add(names []string) {
c.mu.Lock()
for _, name := range names {
c.names[strings.ToLower(name)] = struct{}{}
}
c.mu.Unlock()
}
// Remove removes names from c. It is safe for concurrent use.
func (c *nameCoordinator) Remove(names []string) {
c.mu.Lock()
for _, name := range names {
delete(c.names, strings.ToLower(name))
}
c.mu.Unlock()
}
// Has returns true if c has name. It is safe for concurrent use.
func (c *nameCoordinator) Has(name string) bool {
hostname, _, err := net.SplitHostPort(name)
if err != nil {
hostname = name
}
c.mu.RLock()
_, ok := c.names[strings.ToLower(hostname)]
c.mu.RUnlock()
return ok
}
// KnownACMECAs is a list of ACME directory endpoints of
// known, public, and trusted ACME-compatible certificate
// authorities.
var KnownACMECAs = []string{
"https://acme-v02.api.letsencrypt.org/directory",
}

View File

@ -21,7 +21,10 @@ import (
"sync"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/certcrypto"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/tlsalpn01"
"github.com/xenolf/lego/lego"
)
// Config configures a certificate manager instance.
@ -93,11 +96,11 @@ type Config struct {
// The DNS provider to use when solving the
// ACME DNS challenge
DNSProvider acme.ChallengeProvider
DNSProvider challenge.Provider
// The type of key to use when generating
// certificates
KeyType acme.KeyType
KeyType certcrypto.KeyType
// The state needed to operate on-demand TLS
OnDemand *OnDemandConfig
@ -116,7 +119,7 @@ type Config struct {
// Map of client config key to ACME clients
// so they can be reused
acmeClients map[string]*acme.Client
acmeClients map[string]*lego.Client
acmeClientsMu *sync.Mutex
}
@ -213,7 +216,7 @@ func NewWithCache(certCache *Cache, cfg Config) *Config {
// ensure the unexported fields are valid
cfg.certificates = make(map[string]string)
cfg.certCache = certCache
cfg.acmeClients = make(map[string]*acme.Client)
cfg.acmeClients = make(map[string]*lego.Client)
cfg.acmeClientsMu = new(sync.Mutex)
return &cfg
@ -325,7 +328,7 @@ func (cfg *Config) RevokeCert(domain string, interactive bool) error {
func (cfg *Config) TLSConfig() *tls.Config {
return &tls.Config{
GetCertificate: cfg.GetCertificate,
NextProtos: []string{"h2", "http/1.1", acme.ACMETLS1Protocol},
NextProtos: []string{"h2", "http/1.1", tlsalpn01.ACMETLS1Protocol},
}
}

View File

@ -25,7 +25,7 @@ import (
"fmt"
"hash/fnv"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/certificate"
)
// encodePrivateKey marshals a EC or RSA private key into a PEM-encoded array of bytes.
@ -96,7 +96,7 @@ func fastHash(input []byte) string {
// saveCertResource saves the certificate resource to disk. This
// includes the certificate file itself, the private key, and the
// metadata file.
func (cfg *Config) saveCertResource(cert *acme.CertificateResource) error {
func (cfg *Config) saveCertResource(cert *certificate.Resource) error {
metaBytes, err := json.MarshalIndent(&cert, "", "\t")
if err != nil {
return fmt.Errorf("encoding certificate metadata: %v", err)
@ -120,8 +120,8 @@ func (cfg *Config) saveCertResource(cert *acme.CertificateResource) error {
return storeTx(cfg.certCache.storage, all)
}
func (cfg *Config) loadCertResource(domain string) (acme.CertificateResource, error) {
var certRes acme.CertificateResource
func (cfg *Config) loadCertResource(domain string) (certificate.Resource, error) {
var certRes certificate.Resource
certBytes, err := cfg.certCache.storage.Load(prefixSiteCert(cfg.CA, domain))
if err != nil {
return certRes, err

View File

@ -25,7 +25,7 @@ import (
"sync/atomic"
"time"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/challenge/tlsalpn01"
)
// GetCertificate gets a certificate to satisfy clientHello. In getting
@ -44,7 +44,7 @@ func (cfg *Config) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certif
// special case: serve up the certificate for a TLS-ALPN ACME challenge
// (https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-05)
for _, proto := range clientHello.SupportedProtos {
if proto == acme.ACMETLS1Protocol {
if proto == tlsalpn01.ACMETLS1Protocol {
cfg.certCache.mu.RLock()
challengeCert, ok := cfg.certCache.cache[tlsALPNCertKeyName(clientHello.ServerName)]
cfg.certCache.mu.RUnlock()
@ -385,7 +385,7 @@ func (cfg *Config) tryDistributedChallengeSolver(clientHello *tls.ClientHelloInf
return Certificate{}, false, fmt.Errorf("decoding challenge token file %s (corrupted?): %v", tokenKey, err)
}
cert, err := acme.TLSALPNChallengeCert(chalInfo.Domain, chalInfo.KeyAuth)
cert, err := tlsalpn01.ChallengeCert(chalInfo.Domain, chalInfo.KeyAuth)
if err != nil {
return Certificate{}, false, fmt.Errorf("making TLS-ALPN challenge certificate: %v", err)
}

View File

@ -20,7 +20,7 @@ import (
"net/http"
"strings"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/challenge/http01"
)
// HTTPChallengeHandler wraps h in a handler that can solve the ACME
@ -95,7 +95,7 @@ func (cfg *Config) distributedHTTPChallengeSolver(w http.ResponseWriter, r *http
// Most of this code borrowed from xenolf/lego's built-in HTTP-01
// challenge solver in March 2018.
func answerHTTPChallenge(w http.ResponseWriter, r *http.Request, chalInfo challengeInfo) bool {
challengeReqPath := acme.HTTP01ChallengePath(chalInfo.Token)
challengeReqPath := http01.ChallengePath(chalInfo.Token)
if r.URL.Path == challengeReqPath &&
strings.HasPrefix(r.Host, chalInfo.Domain) &&
r.Method == "GET" {

View File

@ -46,8 +46,8 @@ func (certCache *Cache) maintainAssets() {
log.Println("[INFO] Done checking certificates")
case <-ocspTicker.C:
log.Println("[INFO] Scanning for stale OCSP staples")
certCache.UpdateOCSPStaples()
certCache.DeleteOldStapleFiles()
certCache.updateOCSPStaples()
certCache.deleteOldStapleFiles()
log.Println("[INFO] Done checking OCSP staples")
case <-certCache.stopChan:
renewalTicker.Stop()
@ -59,7 +59,9 @@ func (certCache *Cache) maintainAssets() {
}
// RenewManagedCertificates renews managed certificates,
// including ones loaded on-demand.
// including ones loaded on-demand. Note that this is done
// automatically on a regular basis; normally you will not
// need to call this.
func (certCache *Cache) RenewManagedCertificates(interactive bool) error {
// we use the queues for a very important reason: to do any and all
// operations that could require an exclusive write lock outside
@ -193,13 +195,13 @@ func (certCache *Cache) RenewManagedCertificates(interactive bool) error {
return nil
}
// UpdateOCSPStaples updates the OCSP stapling in all
// updateOCSPStaples updates the OCSP stapling in all
// eligible, cached certificates.
//
// OCSP maintenance strives to abide the relevant points on
// Ryan Sleevi's recommendations for good OCSP support:
// https://gist.github.com/sleevi/5efe9ef98961ecfb4da8
func (certCache *Cache) UpdateOCSPStaples() {
func (certCache *Cache) updateOCSPStaples() {
// Create a temporary place to store updates
// until we release the potentially long-lived
// read lock and use a short-lived write lock
@ -256,9 +258,9 @@ func (certCache *Cache) UpdateOCSPStaples() {
}
}
// DeleteOldStapleFiles deletes cached OCSP staples that have expired.
// deleteOldStapleFiles deletes cached OCSP staples that have expired.
// TODO: We should do this for long-expired certificates, too.
func (certCache *Cache) DeleteOldStapleFiles() {
func (certCache *Cache) deleteOldStapleFiles() {
ocspKeys, err := certCache.storage.List(prefixOCSP)
if err != nil {
// maybe just hasn't been created yet; no big deal

View File

@ -20,7 +20,8 @@ import (
"log"
"path/filepath"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/challenge"
"github.com/xenolf/lego/challenge/tlsalpn01"
)
// tlsALPNSolver is a type that can solve TLS-ALPN challenges using
@ -31,7 +32,7 @@ type tlsALPNSolver struct {
// Present adds the challenge certificate to the cache.
func (s tlsALPNSolver) Present(domain, token, keyAuth string) error {
cert, err := acme.TLSALPNChallengeCert(domain, keyAuth)
cert, err := tlsalpn01.ChallengeCert(domain, keyAuth)
if err != nil {
return err
}
@ -93,7 +94,7 @@ type distributedSolver struct {
// Since the distributedSolver is only a
// wrapper over an actual solver, place
// the actual solver here.
providerServer acme.ChallengeProvider
providerServer challenge.Provider
}
// Present invokes the underlying solver's Present method

11
user.go
View File

@ -27,13 +27,14 @@ import (
"sort"
"strings"
"github.com/xenolf/lego/acme"
"github.com/xenolf/lego/lego"
"github.com/xenolf/lego/registration"
)
// User represents a Let's Encrypt user account.
type User struct {
Email string
Registration *acme.RegistrationResource
Registration *registration.Resource
key crypto.PrivateKey
}
@ -43,7 +44,7 @@ func (u User) GetEmail() string {
}
// GetRegistration gets u's registration resource.
func (u User) GetRegistration() *acme.RegistrationResource {
func (u User) GetRegistration() *registration.Resource {
return u.Registration
}
@ -107,7 +108,9 @@ func (cfg *Config) getEmail(userPresent bool) (string, error) {
if cfg.CA != "" {
caURL = cfg.CA
}
tempClient, err := acme.NewClient(caURL, user, "")
legoConfig := lego.NewConfig(user)
legoConfig.CADirURL = caURL
tempClient, err := lego.NewClient(legoConfig)
if err != nil {
return "", fmt.Errorf("making ACME client to get ToS URL: %v", err)
}