feat: rework acme config format

This commit is contained in:
Toby 2024-06-10 16:28:21 -07:00
parent bc0e18980b
commit 18d075cc07
3 changed files with 112 additions and 54 deletions

View file

@ -6,12 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/libdns/cloudflare"
"github.com/libdns/duckdns"
"github.com/libdns/gandi"
"github.com/libdns/godaddy"
"github.com/libdns/namedotcom"
"github.com/libdns/vultr"
"net"
"net/http"
"net/http/httputil"
@ -22,6 +16,12 @@ import (
"time"
"github.com/caddyserver/certmagic"
"github.com/libdns/cloudflare"
"github.com/libdns/duckdns"
"github.com/libdns/gandi"
"github.com/libdns/godaddy"
"github.com/libdns/namedotcom"
"github.com/libdns/vultr"
"github.com/mholt/acmez/acme"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -85,19 +85,36 @@ type serverConfigTLS struct {
}
type serverConfigACME struct {
Domains []string `mapstructure:"domains"`
Email string `mapstructure:"email"`
CA string `mapstructure:"ca"`
DisableHTTP bool `mapstructure:"disableHTTP"`
DisableTLSALPN bool `mapstructure:"disableTLSALPN"`
ListenHost string `mapstructure:"listenHost"`
AltHTTPPort int `mapstructure:"altHTTPPort"`
AltTLSALPNPort int `mapstructure:"altTLSALPNPort"`
DNSProvider serverConfigACMEDNSProvider `mapstructure:"dnsProvider"`
Dir string `mapstructure:"dir"`
// Common fields
Domains []string `mapstructure:"domains"`
Email string `mapstructure:"email"`
CA string `mapstructure:"ca"`
ListenHost string `mapstructure:"listenHost"`
Dir string `mapstructure:"dir"`
// Type selection
Type string `mapstructure:"type"`
HTTP serverConfigACMEHTTP `mapstructure:"http"`
TLS serverConfigACMETLS `mapstructure:"tls"`
DNS serverConfigACMEDNS `mapstructure:"dns"`
// Legacy fields for backwards compatibility
// Only applicable when Type is empty
DisableHTTP bool `mapstructure:"disableHTTP"`
DisableTLSALPN bool `mapstructure:"disableTLSALPN"`
AltHTTPPort int `mapstructure:"altHTTPPort"`
AltTLSALPNPort int `mapstructure:"altTLSALPNPort"`
}
type serverConfigACMEDNSProvider struct {
type serverConfigACMEHTTP struct {
AltPort int `mapstructure:"altPort"`
}
type serverConfigACMETLS struct {
AltPort int `mapstructure:"altPort"`
}
type serverConfigACMEDNS struct {
Name string `mapstructure:"name"`
Config map[string]string `mapstructure:"config"`
}
@ -304,14 +321,10 @@ func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
Logger: logger,
}
cmIssuer := certmagic.NewACMEIssuer(cmCfg, certmagic.ACMEIssuer{
Email: c.ACME.Email,
Agreed: true,
DisableHTTPChallenge: c.ACME.DisableHTTP,
DisableTLSALPNChallenge: c.ACME.DisableTLSALPN,
ListenHost: c.ACME.ListenHost,
AltHTTPPort: c.ACME.AltHTTPPort,
AltTLSALPNPort: c.ACME.AltTLSALPNPort,
Logger: logger,
Email: c.ACME.Email,
Agreed: true,
ListenHost: c.ACME.ListenHost,
Logger: logger,
})
switch strings.ToLower(c.ACME.CA) {
case "letsencrypt", "le", "":
@ -325,51 +338,80 @@ func (c *serverConfig) fillTLSConfig(hyConfig *server.Config) error {
}
cmIssuer.ExternalAccount = eab
default:
return configError{Field: "acme.ca", Err: errors.New("unknown CA")}
return configError{Field: "acme.ca", Err: errors.New("unsupported CA")}
}
if c.ACME.DNSProvider.Name != "" && c.ACME.DNSProvider.Config != nil {
switch strings.ToLower(c.ACME.DNSProvider.Name) {
switch strings.ToLower(c.ACME.Type) {
case "http":
cmIssuer.DisableHTTPChallenge = false
cmIssuer.DisableTLSALPNChallenge = true
cmIssuer.DNS01Solver = nil
cmIssuer.AltHTTPPort = c.ACME.HTTP.AltPort
case "tls":
cmIssuer.DisableHTTPChallenge = true
cmIssuer.DisableTLSALPNChallenge = false
cmIssuer.DNS01Solver = nil
cmIssuer.AltTLSALPNPort = c.ACME.TLS.AltPort
case "dns":
cmIssuer.DisableHTTPChallenge = true
cmIssuer.DisableTLSALPNChallenge = true
if c.ACME.DNS.Name == "" {
return configError{Field: "acme.dns.name", Err: errors.New("empty DNS provider name")}
}
if c.ACME.DNS.Config == nil {
return configError{Field: "acme.dns.config", Err: errors.New("empty DNS provider config")}
}
switch strings.ToLower(c.ACME.DNS.Name) {
case "cloudflare":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &cloudflare.Provider{
APIToken: c.ACME.DNSProvider.Config["cloudflare_api_token"],
APIToken: c.ACME.DNS.Config["cloudflare_api_token"],
},
}
case "duckdns":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &duckdns.Provider{
APIToken: c.ACME.DNSProvider.Config["duckdns_api_token"],
OverrideDomain: c.ACME.DNSProvider.Config["duckdns_override_domain"],
APIToken: c.ACME.DNS.Config["duckdns_api_token"],
OverrideDomain: c.ACME.DNS.Config["duckdns_override_domain"],
},
}
case "gandi":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &gandi.Provider{
BearerToken: c.ACME.DNSProvider.Config["gandi_api_token"],
BearerToken: c.ACME.DNS.Config["gandi_api_token"],
},
}
case "godaddy":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &godaddy.Provider{
APIToken: c.ACME.DNSProvider.Config["godaddy_api_token"],
APIToken: c.ACME.DNS.Config["godaddy_api_token"],
},
}
case "namedotcom":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &namedotcom.Provider{
Token: c.ACME.DNSProvider.Config["namedotcom_token"],
User: c.ACME.DNSProvider.Config["namedotcom_user"],
Server: c.ACME.DNSProvider.Config["namedotcom_server"],
Token: c.ACME.DNS.Config["namedotcom_token"],
User: c.ACME.DNS.Config["namedotcom_user"],
Server: c.ACME.DNS.Config["namedotcom_server"],
},
}
case "vultr":
cmIssuer.DNS01Solver = &certmagic.DNS01Solver{
DNSProvider: &vultr.Provider{
APIToken: c.ACME.DNSProvider.Config["vultr_api_token"],
APIToken: c.ACME.DNS.Config["vultr_api_token"],
},
}
default:
return configError{Field: "acme.dns.name", Err: errors.New("unsupported DNS provider")}
}
case "":
// Legacy compatibility mode
cmIssuer.DisableHTTPChallenge = c.ACME.DisableHTTP
cmIssuer.DisableTLSALPNChallenge = c.ACME.DisableTLSALPN
cmIssuer.AltHTTPPort = c.ACME.AltHTTPPort
cmIssuer.AltTLSALPNPort = c.ACME.AltTLSALPNPort
default:
return configError{Field: "acme.type", Err: errors.New("unsupported ACME type")}
}
cmCfg.Issuers = []certmagic.Issuer{cmIssuer}

