maddy/internal/tls/acme/acme.go
fox.cpp 78e4600a17
Upgrade all dependencies
1. go-smtp is replaced by a fork that reverts StartTLS removal.
2. SASL LOGIN is no longer supported by upstream go-sasl, readded disabled by default.
3. Updated endpoint code to match new go-smtp authentication interfaces.
4. certmagic repo had some renames
5. Minimum Go version increased to 1.23 to match dependencies.
2025-01-24 21:29:48 +03:00

164 lines
4 KiB
Go

package acme
import (
"context"
"crypto/tls"
"fmt"
"path/filepath"
"github.com/caddyserver/certmagic"
"github.com/foxcpp/maddy/framework/config"
modconfig "github.com/foxcpp/maddy/framework/config/module"
"github.com/foxcpp/maddy/framework/hooks"
"github.com/foxcpp/maddy/framework/log"
"github.com/foxcpp/maddy/framework/module"
)
const modName = "tls.loader.acme"
type Loader struct {
instName string
store certmagic.Storage
cache *certmagic.Cache
cfg *certmagic.Config
cancelManage context.CancelFunc
log log.Logger
}
func New(_, instName string, _, inlineArgs []string) (module.Module, error) {
if len(inlineArgs) != 0 {
return nil, fmt.Errorf("%s: no inline args expected", modName)
}
return &Loader{
instName: instName,
log: log.Logger{Name: modName},
}, nil
}
func (l *Loader) Init(cfg *config.Map) error {
var (
hostname string
extraNames []string
storePath string
caPath string
testCAPath string
email string
agreed bool
challenge string
overrideDomain string
provider certmagic.DNSProvider
)
cfg.Bool("debug", true, false, &l.log.Debug)
cfg.String("hostname", true, true, "", &hostname)
cfg.StringList("extra_names", false, false, nil, &extraNames)
cfg.String("store_path", false, false,
filepath.Join(config.StateDirectory, "acme"), &storePath)
cfg.String("ca", false, false,
certmagic.LetsEncryptProductionCA, &caPath)
cfg.String("test_ca", false, false,
certmagic.LetsEncryptStagingCA, &testCAPath)
cfg.String("email", false, false,
"", &email)
cfg.String("override_domain", false, false,
"", &overrideDomain)
cfg.Bool("agreed", false, false, &agreed)
cfg.Enum("challenge", false, true,
[]string{"dns-01"}, "dns-01", &challenge)
cfg.Custom("dns", false, false, func() (interface{}, error) {
return nil, nil
}, func(m *config.Map, node config.Node) (interface{}, error) {
var p certmagic.DNSProvider
err := modconfig.ModuleFromNode("libdns", node.Args, node, m.Globals, &p)
return p, err
}, &provider)
if _, err := cfg.Process(); err != nil {
return err
}
cmLog := l.log.Zap()
l.store = &certmagic.FileStorage{Path: storePath}
l.cache = certmagic.NewCache(certmagic.CacheOptions{
Logger: cmLog,
GetConfigForCert: func(c certmagic.Certificate) (*certmagic.Config, error) {
return l.cfg, nil
},
})
l.cfg = certmagic.New(l.cache, certmagic.Config{
Storage: l.store, // not sure if it is necessary to set these twice
Logger: cmLog,
DefaultServerName: hostname,
})
issuer := certmagic.NewACMEIssuer(l.cfg, certmagic.ACMEIssuer{
Logger: cmLog,
CA: caPath,
TestCA: testCAPath,
Email: email,
Agreed: agreed,
})
switch challenge {
case "dns-01":
issuer.DisableTLSALPNChallenge = true
issuer.DisableHTTPChallenge = true
if provider == nil {
return fmt.Errorf("tls.loader.acme: dns-01 challenge requires a configured DNS provider")
}
issuer.DNS01Solver = &certmagic.DNS01Solver{
DNSManager: certmagic.DNSManager{
DNSProvider: provider,
OverrideDomain: overrideDomain,
},
}
default:
return fmt.Errorf("tls.loader.acme: challenge not supported")
}
l.cfg.Issuers = []certmagic.Issuer{issuer}
if module.NoRun {
return nil
}
manageCtx, cancelManage := context.WithCancel(context.Background())
err := l.cfg.ManageAsync(manageCtx, append([]string{hostname}, extraNames...))
if err != nil {
cancelManage()
return err
}
l.cancelManage = cancelManage
return nil
}
func (l *Loader) ConfigureTLS(c *tls.Config) error {
c.GetCertificate = l.cfg.GetCertificate
return nil
}
func (l *Loader) Close() error {
l.cancelManage()
l.cache.Stop()
return nil
}
func (l *Loader) Name() string {
return modName
}
func (l *Loader) InstanceName() string {
return l.instName
}
func init() {
hooks.AddHook(hooks.EventShutdown, func() {
certmagic.CleanUpOwnLocks(context.TODO(), log.DefaultLogger.Zap())
})
}
func init() {
var _ module.TLSLoader = &Loader{}
module.Register(modName, New)
}