lego/cmd/internal/flags/flags.go
2026-03-11 17:15:45 +01:00

747 lines
25 KiB
Go

package flags
import (
"context"
"errors"
"fmt"
"log/slog"
"os"
"path/filepath"
"strings"
"time"
"github.com/go-acme/lego/v5/acme"
"github.com/go-acme/lego/v5/certificate"
"github.com/go-acme/lego/v5/cmd/internal/storage"
"github.com/go-acme/lego/v5/lego"
"github.com/go-acme/lego/v5/log"
"github.com/urfave/cli/v3"
"software.sslmate.com/src/go-pkcs12"
)
func CreateLogFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryLogs,
Name: FlgLogLevel,
Sources: cli.EnvVars(toEnvName(FlgLogLevel)),
Usage: "Set the logging level. Supported values: 'debug', 'info', 'warn', 'error'.",
Value: "info",
},
&cli.StringFlag{
Category: categoryLogs,
Name: FlgLogFormat,
Sources: cli.EnvVars(toEnvName(FlgLogFormat)),
Usage: "Set the logging format. Supported values: 'colored', 'text', 'json'.",
Value: "colored",
},
}
}
func CreateRunFlags() []cli.Flag {
flags := []cli.Flag{
createDomainFlag(),
createCertNameFlag(),
}
flags = append(flags, createAccountFlags()...)
flags = append(flags, createACMEClientFlags()...)
flags = append(flags, createStorageFlags()...)
flags = append(flags, createAcceptFlag())
flags = append(flags, createChallengesFlags()...)
flags = append(flags, createObtainFlags()...)
flags = append(flags, createPreHookFlags()...)
flags = append(flags, createDeployHookFlags()...)
flags = append(flags, createPostHookFlags()...)
flags = append(flags,
&cli.StringFlag{
Category: categoryAdvanced,
Name: FlgPrivateKey,
Sources: cli.EnvVars(toEnvName(FlgPrivateKey)),
Usage: "Path to a private key (in PEM encoding) for the certificate. By default, a private key is generated.",
},
)
return flags
}
func CreateRenewFlags() []cli.Flag {
flags := []cli.Flag{
createDomainFlag(),
createCertNameFlag(),
}
flags = append(flags, createAccountFlags()...)
flags = append(flags, createACMEClientFlags()...)
flags = append(flags, createStorageFlags()...)
flags = append(flags, createChallengesFlags()...)
flags = append(flags, createObtainFlags()...)
flags = append(flags, createPreHookFlags()...)
flags = append(flags, createDeployHookFlags()...)
flags = append(flags, createPostHookFlags()...)
flags = append(flags,
&cli.IntFlag{
Name: FlgRenewDays,
Sources: cli.EnvVars(toEnvName(FlgRenewDays)),
Usage: "The number of days left on a certificate to renew it." +
"\n\tBy default, compute dynamically, based on the lifetime of the certificate(s), when to renew: use 1/3rd of the lifetime left, or 1/2 of the lifetime for short-lived certificates).",
},
&cli.BoolFlag{
Name: FlgRenewForce,
Sources: cli.EnvVars(toEnvName(FlgRenewForce)),
Usage: "Force the renewal of the certificate even if it is not due for renewal yet.",
},
&cli.BoolFlag{
Category: categoryARI,
Name: FlgARIDisable,
Sources: cli.EnvVars(toEnvName(FlgARIDisable)),
Usage: "Do not use the renewalInfo endpoint (RFC9773) to check if a certificate should be renewed.",
},
&cli.DurationFlag{
Category: categoryARI,
Name: FlgARIWaitToRenewDuration,
Sources: cli.EnvVars(toEnvName(FlgARIWaitToRenewDuration)),
Usage: "The maximum duration you're willing to sleep for a renewal time returned by the renewalInfo endpoint.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgReuseKey,
Sources: cli.EnvVars(toEnvName(FlgReuseKey)),
Usage: "Used to indicate you want to reuse your current private key for the new certificate.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgNoRandomSleep,
Sources: cli.EnvVars(toEnvName(FlgNoRandomSleep)),
Usage: "Do not add a random sleep before the renewal." +
" We do not recommend using this flag if you are doing your renewals in an automated way.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgForceCertDomains,
Sources: cli.EnvVars(toEnvName(FlgForceCertDomains)),
Usage: "Check and ensure that the cert's domain list matches those passed in the domains argument.",
},
)
return flags
}
func CreateRevokeFlags() []cli.Flag {
flags := []cli.Flag{
createPathFlag(false),
createCertNamesFlag(),
&cli.BoolFlag{
Name: FlgKeep,
Sources: cli.EnvVars(toEnvName(FlgKeep)),
Usage: "Keep the certificates after the revocation instead of archiving them.",
},
&cli.UintFlag{
Name: FlgReason,
Sources: cli.EnvVars(toEnvName(FlgReason)),
Usage: "Identifies the reason for the certificate revocation." +
" See https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1." +
"\n\tValid values are:" +
" 0 (unspecified), 1 (keyCompromise), 2 (cACompromise), 3 (affiliationChanged)," +
" 4 (superseded), 5 (cessationOfOperation), 6 (certificateHold), 8 (removeFromCRL)," +
" 9 (privilegeWithdrawn), or 10 (aACompromise).",
Value: acme.CRLReasonUnspecified,
},
}
flags = append(flags, createAccountFlags()...)
flags = append(flags, createACMEClientFlags()...)
return flags
}
func CreateRegisterFlags() []cli.Flag {
flags := []cli.Flag{
createPathFlag(true),
createAcceptFlag(),
}
flags = append(flags, createACMEClientFlags()...)
flags = append(flags, createAccountFlags()...)
return flags
}
func CreateListFlags() []cli.Flag {
return []cli.Flag{
createPathFlag(false),
&cli.BoolFlag{
Name: FlgFormatJSON,
Usage: "Format the output as JSON.",
},
}
}
func CreateMigrateFlags() []cli.Flag {
return []cli.Flag{
createPathFlag(false),
&cli.BoolFlag{
Name: FlgAccountOnly,
Sources: cli.EnvVars(toEnvName(FlgAccountOnly)),
Usage: "Only migrate accounts.",
Value: false,
},
}
}
func createACMEClientFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
// NOTE(ldez): if Required is true, then the default value is not display in the help.
Name: FlgServer,
Aliases: []string{flgAliasServer},
Sources: cli.EnvVars(toEnvName(FlgServer)),
Usage: fmt.Sprintf("CA (ACME server). It can be either a URL or a shortcode."+
"\n\t(available shortcodes: %s)", strings.Join(lego.GetAllCodes(), ", ")),
Value: lego.DirectoryURLLetsEncrypt,
Action: func(ctx context.Context, cmd *cli.Command, s string) error {
directoryURL, err := lego.GetDirectoryURL(s)
if err != nil {
log.Debug("Server shortcode not found. Use the value as URL.", slog.String("value", s), log.ErrorAttr(err))
directoryURL = s
}
return cmd.Set(FlgServer, directoryURL)
},
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgEnableCommonName,
Sources: cli.EnvVars(toEnvName(FlgEnableCommonName)),
Usage: "Enable the use of the common name. (Not recommended)",
},
&cli.StringFlag{
Name: FlgKeyType,
Aliases: []string{flgAliasKeyType},
Sources: cli.EnvVars(toEnvName(FlgKeyType)),
Value: "ec256",
Usage: "Key type to use for private keys. Supported: rsa2048, rsa3072, rsa4096, rsa8192, ec256, ec384.",
},
&cli.IntFlag{
Category: categoryACMEClient,
Name: FlgHTTPTimeout,
Sources: cli.EnvVars(toEnvName(FlgHTTPTimeout)),
Usage: "Set the HTTP timeout value to a specific value in seconds.",
},
&cli.BoolFlag{
Category: categoryACMEClient,
Name: FlgTLSSkipVerify,
Sources: cli.EnvVars(toEnvName(FlgTLSSkipVerify)),
Usage: "Skip the TLS verification of the ACME server.",
},
&cli.IntFlag{
Category: categoryAdvanced,
Name: FlgCertTimeout,
Sources: cli.EnvVars(toEnvName(FlgCertTimeout)),
Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.",
Value: 30,
},
&cli.IntFlag{
Category: categoryACMEClient,
Name: FlgOverallRequestLimit,
Sources: cli.EnvVars(toEnvName(FlgOverallRequestLimit)),
Usage: "ACME overall requests limit.",
Value: certificate.DefaultOverallRequestLimit,
},
&cli.StringFlag{
Category: categoryACMEClient,
Name: FlgUserAgent,
Sources: cli.EnvVars(toEnvName(FlgUserAgent)),
Usage: "Add to the user-agent sent to the CA to identify an application embedding lego-cli",
},
}
}
func createChallengesFlags() []cli.Flag {
var flags []cli.Flag
flags = append(flags, createHTTPChallengeFlags()...)
flags = append(flags, createTLSChallengeFlags()...)
flags = append(flags, createDNSChallengeFlags()...)
flags = append(flags, createDNSPersistChallengeFlags()...)
flags = append(flags, createNetworkStackFlags()...)
return flags
}
func createNetworkStackFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgIPv4Only,
Aliases: []string{flgAliasIPv4Only},
Sources: cli.EnvVars(toEnvName(FlgIPv4Only)),
Usage: "Use IPv4 only.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgIPv6Only,
Aliases: []string{flgAliasIPv6Only},
Sources: cli.EnvVars(toEnvName(FlgIPv6Only)),
Usage: "Use IPv6 only.",
},
}
}
func createHTTPChallengeFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTP,
Sources: cli.EnvVars(toEnvName(FlgHTTP)),
Usage: "Use the HTTP-01 challenge to solve challenges. Can be mixed with other types of challenges.",
},
&cli.StringFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPPort,
Sources: cli.EnvVars(toEnvName(FlgHTTPPort)),
Usage: "Set the port and interface to use for HTTP-01 based challenges to listen on. Supported: interface:port or :port.",
Value: ":80",
},
&cli.DurationFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPDelay,
Sources: cli.EnvVars(toEnvName(FlgHTTPDelay)),
Usage: "Delay between the starts of the HTTP server (use for HTTP-01 based challenges) and the validation of the challenge.",
Value: 0,
},
&cli.StringFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPProxyHeader,
Sources: cli.EnvVars(toEnvName(FlgHTTPProxyHeader)),
Usage: "Validate against this HTTP header when solving HTTP-01 based challenges behind a reverse proxy.",
Value: "Host",
},
&cli.StringFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPWebroot,
Sources: cli.EnvVars(toEnvName(FlgHTTPWebroot)),
Usage: "Set the webroot folder to use for HTTP-01 based challenges to write directly to the .well-known/acme-challenge file." +
" This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge",
},
&cli.StringSliceFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPMemcachedHost,
Sources: cli.EnvVars(toEnvName(FlgHTTPMemcachedHost)),
Usage: "Set the memcached host(s) to use for HTTP-01 based challenges. Challenges will be written to all specified hosts.",
},
&cli.StringFlag{
Category: categoryHTTP01Challenge,
Name: FlgHTTPS3Bucket,
Sources: cli.EnvVars(toEnvName(FlgHTTPS3Bucket)),
Usage: "Set the S3 bucket name to use for HTTP-01 based challenges. Challenges will be written to the S3 bucket.",
},
}
}
func createTLSChallengeFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Category: categoryTLSALPN01Challenge,
Name: FlgTLS,
Sources: cli.EnvVars(toEnvName(FlgTLS)),
Usage: "Use the TLS-ALPN-01 challenge to solve challenges. Can be mixed with other types of challenges.",
},
&cli.StringFlag{
Category: categoryTLSALPN01Challenge,
Name: FlgTLSPort,
Sources: cli.EnvVars(toEnvName(FlgTLSPort)),
Usage: "Set the port and interface to use for TLS-ALPN-01 based challenges to listen on. Supported: interface:port or :port.",
Value: ":443",
},
&cli.DurationFlag{
Category: categoryTLSALPN01Challenge,
Name: FlgTLSDelay,
Sources: cli.EnvVars(toEnvName(FlgTLSDelay)),
Usage: "Delay between the start of the TLS listener (use for TLSALPN-01 based challenges) and the validation of the challenge.",
Value: 0,
},
}
}
func createDNSChallengeFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryDNS01Challenge,
Name: FlgDNS,
Sources: cli.EnvVars(toEnvName(FlgDNS)),
Usage: "Solve a DNS-01 challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.",
},
&cli.BoolFlag{
Category: categoryDNS01Challenge,
Name: FlgDNSPropagationDisableANS,
Sources: cli.EnvVars(toEnvName(FlgDNSPropagationDisableANS)),
Usage: "By setting this flag to true, disables the need to await propagation of the TXT record to all authoritative name servers.",
},
&cli.BoolFlag{
Category: categoryDNS01Challenge,
Name: FlgDNSPropagationDisableRNS,
Sources: cli.EnvVars(toEnvName(FlgDNSPropagationDisableRNS)),
Usage: "By setting this flag to true, disables the need to await propagation of the TXT record to all recursive name servers (aka resolvers).",
},
&cli.DurationFlag{
Category: categoryDNS01Challenge,
Name: FlgDNSPropagationWait,
Sources: cli.EnvVars(toEnvName(FlgDNSPropagationWait)),
Usage: "By setting this flag, disables all the propagation checks of the TXT record and uses a wait duration instead.",
Validator: func(d time.Duration) error {
if d < 0 {
return errors.New("it cannot be negative")
}
return nil
},
},
&cli.StringSliceFlag{
Category: categoryDNS01Challenge,
Name: FlgDNSResolvers,
Sources: cli.EnvVars(toEnvName(FlgDNSResolvers)),
Usage: "Set the resolvers to use for performing (recursive) CNAME resolving and apex domain determination." +
" For DNS-01 challenge verification, the authoritative DNS server is queried directly." +
" Supported: host:port." +
" The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.",
},
&cli.IntFlag{
Category: categoryDNS01Challenge,
Name: FlgDNSTimeout,
Sources: cli.EnvVars(toEnvName(FlgDNSTimeout)),
Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name server queries.",
Value: 10,
},
}
}
func createDNSPersistChallengeFlags() []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersist,
Sources: cli.EnvVars(toEnvName(FlgDNSPersist)),
Usage: "Use the DNS-PERSIST-01 challenge to solve challenges. Manual verification only. Can be mixed with other types of challenges.",
},
&cli.StringFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistIssuerDomainName,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistIssuerDomainName)),
Usage: "Override the issuer-domain-name to use for DNS-PERSIST-01 when multiple are offered. Must be offered by the challenge.",
},
&cli.TimestampFlag{
Name: FlgDNSPersistPersistUntil,
Category: categoryDNSPersist01Challenge,
Usage: "Set the optional persistUntil for DNS-PERSIST-01 records as an RFC3339 timestamp (for example 2026-03-01T00:00:00Z).",
Sources: cli.EnvVars(toEnvName(FlgDNSPersistPersistUntil)),
Config: cli.TimestampConfig{
Layouts: []string{time.RFC3339},
},
},
&cli.DurationFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistPropagationWait,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistPropagationWait)),
Usage: "By setting this flag, disables all the propagation checks of the TXT record and uses a wait duration instead.",
Validator: func(d time.Duration) error {
if d < 0 {
return errors.New("it cannot be negative")
}
return nil
},
},
&cli.BoolFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistPropagationDisableANS,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistPropagationDisableANS)),
Usage: "By setting this flag to true, disables the need to await propagation of the TXT record to all authoritative name servers.",
},
&cli.BoolFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistPropagationDisableRNS,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistPropagationDisableRNS)),
Usage: "By setting this flag to true, disables the need to await propagation of the TXT record to all recursive name servers (aka resolvers).",
},
&cli.StringSliceFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistResolvers,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistResolvers)),
Usage: "Set the resolvers to use for DNS-PERSIST-01 TXT lookups." +
" Supported: host:port." +
" The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.",
},
&cli.IntFlag{
Category: categoryDNSPersist01Challenge,
Name: FlgDNSPersistTimeout,
Sources: cli.EnvVars(toEnvName(FlgDNSPersistTimeout)),
Usage: "Set the DNS timeout value to a specific value in seconds. Used for DNS-PERSIST-01 lookups.",
},
}
}
func createStorageFlags() []cli.Flag {
return []cli.Flag{
createPathFlag(true),
&cli.BoolFlag{
Category: categoryStorage,
Name: FlgPEM,
Sources: cli.EnvVars(toEnvName(FlgPEM)),
Usage: "Generate an additional .pem (base64) file by concatenating the .key and .crt files together.",
},
&cli.BoolFlag{
Category: categoryStorage,
Name: FlgPFX,
Sources: cli.EnvVars(toEnvName(FlgPFX)),
Usage: "Generate an additional .pfx (PKCS#12) file by concatenating the .key and .crt and issuer .crt files together.",
},
&cli.StringFlag{
Category: categoryStorage,
Name: FlgPFXPass,
Sources: cli.EnvVars(toEnvName(FlgPFXPass)),
Usage: "The password used to encrypt the .pfx (PCKS#12) file.",
Value: pkcs12.DefaultPassword,
},
&cli.StringFlag{
Category: categoryStorage,
Name: FlgPFXFormat,
Sources: cli.EnvVars(toEnvName(FlgPFXFormat)),
Usage: "The encoding format to use when encrypting the .pfx (PCKS#12) file. Supported: RC2, DES, SHA256.",
Value: "RC2",
},
}
}
func createAccountFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: FlgEmail,
Aliases: []string{flgAliasEmail},
Sources: cli.EnvVars(toEnvName(FlgEmail)),
Usage: "Email used for registration and recovery contact.",
},
&cli.StringFlag{
Category: categoryStorage,
Name: FlgAccountID,
Sources: cli.EnvVars(toEnvName(FlgAccountID)),
Usage: "Account identifier (The email is used if there is account ID is undefined).",
},
&cli.BoolFlag{
Category: categoryEAB,
Name: FlgEAB,
Sources: cli.EnvVars(toEnvName(FlgEAB)),
Usage: fmt.Sprintf("Use External Account Binding for account registration. Requires %s and %s.", FlgEABKID, FlgEABHMAC),
},
&cli.StringFlag{
Category: categoryEAB,
Name: FlgEABKID,
Sources: cli.EnvVars(toEnvName(FlgEABKID)),
Usage: "Key identifier for External Account Binding.",
},
&cli.StringFlag{
Category: categoryEAB,
Name: FlgEABHMAC,
Sources: cli.EnvVars(toEnvName(FlgEABHMAC)),
Usage: "MAC key for External Account Binding. Should be in Base64 URL Encoding without padding format.",
},
}
}
func createObtainFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryAdvanced,
Name: FlgCSR,
Sources: cli.EnvVars(toEnvName(FlgCSR)),
Usage: "Certificate signing request filename, if an external CSR is to be used.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgNoBundle,
Sources: cli.EnvVars(toEnvName(FlgNoBundle)),
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
},
&cli.BoolFlag{
Category: categoryAdvanced,
Name: FlgMustStaple,
Sources: cli.EnvVars(toEnvName(FlgMustStaple)),
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate." +
" Only works if the CSR is generated by lego.",
},
&cli.TimestampFlag{
Category: categoryAdvanced,
Name: FlgNotBefore,
Sources: cli.EnvVars(toEnvName(FlgNotBefore)),
Usage: "Set the notBefore field in the certificate (RFC3339 format)",
Config: cli.TimestampConfig{
Layouts: []string{time.RFC3339},
},
},
&cli.TimestampFlag{
Category: categoryAdvanced,
Name: FlgNotAfter,
Sources: cli.EnvVars(toEnvName(FlgNotAfter)),
Usage: "Set the notAfter field in the certificate (RFC3339 format)",
Config: cli.TimestampConfig{
Layouts: []string{time.RFC3339},
},
},
&cli.StringFlag{
Category: categoryAdvanced,
Name: FlgPreferredChain,
Sources: cli.EnvVars(toEnvName(FlgPreferredChain)),
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name." +
" If no match, the default offered chain will be used.",
},
&cli.StringFlag{
Category: categoryAdvanced,
Name: FlgProfile,
Sources: cli.EnvVars(toEnvName(FlgProfile)),
Usage: "If the CA offers multiple certificate profiles (draft-ietf-acme-profiles), choose this one.",
},
&cli.StringFlag{
Category: categoryAdvanced,
Name: FlgAlwaysDeactivateAuthorizations,
Sources: cli.EnvVars(toEnvName(FlgAlwaysDeactivateAuthorizations)),
Usage: "Force the authorizations to be relinquished even if the certificate request was successful.",
},
}
}
func createPreHookFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryHooks,
Name: FlgPreHook,
Sources: cli.EnvVars(toEnvName(FlgPreHook)),
Usage: "Define a pre-hook. This hook runs, before the creation or the renewal, in cases where a certificate will be effectively created/renewed.",
},
&cli.DurationFlag{
Category: categoryHooks,
Name: FlgPreHookTimeout,
Sources: cli.EnvVars(toEnvName(FlgPreHookTimeout)),
Usage: "Define the timeout for the pre-hook execution.",
Value: 2 * time.Minute,
},
}
}
func createDeployHookFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryHooks,
Name: FlgDeployHook,
Sources: cli.EnvVars(toEnvName(FlgDeployHook)),
Usage: "Define a hook. The hook runs, after the creation or the renewal, in cases where a certificate is successfully created/renewed.",
},
&cli.DurationFlag{
Category: categoryHooks,
Name: FlgDeployHookTimeout,
Sources: cli.EnvVars(toEnvName(FlgDeployHookTimeout)),
Usage: "Define the timeout for the hook execution.",
Value: 2 * time.Minute,
},
}
}
func createPostHookFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Category: categoryHooks,
Name: FlgPostHook,
Sources: cli.EnvVars(toEnvName(FlgPostHook)),
Usage: "Define a post-hook. This hook runs, after the creation or the renewal, in cases where a certificate is created/renewed, regardless of whether any errors occurred.",
},
&cli.DurationFlag{
Category: categoryHooks,
Name: FlgPostHookTimeout,
Sources: cli.EnvVars(toEnvName(FlgPostHookTimeout)),
Usage: "Define the timeout for the post-hook execution.",
Value: 2 * time.Minute,
},
}
}
func createAcceptFlag() cli.Flag {
return &cli.BoolFlag{
Name: FlgAcceptTOS,
Aliases: []string{flgAliasAcceptTOS},
Sources: cli.EnvVars(toEnvName(FlgAcceptTOS)),
Usage: "By setting this flag to true you indicate that you accept the current CA terms of service.",
}
}
func createDomainFlag() cli.Flag {
return &cli.StringSliceFlag{
Name: FlgDomains,
Aliases: []string{flgAliasDomains},
Sources: cli.EnvVars(toEnvName(FlgDomains)),
Usage: "Add a domain. For multiple domains either repeat the option or provide a comma-separated list.",
}
}
func createCertNameFlag() cli.Flag {
return &cli.StringFlag{
Category: categoryStorage,
Name: FlgCertName,
Aliases: []string{flgAliasCertName},
Sources: cli.EnvVars(toEnvName(FlgCertName)),
Usage: "The certificate ID/Name, used to store and retrieve a certificate. By default, it uses the first domain name.",
}
}
func createCertNamesFlag() cli.Flag {
return &cli.StringSliceFlag{
Name: FlgCertName,
Aliases: []string{flgAliasCertName},
Sources: cli.EnvVars(toEnvName(FlgCertName)),
Usage: "The certificate IDs/Names, used to retrieve the certificates.",
}
}
func createPathFlag(forceCreation bool) cli.Flag {
return &cli.StringFlag{
Category: categoryStorage,
Name: FlgPath,
Sources: cli.NewValueSourceChain(cli.EnvVar(toEnvName(FlgPath)), &defaultPathValueSource{}),
Usage: "Directory to use for storing the data.",
Validator: func(s string) error {
if !forceCreation {
return nil
}
err := storage.CreateNonExistingFolder(s)
if err != nil {
return fmt.Errorf("could not check/create the path %q: %w", s, err)
}
return nil
},
Required: true,
}
}
// defaultPathValueSource gets the default path based on the current working directory.
// The field value is only here because clihelp/generator.
type defaultPathValueSource struct{}
func (p *defaultPathValueSource) String() string {
return "default path"
}
func (p *defaultPathValueSource) GoString() string {
return "&defaultPathValueSource{}"
}
func (p *defaultPathValueSource) Lookup() (string, bool) {
cwd, err := os.Getwd()
if err != nil {
return "", false
}
return filepath.Join(cwd, ".lego"), true
}