View file

@ -34,19 +34,28 @@ func TestServerConfig(t *testing.T) {
"sub1.example.com",
"sub2.example.com",
},
Email: "haha@cringe.net",
CA: "zero",
DisableHTTP: true,
DisableTLSALPN: true,
AltHTTPPort: 9980,
AltTLSALPNPort: 9443,
Dir: "random_dir",
DNSProvider: serverConfigACMEDNSProvider{
Name: "cloudflare",
Email: "haha@cringe.net",
CA: "zero",
ListenHost: "127.0.0.9",
Dir: "random_dir",
Type: "dns",
HTTP: serverConfigACMEHTTP{
AltPort: 8888,
},
TLS: serverConfigACMETLS{
AltPort: 44333,
},
DNS: serverConfigACMEDNS{
Name: "gomommy",
Config: map[string]string{
"cloudflare_api_token": "xxxxxxxxxx",
"key1": "value1",
"key2": "value2",
},
},
DisableHTTP: true,
DisableTLSALPN: true,
AltHTTPPort: 8080,
AltTLSALPNPort: 4433,
},
QUIC: serverConfigQUIC{
InitStreamReceiveWindow: 77881,

View file

@ -15,15 +15,22 @@ acme:
- sub2.example.com
email: haha@cringe.net
ca: zero
listenHost: 127.0.0.9
dir: random_dir
type: dns
http:
altPort: 8888
tls:
altPort: 44333
dns:
name: gomommy
config:
key1: value1
key2: value2
disableHTTP: true
disableTLSALPN: true
altHTTPPort: 9980
altTLSALPNPort: 9443
dir: random_dir
dnsProvider:
name: "cloudflare"
config:
cloudflare_api_token: "xxxxxxxxxx"
altHTTPPort: 8080
altTLSALPNPort: 4433
quic:
initStreamReceiveWindow: 77881