2019-03-11 16:56:48 +00:00
|
|
|
package cmd
|
2018-12-06 21:50:17 +00:00
|
|
|
|
|
|
|
import (
|
2024-09-20 17:47:50 +00:00
|
|
|
"fmt"
|
2019-01-03 15:59:53 +00:00
|
|
|
"net"
|
2018-12-06 21:50:17 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2020-09-02 01:20:01 +00:00
|
|
|
"github.com/go-acme/lego/v4/challenge"
|
|
|
|
"github.com/go-acme/lego/v4/challenge/dns01"
|
|
|
|
"github.com/go-acme/lego/v4/challenge/http01"
|
|
|
|
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
|
|
|
|
"github.com/go-acme/lego/v4/lego"
|
|
|
|
"github.com/go-acme/lego/v4/log"
|
|
|
|
"github.com/go-acme/lego/v4/providers/dns"
|
|
|
|
"github.com/go-acme/lego/v4/providers/http/memcached"
|
2023-07-27 10:42:48 +00:00
|
|
|
"github.com/go-acme/lego/v4/providers/http/s3"
|
2020-09-02 01:20:01 +00:00
|
|
|
"github.com/go-acme/lego/v4/providers/http/webroot"
|
2022-02-13 11:28:51 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
2018-12-06 21:50:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func setupChallenges(ctx *cli.Context, client *lego.Client) {
|
2024-09-20 17:47:50 +00:00
|
|
|
if !ctx.Bool(flgHTTP) && !ctx.Bool(flgTLS) && !ctx.IsSet(flgDNS) {
|
|
|
|
log.Fatalf("No challenge selected. You must specify at least one challenge: `--%s`, `--%s`, `--%s`.", flgHTTP, flgTLS, flgDNS)
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
if ctx.Bool(flgHTTP) {
|
2019-01-03 15:59:53 +00:00
|
|
|
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
if ctx.Bool(flgTLS) {
|
2019-01-03 15:59:53 +00:00
|
|
|
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
if ctx.IsSet(flgDNS) {
|
2024-09-07 19:40:21 +00:00
|
|
|
err := setupDNS(ctx, client)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-27 10:42:48 +00:00
|
|
|
//nolint:gocyclo // the complexity is expected.
|
2019-01-03 15:59:53 +00:00
|
|
|
func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
|
|
|
|
switch {
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.IsSet(flgHTTPWebroot):
|
|
|
|
ps, err := webroot.NewHTTPProvider(ctx.String(flgHTTPWebroot))
|
2019-01-03 15:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
return ps
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.IsSet(flgHTTPMemcachedHost):
|
|
|
|
ps, err := memcached.NewMemcachedProvider(ctx.StringSlice(flgHTTPMemcachedHost))
|
2019-01-03 15:59:53 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
return ps
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.IsSet(flgHTTPS3Bucket):
|
|
|
|
ps, err := s3.NewHTTPProvider(ctx.String(flgHTTPS3Bucket))
|
2023-07-27 10:42:48 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
return ps
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.IsSet(flgHTTPPort):
|
|
|
|
iface := ctx.String(flgHTTPPort)
|
2019-01-03 15:59:53 +00:00
|
|
|
if !strings.Contains(iface, ":") {
|
2024-09-20 17:47:50 +00:00
|
|
|
log.Fatalf("The --%s switch only accepts interface:port or :port for its argument.", flgHTTPPort)
|
2019-01-03 15:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
host, port, err := net.SplitHostPort(iface)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2019-10-05 11:44:38 +00:00
|
|
|
srv := http01.NewProviderServer(host, port)
|
2024-09-20 17:47:50 +00:00
|
|
|
if header := ctx.String(flgHTTPProxyHeader); header != "" {
|
2019-10-05 11:44:38 +00:00
|
|
|
srv.SetProxyHeader(header)
|
|
|
|
}
|
|
|
|
return srv
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.Bool(flgHTTP):
|
2019-10-05 11:44:38 +00:00
|
|
|
srv := http01.NewProviderServer("", "")
|
2024-09-20 17:47:50 +00:00
|
|
|
if header := ctx.String(flgHTTPProxyHeader); header != "" {
|
2019-10-05 11:44:38 +00:00
|
|
|
srv.SetProxyHeader(header)
|
|
|
|
}
|
|
|
|
return srv
|
2019-01-03 15:59:53 +00:00
|
|
|
default:
|
|
|
|
log.Fatal("Invalid HTTP challenge options.")
|
|
|
|
return nil
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-03 15:59:53 +00:00
|
|
|
func setupTLSProvider(ctx *cli.Context) challenge.Provider {
|
|
|
|
switch {
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.IsSet(flgTLSPort):
|
|
|
|
iface := ctx.String(flgTLSPort)
|
2019-01-03 15:59:53 +00:00
|
|
|
if !strings.Contains(iface, ":") {
|
2024-09-20 17:47:50 +00:00
|
|
|
log.Fatalf("The --%s switch only accepts interface:port or :port for its argument.", flgTLSPort)
|
2019-01-03 15:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
host, port, err := net.SplitHostPort(iface)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return tlsalpn01.NewProviderServer(host, port)
|
2024-09-20 17:47:50 +00:00
|
|
|
case ctx.Bool(flgTLS):
|
2019-01-03 15:59:53 +00:00
|
|
|
return tlsalpn01.NewProviderServer("", "")
|
|
|
|
default:
|
|
|
|
log.Fatal("Invalid HTTP challenge options.")
|
|
|
|
return nil
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-07 19:40:21 +00:00
|
|
|
func setupDNS(ctx *cli.Context, client *lego.Client) error {
|
2024-09-26 19:02:39 +00:00
|
|
|
err := checkPropagationExclusiveOptions(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2024-09-07 19:40:21 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
wait := ctx.Duration(flgDNSPropagationWait)
|
2024-09-07 19:40:21 +00:00
|
|
|
if wait < 0 {
|
2024-09-20 17:47:50 +00:00
|
|
|
return fmt.Errorf("'%s' cannot be negative", flgDNSPropagationWait)
|
2024-09-07 19:40:21 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
provider, err := dns.NewDNSChallengeProviderByName(ctx.String(flgDNS))
|
2018-12-06 21:50:17 +00:00
|
|
|
if err != nil {
|
2024-09-07 19:40:21 +00:00
|
|
|
return err
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
servers := ctx.StringSlice(flgDNSResolvers)
|
2024-09-07 19:40:21 +00:00
|
|
|
|
2018-12-06 21:50:17 +00:00
|
|
|
err = client.Challenge.SetDNS01Provider(provider,
|
|
|
|
dns01.CondOption(len(servers) > 0,
|
2024-09-20 17:47:50 +00:00
|
|
|
dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.StringSlice(flgDNSResolvers)))),
|
2024-09-07 19:40:21 +00:00
|
|
|
|
2024-09-26 19:02:39 +00:00
|
|
|
dns01.CondOption(ctx.Bool(flgDNSDisableCP) || ctx.Bool(flgDNSPropagationDisableANS),
|
|
|
|
dns01.DisableAuthoritativeNssPropagationRequirement()),
|
2024-09-07 19:40:21 +00:00
|
|
|
|
2024-09-26 19:02:39 +00:00
|
|
|
dns01.CondOption(ctx.Duration(flgDNSPropagationWait) > 0,
|
2024-10-02 17:31:52 +00:00
|
|
|
// TODO(ldez): inside the next major version we will use flgDNSDisableCP here.
|
|
|
|
// This will change the meaning of this flag to really disable all propagation checks.
|
|
|
|
dns01.PropagationWait(wait, true)),
|
2024-09-26 19:02:39 +00:00
|
|
|
|
|
|
|
dns01.CondOption(ctx.Bool(flgDNSPropagationRNS),
|
|
|
|
dns01.RecursiveNSsPropagationRequirement()),
|
2024-09-07 19:40:21 +00:00
|
|
|
|
2024-09-20 17:47:50 +00:00
|
|
|
dns01.CondOption(ctx.IsSet(flgDNSTimeout),
|
|
|
|
dns01.AddDNSTimeout(time.Duration(ctx.Int(flgDNSTimeout))*time.Second)),
|
2018-12-06 21:50:17 +00:00
|
|
|
)
|
2024-09-07 19:40:21 +00:00
|
|
|
|
|
|
|
return err
|
2018-12-06 21:50:17 +00:00
|
|
|
}
|
2024-09-26 19:02:39 +00:00
|
|
|
|
|
|
|
func checkPropagationExclusiveOptions(ctx *cli.Context) error {
|
|
|
|
if ctx.IsSet(flgDNSDisableCP) {
|
|
|
|
log.Println("The flag '%s' is deprecated use '%s' instead.", flgDNSDisableCP, flgDNSPropagationDisableANS)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isSetBool(ctx, flgDNSDisableCP) || isSetBool(ctx, flgDNSPropagationDisableANS)) && ctx.IsSet(flgDNSPropagationWait) {
|
|
|
|
return fmt.Errorf("'%s' and '%s' are mutually exclusive", flgDNSPropagationDisableANS, flgDNSPropagationWait)
|
|
|
|
}
|
|
|
|
|
|
|
|
if isSetBool(ctx, flgDNSPropagationRNS) && ctx.IsSet(flgDNSPropagationWait) {
|
|
|
|
return fmt.Errorf("'%s' and '%s' are mutually exclusive", flgDNSPropagationRNS, flgDNSPropagationWait)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func isSetBool(ctx *cli.Context, name string) bool {
|
|
|
|
return ctx.IsSet(name) && ctx.Bool(name)
|
|
|
|
}
|