refactor: move flags to a package

This commit is contained in:
Fernandez Ludovic 2026-03-09 22:59:19 +01:00
commit f09752537d
15 changed files with 654 additions and 638 deletions

View file

@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/log"
"github.com/mattn/go-zglob"
@ -26,12 +27,12 @@ func createListAccounts() *cli.Command {
Name: "accounts",
Usage: "Display information about accounts.",
Action: listAccounts,
Flags: createListFlags(),
Flags: flags.CreateListFlags(),
}
}
func listAccounts(ctx context.Context, cmd *cli.Command) error {
if cmd.Bool(flgFormatJSON) {
if cmd.Bool(flags.FlgFormatJSON) {
return listAccountsJSON(ctx, cmd)
}

View file

@ -10,6 +10,7 @@ import (
"time"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/mattn/go-zglob"
"github.com/urfave/cli/v3"
@ -30,12 +31,12 @@ func createListCertificates() *cli.Command {
Name: "certificates",
Usage: "Display information about certificates.",
Action: listCertificates,
Flags: createListFlags(),
Flags: flags.CreateListFlags(),
}
}
func listCertificates(ctx context.Context, cmd *cli.Command) error {
if cmd.Bool(flgFormatJSON) {
if cmd.Bool(flags.FlgFormatJSON) {
return listCertificatesJSON(ctx, cmd)
}
@ -90,7 +91,7 @@ func listCertificatesJSON(_ context.Context, cmd *cli.Command) error {
}
func readCertificates(cmd *cli.Command) ([]ListCertificate, error) {
certsStorage := storage.NewCertificatesStorage(cmd.String(flgPath))
certsStorage := storage.NewCertificatesStorage(cmd.String(flags.FlgPath))
matches, err := zglob.Glob(filepath.Join(certsStorage.GetRootPath(), "**", "*.json"))
if err != nil {

View file

@ -7,6 +7,7 @@ import (
"os"
"strings"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/migrate"
"github.com/go-acme/lego/v5/log"
"github.com/urfave/cli/v3"
@ -21,18 +22,18 @@ func createMigrate() *cli.Command {
return nil
}
err := migrate.Accounts(cmd.String(flgPath))
err := migrate.Accounts(cmd.String(flags.FlgPath))
if err != nil {
return err
}
if cmd.Bool(flgAccountOnly) {
if cmd.Bool(flags.FlgAccountOnly) {
return nil
}
return migrate.Certificates(cmd.String(flgPath))
return migrate.Certificates(cmd.String(flags.FlgPath))
},
Flags: createMigrateFlags(),
Flags: flags.CreateMigrateFlags(),
}
}
@ -40,8 +41,8 @@ func confirmMigration(cmd *cli.Command) bool {
reader := bufio.NewReader(os.Stdin)
log.Warnf(log.LazySprintf("The migration will not work if the certificates have been generated with the '--filename' flag."+
" Use the flag '--%s' to only migrate accounts.", flgAccountOnly))
log.Warnf(log.LazySprintf("Please create a backup of %q before the migration.", cmd.String(flgPath)))
" Use the flag '--%s' to only migrate accounts.", flags.FlgAccountOnly))
log.Warnf(log.LazySprintf("Please create a backup of %q before the migration.", cmd.String(flags.FlgPath)))
for {
fmt.Println("Continue? Y/n")

View file

@ -10,6 +10,7 @@ import (
"github.com/go-acme/lego/v5/acme"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
"github.com/go-acme/lego/v5/log"
@ -34,12 +35,12 @@ func createRegister() *cli.Command {
Name: "register",
Usage: "Register an account.",
Action: register,
Flags: createRegisterFlags(),
Flags: flags.CreateRegisterFlags(),
}
}
func register(ctx context.Context, cmd *cli.Command) error {
keyType, err := certcrypto.GetKeyType(cmd.String(flgKeyType))
keyType, err := certcrypto.GetKeyType(cmd.String(flags.FlgKeyType))
if err != nil {
return fmt.Errorf("get the key type: %w", err)
}
@ -49,7 +50,7 @@ func register(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("accounts storage initialization: %w", err)
}
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flgEmail), cmd.String(flgAccountID))
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flags.FlgEmail), cmd.String(flags.FlgAccountID))
if err != nil {
return fmt.Errorf("set up account: %w", err)
}
@ -84,12 +85,12 @@ func registerAccount(ctx context.Context, cmd *cli.Command, client *lego.Client)
log.Fatal("You did not accept the TOS. Unable to proceed.")
}
if cmd.Bool(flgEAB) {
kid := cmd.String(flgEABKID)
hmacEncoded := cmd.String(flgEABHMAC)
if cmd.Bool(flags.FlgEAB) {
kid := cmd.String(flags.FlgEABKID)
hmacEncoded := cmd.String(flags.FlgEABHMAC)
if kid == "" || hmacEncoded == "" {
log.Fatal(fmt.Sprintf("Requires arguments --%s and --%s.", flgEABKID, flgEABHMAC))
log.Fatal(fmt.Sprintf("Requires arguments --%s and --%s.", flags.FlgEABKID, flags.FlgEABHMAC))
}
return client.Registration.RegisterWithExternalAccountBinding(ctx, registration.RegisterEABOptions{
@ -97,8 +98,8 @@ func registerAccount(ctx context.Context, cmd *cli.Command, client *lego.Client)
Kid: kid,
HmacEncoded: hmacEncoded,
})
} else if zerossl.IsZeroSSL(cmd.String(flgServer)) {
return registration.RegisterWithZeroSSL(ctx, client.Registration, cmd.String(flgEmail))
} else if zerossl.IsZeroSSL(cmd.String(flags.FlgServer)) {
return registration.RegisterWithZeroSSL(ctx, client.Registration, cmd.String(flags.FlgEmail))
}
return client.Registration.Register(ctx, registration.RegisterOptions{TermsOfServiceAgreed: true})
@ -112,7 +113,7 @@ func handleTOS(cmd *cli.Command, client *lego.Client) bool {
}
// Check for a global accept override
if cmd.Bool(flgAcceptTOS) {
if cmd.Bool(flags.FlgAcceptTOS) {
return true
}

View file

@ -17,6 +17,7 @@ import (
"github.com/go-acme/lego/v5/acme/api"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/hook"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
@ -34,13 +35,13 @@ func createRenew() *cli.Command {
Name: "renew",
Usage: "Renew a certificate",
Action: renew,
Before: renewFlagsValidation,
Flags: createRenewFlags(),
Before: flags.RenewFlagsValidation,
Flags: flags.CreateRenewFlags(),
}
}
func renew(ctx context.Context, cmd *cli.Command) error {
keyType, err := certcrypto.GetKeyType(cmd.String(flgKeyType))
keyType, err := certcrypto.GetKeyType(cmd.String(flags.FlgKeyType))
if err != nil {
return fmt.Errorf("get the key type: %w", err)
}
@ -50,7 +51,7 @@ func renew(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("accounts storage initialization: %w", err)
}
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flgEmail), cmd.String(flgAccountID))
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flags.FlgEmail), cmd.String(flags.FlgAccountID))
if err != nil {
return fmt.Errorf("set up account: %w", err)
}
@ -59,7 +60,7 @@ func renew(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("the account %s is not registered", account.GetID())
}
certsStorage := storage.NewCertificatesStorage(cmd.String(flgPath))
certsStorage := storage.NewCertificatesStorage(cmd.String(flags.FlgPath))
lazyClient := sync.OnceValues(func() (*lego.Client, error) {
client, err := newClient(cmd, account, keyType)
@ -75,7 +76,7 @@ func renew(ctx context.Context, cmd *cli.Command) error {
hookManager := newHookManager(cmd, certsStorage, account)
// CSR
if cmd.IsSet(flgCSR) {
if cmd.IsSet(flags.FlgCSR) {
return renewForCSR(ctx, cmd, lazyClient, certsStorage, hookManager)
}
@ -84,9 +85,9 @@ func renew(ctx context.Context, cmd *cli.Command) error {
}
func renewForDomains(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, certsStorage *storage.CertificatesStorage, hookManager *hook.Manager) error {
domains := cmd.StringSlice(flgDomains)
domains := cmd.StringSlice(flags.FlgDomains)
certID := cmd.String(flgCertName)
certID := cmd.String(flags.FlgCertName)
switch {
case certID == "" && len(domains) > 0:
@ -129,11 +130,11 @@ func renewForDomains(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp,
certDomains := certcrypto.ExtractDomains(cert)
renewalDomains := slices.Clone(domains)
if !cmd.Bool(flgForceCertDomains) {
if !cmd.Bool(flags.FlgForceCertDomains) {
renewalDomains = merge(certDomains, domains)
}
if ariRenewalTime == nil && !cmd.Bool(flgRenewForce) && sameDomains(certDomains, renewalDomains) &&
if ariRenewalTime == nil && !cmd.Bool(flags.FlgRenewForce) && sameDomains(certDomains, renewalDomains) &&
!isInRenewalPeriod(cert, certID, getFlagRenewDays(cmd), time.Now()) {
return nil
}
@ -160,7 +161,7 @@ func renewForDomains(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp,
request := newObtainRequest(cmd, renewalDomains)
if cmd.Bool(flgReuseKey) {
if cmd.Bool(flags.FlgReuseKey) {
request.PrivateKey, err = certsStorage.ReadPrivateKey(certID)
if err != nil {
return err
@ -189,12 +190,12 @@ func renewForDomains(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp,
}
func renewForCSR(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, certsStorage *storage.CertificatesStorage, hookManager *hook.Manager) error {
csr, err := storage.ReadCSRFile(cmd.String(flgCSR))
csr, err := storage.ReadCSRFile(cmd.String(flags.FlgCSR))
if err != nil {
return fmt.Errorf("could not read CSR file %q: %w", cmd.String(flgCSR), err)
return fmt.Errorf("could not read CSR file %q: %w", cmd.String(flags.FlgCSR), err)
}
certID := cmd.String(flgCertName)
certID := cmd.String(flags.FlgCertName)
if certID == "" {
certID, err = certcrypto.GetCSRMainDomain(csr)
if err != nil {
@ -222,7 +223,7 @@ func renewForCSR(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, cert
return fmt.Errorf("CSR: %w", err)
}
if ariRenewalTime == nil && !cmd.Bool(flgRenewForce) && sameDomainsCertificate(cert, csr) &&
if ariRenewalTime == nil && !cmd.Bool(flags.FlgRenewForce) && sameDomainsCertificate(cert, csr) &&
!isInRenewalPeriod(cert, certID, getFlagRenewDays(cmd), time.Now()) {
return nil
}
@ -269,8 +270,8 @@ func renewForCSR(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, cert
}
func getFlagRenewDays(cmd *cli.Command) int {
if cmd.IsSet(flgRenewDays) {
return cmd.Int(flgRenewDays)
if cmd.IsSet(flags.FlgRenewDays) {
return cmd.Int(flags.FlgRenewDays)
}
return noDays
@ -315,7 +316,7 @@ func getDueDate(x509Cert *x509.Certificate, days int, now time.Time) time.Time {
}
func getARIInfo(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, certID string, cert *x509.Certificate) (*time.Time, string, error) {
if cmd.Bool(flgARIDisable) {
if cmd.Bool(flags.FlgARIDisable) {
return nil, "", nil
}
@ -324,7 +325,7 @@ func getARIInfo(ctx context.Context, cmd *cli.Command, lazyClient lzSetUp, certI
return nil, "", fmt.Errorf("set up client: %w", err)
}
willingToSleep := cmd.Duration(flgARIWaitToRenewDuration)
willingToSleep := cmd.Duration(flags.FlgARIWaitToRenewDuration)
ariRenewalTime := getARIRenewalTime(ctx, willingToSleep, cert, certID, client)
if ariRenewalTime != nil {
@ -394,7 +395,7 @@ func getARIRenewalTime(ctx context.Context, willingToSleep time.Duration, cert *
func randomSleep(cmd *cli.Command) {
// https://github.com/go-acme/lego/issues/1656
// https://github.com/certbot/certbot/blob/284023a1b7672be2bd4018dd7623b3b92197d4b0/certbot/certbot/_internal/renewal.py#L435-L440
if !isatty.IsTerminal(os.Stdout.Fd()) && !cmd.Bool(flgNoRandomSleep) {
if !isatty.IsTerminal(os.Stdout.Fd()) && !cmd.Bool(flags.FlgNoRandomSleep) {
// https://github.com/certbot/certbot/blob/284023a1b7672be2bd4018dd7623b3b92197d4b0/certbot/certbot/_internal/renewal.py#L472
const jitter = 8 * time.Minute

View file

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
"github.com/go-acme/lego/v5/log"
@ -16,12 +17,12 @@ func createRevoke() *cli.Command {
Name: "revoke",
Usage: "Revoke a certificate",
Action: revoke,
Flags: createRevokeFlags(),
Flags: flags.CreateRevokeFlags(),
}
}
func revoke(ctx context.Context, cmd *cli.Command) error {
keyType, err := certcrypto.GetKeyType(cmd.String(flgKeyType))
keyType, err := certcrypto.GetKeyType(cmd.String(flags.FlgKeyType))
if err != nil {
return fmt.Errorf("get the key type: %w", err)
}
@ -31,7 +32,7 @@ func revoke(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("accounts storage initialization: %w", err)
}
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flgEmail), cmd.String(flgAccountID))
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flags.FlgEmail), cmd.String(flags.FlgAccountID))
if err != nil {
return fmt.Errorf("set up account: %w", err)
}
@ -45,12 +46,12 @@ func revoke(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("new client: %w", err)
}
certsStorage := storage.NewCertificatesStorage(cmd.String(flgPath))
certsStorage := storage.NewCertificatesStorage(cmd.String(flags.FlgPath))
reason := cmd.Uint(flgReason)
keep := cmd.Bool(flgKeep)
reason := cmd.Uint(flags.FlgReason)
keep := cmd.Bool(flags.FlgKeep)
for _, certID := range cmd.StringSlice(flgCertName) {
for _, certID := range cmd.StringSlice(flags.FlgCertName) {
err := revokeCertificate(ctx, client, certsStorage, certID, reason, keep)
if err != nil {
return err

View file

@ -6,6 +6,7 @@ import (
"os"
"strings"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/log"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v3"
@ -25,7 +26,7 @@ func CreateRootCommand() *cli.Command {
return ctx, nil
},
Flags: CreateLogFlags(),
Flags: flags.CreateLogFlags(),
Commands: CreateCommands(),
}
}
@ -46,24 +47,26 @@ func CreateCommands() []*cli.Command {
func setUpLogger(cmd *cli.Command) {
var logger *slog.Logger
switch cmd.String(flgLogFormat) {
level := getLogLeveler(cmd.String(flags.FlgLogLevel))
switch cmd.String(flags.FlgLogFormat) {
case "json":
opts := &slog.HandlerOptions{
Level: getLogLeveler(cmd.String(flgLogLevel)),
Level: level,
}
logger = slog.New(slog.NewJSONHandler(os.Stdout, opts))
case "text":
opts := &slog.HandlerOptions{
Level: getLogLeveler(cmd.String(flgLogLevel)),
Level: level,
}
logger = slog.New(slog.NewTextHandler(os.Stdout, opts))
default:
opts := []slogor.OptionFn{
slogor.SetLevel(getLogLeveler(cmd.String(flgLogLevel))),
slogor.SetLevel(level),
slogor.SetTimeFormat(rfc3339NanoNatural),
}

View file

@ -7,6 +7,7 @@ import (
"github.com/go-acme/lego/v5/acme"
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/certificate"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/hook"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
@ -17,14 +18,14 @@ func createRun() *cli.Command {
return &cli.Command{
Name: "run",
Usage: "Register an account, then create and install a certificate",
Before: runFlagsValidation,
Before: flags.RunFlagsValidation,
Action: run,
Flags: createRunFlags(),
Flags: flags.CreateRunFlags(),
}
}
func run(ctx context.Context, cmd *cli.Command) error {
keyType, err := certcrypto.GetKeyType(cmd.String(flgKeyType))
keyType, err := certcrypto.GetKeyType(cmd.String(flags.FlgKeyType))
if err != nil {
return fmt.Errorf("get the key type: %w", err)
}
@ -34,12 +35,12 @@ func run(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("accounts storage initialization: %w", err)
}
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flgEmail), cmd.String(flgAccountID))
account, err := accountsStorage.Get(ctx, keyType, cmd.String(flags.FlgEmail), cmd.String(flags.FlgAccountID))
if err != nil {
return fmt.Errorf("set up account: %w", err)
}
certsStorage := storage.NewCertificatesStorage(cmd.String(flgPath))
certsStorage := storage.NewCertificatesStorage(cmd.String(flags.FlgPath))
hookManager := newHookManager(cmd, certsStorage, account)
@ -73,7 +74,7 @@ func run(ctx context.Context, cmd *cli.Command) error {
return fmt.Errorf("obtain certificate: %w", err)
}
certID := cmd.String(flgCertName)
certID := cmd.String(flags.FlgCertName)
if certID != "" {
certRes.ID = certID
}
@ -89,10 +90,10 @@ func run(ctx context.Context, cmd *cli.Command) error {
}
func obtainCertificate(ctx context.Context, cmd *cli.Command, client *lego.Client, hookManager *hook.Manager) (*certificate.Resource, error) {
domains := cmd.StringSlice(flgDomains)
domains := cmd.StringSlice(flags.FlgDomains)
if len(domains) > 0 {
err := hookManager.Pre(ctx, cmd.String(flgCertName), domains)
err := hookManager.Pre(ctx, cmd.String(flags.FlgCertName), domains)
if err != nil {
return nil, err
}
@ -103,10 +104,10 @@ func obtainCertificate(ctx context.Context, cmd *cli.Command, client *lego.Clien
request := newObtainRequest(cmd, domains)
// TODO(ldez): factorize?
if cmd.IsSet(flgPrivateKey) {
if cmd.IsSet(flags.FlgPrivateKey) {
var err error
request.PrivateKey, err = storage.ReadPrivateKeyFile(cmd.String(flgPrivateKey))
request.PrivateKey, err = storage.ReadPrivateKeyFile(cmd.String(flags.FlgPrivateKey))
if err != nil {
return nil, fmt.Errorf("load private key: %w", err)
}
@ -116,12 +117,12 @@ func obtainCertificate(ctx context.Context, cmd *cli.Command, client *lego.Clien
}
// read the CSR
csr, err := storage.ReadCSRFile(cmd.String(flgCSR))
csr, err := storage.ReadCSRFile(cmd.String(flags.FlgCSR))
if err != nil {
return nil, err
}
err = hookManager.Pre(ctx, cmd.String(flgCertName), certcrypto.ExtractDomainsCSR(csr))
err = hookManager.Pre(ctx, cmd.String(flags.FlgCertName), certcrypto.ExtractDomainsCSR(csr))
if err != nil {
return nil, err
}
@ -132,10 +133,10 @@ func obtainCertificate(ctx context.Context, cmd *cli.Command, client *lego.Clien
request := newObtainForCSRRequest(cmd, csr)
// TODO(ldez): factorize?
if cmd.IsSet(flgPrivateKey) {
if cmd.IsSet(flags.FlgPrivateKey) {
var err error
request.PrivateKey, err = storage.ReadPrivateKeyFile(cmd.String(flgPrivateKey))
request.PrivateKey, err = storage.ReadPrivateKeyFile(cmd.String(flags.FlgPrivateKey))
if err != nil {
return nil, fmt.Errorf("load private key: %w", err)
}

File diff suppressed because it is too large Load diff

183
cmd/internal/flags/names.go Normal file
View file

@ -0,0 +1,183 @@
package flags
import (
"strings"
"unicode"
)
const (
categoryHTTP01Challenge = "Flags related to the HTTP-01 challenge:"
categoryTLSALPN01Challenge = "Flags related to the TLS-ALPN-01 challenge:"
categoryDNS01Challenge = "Flags related to the DNS-01 challenge:"
categoryDNSPersist01Challenge = "Flags related to the DNS-PERSIST-01 challenge:"
categoryStorage = "Flags related to the storage:"
categoryHooks = "Flags related to hooks:"
categoryEAB = "Flags related to External Account Binding:"
categoryACMEClient = "Flags related to the ACME client:"
categoryAdvanced = "Flags related to advanced options:"
categoryARI = "Flags related to ACME Renewal Information (ARI) Extension:"
categoryLogs = "Flags related to logs:"
)
// Flag aliases (short-codes).
const (
flgAliasAcceptTOS = "a"
flgAliasCertName = "c"
flgAliasDomains = "d"
flgAliasEmail = "m"
flgAliasIPv4Only = "4"
flgAliasIPv6Only = "6"
flgAliasKeyType = "k"
flgAliasServer = "s"
)
// Flag names related to the account.
const (
FlgAcceptTOS = "accept-tos"
FlgEmail = "email"
FlgKeyType = "key-type"
FlgAccountID = "account-id"
FlgEAB = "eab"
FlgEABKID = "eab.kid"
FlgEABHMAC = "eab.hmac"
)
// Flag names related to Obtain certificates.
const (
FlgDomains = "domains"
FlgCSR = "csr"
FlgNoBundle = "no-bundle"
FlgMustStaple = "must-staple"
FlgNotBefore = "not-before"
FlgNotAfter = "not-after"
FlgPreferredChain = "preferred-chain"
FlgProfile = "profile"
FlgAlwaysDeactivateAuthorizations = "always-deactivate-authorizations"
)
// Flag names related to the storage.
const (
FlgPath = "path"
FlgPEM = "pem"
FlgPFX = "pfx"
FlgPFXPass = "pfx.pass"
FlgPFXFormat = "pfx.format"
)
// Flag names related to the ACME client.
const (
FlgServer = "server"
FlgEnableCommonName = "enable-cn"
FlgHTTPTimeout = "http-timeout"
FlgTLSSkipVerify = "tls-skip-verify"
FlgOverallRequestLimit = "overall-request-limit"
FlgUserAgent = "user-agent"
)
// Flag names related to certificates.
const (
FlgCertTimeout = "cert.timeout"
FlgCertName = "cert.name"
)
// Flag names related to the network stack.
const (
FlgIPv4Only = "ipv4only"
FlgIPv6Only = "ipv6only"
)
// Flag names related to HTTP-01 challenge.
const (
FlgHTTP = "http"
FlgHTTPPort = "http.port"
FlgHTTPDelay = "http.delay"
FlgHTTPProxyHeader = "http.proxy-header"
FlgHTTPWebroot = "http.webroot"
FlgHTTPMemcachedHost = "http.memcached-host"
FlgHTTPS3Bucket = "http.s3-bucket"
)
// Flag names related to TLS-ALPN-01 challenge.
const (
FlgTLS = "tls"
FlgTLSPort = "tls.port"
FlgTLSDelay = "tls.delay"
)
// Flag names related to DNS-01 challenge.
const (
FlgDNS = "dns"
FlgDNSPropagationWait = "dns.propagation.wait"
FlgDNSPropagationDisableANS = "dns.propagation.disable-ans"
FlgDNSPropagationDisableRNS = "dns.propagation.disable-rns"
FlgDNSResolvers = "dns.resolvers"
FlgDNSTimeout = "dns.timeout"
)
// Flag names related to the DNS-PERSIST-01 challenge.
const (
FlgDNSPersist = "dns-persist"
FlgDNSPersistIssuerDomainName = "dns-persist.issuer-domain-name"
FlgDNSPersistPersistUntil = "dns-persist.persist-until"
FlgDNSPersistPropagationWait = "dns-persist.propagation.wait"
FlgDNSPersistPropagationDisableANS = "dns-persist.propagation.disable-ans"
FlgDNSPersistPropagationDisableRNS = "dns-persist.propagation.disable-rns"
FlgDNSPersistResolvers = "dns-persist.resolvers"
FlgDNSPersistTimeout = "dns-persist.timeout"
)
// Flags names related to hooks.
const (
FlgPreHook = "pre-hook"
FlgPreHookTimeout = "pre-hook-timeout"
FlgDeployHook = "deploy-hook"
FlgDeployHookTimeout = "deploy-hook-timeout"
FlgPostHook = "post-hook"
FlgPostHookTimeout = "post-hook-timeout"
)
// Flag names related to logs.
const (
FlgLogLevel = "log.level"
FlgLogFormat = "log.format"
)
// Flag names related to the specific run command.
const (
FlgPrivateKey = "private-key"
)
// Flag names related to the specific renew command.
const (
FlgRenewDays = "renew-days"
FlgRenewForce = "renew-force"
FlgARIDisable = "ari-disable"
FlgARIWaitToRenewDuration = "ari-wait-to-renew-duration"
FlgReuseKey = "reuse-key"
FlgNoRandomSleep = "no-random-sleep"
FlgForceCertDomains = "force-cert-domains"
)
// Flag names related to the specific revoke command.
const (
FlgKeep = "keep"
FlgReason = "reason"
)
// Flag names related to the list commands.
const (
FlgFormatJSON = "json"
)
// Flag names related to the migrate command.
const (
FlgAccountOnly = "account-only"
)
func toEnvName(flg string) string {
fields := strings.FieldsFunc(flg, func(r rune) bool {
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
})
return "LEGO_" + strings.ToUpper(strings.Join(fields, "_"))
}

View file

@ -1,4 +1,4 @@
package cmd
package flags
import (
"testing"
@ -14,22 +14,22 @@ func Test_toEnvName(t *testing.T) {
}{
{
desc: "only letters",
flag: flgServer,
flag: FlgServer,
expected: "LEGO_SERVER",
},
{
desc: "letters and digits",
flag: flgIPv6Only,
flag: FlgIPv6Only,
expected: "LEGO_IPV6ONLY",
},
{
desc: "hyphen",
flag: flgHTTPPort,
flag: FlgHTTPPort,
expected: "LEGO_HTTP_PORT",
},
{
desc: "dot, hyphen",
flag: flgDNSPropagationDisableRNS,
flag: FlgDNSPropagationDisableRNS,
expected: "LEGO_DNS_PROPAGATION_DISABLE_RNS",
},
}

View file

@ -1,4 +1,4 @@
package cmd
package flags
import (
"context"
@ -7,19 +7,19 @@ import (
"github.com/urfave/cli/v3"
)
func runFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Context, error) {
func RunFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Context, error) {
// we require either domains or csr, but not both
hasDomains := len(cmd.StringSlice(flgDomains)) > 0
hasDomains := len(cmd.StringSlice(FlgDomains)) > 0
hasCsr := cmd.String(flgCSR) != ""
hasCsr := cmd.String(FlgCSR) != ""
if hasDomains && hasCsr {
return ctx, fmt.Errorf("please specify either '--%s'/'-%s' or '--%s', but not both",
flgDomains, flgAliasDomains, flgCSR)
FlgDomains, flgAliasDomains, FlgCSR)
}
if !hasDomains && !hasCsr {
return ctx, fmt.Errorf("please specify '--%s'/'-%s' (or '--%s' if you already have a CSR)",
flgDomains, flgAliasDomains, flgCSR)
FlgDomains, flgAliasDomains, FlgCSR)
}
err := validateChallengeRequirements(cmd)
@ -30,24 +30,24 @@ func runFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Context,
return ctx, validateNetworkStack(cmd)
}
func renewFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Context, error) {
hasDomains := len(cmd.StringSlice(flgDomains)) > 0
hasCsr := cmd.String(flgCSR) != ""
hasCertID := cmd.String(flgCertName) != ""
func RenewFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Context, error) {
hasDomains := len(cmd.StringSlice(FlgDomains)) > 0
hasCsr := cmd.String(FlgCSR) != ""
hasCertID := cmd.String(FlgCertName) != ""
if hasDomains && hasCsr {
return ctx, fmt.Errorf("please specify either '--%s'/'-%s' or '--%s', but not both",
flgDomains, flgAliasDomains, flgCSR)
FlgDomains, flgAliasDomains, FlgCSR)
}
if !hasCertID && !hasDomains && !hasCsr {
return ctx, fmt.Errorf("please specify '--%s' or '--%s'/'-%s' (or '--%s' if you already have a CSR)",
flgCertName, flgDomains, flgAliasDomains, flgCSR)
FlgCertName, FlgDomains, flgAliasDomains, FlgCSR)
}
if cmd.Bool(flgForceCertDomains) && hasCsr {
if cmd.Bool(FlgForceCertDomains) && hasCsr {
return ctx, fmt.Errorf("'--%s' only works with '--%s'/'-%s', '--%s' doesn't support this option",
flgForceCertDomains, flgDomains, flgAliasDomains, flgCSR)
FlgForceCertDomains, FlgDomains, flgAliasDomains, FlgCSR)
}
err := validateChallengeRequirements(cmd)
@ -59,28 +59,28 @@ func renewFlagsValidation(ctx context.Context, cmd *cli.Command) (context.Contex
}
func validateNetworkStack(cmd *cli.Command) error {
if cmd.Bool(flgIPv4Only) && cmd.Bool(flgIPv6Only) {
return fmt.Errorf("cannot specify both '--%s' and '--%s'", flgIPv4Only, flgIPv6Only)
if cmd.Bool(FlgIPv4Only) && cmd.Bool(FlgIPv6Only) {
return fmt.Errorf("cannot specify both '--%s' and '--%s'", FlgIPv4Only, FlgIPv6Only)
}
return nil
}
func validateChallengeRequirements(cmd *cli.Command) error {
if !cmd.Bool(flgHTTP) && !cmd.Bool(flgTLS) && !cmd.IsSet(flgDNS) && !cmd.Bool(flgDNSPersist) {
if !cmd.Bool(FlgHTTP) && !cmd.Bool(FlgTLS) && !cmd.IsSet(FlgDNS) && !cmd.Bool(FlgDNSPersist) {
return fmt.Errorf("no challenge selected: you must specify at least one challenge: '--%s', '--%s', '--%s', '--%s'",
flgHTTP, flgTLS, flgDNS, flgDNSPersist)
FlgHTTP, FlgTLS, FlgDNS, FlgDNSPersist)
}
if isSetBool(cmd, flgDNS) {
err := validatePropagationExclusiveOptions(cmd, flgDNSPropagationWait, flgDNSPropagationDisableANS, flgDNSPropagationDisableRNS)
if isSetBool(cmd, FlgDNS) {
err := validatePropagationExclusiveOptions(cmd, FlgDNSPropagationWait, FlgDNSPropagationDisableANS, FlgDNSPropagationDisableRNS)
if err != nil {
return err
}
}
if isSetBool(cmd, flgDNSPersist) {
err := validatePropagationExclusiveOptions(cmd, flgDNSPersistPropagationWait, flgDNSPersistPropagationDisableANS, flgDNSPersistIssuerDomainName)
if isSetBool(cmd, FlgDNSPersist) {
err := validatePropagationExclusiveOptions(cmd, FlgDNSPersistPropagationWait, FlgDNSPersistPropagationDisableANS, FlgDNSPersistIssuerDomainName)
if err != nil {
return err
}

View file

@ -12,6 +12,7 @@ import (
"github.com/go-acme/lego/v5/certcrypto"
"github.com/go-acme/lego/v5/certificate"
"github.com/go-acme/lego/v5/cmd/internal"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/cmd/internal/hook"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
@ -25,7 +26,7 @@ func newClient(cmd *cli.Command, account registration.User, keyType certcrypto.K
return nil, fmt.Errorf("new client: %w", err)
}
if client.GetServerMetadata().ExternalAccountRequired && !cmd.IsSet(flgEAB) {
if client.GetServerMetadata().ExternalAccountRequired && !cmd.IsSet(flags.FlgEAB) {
return nil, errors.New("server requires External Account Binding (EAB)")
}
@ -34,20 +35,20 @@ func newClient(cmd *cli.Command, account registration.User, keyType certcrypto.K
func newClientConfig(cmd *cli.Command, account registration.User, keyType certcrypto.KeyType) *lego.Config {
config := lego.NewConfig(account)
config.CADirURL = cmd.String(flgServer)
config.CADirURL = cmd.String(flags.FlgServer)
config.UserAgent = getUserAgent(cmd)
config.Certificate = lego.CertificateConfig{
KeyType: keyType,
Timeout: time.Duration(cmd.Int(flgCertTimeout)) * time.Second,
OverallRequestLimit: cmd.Int(flgOverallRequestLimit),
Timeout: time.Duration(cmd.Int(flags.FlgCertTimeout)) * time.Second,
OverallRequestLimit: cmd.Int(flags.FlgOverallRequestLimit),
}
if cmd.IsSet(flgHTTPTimeout) {
config.HTTPClient.Timeout = time.Duration(cmd.Int(flgHTTPTimeout)) * time.Second
if cmd.IsSet(flags.FlgHTTPTimeout) {
config.HTTPClient.Timeout = time.Duration(cmd.Int(flags.FlgHTTPTimeout)) * time.Second
}
if cmd.Bool(flgTLSSkipVerify) {
if cmd.Bool(flags.FlgTLSSkipVerify) {
defaultTransport, ok := config.HTTPClient.Transport.(*http.Transport)
if ok { // This is always true because the default client used by the CLI defined the transport.
tr := defaultTransport.Clone()
@ -62,59 +63,59 @@ func newClientConfig(cmd *cli.Command, account registration.User, keyType certcr
}
func getUserAgent(cmd *cli.Command) string {
return strings.TrimSpace(fmt.Sprintf("%s lego-cli/%s", cmd.String(flgUserAgent), cmd.Version))
return strings.TrimSpace(fmt.Sprintf("%s lego-cli/%s", cmd.String(flags.FlgUserAgent), cmd.Version))
}
func newObtainRequest(cmd *cli.Command, domains []string) certificate.ObtainRequest {
return certificate.ObtainRequest{
Domains: domains,
MustStaple: cmd.Bool(flgMustStaple),
NotBefore: cmd.Timestamp(flgNotBefore),
NotAfter: cmd.Timestamp(flgNotAfter),
Bundle: !cmd.Bool(flgNoBundle),
PreferredChain: cmd.String(flgPreferredChain),
EnableCommonName: cmd.Bool(flgEnableCommonName),
Profile: cmd.String(flgProfile),
AlwaysDeactivateAuthorizations: cmd.Bool(flgAlwaysDeactivateAuthorizations),
MustStaple: cmd.Bool(flags.FlgMustStaple),
NotBefore: cmd.Timestamp(flags.FlgNotBefore),
NotAfter: cmd.Timestamp(flags.FlgNotAfter),
Bundle: !cmd.Bool(flags.FlgNoBundle),
PreferredChain: cmd.String(flags.FlgPreferredChain),
EnableCommonName: cmd.Bool(flags.FlgEnableCommonName),
Profile: cmd.String(flags.FlgProfile),
AlwaysDeactivateAuthorizations: cmd.Bool(flags.FlgAlwaysDeactivateAuthorizations),
}
}
func newObtainForCSRRequest(cmd *cli.Command, csr *x509.CertificateRequest) certificate.ObtainForCSRRequest {
return certificate.ObtainForCSRRequest{
CSR: csr,
NotBefore: cmd.Timestamp(flgNotBefore),
NotAfter: cmd.Timestamp(flgNotAfter),
Bundle: !cmd.Bool(flgNoBundle),
PreferredChain: cmd.String(flgPreferredChain),
EnableCommonName: cmd.Bool(flgEnableCommonName),
Profile: cmd.String(flgProfile),
AlwaysDeactivateAuthorizations: cmd.Bool(flgAlwaysDeactivateAuthorizations),
NotBefore: cmd.Timestamp(flags.FlgNotBefore),
NotAfter: cmd.Timestamp(flags.FlgNotAfter),
Bundle: !cmd.Bool(flags.FlgNoBundle),
PreferredChain: cmd.String(flags.FlgPreferredChain),
EnableCommonName: cmd.Bool(flags.FlgEnableCommonName),
Profile: cmd.String(flags.FlgProfile),
AlwaysDeactivateAuthorizations: cmd.Bool(flags.FlgAlwaysDeactivateAuthorizations),
}
}
func newAccountsStorageConfig(cmd *cli.Command) storage.AccountsStorageConfig {
return storage.AccountsStorageConfig{
BasePath: cmd.String(flgPath),
Server: cmd.String(flgServer),
BasePath: cmd.String(flags.FlgPath),
Server: cmd.String(flags.FlgServer),
UserAgent: getUserAgent(cmd),
}
}
func newSaveOptions(cmd *cli.Command) *storage.SaveOptions {
return &storage.SaveOptions{
PEM: cmd.Bool(flgPEM),
PFX: cmd.Bool(flgPFX),
PFXFormat: cmd.String(flgPFXPass),
PFXPassword: cmd.String(flgPFXFormat),
PEM: cmd.Bool(flags.FlgPEM),
PFX: cmd.Bool(flags.FlgPFX),
PFXFormat: cmd.String(flags.FlgPFXPass),
PFXPassword: cmd.String(flags.FlgPFXFormat),
}
}
func newHookManager(cmd *cli.Command, certsStorage *storage.CertificatesStorage, account *storage.Account) *hook.Manager {
return hook.NewManager(
certsStorage,
hook.WithPre(cmd.String(flgPreHook), cmd.Duration(flgPreHookTimeout)),
hook.WithDeploy(cmd.String(flgDeployHook), cmd.Duration(flgDeployHookTimeout)),
hook.WithPost(cmd.String(flgPostHook), cmd.Duration(flgPostHookTimeout)),
hook.WithPre(cmd.String(flags.FlgPreHook), cmd.Duration(flags.FlgPreHookTimeout)),
hook.WithDeploy(cmd.String(flags.FlgDeployHook), cmd.Duration(flags.FlgDeployHookTimeout)),
hook.WithPost(cmd.String(flags.FlgPostHook), cmd.Duration(flags.FlgPostHookTimeout)),
hook.WithAccountMetadata(account),
)
}

View file

@ -11,6 +11,7 @@ import (
"github.com/go-acme/lego/v5/challenge/dnspersist01"
"github.com/go-acme/lego/v5/challenge/http01"
"github.com/go-acme/lego/v5/challenge/tlsalpn01"
"github.com/go-acme/lego/v5/cmd/internal/flags"
"github.com/go-acme/lego/v5/lego"
"github.com/go-acme/lego/v5/log"
"github.com/go-acme/lego/v5/providers/dns"
@ -21,28 +22,28 @@ import (
)
func setupChallenges(cmd *cli.Command, client *lego.Client) {
if cmd.Bool(flgHTTP) {
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(cmd), http01.SetDelay(cmd.Duration(flgHTTPDelay)))
if cmd.Bool(flags.FlgHTTP) {
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(cmd), http01.SetDelay(cmd.Duration(flags.FlgHTTPDelay)))
if err != nil {
log.Fatal("Could not set HTTP challenge provider.", log.ErrorAttr(err))
}
}
if cmd.Bool(flgTLS) {
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(cmd), tlsalpn01.SetDelay(cmd.Duration(flgTLSDelay)))
if cmd.Bool(flags.FlgTLS) {
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(cmd), tlsalpn01.SetDelay(cmd.Duration(flags.FlgTLSDelay)))
if err != nil {
log.Fatal("Could not set TLS challenge provider.", log.ErrorAttr(err))
}
}
if cmd.IsSet(flgDNS) {
if cmd.IsSet(flags.FlgDNS) {
err := setupDNS(cmd, client)
if err != nil {
log.Fatal("Could not set DNS challenge provider.", log.ErrorAttr(err))
}
}
if cmd.Bool(flgDNSPersist) {
if cmd.Bool(flags.FlgDNSPersist) {
err := setupDNSPersist(cmd, client)
if err != nil {
log.Fatal("Could not set DNS-PERSIST-01 challenge provider.", log.ErrorAttr(err))
@ -52,44 +53,44 @@ func setupChallenges(cmd *cli.Command, client *lego.Client) {
func setupHTTPProvider(cmd *cli.Command) challenge.Provider {
switch {
case cmd.IsSet(flgHTTPWebroot):
ps, err := webroot.NewHTTPProvider(cmd.String(flgHTTPWebroot))
case cmd.IsSet(flags.FlgHTTPWebroot):
ps, err := webroot.NewHTTPProvider(cmd.String(flags.FlgHTTPWebroot))
if err != nil {
log.Fatal("Could not create the webroot provider.",
slog.String("flag", flgHTTPWebroot),
slog.String("webRoot", cmd.String(flgHTTPWebroot)),
slog.String("flag", flags.FlgHTTPWebroot),
slog.String("webRoot", cmd.String(flags.FlgHTTPWebroot)),
log.ErrorAttr(err),
)
}
return ps
case cmd.IsSet(flgHTTPMemcachedHost):
ps, err := memcached.NewMemcachedProvider(cmd.StringSlice(flgHTTPMemcachedHost))
case cmd.IsSet(flags.FlgHTTPMemcachedHost):
ps, err := memcached.NewMemcachedProvider(cmd.StringSlice(flags.FlgHTTPMemcachedHost))
if err != nil {
log.Fatal("Could not create the memcached provider.",
slog.String("flag", flgHTTPMemcachedHost),
slog.String("memcachedHosts", strings.Join(cmd.StringSlice(flgHTTPMemcachedHost), ", ")),
slog.String("flag", flags.FlgHTTPMemcachedHost),
slog.String("memcachedHosts", strings.Join(cmd.StringSlice(flags.FlgHTTPMemcachedHost), ", ")),
log.ErrorAttr(err),
)
}
return ps
case cmd.IsSet(flgHTTPS3Bucket):
ps, err := s3.NewHTTPProvider(cmd.String(flgHTTPS3Bucket))
case cmd.IsSet(flags.FlgHTTPS3Bucket):
ps, err := s3.NewHTTPProvider(cmd.String(flags.FlgHTTPS3Bucket))
if err != nil {
log.Fatal("Could not create the S3 provider.",
slog.String("flag", flgHTTPS3Bucket),
slog.String("bucket", cmd.String(flgHTTPS3Bucket)),
slog.String("flag", flags.FlgHTTPS3Bucket),
slog.String("bucket", cmd.String(flags.FlgHTTPS3Bucket)),
log.ErrorAttr(err),
)
}
return ps
case cmd.IsSet(flgHTTPPort):
host, port, err := parseAddress(cmd, flgHTTPPort)
case cmd.IsSet(flags.FlgHTTPPort):
host, port, err := parseAddress(cmd, flags.FlgHTTPPort)
if err != nil {
log.Fatal("Invalid address.", log.ErrorAttr(err))
}
@ -99,19 +100,19 @@ func setupHTTPProvider(cmd *cli.Command) challenge.Provider {
Address: net.JoinHostPort(host, port),
})
if header := cmd.String(flgHTTPProxyHeader); header != "" {
if header := cmd.String(flags.FlgHTTPProxyHeader); header != "" {
srv.SetProxyHeader(header)
}
return srv
case cmd.Bool(flgHTTP):
case cmd.Bool(flags.FlgHTTP):
srv := http01.NewProviderServerWithOptions(http01.Options{
Network: getNetworkStack(cmd).Network("tcp"),
Address: net.JoinHostPort("", ":80"),
})
if header := cmd.String(flgHTTPProxyHeader); header != "" {
if header := cmd.String(flags.FlgHTTPProxyHeader); header != "" {
srv.SetProxyHeader(header)
}
@ -125,8 +126,8 @@ func setupHTTPProvider(cmd *cli.Command) challenge.Provider {
func setupTLSProvider(cmd *cli.Command) challenge.Provider {
switch {
case cmd.IsSet(flgTLSPort):
host, port, err := parseAddress(cmd, flgTLSPort)
case cmd.IsSet(flags.FlgTLSPort):
host, port, err := parseAddress(cmd, flags.FlgTLSPort)
if err != nil {
log.Fatal("Invalid address.", log.ErrorAttr(err))
}
@ -137,7 +138,7 @@ func setupTLSProvider(cmd *cli.Command) challenge.Provider {
Port: port,
})
case cmd.Bool(flgTLS):
case cmd.Bool(flags.FlgTLS):
return tlsalpn01.NewProviderServerWithOptions(tlsalpn01.Options{
Network: getNetworkStack(cmd).Network("tcp"),
})
@ -149,32 +150,32 @@ func setupTLSProvider(cmd *cli.Command) challenge.Provider {
}
func setupDNS(cmd *cli.Command, client *lego.Client) error {
provider, err := dns.NewDNSChallengeProviderByName(cmd.String(flgDNS))
provider, err := dns.NewDNSChallengeProviderByName(cmd.String(flags.FlgDNS))
if err != nil {
return err
}
opts := &dns01.Options{RecursiveNameservers: cmd.StringSlice(flgDNSResolvers)}
opts := &dns01.Options{RecursiveNameservers: cmd.StringSlice(flags.FlgDNSResolvers)}
if cmd.IsSet(flgDNSTimeout) {
opts.Timeout = time.Duration(cmd.Int(flgDNSTimeout)) * time.Second
if cmd.IsSet(flags.FlgDNSTimeout) {
opts.Timeout = time.Duration(cmd.Int(flags.FlgDNSTimeout)) * time.Second
}
opts.NetworkStack = getNetworkStack(cmd)
dns01.SetDefaultClient(dns01.NewClient(opts))
shouldWait := cmd.IsSet(flgDNSPropagationWait)
shouldWait := cmd.IsSet(flags.FlgDNSPropagationWait)
err = client.Challenge.SetDNS01Provider(provider,
dns01.CondOptions(shouldWait,
dns01.PropagationWait(cmd.Duration(flgDNSPropagationWait), true),
dns01.PropagationWait(cmd.Duration(flags.FlgDNSPropagationWait), true),
),
dns01.CondOptions(!shouldWait,
dns01.CondOptions(cmd.Bool(flgDNSPropagationDisableANS),
dns01.CondOptions(cmd.Bool(flags.FlgDNSPropagationDisableANS),
dns01.DisableAuthoritativeNssPropagationRequirement(),
),
dns01.CondOptions(cmd.Bool(flgDNSPropagationDisableRNS),
dns01.CondOptions(cmd.Bool(flags.FlgDNSPropagationDisableRNS),
dns01.DisableRecursiveNSsPropagationRequirement(),
),
),
@ -184,31 +185,31 @@ func setupDNS(cmd *cli.Command, client *lego.Client) error {
}
func setupDNSPersist(cmd *cli.Command, client *lego.Client) error {
opts := &dnspersist01.Options{RecursiveNameservers: cmd.StringSlice(flgDNSPersistResolvers)}
opts := &dnspersist01.Options{RecursiveNameservers: cmd.StringSlice(flags.FlgDNSPersistResolvers)}
if cmd.IsSet(flgDNSPersistTimeout) {
opts.Timeout = time.Duration(cmd.Int(flgDNSPersistTimeout)) * time.Second
if cmd.IsSet(flags.FlgDNSPersistTimeout) {
opts.Timeout = time.Duration(cmd.Int(flags.FlgDNSPersistTimeout)) * time.Second
}
opts.NetworkStack = getNetworkStack(cmd)
dnspersist01.SetDefaultClient(dnspersist01.NewClient(opts))
shouldWait := cmd.IsSet(flgDNSPersistPropagationWait)
shouldWait := cmd.IsSet(flags.FlgDNSPersistPropagationWait)
return client.Challenge.SetDNSPersist01(
dnspersist01.WithIssuerDomainName(cmd.String(flgDNSPersistIssuerDomainName)),
dnspersist01.CondOptions(cmd.IsSet(flgDNSPersistPersistUntil),
dnspersist01.WithPersistUntil(cmd.Timestamp(flgDNSPersistPersistUntil)),
dnspersist01.WithIssuerDomainName(cmd.String(flags.FlgDNSPersistIssuerDomainName)),
dnspersist01.CondOptions(cmd.IsSet(flags.FlgDNSPersistPersistUntil),
dnspersist01.WithPersistUntil(cmd.Timestamp(flags.FlgDNSPersistPersistUntil)),
),
dnspersist01.CondOptions(shouldWait,
dnspersist01.PropagationWait(cmd.Duration(flgDNSPersistPropagationWait), true),
dnspersist01.PropagationWait(cmd.Duration(flags.FlgDNSPersistPropagationWait), true),
),
dnspersist01.CondOptions(!shouldWait,
dnspersist01.CondOptions(cmd.Bool(flgDNSPersistPropagationDisableANS),
dnspersist01.CondOptions(cmd.Bool(flags.FlgDNSPersistPropagationDisableANS),
dnspersist01.DisableAuthoritativeNssPropagationRequirement(),
),
dnspersist01.CondOptions(cmd.Bool(flgDNSPersistPropagationDisableRNS),
dnspersist01.CondOptions(cmd.Bool(flags.FlgDNSPersistPropagationDisableRNS),
dnspersist01.DisableRecursiveNSsPropagationRequirement(),
),
),
@ -217,10 +218,10 @@ func setupDNSPersist(cmd *cli.Command, client *lego.Client) error {
func getNetworkStack(cmd *cli.Command) challenge.NetworkStack {
switch {
case cmd.Bool(flgIPv4Only):
case cmd.Bool(flags.FlgIPv4Only):
return challenge.IPv4Only
case cmd.Bool(flgIPv6Only):
case cmd.Bool(flags.FlgIPv6Only):
return challenge.IPv6Only
default:

View file

@ -89,12 +89,11 @@ func generate(ctx context.Context) error {
// - do not include version information, because we're likely running against a snapshot
// - skip DNS help and provider list, as initialization takes time, and we don't generate `lego dns --help` here.
func createStubApp() *cli.Command {
return &cli.Command{
Name: "lego",
Usage: "ACME client written in Go",
Commands: cmd.CreateCommands(),
Flags: cmd.CreateLogFlags(),
}
root := cmd.CreateRootCommand()
root.EnableShellCompletion = false
root.Before = nil
return root
}
func run(ctx context.Context, app *cli.Command, args []string) (h commandHelp, err error) {