104 lines
3.2 KiB
Go
104 lines
3.2 KiB
Go
package lego
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/go-acme/lego/certcrypto"
|
|
"github.com/go-acme/lego/registration"
|
|
)
|
|
|
|
const (
|
|
// caCertificatesEnvVar is the environment variable name that can be used to
|
|
// specify the path to PEM encoded CA Certificates that can be used to
|
|
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
|
// the system-wide trusted root list.
|
|
caCertificatesEnvVar = "LEGO_CA_CERTIFICATES"
|
|
|
|
// caServerNameEnvVar is the environment variable name that can be used to
|
|
// specify the CA server name that can be used to
|
|
// authenticate an ACME server with a HTTPS certificate not issued by a CA in
|
|
// the system-wide trusted root list.
|
|
caServerNameEnvVar = "LEGO_CA_SERVER_NAME"
|
|
|
|
// LEDirectoryProduction URL to the Let's Encrypt production
|
|
LEDirectoryProduction = "https://acme-v02.api.letsencrypt.org/directory"
|
|
|
|
// LEDirectoryStaging URL to the Let's Encrypt staging
|
|
LEDirectoryStaging = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
|
)
|
|
|
|
type Config struct {
|
|
CADirURL string
|
|
User registration.User
|
|
UserAgent string
|
|
HTTPClient *http.Client
|
|
Certificate CertificateConfig
|
|
}
|
|
|
|
func NewConfig(user registration.User) *Config {
|
|
return &Config{
|
|
CADirURL: LEDirectoryProduction,
|
|
User: user,
|
|
HTTPClient: createDefaultHTTPClient(),
|
|
Certificate: CertificateConfig{
|
|
KeyType: certcrypto.RSA2048,
|
|
Timeout: 30 * time.Second,
|
|
},
|
|
}
|
|
}
|
|
|
|
type CertificateConfig struct {
|
|
KeyType certcrypto.KeyType
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// createDefaultHTTPClient Creates an HTTP client with a reasonable timeout value
|
|
// and potentially a custom *x509.CertPool
|
|
// based on the caCertificatesEnvVar environment variable (see the `initCertPool` function)
|
|
func createDefaultHTTPClient() *http.Client {
|
|
return &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: http.ProxyFromEnvironment,
|
|
DialContext: (&net.Dialer{
|
|
Timeout: 30 * time.Second,
|
|
KeepAlive: 30 * time.Second,
|
|
}).DialContext,
|
|
TLSHandshakeTimeout: 15 * time.Second,
|
|
ResponseHeaderTimeout: 15 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
TLSClientConfig: &tls.Config{
|
|
ServerName: os.Getenv(caServerNameEnvVar),
|
|
RootCAs: initCertPool(),
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
// initCertPool creates a *x509.CertPool populated with the PEM certificates
|
|
// found in the filepath specified in the caCertificatesEnvVar OS environment
|
|
// variable. If the caCertificatesEnvVar is not set then initCertPool will
|
|
// return nil. If there is an error creating a *x509.CertPool from the provided
|
|
// caCertificatesEnvVar value then initCertPool will panic.
|
|
func initCertPool() *x509.CertPool {
|
|
if customCACertsPath := os.Getenv(caCertificatesEnvVar); customCACertsPath != "" {
|
|
customCAs, err := ioutil.ReadFile(customCACertsPath)
|
|
if err != nil {
|
|
panic(fmt.Sprintf("error reading %s=%q: %v",
|
|
caCertificatesEnvVar, customCACertsPath, err))
|
|
}
|
|
certPool := x509.NewCertPool()
|
|
if ok := certPool.AppendCertsFromPEM(customCAs); !ok {
|
|
panic(fmt.Sprintf("error creating x509 cert pool from %s=%q: %v",
|
|
caCertificatesEnvVar, customCACertsPath, err))
|
|
}
|
|
return certPool
|
|
}
|
|
return nil
|
|
}
|