chore: use contants for flag names (#2283)
This commit is contained in:
parent
20c8d6c413
commit
d2898e1706
11 changed files with 245 additions and 175 deletions
|
@ -71,12 +71,12 @@ func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
|
|||
// TODO: move to account struct? Currently MUST pass email.
|
||||
email := getEmail(ctx)
|
||||
|
||||
serverURL, err := url.Parse(ctx.String("server"))
|
||||
serverURL, err := url.Parse(ctx.String(flgServer))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
rootPath := filepath.Join(ctx.String("path"), baseAccountsRootFolderName)
|
||||
rootPath := filepath.Join(ctx.String(flgPath), baseAccountsRootFolderName)
|
||||
serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host)
|
||||
accountsPath := filepath.Join(rootPath, serverPath)
|
||||
rootUserPath := filepath.Join(accountsPath, email)
|
||||
|
@ -224,7 +224,7 @@ func loadPrivateKey(file string) (crypto.PrivateKey, error) {
|
|||
func tryRecoverRegistration(ctx *cli.Context, privateKey crypto.PrivateKey) (*registration.Resource, error) {
|
||||
// couldn't load account but got a key. Try to look the account up.
|
||||
config := lego.NewConfig(&Account{key: privateKey})
|
||||
config.CADirURL = ctx.String("server")
|
||||
config.CADirURL = ctx.String(flgServer)
|
||||
config.UserAgent = getUserAgent(ctx)
|
||||
|
||||
client, err := lego.NewClient(config)
|
||||
|
|
|
@ -61,7 +61,7 @@ type CertificatesStorage struct {
|
|||
|
||||
// NewCertificatesStorage create a new certificates storage.
|
||||
func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage {
|
||||
pfxFormat := ctx.String("pfx.format")
|
||||
pfxFormat := ctx.String(flgPFXFormat)
|
||||
|
||||
switch pfxFormat {
|
||||
case "DES", "RC2", "SHA256":
|
||||
|
@ -70,13 +70,13 @@ func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage {
|
|||
}
|
||||
|
||||
return &CertificatesStorage{
|
||||
rootPath: filepath.Join(ctx.String("path"), baseCertificatesFolderName),
|
||||
archivePath: filepath.Join(ctx.String("path"), baseArchivesFolderName),
|
||||
pem: ctx.Bool("pem"),
|
||||
pfx: ctx.Bool("pfx"),
|
||||
pfxPassword: ctx.String("pfx.pass"),
|
||||
rootPath: filepath.Join(ctx.String(flgPath), baseCertificatesFolderName),
|
||||
archivePath: filepath.Join(ctx.String(flgPath), baseArchivesFolderName),
|
||||
pem: ctx.Bool(flgPEM),
|
||||
pfx: ctx.Bool(flgPFX),
|
||||
pfxPassword: ctx.String(flgPFXPass),
|
||||
pfxFormat: pfxFormat,
|
||||
filename: ctx.String("filename"),
|
||||
filename: ctx.String(flgFilename),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,17 +6,17 @@ import (
|
|||
)
|
||||
|
||||
func Before(ctx *cli.Context) error {
|
||||
if ctx.String("path") == "" {
|
||||
log.Fatal("Could not determine current working directory. Please pass --path.")
|
||||
if ctx.String(flgPath) == "" {
|
||||
log.Fatalf("Could not determine current working directory. Please pass --%s.", flgPath)
|
||||
}
|
||||
|
||||
err := createNonExistingFolder(ctx.String("path"))
|
||||
err := createNonExistingFolder(ctx.String(flgPath))
|
||||
if err != nil {
|
||||
log.Fatalf("Could not check/create path: %v", err)
|
||||
}
|
||||
|
||||
if ctx.String("server") == "" {
|
||||
log.Fatal("Could not determine current working server. Please pass --server.")
|
||||
if ctx.String(flgServer) == "" {
|
||||
log.Fatalf("Could not determine current working server. Please pass --%s.", flgServer)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -9,6 +9,8 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const flgCode = "code"
|
||||
|
||||
func createDNSHelp() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "dnshelp",
|
||||
|
@ -16,7 +18,7 @@ func createDNSHelp() *cli.Command {
|
|||
Action: dnsHelp,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "code",
|
||||
Name: flgCode,
|
||||
Aliases: []string{"c"},
|
||||
Usage: fmt.Sprintf("DNS code: %s", allDNSCodes()),
|
||||
},
|
||||
|
@ -25,7 +27,7 @@ func createDNSHelp() *cli.Command {
|
|||
}
|
||||
|
||||
func dnsHelp(ctx *cli.Context) error {
|
||||
code := ctx.String("code")
|
||||
code := ctx.String(flgCode)
|
||||
if code == "" {
|
||||
w := tabwriter.NewWriter(ctx.App.Writer, 0, 0, 2, ' ', 0)
|
||||
ew := &errWriter{w: w}
|
||||
|
|
|
@ -12,6 +12,11 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
flgAccounts = "accounts"
|
||||
flgNames = "names"
|
||||
)
|
||||
|
||||
func createList() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "list",
|
||||
|
@ -19,18 +24,18 @@ func createList() *cli.Command {
|
|||
Action: list,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "accounts",
|
||||
Name: flgAccounts,
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Display accounts.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "names",
|
||||
Name: flgNames,
|
||||
Aliases: []string{"n"},
|
||||
Usage: "Display certificate common names only.",
|
||||
},
|
||||
// fake email, needed by NewAccountsStorage
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Name: flgEmail,
|
||||
Value: "unknown",
|
||||
Hidden: true,
|
||||
},
|
||||
|
@ -39,7 +44,7 @@ func createList() *cli.Command {
|
|||
}
|
||||
|
||||
func list(ctx *cli.Context) error {
|
||||
if ctx.Bool("accounts") && !ctx.Bool("names") {
|
||||
if ctx.Bool(flgAccounts) && !ctx.Bool(flgNames) {
|
||||
if err := listAccount(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -56,7 +61,7 @@ func listCertificates(ctx *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
names := ctx.Bool("names")
|
||||
names := ctx.Bool(flgNames)
|
||||
|
||||
if len(matches) == 0 {
|
||||
if !names {
|
||||
|
@ -70,7 +75,7 @@ func listCertificates(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
for _, filename := range matches {
|
||||
if strings.HasSuffix(filename, ".issuer.crt") {
|
||||
if strings.HasSuffix(filename, issuerExt) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,16 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Flag names.
|
||||
const (
|
||||
flgDays = "days"
|
||||
flgARIEnable = "ari-enable"
|
||||
flgARIWaitToRenewDuration = "ari-wait-to-renew-duration"
|
||||
flgReuseKey = "reuse-key"
|
||||
flgRenewHook = "renew-hook"
|
||||
flgNoRandomSleep = "no-random-sleep"
|
||||
)
|
||||
|
||||
const (
|
||||
renewEnvAccountEmail = "LEGO_ACCOUNT_EMAIL"
|
||||
renewEnvCertDomain = "LEGO_CERT_DOMAIN"
|
||||
|
@ -34,68 +44,68 @@ func createRenew() *cli.Command {
|
|||
Action: renew,
|
||||
Before: func(ctx *cli.Context) error {
|
||||
// we require either domains or csr, but not both
|
||||
hasDomains := len(ctx.StringSlice("domains")) > 0
|
||||
hasCsr := ctx.String("csr") != ""
|
||||
hasDomains := len(ctx.StringSlice(flgDomains)) > 0
|
||||
hasCsr := ctx.String(flgCSR) != ""
|
||||
if hasDomains && hasCsr {
|
||||
log.Fatal("Please specify either --domains/-d or --csr/-c, but not both")
|
||||
log.Fatal("Please specify either --%s/-d or --%s/-c, but not both", flgDomains, flgCSR)
|
||||
}
|
||||
if !hasDomains && !hasCsr {
|
||||
log.Fatal("Please specify --domains/-d (or --csr/-c if you already have a CSR)")
|
||||
log.Fatal("Please specify --%s/-d (or --%s/-c if you already have a CSR)", flgDomains, flgCSR)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Flags: []cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "days",
|
||||
Name: flgDays,
|
||||
Value: 30,
|
||||
Usage: "The number of days left on a certificate to renew it.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "ari-enable",
|
||||
Name: flgARIEnable,
|
||||
Usage: "Use the renewalInfo endpoint (draft-ietf-acme-ari) to check if a certificate should be renewed.",
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "ari-wait-to-renew-duration",
|
||||
Name: flgARIWaitToRenewDuration,
|
||||
Usage: "The maximum duration you're willing to sleep for a renewal time returned by the renewalInfo endpoint.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "reuse-key",
|
||||
Name: flgReuseKey,
|
||||
Usage: "Used to indicate you want to reuse your current private key for the new certificate.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "no-bundle",
|
||||
Name: flgNoBundle,
|
||||
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-staple",
|
||||
Name: 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{
|
||||
Name: "not-before",
|
||||
Name: flgNotBefore,
|
||||
Usage: "Set the notBefore field in the certificate (RFC3339 format)",
|
||||
Layout: time.RFC3339,
|
||||
},
|
||||
&cli.TimestampFlag{
|
||||
Name: "not-after",
|
||||
Name: flgNotAfter,
|
||||
Usage: "Set the notAfter field in the certificate (RFC3339 format)",
|
||||
Layout: time.RFC3339,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "preferred-chain",
|
||||
Name: 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{
|
||||
Name: "always-deactivate-authorizations",
|
||||
Name: flgAlwaysDeactivateAuthorizations,
|
||||
Usage: "Force the authorizations to be relinquished even if the certificate request was successful.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "renew-hook",
|
||||
Name: flgRenewHook,
|
||||
Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "no-random-sleep",
|
||||
Name: 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.",
|
||||
},
|
||||
|
@ -113,12 +123,12 @@ func renew(ctx *cli.Context) error {
|
|||
|
||||
certsStorage := NewCertificatesStorage(ctx)
|
||||
|
||||
bundle := !ctx.Bool("no-bundle")
|
||||
bundle := !ctx.Bool(flgNoBundle)
|
||||
|
||||
meta := map[string]string{renewEnvAccountEmail: account.Email}
|
||||
|
||||
// CSR
|
||||
if ctx.IsSet("csr") {
|
||||
if ctx.IsSet(flgCSR) {
|
||||
return renewForCSR(ctx, client, certsStorage, bundle, meta)
|
||||
}
|
||||
|
||||
|
@ -127,13 +137,13 @@ func renew(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
|
||||
domains := ctx.StringSlice("domains")
|
||||
domains := ctx.StringSlice(flgDomains)
|
||||
domain := domains[0]
|
||||
|
||||
// load the cert resource from files.
|
||||
// We store the certificate, private key and metadata in different files
|
||||
// as web servers would not be able to work with a combined file.
|
||||
certificates, err := certsStorage.ReadCertificate(domain, ".crt")
|
||||
certificates, err := certsStorage.ReadCertificate(domain, certExt)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while loading the certificate for domain %s\n\t%v", domain, err)
|
||||
}
|
||||
|
@ -141,7 +151,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
cert := certificates[0]
|
||||
|
||||
var ariRenewalTime *time.Time
|
||||
if ctx.Bool("ari-enable") {
|
||||
if ctx.Bool(flgARIEnable) {
|
||||
ariRenewalTime = getARIRenewalTime(ctx, cert, domain, client)
|
||||
if ariRenewalTime != nil {
|
||||
now := time.Now().UTC()
|
||||
|
@ -153,7 +163,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
}
|
||||
}
|
||||
|
||||
if ariRenewalTime == nil && !needRenewal(cert, domain, ctx.Int("days")) {
|
||||
if ariRenewalTime == nil && !needRenewal(cert, domain, ctx.Int(flgDays)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -164,8 +174,8 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
certDomains := certcrypto.ExtractDomains(cert)
|
||||
|
||||
var privateKey crypto.PrivateKey
|
||||
if ctx.Bool("reuse-key") {
|
||||
keyBytes, errR := certsStorage.ReadFile(domain, ".key")
|
||||
if ctx.Bool(flgReuseKey) {
|
||||
keyBytes, errR := certsStorage.ReadFile(domain, keyExt)
|
||||
if errR != nil {
|
||||
log.Fatalf("Error while loading the private key for domain %s\n\t%v", domain, errR)
|
||||
}
|
||||
|
@ -178,7 +188,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
|
||||
// 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()) && !ctx.Bool("no-random-sleep") {
|
||||
if !isatty.IsTerminal(os.Stdout.Fd()) && !ctx.Bool(flgNoRandomSleep) {
|
||||
// https://github.com/certbot/certbot/blob/284023a1b7672be2bd4018dd7623b3b92197d4b0/certbot/certbot/_internal/renewal.py#L472
|
||||
const jitter = 8 * time.Minute
|
||||
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
@ -191,15 +201,15 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
request := certificate.ObtainRequest{
|
||||
Domains: merge(certDomains, domains),
|
||||
PrivateKey: privateKey,
|
||||
MustStaple: ctx.Bool("must-staple"),
|
||||
NotBefore: getTime(ctx, "not-before"),
|
||||
NotAfter: getTime(ctx, "not-after"),
|
||||
MustStaple: ctx.Bool(flgMustStaple),
|
||||
NotBefore: getTime(ctx, flgNotBefore),
|
||||
NotAfter: getTime(ctx, flgNotAfter),
|
||||
Bundle: bundle,
|
||||
PreferredChain: ctx.String("preferred-chain"),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool("always-deactivate-authorizations"),
|
||||
PreferredChain: ctx.String(flgPreferredChain),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
|
||||
}
|
||||
|
||||
if ctx.Bool("ari-enable") {
|
||||
if ctx.Bool(flgARIEnable) {
|
||||
request.ReplacesCertID, err = certificate.MakeARICertID(cert)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while construction the ARI CertID for domain %s\n\t%v", domain, err)
|
||||
|
@ -215,11 +225,11 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
|
|||
|
||||
addPathToMetadata(meta, domain, certRes, certsStorage)
|
||||
|
||||
return launchHook(ctx.String("renew-hook"), meta)
|
||||
return launchHook(ctx.String(flgRenewHook), meta)
|
||||
}
|
||||
|
||||
func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
|
||||
csr, err := readCSRFile(ctx.String("csr"))
|
||||
csr, err := readCSRFile(ctx.String(flgCSR))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -232,7 +242,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
|||
// load the cert resource from files.
|
||||
// We store the certificate, private key and metadata in different files
|
||||
// as web servers would not be able to work with a combined file.
|
||||
certificates, err := certsStorage.ReadCertificate(domain, ".crt")
|
||||
certificates, err := certsStorage.ReadCertificate(domain, certExt)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while loading the certificate for domain %s\n\t%v", domain, err)
|
||||
}
|
||||
|
@ -240,7 +250,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
|||
cert := certificates[0]
|
||||
|
||||
var ariRenewalTime *time.Time
|
||||
if ctx.Bool("ari-enable") {
|
||||
if ctx.Bool(flgARIEnable) {
|
||||
ariRenewalTime = getARIRenewalTime(ctx, cert, domain, client)
|
||||
if ariRenewalTime != nil {
|
||||
now := time.Now().UTC()
|
||||
|
@ -252,7 +262,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
|||
}
|
||||
}
|
||||
|
||||
if ariRenewalTime == nil && !needRenewal(cert, domain, ctx.Int("days")) {
|
||||
if ariRenewalTime == nil && !needRenewal(cert, domain, ctx.Int(flgDays)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -262,14 +272,14 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
|||
|
||||
request := certificate.ObtainForCSRRequest{
|
||||
CSR: csr,
|
||||
NotBefore: getTime(ctx, "not-before"),
|
||||
NotAfter: getTime(ctx, "not-after"),
|
||||
NotBefore: getTime(ctx, flgNotBefore),
|
||||
NotAfter: getTime(ctx, flgNotAfter),
|
||||
Bundle: bundle,
|
||||
PreferredChain: ctx.String("preferred-chain"),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool("always-deactivate-authorizations"),
|
||||
PreferredChain: ctx.String(flgPreferredChain),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
|
||||
}
|
||||
|
||||
if ctx.Bool("ari-enable") {
|
||||
if ctx.Bool(flgARIEnable) {
|
||||
request.ReplacesCertID, err = certificate.MakeARICertID(cert)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while construction the ARI CertID for domain %s\n\t%v", domain, err)
|
||||
|
@ -285,7 +295,7 @@ func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *Certificat
|
|||
|
||||
addPathToMetadata(meta, domain, certRes, certsStorage)
|
||||
|
||||
return launchHook(ctx.String("renew-hook"), meta)
|
||||
return launchHook(ctx.String(flgRenewHook), meta)
|
||||
}
|
||||
|
||||
func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool {
|
||||
|
@ -323,7 +333,7 @@ func getARIRenewalTime(ctx *cli.Context, cert *x509.Certificate, domain string,
|
|||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
renewalTime := renewalInfo.ShouldRenewAt(now, ctx.Duration("ari-wait-to-renew-duration"))
|
||||
renewalTime := renewalInfo.ShouldRenewAt(now, ctx.Duration(flgARIWaitToRenewDuration))
|
||||
if renewalTime == nil {
|
||||
log.Infof("[%s] acme: renewalInfo endpoint indicates that renewal is not needed", domain)
|
||||
return nil
|
||||
|
|
|
@ -6,6 +6,12 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Flag names.
|
||||
const (
|
||||
flgKeep = "keep"
|
||||
flgReason = "reason"
|
||||
)
|
||||
|
||||
func createRevoke() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "revoke",
|
||||
|
@ -13,12 +19,12 @@ func createRevoke() *cli.Command {
|
|||
Action: revoke,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "keep",
|
||||
Name: flgKeep,
|
||||
Aliases: []string{"k"},
|
||||
Usage: "Keep the certificates after the revocation instead of archiving them.",
|
||||
},
|
||||
&cli.UintFlag{
|
||||
Name: "reason",
|
||||
Name: flgReason,
|
||||
Usage: "Identifies the reason for the certificate revocation." +
|
||||
" See https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1." +
|
||||
" Valid values are:" +
|
||||
|
@ -41,15 +47,15 @@ func revoke(ctx *cli.Context) error {
|
|||
certsStorage := NewCertificatesStorage(ctx)
|
||||
certsStorage.CreateRootFolder()
|
||||
|
||||
for _, domain := range ctx.StringSlice("domains") {
|
||||
for _, domain := range ctx.StringSlice(flgDomains) {
|
||||
log.Printf("Trying to revoke certificate for domain %s", domain)
|
||||
|
||||
certBytes, err := certsStorage.ReadFile(domain, ".crt")
|
||||
certBytes, err := certsStorage.ReadFile(domain, certExt)
|
||||
if err != nil {
|
||||
log.Fatalf("Error while revoking the certificate for domain %s\n\t%v", domain, err)
|
||||
}
|
||||
|
||||
reason := ctx.Uint("reason")
|
||||
reason := ctx.Uint(flgReason)
|
||||
|
||||
err = client.Certificate.RevokeWithReason(certBytes, &reason)
|
||||
if err != nil {
|
||||
|
@ -58,7 +64,7 @@ func revoke(ctx *cli.Context) error {
|
|||
|
||||
log.Println("Certificate was revoked.")
|
||||
|
||||
if ctx.Bool("keep") {
|
||||
if ctx.Bool(flgKeep) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -14,14 +14,25 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// Flag names.
|
||||
const (
|
||||
flgNoBundle = "no-bundle"
|
||||
flgMustStaple = "must-staple"
|
||||
flgNotBefore = "not-before"
|
||||
flgNotAfter = "not-after"
|
||||
flgPreferredChain = "preferred-chain"
|
||||
flgAlwaysDeactivateAuthorizations = "always-deactivate-authorizations"
|
||||
flgRunHook = "run-hook"
|
||||
)
|
||||
|
||||
func createRun() *cli.Command {
|
||||
return &cli.Command{
|
||||
Name: "run",
|
||||
Usage: "Register an account, then create and install a certificate",
|
||||
Before: func(ctx *cli.Context) error {
|
||||
// we require either domains or csr, but not both
|
||||
hasDomains := len(ctx.StringSlice("domains")) > 0
|
||||
hasCsr := ctx.String("csr") != ""
|
||||
hasDomains := len(ctx.StringSlice(flgDomains)) > 0
|
||||
hasCsr := ctx.String(flgCSR) != ""
|
||||
if hasDomains && hasCsr {
|
||||
log.Fatal("Please specify either --domains/-d or --csr/-c, but not both")
|
||||
}
|
||||
|
@ -33,35 +44,35 @@ func createRun() *cli.Command {
|
|||
Action: run,
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "no-bundle",
|
||||
Name: flgNoBundle,
|
||||
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "must-staple",
|
||||
Name: 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{
|
||||
Name: "not-before",
|
||||
Name: flgNotBefore,
|
||||
Usage: "Set the notBefore field in the certificate (RFC3339 format)",
|
||||
Layout: time.RFC3339,
|
||||
},
|
||||
&cli.TimestampFlag{
|
||||
Name: "not-after",
|
||||
Name: flgNotAfter,
|
||||
Usage: "Set the notAfter field in the certificate (RFC3339 format)",
|
||||
Layout: time.RFC3339,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "preferred-chain",
|
||||
Name: 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{
|
||||
Name: "always-deactivate-authorizations",
|
||||
Name: flgAlwaysDeactivateAuthorizations,
|
||||
Usage: "Force the authorizations to be relinquished even if the certificate request was successful.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "run-hook",
|
||||
Name: flgRunHook,
|
||||
Usage: "Define a hook. The hook is executed when the certificates are effectively created.",
|
||||
},
|
||||
},
|
||||
|
@ -117,12 +128,12 @@ func run(ctx *cli.Context) error {
|
|||
|
||||
addPathToMetadata(meta, cert.Domain, cert, certsStorage)
|
||||
|
||||
return launchHook(ctx.String("run-hook"), meta)
|
||||
return launchHook(ctx.String(flgRunHook), meta)
|
||||
}
|
||||
|
||||
func handleTOS(ctx *cli.Context, client *lego.Client) bool {
|
||||
// Check for a global accept override
|
||||
if ctx.Bool("accept-tos") {
|
||||
if ctx.Bool(flgAcceptTOS) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -154,12 +165,12 @@ func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, er
|
|||
log.Fatal("You did not accept the TOS. Unable to proceed.")
|
||||
}
|
||||
|
||||
if ctx.Bool("eab") {
|
||||
kid := ctx.String("kid")
|
||||
hmacEncoded := ctx.String("hmac")
|
||||
if ctx.Bool(flgEAB) {
|
||||
kid := ctx.String(flgKID)
|
||||
hmacEncoded := ctx.String(flgHMAC)
|
||||
|
||||
if kid == "" || hmacEncoded == "" {
|
||||
log.Fatalf("Requires arguments --kid and --hmac.")
|
||||
log.Fatalf("Requires arguments --%s and --%s.", flgKID, flgHMAC)
|
||||
}
|
||||
|
||||
return client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
|
||||
|
@ -173,25 +184,25 @@ func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, er
|
|||
}
|
||||
|
||||
func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Resource, error) {
|
||||
bundle := !ctx.Bool("no-bundle")
|
||||
bundle := !ctx.Bool(flgNoBundle)
|
||||
|
||||
domains := ctx.StringSlice("domains")
|
||||
domains := ctx.StringSlice(flgDomains)
|
||||
if len(domains) > 0 {
|
||||
// obtain a certificate, generating a new private key
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: domains,
|
||||
Bundle: bundle,
|
||||
MustStaple: ctx.Bool("must-staple"),
|
||||
PreferredChain: ctx.String("preferred-chain"),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool("always-deactivate-authorizations"),
|
||||
MustStaple: ctx.Bool(flgMustStaple),
|
||||
PreferredChain: ctx.String(flgPreferredChain),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
|
||||
}
|
||||
|
||||
notBefore := ctx.Timestamp("not-before")
|
||||
notBefore := ctx.Timestamp(flgNotBefore)
|
||||
if notBefore != nil {
|
||||
request.NotBefore = *notBefore
|
||||
}
|
||||
|
||||
notAfter := ctx.Timestamp("not-after")
|
||||
notAfter := ctx.Timestamp(flgNotAfter)
|
||||
if notAfter != nil {
|
||||
request.NotAfter = *notAfter
|
||||
}
|
||||
|
@ -200,7 +211,7 @@ func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Reso
|
|||
}
|
||||
|
||||
// read the CSR
|
||||
csr, err := readCSRFile(ctx.String("csr"))
|
||||
csr, err := readCSRFile(ctx.String(flgCSR))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -208,11 +219,11 @@ func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Reso
|
|||
// obtain a certificate for this CSR
|
||||
request := certificate.ObtainForCSRRequest{
|
||||
CSR: csr,
|
||||
NotBefore: getTime(ctx, "not-before"),
|
||||
NotAfter: getTime(ctx, "not-after"),
|
||||
NotBefore: getTime(ctx, flgNotBefore),
|
||||
NotAfter: getTime(ctx, flgNotAfter),
|
||||
Bundle: bundle,
|
||||
PreferredChain: ctx.String("preferred-chain"),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool("always-deactivate-authorizations"),
|
||||
PreferredChain: ctx.String(flgPreferredChain),
|
||||
AlwaysDeactivateAuthorizations: ctx.Bool(flgAlwaysDeactivateAuthorizations),
|
||||
}
|
||||
|
||||
return client.Certificate.ObtainForCSR(request)
|
||||
|
|
100
cmd/flags.go
100
cmd/flags.go
|
@ -9,163 +9,199 @@ import (
|
|||
"software.sslmate.com/src/go-pkcs12"
|
||||
)
|
||||
|
||||
// Flag names.
|
||||
const (
|
||||
flgDomains = "domains"
|
||||
flgServer = "server"
|
||||
flgAcceptTOS = "accept-tos"
|
||||
flgEmail = "email"
|
||||
flgCSR = "csr"
|
||||
flgEAB = "eab"
|
||||
flgKID = "kid"
|
||||
flgHMAC = "hmac"
|
||||
flgKeyType = "key-type"
|
||||
flgFilename = "filename"
|
||||
flgPath = "path"
|
||||
flgHTTP = "http"
|
||||
flgHTTPPort = "http.port"
|
||||
flgHTTPProxyHeader = "http.proxy-header"
|
||||
flgHTTPWebroot = "http.webroot"
|
||||
flgHTTPMemcachedHost = "http.memcached-host"
|
||||
flgHTTPS3Bucket = "http.s3-bucket"
|
||||
flgTLS = "tls"
|
||||
flgTLSPort = "tls.port"
|
||||
flgDNS = "dns"
|
||||
flgDNSDisableCP = "dns.disable-cp"
|
||||
flgDNSPropagationWait = "dns.propagation-wait"
|
||||
flgDNSResolvers = "dns.resolvers"
|
||||
flgHTTPTimeout = "http-timeout"
|
||||
flgDNSTimeout = "dns-timeout"
|
||||
flgPEM = "pem"
|
||||
flgPFX = "pfx"
|
||||
flgPFXPass = "pfx.pass"
|
||||
flgPFXFormat = "pfx.format"
|
||||
flgCertTimeout = "cert.timeout"
|
||||
flgOverallRequestLimit = "overall-request-limit"
|
||||
flgUserAgent = "user-agent"
|
||||
)
|
||||
|
||||
func CreateFlags(defaultPath string) []cli.Flag {
|
||||
return []cli.Flag{
|
||||
&cli.StringSliceFlag{
|
||||
Name: "domains",
|
||||
Name: flgDomains,
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Add a domain to the process. Can be specified multiple times.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "server",
|
||||
Name: flgServer,
|
||||
Aliases: []string{"s"},
|
||||
EnvVars: []string{"LEGO_SERVER"},
|
||||
Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.",
|
||||
Value: lego.LEDirectoryProduction,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "accept-tos",
|
||||
Name: flgAcceptTOS,
|
||||
Aliases: []string{"a"},
|
||||
Usage: "By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Name: flgEmail,
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Email used for registration and recovery contact.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "csr",
|
||||
Name: flgCSR,
|
||||
Aliases: []string{"c"},
|
||||
Usage: "Certificate signing request filename, if an external CSR is to be used.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "eab",
|
||||
Name: flgEAB,
|
||||
EnvVars: []string{"LEGO_EAB"},
|
||||
Usage: "Use External Account Binding for account registration. Requires --kid and --hmac.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "kid",
|
||||
Name: flgKID,
|
||||
EnvVars: []string{"LEGO_EAB_KID"},
|
||||
Usage: "Key identifier from External CA. Used for External Account Binding.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "hmac",
|
||||
Name: flgHMAC,
|
||||
EnvVars: []string{"LEGO_EAB_HMAC"},
|
||||
Usage: "MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key-type",
|
||||
Name: flgKeyType,
|
||||
Aliases: []string{"k"},
|
||||
Value: "ec256",
|
||||
Usage: "Key type to use for private keys. Supported: rsa2048, rsa3072, rsa4096, rsa8192, ec256, ec384.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "filename",
|
||||
Name: flgFilename,
|
||||
Usage: "(deprecated) Filename of the generated certificate.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "path",
|
||||
Name: flgPath,
|
||||
EnvVars: []string{"LEGO_PATH"},
|
||||
Usage: "Directory to use for storing the data.",
|
||||
Value: defaultPath,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "http",
|
||||
Name: flgHTTP,
|
||||
Usage: "Use the HTTP-01 challenge to solve challenges. Can be mixed with other types of challenges.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "http.port",
|
||||
Name: 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.StringFlag{
|
||||
Name: "http.proxy-header",
|
||||
Name: flgHTTPProxyHeader,
|
||||
Usage: "Validate against this HTTP header when solving HTTP-01 based challenges behind a reverse proxy.",
|
||||
Value: "Host",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "http.webroot",
|
||||
Name: 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{
|
||||
Name: "http.memcached-host",
|
||||
Name: flgHTTPMemcachedHost,
|
||||
Usage: "Set the memcached host(s) to use for HTTP-01 based challenges. Challenges will be written to all specified hosts.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "http.s3-bucket",
|
||||
Name: flgHTTPS3Bucket,
|
||||
Usage: "Set the S3 bucket name to use for HTTP-01 based challenges. Challenges will be written to the S3 bucket.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "tls",
|
||||
Name: flgTLS,
|
||||
Usage: "Use the TLS-ALPN-01 challenge to solve challenges. Can be mixed with other types of challenges.",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "tls.port",
|
||||
Name: 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.StringFlag{
|
||||
Name: "dns",
|
||||
Name: 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{
|
||||
Name: "dns.disable-cp",
|
||||
Name: flgDNSDisableCP,
|
||||
Usage: "By setting this flag to true, disables the need to await propagation of the TXT record to all authoritative name servers.",
|
||||
},
|
||||
&cli.DurationFlag{
|
||||
Name: "dns.propagation-wait",
|
||||
Name: flgDNSPropagationWait,
|
||||
Usage: "By setting this flag, disables all the propagation checks and uses a wait duration instead.",
|
||||
},
|
||||
&cli.StringSliceFlag{
|
||||
Name: "dns.resolvers",
|
||||
Name: 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{
|
||||
Name: "http-timeout",
|
||||
Name: flgHTTPTimeout,
|
||||
Usage: "Set the HTTP timeout value to a specific value in seconds.",
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "dns-timeout",
|
||||
Name: flgDNSTimeout,
|
||||
Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name server queries.",
|
||||
Value: 10,
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "pem",
|
||||
Name: flgPEM,
|
||||
Usage: "Generate an additional .pem (base64) file by concatenating the .key and .crt files together.",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "pfx",
|
||||
Name: flgPFX,
|
||||
Usage: "Generate an additional .pfx (PKCS#12) file by concatenating the .key and .crt and issuer .crt files together.",
|
||||
EnvVars: []string{"LEGO_PFX"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pfx.pass",
|
||||
Name: flgPFXPass,
|
||||
Usage: "The password used to encrypt the .pfx (PCKS#12) file.",
|
||||
Value: pkcs12.DefaultPassword,
|
||||
EnvVars: []string{"LEGO_PFX_PASSWORD"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "pfx.format",
|
||||
Name: flgPFXFormat,
|
||||
Usage: "The encoding format to use when encrypting the .pfx (PCKS#12) file. Supported: RC2, DES, SHA256.",
|
||||
Value: "RC2",
|
||||
EnvVars: []string{"LEGO_PFX_FORMAT"},
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "cert.timeout",
|
||||
Name: flgCertTimeout,
|
||||
Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.",
|
||||
Value: 30,
|
||||
},
|
||||
&cli.IntFlag{
|
||||
Name: "overall-request-limit",
|
||||
Name: flgOverallRequestLimit,
|
||||
Usage: "ACME overall requests limit.",
|
||||
Value: certificate.DefaultOverallRequestLimit,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "user-agent",
|
||||
Name: flgUserAgent,
|
||||
Usage: "Add to the user-agent sent to the CA to identify an application embedding lego-cli",
|
||||
},
|
||||
}
|
||||
|
|
22
cmd/setup.go
22
cmd/setup.go
|
@ -35,17 +35,17 @@ func setup(ctx *cli.Context, accountsStorage *AccountsStorage) (*Account, *lego.
|
|||
|
||||
func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyType) *lego.Client {
|
||||
config := lego.NewConfig(acc)
|
||||
config.CADirURL = ctx.String("server")
|
||||
config.CADirURL = ctx.String(flgServer)
|
||||
|
||||
config.Certificate = lego.CertificateConfig{
|
||||
KeyType: keyType,
|
||||
Timeout: time.Duration(ctx.Int("cert.timeout")) * time.Second,
|
||||
OverallRequestLimit: ctx.Int("overall-request-limit"),
|
||||
Timeout: time.Duration(ctx.Int(flgCertTimeout)) * time.Second,
|
||||
OverallRequestLimit: ctx.Int(flgOverallRequestLimit),
|
||||
}
|
||||
config.UserAgent = getUserAgent(ctx)
|
||||
|
||||
if ctx.IsSet("http-timeout") {
|
||||
config.HTTPClient.Timeout = time.Duration(ctx.Int("http-timeout")) * time.Second
|
||||
if ctx.IsSet(flgHTTPTimeout) {
|
||||
config.HTTPClient.Timeout = time.Duration(ctx.Int(flgHTTPTimeout)) * time.Second
|
||||
}
|
||||
|
||||
client, err := lego.NewClient(config)
|
||||
|
@ -53,8 +53,8 @@ func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyTy
|
|||
log.Fatalf("Could not create client: %v", err)
|
||||
}
|
||||
|
||||
if client.GetExternalAccountRequired() && !ctx.IsSet("eab") {
|
||||
log.Fatal("Server requires External Account Binding. Use --eab with --kid and --hmac.")
|
||||
if client.GetExternalAccountRequired() && !ctx.IsSet(flgEAB) {
|
||||
log.Fatalf("Server requires External Account Binding. Use --%s with --%s and --%s.", flgEAB, flgKID, flgHMAC)
|
||||
}
|
||||
|
||||
return client
|
||||
|
@ -62,7 +62,7 @@ func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyTy
|
|||
|
||||
// getKeyType the type from which private keys should be generated.
|
||||
func getKeyType(ctx *cli.Context) certcrypto.KeyType {
|
||||
keyType := ctx.String("key-type")
|
||||
keyType := ctx.String(flgKeyType)
|
||||
switch strings.ToUpper(keyType) {
|
||||
case "RSA2048":
|
||||
return certcrypto.RSA2048
|
||||
|
@ -83,15 +83,15 @@ func getKeyType(ctx *cli.Context) certcrypto.KeyType {
|
|||
}
|
||||
|
||||
func getEmail(ctx *cli.Context) string {
|
||||
email := ctx.String("email")
|
||||
email := ctx.String(flgEmail)
|
||||
if email == "" {
|
||||
log.Fatal("You have to pass an account (email address) to the program using --email or -m")
|
||||
log.Fatalf("You have to pass an account (email address) to the program using --%s or -m", flgEmail)
|
||||
}
|
||||
return email
|
||||
}
|
||||
|
||||
func getUserAgent(ctx *cli.Context) string {
|
||||
return strings.TrimSpace(fmt.Sprintf("%s lego-cli/%s", ctx.String("user-agent"), ctx.App.Version))
|
||||
return strings.TrimSpace(fmt.Sprintf("%s lego-cli/%s", ctx.String(flgUserAgent), ctx.App.Version))
|
||||
}
|
||||
|
||||
func createNonExistingFolder(path string) error {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -20,25 +20,25 @@ import (
|
|||
)
|
||||
|
||||
func setupChallenges(ctx *cli.Context, client *lego.Client) {
|
||||
if !ctx.Bool("http") && !ctx.Bool("tls") && !ctx.IsSet("dns") {
|
||||
log.Fatal("No challenge selected. You must specify at least one challenge: `--http`, `--tls`, `--dns`.")
|
||||
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)
|
||||
}
|
||||
|
||||
if ctx.Bool("http") {
|
||||
if ctx.Bool(flgHTTP) {
|
||||
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.Bool("tls") {
|
||||
if ctx.Bool(flgTLS) {
|
||||
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.IsSet("dns") {
|
||||
if ctx.IsSet(flgDNS) {
|
||||
err := setupDNS(ctx, client)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -49,28 +49,28 @@ func setupChallenges(ctx *cli.Context, client *lego.Client) {
|
|||
//nolint:gocyclo // the complexity is expected.
|
||||
func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
|
||||
switch {
|
||||
case ctx.IsSet("http.webroot"):
|
||||
ps, err := webroot.NewHTTPProvider(ctx.String("http.webroot"))
|
||||
case ctx.IsSet(flgHTTPWebroot):
|
||||
ps, err := webroot.NewHTTPProvider(ctx.String(flgHTTPWebroot))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return ps
|
||||
case ctx.IsSet("http.memcached-host"):
|
||||
ps, err := memcached.NewMemcachedProvider(ctx.StringSlice("http.memcached-host"))
|
||||
case ctx.IsSet(flgHTTPMemcachedHost):
|
||||
ps, err := memcached.NewMemcachedProvider(ctx.StringSlice(flgHTTPMemcachedHost))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return ps
|
||||
case ctx.IsSet("http.s3-bucket"):
|
||||
ps, err := s3.NewHTTPProvider(ctx.String("http.s3-bucket"))
|
||||
case ctx.IsSet(flgHTTPS3Bucket):
|
||||
ps, err := s3.NewHTTPProvider(ctx.String(flgHTTPS3Bucket))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
return ps
|
||||
case ctx.IsSet("http.port"):
|
||||
iface := ctx.String("http.port")
|
||||
case ctx.IsSet(flgHTTPPort):
|
||||
iface := ctx.String(flgHTTPPort)
|
||||
if !strings.Contains(iface, ":") {
|
||||
log.Fatalf("The --http switch only accepts interface:port or :port for its argument.")
|
||||
log.Fatalf("The --%s switch only accepts interface:port or :port for its argument.", flgHTTPPort)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(iface)
|
||||
|
@ -79,13 +79,13 @@ func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
|
|||
}
|
||||
|
||||
srv := http01.NewProviderServer(host, port)
|
||||
if header := ctx.String("http.proxy-header"); header != "" {
|
||||
if header := ctx.String(flgHTTPProxyHeader); header != "" {
|
||||
srv.SetProxyHeader(header)
|
||||
}
|
||||
return srv
|
||||
case ctx.Bool("http"):
|
||||
case ctx.Bool(flgHTTP):
|
||||
srv := http01.NewProviderServer("", "")
|
||||
if header := ctx.String("http.proxy-header"); header != "" {
|
||||
if header := ctx.String(flgHTTPProxyHeader); header != "" {
|
||||
srv.SetProxyHeader(header)
|
||||
}
|
||||
return srv
|
||||
|
@ -97,10 +97,10 @@ func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
|
|||
|
||||
func setupTLSProvider(ctx *cli.Context) challenge.Provider {
|
||||
switch {
|
||||
case ctx.IsSet("tls.port"):
|
||||
iface := ctx.String("tls.port")
|
||||
case ctx.IsSet(flgTLSPort):
|
||||
iface := ctx.String(flgTLSPort)
|
||||
if !strings.Contains(iface, ":") {
|
||||
log.Fatalf("The --tls switch only accepts interface:port or :port for its argument.")
|
||||
log.Fatalf("The --%s switch only accepts interface:port or :port for its argument.", flgTLSPort)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(iface)
|
||||
|
@ -109,7 +109,7 @@ func setupTLSProvider(ctx *cli.Context) challenge.Provider {
|
|||
}
|
||||
|
||||
return tlsalpn01.NewProviderServer(host, port)
|
||||
case ctx.Bool("tls"):
|
||||
case ctx.Bool(flgTLS):
|
||||
return tlsalpn01.NewProviderServer("", "")
|
||||
default:
|
||||
log.Fatal("Invalid HTTP challenge options.")
|
||||
|
@ -118,38 +118,38 @@ func setupTLSProvider(ctx *cli.Context) challenge.Provider {
|
|||
}
|
||||
|
||||
func setupDNS(ctx *cli.Context, client *lego.Client) error {
|
||||
if ctx.IsSet("dns.disable-cp") && ctx.Bool("dns.disable-cp") && ctx.IsSet("dns.propagation-wait") {
|
||||
return errors.New("'dns.disable-cp' and 'dns.propagation-wait' are mutually exclusive")
|
||||
if ctx.IsSet(flgDNSDisableCP) && ctx.Bool(flgDNSDisableCP) && ctx.IsSet(flgDNSPropagationWait) {
|
||||
return fmt.Errorf("'%s' and '%s' are mutually exclusive", flgDNSDisableCP, flgDNSPropagationWait)
|
||||
}
|
||||
|
||||
wait := ctx.Duration("dns.propagation-wait")
|
||||
wait := ctx.Duration(flgDNSPropagationWait)
|
||||
if wait < 0 {
|
||||
return errors.New("'dns.propagation-wait' cannot be negative")
|
||||
return fmt.Errorf("'%s' cannot be negative", flgDNSPropagationWait)
|
||||
}
|
||||
|
||||
provider, err := dns.NewDNSChallengeProviderByName(ctx.String("dns"))
|
||||
provider, err := dns.NewDNSChallengeProviderByName(ctx.String(flgDNS))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
servers := ctx.StringSlice("dns.resolvers")
|
||||
servers := ctx.StringSlice(flgDNSResolvers)
|
||||
|
||||
err = client.Challenge.SetDNS01Provider(provider,
|
||||
dns01.CondOption(len(servers) > 0,
|
||||
dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.StringSlice("dns.resolvers")))),
|
||||
dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.StringSlice(flgDNSResolvers)))),
|
||||
|
||||
dns01.CondOption(ctx.Bool("dns.disable-cp"),
|
||||
dns01.CondOption(ctx.Bool(flgDNSDisableCP),
|
||||
dns01.DisableCompletePropagationRequirement()),
|
||||
|
||||
dns01.CondOption(ctx.IsSet("dns.propagation-wait"), dns01.WrapPreCheck(
|
||||
dns01.CondOption(ctx.IsSet(flgDNSPropagationWait), dns01.WrapPreCheck(
|
||||
func(domain, fqdn, value string, check dns01.PreCheckFunc) (bool, error) {
|
||||
time.Sleep(wait)
|
||||
return true, nil
|
||||
},
|
||||
)),
|
||||
|
||||
dns01.CondOption(ctx.IsSet("dns-timeout"),
|
||||
dns01.AddDNSTimeout(time.Duration(ctx.Int("dns-timeout"))*time.Second)),
|
||||
dns01.CondOption(ctx.IsSet(flgDNSTimeout),
|
||||
dns01.AddDNSTimeout(time.Duration(ctx.Int(flgDNSTimeout))*time.Second)),
|
||||
)
|
||||
|
||||
return err
|
||||
|
|
Loading…
Reference in a new issue