diff --git a/common/legocmd/cmd/cmd.go b/common/legocmd/cmd/cmd.go deleted file mode 100644 index 05b135f..0000000 --- a/common/legocmd/cmd/cmd.go +++ /dev/null @@ -1,14 +0,0 @@ -package cmd - -import "github.com/urfave/cli" - -// CreateCommands Creates all CLI commands. -func CreateCommands() []cli.Command { - return []cli.Command{ - createRun(), - createRevoke(), - createRenew(), - createDNSHelp(), - createList(), - } -} diff --git a/common/legocmd/cmd/cmd_before.go b/common/legocmd/cmd/cmd_before.go deleted file mode 100644 index f1326dd..0000000 --- a/common/legocmd/cmd/cmd_before.go +++ /dev/null @@ -1,24 +0,0 @@ -package cmd - -import ( - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -func Before(ctx *cli.Context) error { - if ctx.GlobalString("path") == "" { - log.Panic("Could not determine current working directory. Please pass --path.") - } - - err := createNonExistingFolder(ctx.GlobalString("path")) - if err != nil { - log.Panicf("Could not check/create path: %v", err) - } - - if ctx.GlobalString("server") == "" { - log.Panic("Could not determine current working server. Please pass --server.") - } - - return nil -} diff --git a/common/legocmd/cmd/cmd_dnshelp.go b/common/legocmd/cmd/cmd_dnshelp.go deleted file mode 100644 index 3359211..0000000 --- a/common/legocmd/cmd/cmd_dnshelp.go +++ /dev/null @@ -1,73 +0,0 @@ -package cmd - -import ( - "fmt" - "io" - "os" - "strings" - "text/tabwriter" - - "github.com/urfave/cli" -) - -func createDNSHelp() cli.Command { - return cli.Command{ - Name: "dnshelp", - Usage: "Shows additional help for the '--dns' global option", - Action: dnsHelp, - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "code, c", - Usage: fmt.Sprintf("DNS code: %s", allDNSCodes()), - }, - }, - } -} - -func dnsHelp(ctx *cli.Context) error { - code := ctx.String("code") - if code == "" { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - ew := &errWriter{w: w} - - ew.writeln(`Credentials for DNS providers must be passed through environment variables.`) - ew.writeln() - ew.writeln(`To display the documentation for a DNS providers:`) - ew.writeln() - ew.writeln("\t$ lego dnshelp -c code") - ew.writeln() - ew.writeln("All DNS codes:") - ew.writef("\t%s\n", allDNSCodes()) - ew.writeln() - ew.writeln("More information: https://go-acme.github.io/lego/dns") - - if ew.err != nil { - return ew.err - } - - return w.Flush() - } - - return displayDNSHelp(strings.ToLower(code)) -} - -type errWriter struct { - w io.Writer - err error -} - -func (ew *errWriter) writeln(a ...interface{}) { - if ew.err != nil { - return - } - - _, ew.err = fmt.Fprintln(ew.w, a...) -} - -func (ew *errWriter) writef(format string, a ...interface{}) { - if ew.err != nil { - return - } - - _, ew.err = fmt.Fprintf(ew.w, format, a...) -} diff --git a/common/legocmd/cmd/cmd_list.go b/common/legocmd/cmd/cmd_list.go deleted file mode 100644 index 68fd0c7..0000000 --- a/common/legocmd/cmd/cmd_list.go +++ /dev/null @@ -1,136 +0,0 @@ -package cmd - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/url" - "path/filepath" - "strings" - - "github.com/go-acme/lego/v4/certcrypto" - "github.com/urfave/cli" -) - -func createList() cli.Command { - return cli.Command{ - Name: "list", - Usage: "Display certificates and accounts information.", - Action: list, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "accounts, a", - Usage: "Display accounts.", - }, - cli.BoolFlag{ - Name: "names, n", - Usage: "Display certificate common names only.", - }, - }, - } -} - -func list(ctx *cli.Context) error { - if ctx.Bool("accounts") && !ctx.Bool("names") { - if err := listAccount(ctx); err != nil { - return err - } - } - - return listCertificates(ctx) -} - -func listCertificates(ctx *cli.Context) error { - certsStorage := NewCertificatesStorage(ctx) - - matches, err := filepath.Glob(filepath.Join(certsStorage.GetRootPath(), "*.crt")) - if err != nil { - return err - } - - names := ctx.Bool("names") - - if len(matches) == 0 { - if !names { - fmt.Println("No certificates found.") - } - return nil - } - - if !names { - fmt.Println("Found the following certs:") - } - - for _, filename := range matches { - if strings.HasSuffix(filename, ".issuer.crt") { - continue - } - - data, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - - pCert, err := certcrypto.ParsePEMCertificate(data) - if err != nil { - return err - } - - if names { - fmt.Println(pCert.Subject.CommonName) - } else { - fmt.Println(" Certificate Name:", pCert.Subject.CommonName) - fmt.Println(" Domains:", strings.Join(pCert.DNSNames, ", ")) - fmt.Println(" Expiry Date:", pCert.NotAfter) - fmt.Println(" Certificate Path:", filename) - fmt.Println() - } - } - - return nil -} - -func listAccount(ctx *cli.Context) error { - // fake email, needed by NewAccountsStorage - if err := ctx.GlobalSet("email", "unknown"); err != nil { - return err - } - - accountsStorage := NewAccountsStorage(ctx) - - matches, err := filepath.Glob(filepath.Join(accountsStorage.GetRootPath(), "*", "*", "*.json")) - if err != nil { - return err - } - - if len(matches) == 0 { - fmt.Println("No accounts found.") - return nil - } - - fmt.Println("Found the following accounts:") - for _, filename := range matches { - data, err := ioutil.ReadFile(filename) - if err != nil { - return err - } - - var account Account - err = json.Unmarshal(data, &account) - if err != nil { - return err - } - - uri, err := url.Parse(account.Registration.URI) - if err != nil { - return err - } - - fmt.Println(" Email:", account.Email) - fmt.Println(" Server:", uri.Host) - fmt.Println(" Path:", filepath.Dir(filename)) - fmt.Println() - } - - return nil -} diff --git a/common/legocmd/cmd/cmd_renew.go b/common/legocmd/cmd/cmd_renew.go deleted file mode 100644 index ebb47f7..0000000 --- a/common/legocmd/cmd/cmd_renew.go +++ /dev/null @@ -1,226 +0,0 @@ -package cmd - -import ( - "crypto" - "crypto/x509" - "time" - - "github.com/go-acme/lego/v4/certcrypto" - "github.com/go-acme/lego/v4/certificate" - "github.com/go-acme/lego/v4/lego" - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -const ( - renewEnvAccountEmail = "LEGO_ACCOUNT_EMAIL" - renewEnvCertDomain = "LEGO_CERT_DOMAIN" - renewEnvCertPath = "LEGO_CERT_PATH" - renewEnvCertKeyPath = "LEGO_CERT_KEY_PATH" -) - -func createRenew() cli.Command { - return cli.Command{ - Name: "renew", - Usage: "Renew a certificate", - Action: renew, - Before: func(ctx *cli.Context) error { - // we require either domains or csr, but not both - hasDomains := len(ctx.GlobalStringSlice("domains")) > 0 - hasCsr := len(ctx.GlobalString("csr")) > 0 - if hasDomains && hasCsr { - log.Panic("Please specify either --domains/-d or --csr/-c, but not both") - } - if !hasDomains && !hasCsr { - log.Panic("Please specify --domains/-d (or --csr/-c if you already have a CSR)") - } - return nil - }, - Flags: []cli.Flag{ - cli.IntFlag{ - Name: "days", - Value: 30, - Usage: "The number of days left on a certificate to renew it.", - }, - cli.BoolFlag{ - Name: "reuse-key", - Usage: "Used to indicate you want to reuse your current private key for the new certificate.", - }, - cli.BoolFlag{ - Name: "no-bundle", - Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.", - }, - cli.BoolFlag{ - Name: "must-staple", - Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.", - }, - cli.StringFlag{ - Name: "renew-hook", - Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.", - }, - cli.StringFlag{ - Name: "preferred-chain", - 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.", - }, - }, - } -} - -func renew(ctx *cli.Context) error { - account, client := setup(ctx, NewAccountsStorage(ctx)) - setupChallenges(ctx, client) - - if account.Registration == nil { - log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", account.Email) - } - - certsStorage := NewCertificatesStorage(ctx) - - bundle := !ctx.Bool("no-bundle") - - meta := map[string]string{renewEnvAccountEmail: account.Email} - - // CSR - if ctx.GlobalIsSet("csr") { - return renewForCSR(ctx, client, certsStorage, bundle, meta) - } - - // Domains - return renewForDomains(ctx, client, certsStorage, bundle, meta) -} - -func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error { - domains := ctx.GlobalStringSlice("domains") - 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") - if err != nil { - log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err) - } - - cert := certificates[0] - - if !needRenewal(cert, domain, ctx.Int("days")) { - return nil - } - - // This is just meant to be informal for the user. - timeLeft := cert.NotAfter.Sub(time.Now().UTC()) - log.Infof("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours())) - - certDomains := certcrypto.ExtractDomains(cert) - - var privateKey crypto.PrivateKey - if ctx.Bool("reuse-key") { - keyBytes, errR := certsStorage.ReadFile(domain, ".key") - if errR != nil { - log.Panicf("Error while loading the private key for domain %s\n\t%v", domain, errR) - } - - privateKey, errR = certcrypto.ParsePEMPrivateKey(keyBytes) - if errR != nil { - return errR - } - } - - request := certificate.ObtainRequest{ - Domains: merge(certDomains, domains), - Bundle: bundle, - PrivateKey: privateKey, - MustStaple: ctx.Bool("must-staple"), - PreferredChain: ctx.String("preferred-chain"), - } - certRes, err := client.Certificate.Obtain(request) - if err != nil { - log.Panic(err) - } - - certsStorage.SaveResource(certRes) - - meta[renewEnvCertDomain] = domain - meta[renewEnvCertPath] = certsStorage.GetFileName(domain, ".crt") - meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, ".key") - - return launchHook(ctx.String("renew-hook"), meta) -} - -func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error { - csr, err := readCSRFile(ctx.GlobalString("csr")) - if err != nil { - log.Panic(err) - } - - domain := csr.Subject.CommonName - - // 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") - if err != nil { - log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err) - } - - cert := certificates[0] - - if !needRenewal(cert, domain, ctx.Int("days")) { - return nil - } - - // This is just meant to be informal for the user. - timeLeft := cert.NotAfter.Sub(time.Now().UTC()) - log.Infof("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours())) - - certRes, err := client.Certificate.ObtainForCSR(certificate.ObtainForCSRRequest{ - CSR: csr, - Bundle: bundle, - PreferredChain: ctx.String("preferred-chain"), - }) - if err != nil { - log.Panic(err) - } - - certsStorage.SaveResource(certRes) - - meta[renewEnvCertDomain] = domain - meta[renewEnvCertPath] = certsStorage.GetFileName(domain, ".crt") - meta[renewEnvCertKeyPath] = certsStorage.GetFileName(domain, ".key") - - return launchHook(ctx.String("renew-hook"), meta) -} - -func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool { - if x509Cert.IsCA { - log.Panicf("[%s] Certificate bundle starts with a CA certificate", domain) - } - - if days >= 0 { - notAfter := int(time.Until(x509Cert.NotAfter).Hours() / 24.0) - if notAfter > days { - log.Printf("[%s] The certificate expires in %d days, the number of days defined to perform the renewal is %d: no renewal.", - domain, notAfter, days) - return false - } - } - - return true -} - -func merge(prevDomains, nextDomains []string) []string { - for _, next := range nextDomains { - var found bool - for _, prev := range prevDomains { - if prev == next { - found = true - break - } - } - if !found { - prevDomains = append(prevDomains, next) - } - } - return prevDomains -} diff --git a/common/legocmd/cmd/cmd_revoke.go b/common/legocmd/cmd/cmd_revoke.go deleted file mode 100644 index 9e80b93..0000000 --- a/common/legocmd/cmd/cmd_revoke.go +++ /dev/null @@ -1,63 +0,0 @@ -package cmd - -import ( - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -func createRevoke() cli.Command { - return cli.Command{ - Name: "revoke", - Usage: "Revoke a certificate", - Action: revoke, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "keep, k", - Usage: "Keep the certificates after the revocation instead of archiving them.", - }, - }, - } -} - -func revoke(ctx *cli.Context) error { - acc, client := setup(ctx, NewAccountsStorage(ctx)) - - if acc.Registration == nil { - log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", acc.Email) - } - - certsStorage := NewCertificatesStorage(ctx) - certsStorage.CreateRootFolder() - - for _, domain := range ctx.GlobalStringSlice("domains") { - log.Printf("Trying to revoke certificate for domain %s", domain) - - certBytes, err := certsStorage.ReadFile(domain, ".crt") - if err != nil { - log.Panicf("Error while revoking the certificate for domain %s\n\t%v", domain, err) - } - - err = client.Certificate.Revoke(certBytes) - if err != nil { - log.Panicf("Error while revoking the certificate for domain %s\n\t%v", domain, err) - } - - log.Println("Certificate was revoked.") - - if ctx.Bool("keep") { - return nil - } - - certsStorage.CreateArchiveFolder() - - err = certsStorage.MoveToArchive(domain) - if err != nil { - return err - } - - log.Println("Certificate was archived for domain:", domain) - } - - return nil -} diff --git a/common/legocmd/cmd/cmd_run.go b/common/legocmd/cmd/cmd_run.go deleted file mode 100644 index 7193d79..0000000 --- a/common/legocmd/cmd/cmd_run.go +++ /dev/null @@ -1,187 +0,0 @@ -package cmd - -import ( - "bufio" - "fmt" - "os" - "strings" - - "github.com/go-acme/lego/v4/certificate" - "github.com/go-acme/lego/v4/lego" - "github.com/go-acme/lego/v4/registration" - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -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.GlobalStringSlice("domains")) > 0 - hasCsr := len(ctx.GlobalString("csr")) > 0 - if hasDomains && hasCsr { - log.Panic("Please specify either --domains/-d or --csr/-c, but not both") - } - if !hasDomains && !hasCsr { - log.Panic("Please specify --domains/-d (or --csr/-c if you already have a CSR)") - } - return nil - }, - Action: run, - Flags: []cli.Flag{ - cli.BoolFlag{ - Name: "no-bundle", - Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.", - }, - cli.BoolFlag{ - Name: "must-staple", - Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.", - }, - cli.StringFlag{ - Name: "run-hook", - Usage: "Define a hook. The hook is executed when the certificates are effectively created.", - }, - cli.StringFlag{ - Name: "preferred-chain", - 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.", - }, - }, - } -} - -const rootPathWarningMessage = `!!!! HEADS UP !!!! - -Your account credentials have been saved in your Let's Encrypt -configuration directory at "%s". - -You should make a secure backup of this folder now. This -configuration directory will also contain certificates and -private keys obtained from Let's Encrypt so making regular -backups of this folder is ideal. -` - -func run(ctx *cli.Context) error { - accountsStorage := NewAccountsStorage(ctx) - - account, client := setup(ctx, accountsStorage) - setupChallenges(ctx, client) - - if account.Registration == nil { - reg, err := register(ctx, client) - if err != nil { - log.Panicf("Could not complete registration\n\t%v", err) - } - - account.Registration = reg - if err = accountsStorage.Save(account); err != nil { - log.Panic(err) - } - - fmt.Printf(rootPathWarningMessage, accountsStorage.GetRootPath()) - } - - certsStorage := NewCertificatesStorage(ctx) - certsStorage.CreateRootFolder() - - cert, err := obtainCertificate(ctx, client) - if err != nil { - // Make sure to return a non-zero exit code if ObtainSANCertificate returned at least one error. - // Due to us not returning partial certificate we can just exit here instead of at the end. - log.Panicf("Could not obtain certificates:\n\t%v", err) - } - - certsStorage.SaveResource(cert) - - meta := map[string]string{ - renewEnvAccountEmail: account.Email, - renewEnvCertDomain: cert.Domain, - renewEnvCertPath: certsStorage.GetFileName(cert.Domain, ".crt"), - renewEnvCertKeyPath: certsStorage.GetFileName(cert.Domain, ".key"), - } - - return launchHook(ctx.String("run-hook"), meta) -} - -func handleTOS(ctx *cli.Context, client *lego.Client) bool { - // Check for a global accept override - if ctx.GlobalBool("accept-tos") { - return true - } - - reader := bufio.NewReader(os.Stdin) - log.Printf("Please review the TOS at %s", client.GetToSURL()) - - for { - fmt.Println("Do you accept the TOS? Y/n") - text, err := reader.ReadString('\n') - if err != nil { - log.Panicf("Could not read from console: %v", err) - } - - text = strings.Trim(text, "\r\n") - switch text { - case "", "y", "Y": - return true - case "n", "N": - return false - default: - fmt.Println("Your input was invalid. Please answer with one of Y/y, n/N or by pressing enter.") - } - } -} - -func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, error) { - accepted := handleTOS(ctx, client) - if !accepted { - log.Panic("You did not accept the TOS. Unable to proceed.") - } - - if ctx.GlobalBool("eab") { - kid := ctx.GlobalString("kid") - hmacEncoded := ctx.GlobalString("hmac") - - if kid == "" || hmacEncoded == "" { - log.Panicf("Requires arguments --kid and --hmac.") - } - - return client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{ - TermsOfServiceAgreed: accepted, - Kid: kid, - HmacEncoded: hmacEncoded, - }) - } - - return client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) -} - -func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Resource, error) { - bundle := !ctx.Bool("no-bundle") - - domains := ctx.GlobalStringSlice("domains") - 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"), - } - return client.Certificate.Obtain(request) - } - - // read the CSR - csr, err := readCSRFile(ctx.GlobalString("csr")) - if err != nil { - return nil, err - } - - // obtain a certificate for this CSR - return client.Certificate.ObtainForCSR(certificate.ObtainForCSRRequest{ - CSR: csr, - Bundle: bundle, - PreferredChain: ctx.String("preferred-chain"), - }) -} diff --git a/common/legocmd/cmd/flags.go b/common/legocmd/cmd/flags.go deleted file mode 100644 index 8307b2c..0000000 --- a/common/legocmd/cmd/flags.go +++ /dev/null @@ -1,120 +0,0 @@ -package cmd - -import ( - "github.com/go-acme/lego/v4/lego" - "github.com/urfave/cli" -) - -func CreateFlags(defaultPath string) []cli.Flag { - return []cli.Flag{ - cli.StringSliceFlag{ - Name: "domains, d", - Usage: "Add a domain to the process. Can be specified multiple times.", - }, - cli.StringFlag{ - Name: "server, s", - 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, 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, m", - Usage: "Email used for registration and recovery contact.", - }, - cli.StringFlag{ - Name: "csr, c", - Usage: "Certificate signing request filename, if an external CSR is to be used.", - }, - cli.BoolFlag{ - Name: "eab", - Usage: "Use External Account Binding for account registration. Requires --kid and --hmac.", - }, - cli.StringFlag{ - Name: "kid", - Usage: "Key identifier from External CA. Used for External Account Binding.", - }, - cli.StringFlag{ - Name: "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, k", - Value: "ec256", - Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384.", - }, - cli.StringFlag{ - Name: "filename", - Usage: "(deprecated) Filename of the generated certificate.", - }, - cli.StringFlag{ - Name: "path", - EnvVar: "LEGO_PATH", - Usage: "Directory to use for storing the data.", - Value: defaultPath, - }, - cli.BoolFlag{ - Name: "http", - Usage: "Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.", - }, - cli.StringFlag{ - Name: "http.port", - Usage: "Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port.", - Value: ":80", - }, - cli.StringFlag{ - Name: "http.proxy-header", - Usage: "Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy.", - Value: "Host", - }, - cli.StringFlag{ - Name: "http.webroot", - Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. 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", - Usage: "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.", - }, - cli.BoolFlag{ - Name: "tls", - Usage: "Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.", - }, - cli.StringFlag{ - Name: "tls.port", - Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port.", - Value: ":443", - }, - cli.StringFlag{ - Name: "dns", - Usage: "Solve a DNS 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", - Usage: "By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.", - }, - cli.StringSliceFlag{ - Name: "dns.resolvers", - Usage: "Set the resolvers to use for performing recursive DNS queries. 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", - Usage: "Set the HTTP timeout value to a specific value in seconds.", - }, - cli.IntFlag{ - Name: "dns-timeout", - Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries.", - Value: 10, - }, - cli.BoolFlag{ - Name: "pem", - Usage: "Generate a .pem file by concatenating the .key and .crt files together.", - }, - cli.IntFlag{ - Name: "cert.timeout", - Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.", - Value: 30, - }, - } -} diff --git a/common/legocmd/cmd/hook.go b/common/legocmd/cmd/hook.go deleted file mode 100644 index 0b0ca40..0000000 --- a/common/legocmd/cmd/hook.go +++ /dev/null @@ -1,47 +0,0 @@ -package cmd - -import ( - "context" - "errors" - "fmt" - "os" - "os/exec" - "strings" - "time" -) - -func launchHook(hook string, meta map[string]string) error { - if hook == "" { - return nil - } - - ctxCmd, cancel := context.WithTimeout(context.Background(), 120*time.Second) - defer cancel() - - parts := strings.Fields(hook) - - cmdCtx := exec.CommandContext(ctxCmd, parts[0], parts[1:]...) - cmdCtx.Env = append(os.Environ(), metaToEnv(meta)...) - - output, err := cmdCtx.CombinedOutput() - - if len(output) > 0 { - fmt.Println(string(output)) - } - - if errors.Is(ctxCmd.Err(), context.DeadlineExceeded) { - return errors.New("hook timed out") - } - - return err -} - -func metaToEnv(meta map[string]string) []string { - var envs []string - - for k, v := range meta { - envs = append(envs, k+"="+v) - } - - return envs -} diff --git a/common/legocmd/cmd/setup.go b/common/legocmd/cmd/setup.go deleted file mode 100644 index 9207e68..0000000 --- a/common/legocmd/cmd/setup.go +++ /dev/null @@ -1,130 +0,0 @@ -package cmd - -import ( - "crypto/x509" - "encoding/pem" - "fmt" - "io/ioutil" - "os" - "strings" - "time" - - "github.com/go-acme/lego/v4/certcrypto" - "github.com/go-acme/lego/v4/lego" - "github.com/go-acme/lego/v4/registration" - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -const filePerm os.FileMode = 0o600 - -func setup(ctx *cli.Context, accountsStorage *AccountsStorage) (*Account, *lego.Client) { - keyType := getKeyType(ctx) - privateKey := accountsStorage.GetPrivateKey(keyType) - - var account *Account - if accountsStorage.ExistsAccountFilePath() { - account = accountsStorage.LoadAccount(privateKey) - } else { - account = &Account{Email: accountsStorage.GetUserID(), key: privateKey} - } - - client := newClient(ctx, account, keyType) - - return account, client -} - -func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyType) *lego.Client { - config := lego.NewConfig(acc) - config.CADirURL = ctx.GlobalString("server") - - config.Certificate = lego.CertificateConfig{ - KeyType: keyType, - Timeout: time.Duration(ctx.GlobalInt("cert.timeout")) * time.Second, - } - config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version) - - if ctx.GlobalIsSet("http-timeout") { - config.HTTPClient.Timeout = time.Duration(ctx.GlobalInt("http-timeout")) * time.Second - } - - client, err := lego.NewClient(config) - if err != nil { - log.Panicf("Could not create client: %v", err) - } - - if client.GetExternalAccountRequired() && !ctx.GlobalIsSet("eab") { - log.Panic("Server requires External Account Binding. Use --eab with --kid and --hmac.") - } - - return client -} - -// getKeyType the type from which private keys should be generated. -func getKeyType(ctx *cli.Context) certcrypto.KeyType { - keyType := ctx.GlobalString("key-type") - switch strings.ToUpper(keyType) { - case "RSA2048": - return certcrypto.RSA2048 - case "RSA4096": - return certcrypto.RSA4096 - case "RSA8192": - return certcrypto.RSA8192 - case "EC256": - return certcrypto.EC256 - case "EC384": - return certcrypto.EC384 - } - - log.Panicf("Unsupported KeyType: %s", keyType) - return "" -} - -func getEmail(ctx *cli.Context) string { - email := ctx.GlobalString("email") - if email == "" { - log.Panic("You have to pass an account (email address) to the program using --email or -m") - } - return email -} - -func createNonExistingFolder(path string) error { - if _, err := os.Stat(path); os.IsNotExist(err) { - return os.MkdirAll(path, 0o700) - } else if err != nil { - return err - } - return nil -} - -func readCSRFile(filename string) (*x509.CertificateRequest, error) { - bytes, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - raw := bytes - - // see if we can find a PEM-encoded CSR - var p *pem.Block - rest := bytes - for { - // decode a PEM block - p, rest = pem.Decode(rest) - - // did we fail? - if p == nil { - break - } - - // did we get a CSR? - if p.Type == "CERTIFICATE REQUEST" { - raw = p.Bytes - } - } - - // no PEM-encoded CSR - // assume we were given a DER-encoded ASN.1 CSR - // (if this assumption is wrong, parsing these bytes will fail) - return x509.ParseCertificateRequest(raw) -} diff --git a/common/legocmd/cmd/setup_challenges.go b/common/legocmd/cmd/setup_challenges.go deleted file mode 100644 index b4003f1..0000000 --- a/common/legocmd/cmd/setup_challenges.go +++ /dev/null @@ -1,127 +0,0 @@ -package cmd - -import ( - "net" - "strings" - "time" - - "github.com/go-acme/lego/v4/challenge" - "github.com/go-acme/lego/v4/challenge/dns01" - "github.com/go-acme/lego/v4/challenge/http01" - "github.com/go-acme/lego/v4/challenge/tlsalpn01" - "github.com/go-acme/lego/v4/lego" - "github.com/go-acme/lego/v4/providers/dns" - "github.com/go-acme/lego/v4/providers/http/memcached" - "github.com/go-acme/lego/v4/providers/http/webroot" - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" -) - -func setupChallenges(ctx *cli.Context, client *lego.Client) { - if !ctx.GlobalBool("http") && !ctx.GlobalBool("tls") && !ctx.GlobalIsSet("dns") { - log.Panic("No challenge selected. You must specify at least one challenge: `--http`, `--tls`, `--dns`.") - } - - if ctx.GlobalBool("http") { - err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx)) - if err != nil { - log.Panic(err) - } - } - - if ctx.GlobalBool("tls") { - err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx)) - if err != nil { - log.Panic(err) - } - } - - if ctx.GlobalIsSet("dns") { - setupDNS(ctx, client) - } -} - -func setupHTTPProvider(ctx *cli.Context) challenge.Provider { - switch { - case ctx.GlobalIsSet("http.webroot"): - ps, err := webroot.NewHTTPProvider(ctx.GlobalString("http.webroot")) - if err != nil { - log.Panic(err) - } - return ps - case ctx.GlobalIsSet("http.memcached-host"): - ps, err := memcached.NewMemcachedProvider(ctx.GlobalStringSlice("http.memcached-host")) - if err != nil { - log.Panic(err) - } - return ps - case ctx.GlobalIsSet("http.port"): - iface := ctx.GlobalString("http.port") - if !strings.Contains(iface, ":") { - log.Panicf("The --http switch only accepts interface:port or :port for its argument.") - } - - host, port, err := net.SplitHostPort(iface) - if err != nil { - log.Panic(err) - } - - srv := http01.NewProviderServer(host, port) - if header := ctx.GlobalString("http.proxy-header"); header != "" { - srv.SetProxyHeader(header) - } - return srv - case ctx.GlobalBool("http"): - srv := http01.NewProviderServer("", "") - if header := ctx.GlobalString("http.proxy-header"); header != "" { - srv.SetProxyHeader(header) - } - return srv - default: - log.Panic("Invalid HTTP challenge options.") - return nil - } -} - -func setupTLSProvider(ctx *cli.Context) challenge.Provider { - switch { - case ctx.GlobalIsSet("tls.port"): - iface := ctx.GlobalString("tls.port") - if !strings.Contains(iface, ":") { - log.Panicf("The --tls switch only accepts interface:port or :port for its argument.") - } - - host, port, err := net.SplitHostPort(iface) - if err != nil { - log.Panic(err) - } - - return tlsalpn01.NewProviderServer(host, port) - case ctx.GlobalBool("tls"): - return tlsalpn01.NewProviderServer("", "") - default: - log.Panic("Invalid HTTP challenge options.") - return nil - } -} - -func setupDNS(ctx *cli.Context, client *lego.Client) { - provider, err := dns.NewDNSChallengeProviderByName(ctx.GlobalString("dns")) - if err != nil { - log.Panic(err) - } - - servers := ctx.GlobalStringSlice("dns.resolvers") - err = client.Challenge.SetDNS01Provider(provider, - dns01.CondOption(len(servers) > 0, - dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.GlobalStringSlice("dns.resolvers")))), - dns01.CondOption(ctx.GlobalBool("dns.disable-cp"), - dns01.DisableCompletePropagationRequirement()), - dns01.CondOption(ctx.GlobalIsSet("dns-timeout"), - dns01.AddDNSTimeout(time.Duration(ctx.GlobalInt("dns-timeout"))*time.Second)), - ) - if err != nil { - log.Panic(err) - } -} diff --git a/common/legocmd/cmd/zz_gen_cmd_dnshelp.go b/common/legocmd/cmd/zz_gen_cmd_dnshelp.go deleted file mode 100644 index 29db62c..0000000 --- a/common/legocmd/cmd/zz_gen_cmd_dnshelp.go +++ /dev/null @@ -1,1884 +0,0 @@ -package cmd - -// CODE GENERATED AUTOMATICALLY -// THIS FILE MUST NOT BE EDITED BY HAND - -import ( - "fmt" - "os" - "sort" - "strings" - "text/tabwriter" -) - -func allDNSCodes() string { - providers := []string{ - "manual", - "acme-dns", - "alidns", - "arvancloud", - "auroradns", - "autodns", - "azure", - "bindman", - "bluecat", - "checkdomain", - "clouddns", - "cloudflare", - "cloudns", - "cloudxns", - "conoha", - "constellix", - "desec", - "designate", - "digitalocean", - "dnsimple", - "dnsmadeeasy", - "dnspod", - "dode", - "domeneshop", - "dreamhost", - "duckdns", - "dyn", - "dynu", - "easydns", - "edgedns", - "exec", - "exoscale", - "gandi", - "gandiv5", - "gcloud", - "glesys", - "godaddy", - "hetzner", - "hostingde", - "httpreq", - "hurricane", - "hyperone", - "iij", - "infomaniak", - "inwx", - "ionos", - "joker", - "lightsail", - "linode", - "liquidweb", - "loopia", - "luadns", - "mydnsjp", - "mythicbeasts", - "namecheap", - "namedotcom", - "namesilo", - "netcup", - "netlify", - "nifcloud", - "njalla", - "ns1", - "oraclecloud", - "otc", - "ovh", - "pdns", - "rackspace", - "regru", - "rfc2136", - "rimuhosting", - "route53", - "sakuracloud", - "scaleway", - "selectel", - "servercow", - "stackpath", - "transip", - "vegadns", - "versio", - "vscale", - "vultr", - "yandex", - "zoneee", - "zonomi", - } - sort.Strings(providers) - return strings.Join(providers, ", ") -} - -func displayDNSHelp(name string) error { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) - ew := &errWriter{w: w} - - switch name { - case "acme-dns": - // generated from: providers/dns/acmedns/acmedns.toml - ew.writeln(`Configuration for Joohoi's ACME-DNS.`) - ew.writeln(`Code: 'acme-dns'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "ACME_DNS_API_BASE": The ACME-DNS API address`) - ew.writeln(` - "ACME_DNS_STORAGE_PATH": The ACME-DNS JSON account data file. A per-domain account will be registered/persisted to this file and used for TXT updates.`) - ew.writeln() - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/acme-dns`) - - case "alidns": - // generated from: providers/dns/alidns/alidns.toml - ew.writeln(`Configuration for Alibaba Cloud DNS.`) - ew.writeln(`Code: 'alidns'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "ALICLOUD_ACCESS_KEY": Access key ID`) - ew.writeln(` - "ALICLOUD_SECRET_KEY": Access Key secret`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "ALICLOUD_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "ALICLOUD_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "ALICLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "ALICLOUD_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/alidns`) - - case "arvancloud": - // generated from: providers/dns/arvancloud/arvancloud.toml - ew.writeln(`Configuration for ArvanCloud.`) - ew.writeln(`Code: 'arvancloud'`) - ew.writeln(`Since: 'v3.8.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "ARVANCLOUD_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "ARVANCLOUD_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "ARVANCLOUD_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "ARVANCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "ARVANCLOUD_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "ARVANCLOUD_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/arvancloud`) - - case "auroradns": - // generated from: providers/dns/auroradns/auroradns.toml - ew.writeln(`Configuration for Aurora DNS.`) - ew.writeln(`Code: 'auroradns'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AURORA_KEY": User API key`) - ew.writeln(` - "AURORA_USER_ID": User ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "AURORA_ENDPOINT": API endpoint URL`) - ew.writeln(` - "AURORA_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "AURORA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "AURORA_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/auroradns`) - - case "autodns": - // generated from: providers/dns/autodns/autodns.toml - ew.writeln(`Configuration for Autodns.`) - ew.writeln(`Code: 'autodns'`) - ew.writeln(`Since: 'v3.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AUTODNS_API_PASSWORD": User Password`) - ew.writeln(` - "AUTODNS_API_USER": Username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "AUTODNS_CONTEXT": API context (4 for production, 1 for testing. Defaults to 4)`) - ew.writeln(` - "AUTODNS_ENDPOINT": API endpoint URL, defaults to https://api.autodns.com/v1/`) - ew.writeln(` - "AUTODNS_HTTP_TIMEOUT": API request timeout, defaults to 30 seconds`) - ew.writeln(` - "AUTODNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "AUTODNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "AUTODNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/autodns`) - - case "azure": - // generated from: providers/dns/azure/azure.toml - ew.writeln(`Configuration for Azure.`) - ew.writeln(`Code: 'azure'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AZURE_CLIENT_ID": Client ID`) - ew.writeln(` - "AZURE_CLIENT_SECRET": Client secret`) - ew.writeln(` - "AZURE_ENVIRONMENT": Azure environment, one of: public, usgovernment, german, and china`) - ew.writeln(` - "AZURE_RESOURCE_GROUP": Resource group`) - ew.writeln(` - "AZURE_SUBSCRIPTION_ID": Subscription ID`) - ew.writeln(` - "AZURE_TENANT_ID": Tenant ID`) - ew.writeln(` - "instance metadata service": If the credentials are **not** set via the environment, then it will attempt to get a bearer token via the [instance metadata service](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service).`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "AZURE_METADATA_ENDPOINT": Metadata Service endpoint URL`) - ew.writeln(` - "AZURE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "AZURE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "AZURE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/azure`) - - case "bindman": - // generated from: providers/dns/bindman/bindman.toml - ew.writeln(`Configuration for Bindman.`) - ew.writeln(`Code: 'bindman'`) - ew.writeln(`Since: 'v2.6.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "BINDMAN_MANAGER_ADDRESS": The server URL, should have scheme, hostname, and port (if required) of the Bindman-DNS Manager server`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "BINDMAN_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "BINDMAN_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "BINDMAN_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/bindman`) - - case "bluecat": - // generated from: providers/dns/bluecat/bluecat.toml - ew.writeln(`Configuration for Bluecat.`) - ew.writeln(`Code: 'bluecat'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "BLUECAT_CONFIG_NAME": Configuration name`) - ew.writeln(` - "BLUECAT_DNS_VIEW": External DNS View Name`) - ew.writeln(` - "BLUECAT_PASSWORD": API password`) - ew.writeln(` - "BLUECAT_SERVER_URL": The server URL, should have scheme, hostname, and port (if required) of the authoritative Bluecat BAM serve`) - ew.writeln(` - "BLUECAT_USER_NAME": API username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "BLUECAT_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "BLUECAT_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "BLUECAT_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "BLUECAT_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/bluecat`) - - case "checkdomain": - // generated from: providers/dns/checkdomain/checkdomain.toml - ew.writeln(`Configuration for Checkdomain.`) - ew.writeln(`Code: 'checkdomain'`) - ew.writeln(`Since: 'v3.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CHECKDOMAIN_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CHECKDOMAIN_ENDPOINT": API endpoint URL, defaults to https://api.checkdomain.de`) - ew.writeln(` - "CHECKDOMAIN_HTTP_TIMEOUT": API request timeout, defaults to 30 seconds`) - ew.writeln(` - "CHECKDOMAIN_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CHECKDOMAIN_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CHECKDOMAIN_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/checkdomain`) - - case "clouddns": - // generated from: providers/dns/clouddns/clouddns.toml - ew.writeln(`Configuration for CloudDNS.`) - ew.writeln(`Code: 'clouddns'`) - ew.writeln(`Since: 'v3.6.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CLOUDDNS_CLIENT_ID": Client ID`) - ew.writeln(` - "CLOUDDNS_EMAIL": Account email`) - ew.writeln(` - "CLOUDDNS_PASSWORD": Account password`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CLOUDDNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CLOUDDNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CLOUDDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CLOUDDNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/clouddns`) - - case "cloudflare": - // generated from: providers/dns/cloudflare/cloudflare.toml - ew.writeln(`Configuration for Cloudflare.`) - ew.writeln(`Code: 'cloudflare'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CF_API_EMAIL": Account email`) - ew.writeln(` - "CF_API_KEY": API key`) - ew.writeln(` - "CF_DNS_API_TOKEN": API token with DNS:Edit permission (since v3.1.0)`) - ew.writeln(` - "CF_ZONE_API_TOKEN": API token with Zone:Read permission (since v3.1.0)`) - ew.writeln(` - "CLOUDFLARE_API_KEY": Alias to CF_API_KEY`) - ew.writeln(` - "CLOUDFLARE_DNS_API_TOKEN": Alias to CF_DNS_API_TOKEN`) - ew.writeln(` - "CLOUDFLARE_EMAIL": Alias to CF_API_EMAIL`) - ew.writeln(` - "CLOUDFLARE_ZONE_API_TOKEN": Alias to CF_ZONE_API_TOKEN`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CLOUDFLARE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CLOUDFLARE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CLOUDFLARE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CLOUDFLARE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/cloudflare`) - - case "cloudns": - // generated from: providers/dns/cloudns/cloudns.toml - ew.writeln(`Configuration for ClouDNS.`) - ew.writeln(`Code: 'cloudns'`) - ew.writeln(`Since: 'v2.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CLOUDNS_AUTH_ID": The API user ID`) - ew.writeln(` - "CLOUDNS_AUTH_PASSWORD": The password for API user ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CLOUDNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CLOUDNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CLOUDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CLOUDNS_SUB_AUTH_ID": The API sub user ID`) - ew.writeln(` - "CLOUDNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/cloudns`) - - case "cloudxns": - // generated from: providers/dns/cloudxns/cloudxns.toml - ew.writeln(`Configuration for CloudXNS.`) - ew.writeln(`Code: 'cloudxns'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CLOUDXNS_API_KEY": The API key`) - ew.writeln(` - "CLOUDXNS_SECRET_KEY": The API secret key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CLOUDXNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CLOUDXNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CLOUDXNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CLOUDXNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/cloudxns`) - - case "conoha": - // generated from: providers/dns/conoha/conoha.toml - ew.writeln(`Configuration for ConoHa.`) - ew.writeln(`Code: 'conoha'`) - ew.writeln(`Since: 'v1.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CONOHA_API_PASSWORD": The API password`) - ew.writeln(` - "CONOHA_API_USERNAME": The API username`) - ew.writeln(` - "CONOHA_TENANT_ID": Tenant ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CONOHA_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CONOHA_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CONOHA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CONOHA_REGION": The region`) - ew.writeln(` - "CONOHA_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/conoha`) - - case "constellix": - // generated from: providers/dns/constellix/constellix.toml - ew.writeln(`Configuration for Constellix.`) - ew.writeln(`Code: 'constellix'`) - ew.writeln(`Since: 'v3.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "CONSTELLIX_API_KEY": User API key`) - ew.writeln(` - "CONSTELLIX_SECRET_KEY": User secret key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "CONSTELLIX_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "CONSTELLIX_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "CONSTELLIX_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "CONSTELLIX_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/constellix`) - - case "desec": - // generated from: providers/dns/desec/desec.toml - ew.writeln(`Configuration for deSEC.io.`) - ew.writeln(`Code: 'desec'`) - ew.writeln(`Since: 'v3.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DESEC_TOKEN": Domain token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DESEC_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DESEC_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DESEC_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DESEC_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/desec`) - - case "designate": - // generated from: providers/dns/designate/designate.toml - ew.writeln(`Configuration for Designate DNSaaS for Openstack.`) - ew.writeln(`Code: 'designate'`) - ew.writeln(`Since: 'v2.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "OS_APPLICATION_CREDENTIAL_ID": Application credential ID`) - ew.writeln(` - "OS_APPLICATION_CREDENTIAL_NAME": Application credential name`) - ew.writeln(` - "OS_APPLICATION_CREDENTIAL_SECRET": Application credential secret`) - ew.writeln(` - "OS_AUTH_URL": Identity endpoint URL`) - ew.writeln(` - "OS_PASSWORD": Password`) - ew.writeln(` - "OS_PROJECT_NAME": Project name`) - ew.writeln(` - "OS_REGION_NAME": Region name`) - ew.writeln(` - "OS_USERNAME": Username`) - ew.writeln(` - "OS_USER_ID": User ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DESIGNATE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DESIGNATE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DESIGNATE_TTL": The TTL of the TXT record used for the DNS challenge`) - ew.writeln(` - "OS_PROJECT_ID": Project ID`) - ew.writeln(` - "OS_TENANT_NAME": Tenant name (deprecated see OS_PROJECT_NAME and OS_PROJECT_ID)`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/designate`) - - case "digitalocean": - // generated from: providers/dns/digitalocean/digitalocean.toml - ew.writeln(`Configuration for Digital Ocean.`) - ew.writeln(`Code: 'digitalocean'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DO_AUTH_TOKEN": Authentication token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DO_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DO_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DO_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/digitalocean`) - - case "dnsimple": - // generated from: providers/dns/dnsimple/dnsimple.toml - ew.writeln(`Configuration for DNSimple.`) - ew.writeln(`Code: 'dnsimple'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DNSIMPLE_OAUTH_TOKEN": OAuth token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DNSIMPLE_BASE_URL": API endpoint URL`) - ew.writeln(` - "DNSIMPLE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DNSIMPLE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DNSIMPLE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dnsimple`) - - case "dnsmadeeasy": - // generated from: providers/dns/dnsmadeeasy/dnsmadeeasy.toml - ew.writeln(`Configuration for DNS Made Easy.`) - ew.writeln(`Code: 'dnsmadeeasy'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DNSMADEEASY_API_KEY": The API key`) - ew.writeln(` - "DNSMADEEASY_API_SECRET": The API Secret key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DNSMADEEASY_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DNSMADEEASY_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DNSMADEEASY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DNSMADEEASY_SANDBOX": Activate the sandbox (boolean)`) - ew.writeln(` - "DNSMADEEASY_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dnsmadeeasy`) - - case "dnspod": - // generated from: providers/dns/dnspod/dnspod.toml - ew.writeln(`Configuration for DNSPod.`) - ew.writeln(`Code: 'dnspod'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DNSPOD_API_KEY": The user token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DNSPOD_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DNSPOD_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DNSPOD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DNSPOD_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dnspod`) - - case "dode": - // generated from: providers/dns/dode/dode.toml - ew.writeln(`Configuration for Domain Offensive (do.de).`) - ew.writeln(`Code: 'dode'`) - ew.writeln(`Since: 'v2.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DODE_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DODE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DODE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DODE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DODE_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "DODE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dode`) - - case "domeneshop": - // generated from: providers/dns/domeneshop/domeneshop.toml - ew.writeln(`Configuration for Domeneshop.`) - ew.writeln(`Code: 'domeneshop'`) - ew.writeln(`Since: 'v4.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DOMENESHOP_API_PASSWORD": API secret`) - ew.writeln(` - "DOMENESHOP_API_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DOMENESHOP_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DOMENESHOP_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DOMENESHOP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/domeneshop`) - - case "dreamhost": - // generated from: providers/dns/dreamhost/dreamhost.toml - ew.writeln(`Configuration for DreamHost.`) - ew.writeln(`Code: 'dreamhost'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DREAMHOST_API_KEY": The API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DREAMHOST_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DREAMHOST_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DREAMHOST_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DREAMHOST_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dreamhost`) - - case "duckdns": - // generated from: providers/dns/duckdns/duckdns.toml - ew.writeln(`Configuration for Duck DNS.`) - ew.writeln(`Code: 'duckdns'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DUCKDNS_TOKEN": Account token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DUCKDNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DUCKDNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DUCKDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DUCKDNS_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "DUCKDNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/duckdns`) - - case "dyn": - // generated from: providers/dns/dyn/dyn.toml - ew.writeln(`Configuration for Dyn.`) - ew.writeln(`Code: 'dyn'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DYN_CUSTOMER_NAME": Customer name`) - ew.writeln(` - "DYN_PASSWORD": Password`) - ew.writeln(` - "DYN_USER_NAME": User name`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DYN_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DYN_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DYN_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DYN_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dyn`) - - case "dynu": - // generated from: providers/dns/dynu/dynu.toml - ew.writeln(`Configuration for Dynu.`) - ew.writeln(`Code: 'dynu'`) - ew.writeln(`Since: 'v3.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "DYNU_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "DYNU_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "DYNU_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "DYNU_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "DYNU_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/dynu`) - - case "easydns": - // generated from: providers/dns/easydns/easydns.toml - ew.writeln(`Configuration for EasyDNS.`) - ew.writeln(`Code: 'easydns'`) - ew.writeln(`Since: 'v2.6.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "EASYDNS_KEY": API Key`) - ew.writeln(` - "EASYDNS_TOKEN": API Token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "EASYDNS_ENDPOINT": The endpoint URL of the API Server`) - ew.writeln(` - "EASYDNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "EASYDNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "EASYDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "EASYDNS_SEQUENCE_INTERVAL": Time between sequential requests`) - ew.writeln(` - "EASYDNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/easydns`) - - case "edgedns": - // generated from: providers/dns/edgedns/edgedns.toml - ew.writeln(`Configuration for Akamai EdgeDNS.`) - ew.writeln(`Code: 'edgedns'`) - ew.writeln(`Since: 'v3.9.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AKAMAI_ACCESS_TOKEN": Access token, managed by the Akamai EdgeGrid client`) - ew.writeln(` - "AKAMAI_CLIENT_SECRET": Client secret, managed by the Akamai EdgeGrid client`) - ew.writeln(` - "AKAMAI_CLIENT_TOKEN": Client token, managed by the Akamai EdgeGrid client`) - ew.writeln(` - "AKAMAI_EDGERC": Path to the .edgerc file, managed by the Akamai EdgeGrid client`) - ew.writeln(` - "AKAMAI_EDGERC_SECTION": Configuration section, managed by the Akamai EdgeGrid client`) - ew.writeln(` - "AKAMAI_HOST": API host, managed by the Akamai EdgeGrid client`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "AKAMAI_POLLING_INTERVAL": Time between DNS propagation check. Default: 15 seconds`) - ew.writeln(` - "AKAMAI_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation. Default: 3 minutes`) - ew.writeln(` - "AKAMAI_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/edgedns`) - - case "exec": - // generated from: providers/dns/exec/exec.toml - ew.writeln(`Configuration for External program.`) - ew.writeln(`Code: 'exec'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/exec`) - - case "exoscale": - // generated from: providers/dns/exoscale/exoscale.toml - ew.writeln(`Configuration for Exoscale.`) - ew.writeln(`Code: 'exoscale'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "EXOSCALE_API_KEY": API key`) - ew.writeln(` - "EXOSCALE_API_SECRET": API secret`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "EXOSCALE_ENDPOINT": API endpoint URL`) - ew.writeln(` - "EXOSCALE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "EXOSCALE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "EXOSCALE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "EXOSCALE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/exoscale`) - - case "gandi": - // generated from: providers/dns/gandi/gandi.toml - ew.writeln(`Configuration for Gandi.`) - ew.writeln(`Code: 'gandi'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "GANDI_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "GANDI_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "GANDI_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "GANDI_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "GANDI_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/gandi`) - - case "gandiv5": - // generated from: providers/dns/gandiv5/gandiv5.toml - ew.writeln(`Configuration for Gandi Live DNS (v5).`) - ew.writeln(`Code: 'gandiv5'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "GANDIV5_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "GANDIV5_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "GANDIV5_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "GANDIV5_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "GANDIV5_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/gandiv5`) - - case "gcloud": - // generated from: providers/dns/gcloud/gcloud.toml - ew.writeln(`Configuration for Google Cloud.`) - ew.writeln(`Code: 'gcloud'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "Application Default Credentials": [Documentation](https://cloud.google.com/docs/authentication/production#providing_credentials_to_your_application)`) - ew.writeln(` - "GCE_PROJECT": Project name (by default, the project name is auto-detected by using the metadata service)`) - ew.writeln(` - "GCE_SERVICE_ACCOUNT": Account`) - ew.writeln(` - "GCE_SERVICE_ACCOUNT_FILE": Account file path`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "GCE_ALLOW_PRIVATE_ZONE": Allows requested domain to be in private DNS zone, works only with a private ACME server (by default: false)`) - ew.writeln(` - "GCE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "GCE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "GCE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/gcloud`) - - case "glesys": - // generated from: providers/dns/glesys/glesys.toml - ew.writeln(`Configuration for Glesys.`) - ew.writeln(`Code: 'glesys'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "GLESYS_API_KEY": API key`) - ew.writeln(` - "GLESYS_API_USER": API user`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "GLESYS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "GLESYS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "GLESYS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "GLESYS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/glesys`) - - case "godaddy": - // generated from: providers/dns/godaddy/godaddy.toml - ew.writeln(`Configuration for Go Daddy.`) - ew.writeln(`Code: 'godaddy'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "GODADDY_API_KEY": API key`) - ew.writeln(` - "GODADDY_API_SECRET": API secret`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "GODADDY_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "GODADDY_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "GODADDY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "GODADDY_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "GODADDY_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/godaddy`) - - case "hetzner": - // generated from: providers/dns/hetzner/hetzner.toml - ew.writeln(`Configuration for Hetzner.`) - ew.writeln(`Code: 'hetzner'`) - ew.writeln(`Since: 'v3.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "HETZNER_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "HETZNER_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "HETZNER_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "HETZNER_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "HETZNER_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "HETZNER_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/hetzner`) - - case "hostingde": - // generated from: providers/dns/hostingde/hostingde.toml - ew.writeln(`Configuration for Hosting.de.`) - ew.writeln(`Code: 'hostingde'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "HOSTINGDE_API_KEY": API key`) - ew.writeln(` - "HOSTINGDE_ZONE_NAME": Zone name in ACE format`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "HOSTINGDE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "HOSTINGDE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "HOSTINGDE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "HOSTINGDE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/hostingde`) - - case "httpreq": - // generated from: providers/dns/httpreq/httpreq.toml - ew.writeln(`Configuration for HTTP request.`) - ew.writeln(`Code: 'httpreq'`) - ew.writeln(`Since: 'v2.0.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "HTTPREQ_ENDPOINT": The URL of the server`) - ew.writeln(` - "HTTPREQ_MODE": 'RAW', none`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "HTTPREQ_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "HTTPREQ_PASSWORD": Basic authentication password`) - ew.writeln(` - "HTTPREQ_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "HTTPREQ_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "HTTPREQ_USERNAME": Basic authentication username`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/httpreq`) - - case "hurricane": - // generated from: providers/dns/hurricane/hurricane.toml - ew.writeln(`Configuration for Hurricane Electric DNS.`) - ew.writeln(`Code: 'hurricane'`) - ew.writeln(`Since: 'v4.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "HURRICANE_TOKENS": TXT record names and tokens`) - ew.writeln() - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/hurricane`) - - case "hyperone": - // generated from: providers/dns/hyperone/hyperone.toml - ew.writeln(`Configuration for HyperOne.`) - ew.writeln(`Code: 'hyperone'`) - ew.writeln(`Since: 'v3.9.0'`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "HYPERONE_API_URL": Allows to pass custom API Endpoint to be used in the challenge (default https://api.hyperone.com/v2)`) - ew.writeln(` - "HYPERONE_LOCATION_ID": Specifies location (region) to be used in API calls. (default pl-waw-1)`) - ew.writeln(` - "HYPERONE_PASSPORT_LOCATION": Allows to pass custom passport file location (default ~/.h1/passport.json)`) - ew.writeln(` - "HYPERONE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "HYPERONE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "HYPERONE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/hyperone`) - - case "iij": - // generated from: providers/dns/iij/iij.toml - ew.writeln(`Configuration for Internet Initiative Japan.`) - ew.writeln(`Code: 'iij'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "IIJ_API_ACCESS_KEY": API access key`) - ew.writeln(` - "IIJ_API_SECRET_KEY": API secret key`) - ew.writeln(` - "IIJ_DO_SERVICE_CODE": DO service code`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "IIJ_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "IIJ_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "IIJ_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/iij`) - - case "infomaniak": - // generated from: providers/dns/infomaniak/infomaniak.toml - ew.writeln(`Configuration for Infomaniak.`) - ew.writeln(`Code: 'infomaniak'`) - ew.writeln(`Since: 'v4.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "INFOMANIAK_ACCESS_TOKEN": Access token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "INFOMANIAK_ENDPOINT": https://api.infomaniak.com`) - ew.writeln(` - "INFOMANIAK_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "INFOMANIAK_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "INFOMANIAK_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "INFOMANIAK_TTL": The TTL of the TXT record used for the DNS challenge in seconds`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/infomaniak`) - - case "inwx": - // generated from: providers/dns/inwx/inwx.toml - ew.writeln(`Configuration for INWX.`) - ew.writeln(`Code: 'inwx'`) - ew.writeln(`Since: 'v2.0.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "INWX_PASSWORD": Password`) - ew.writeln(` - "INWX_USERNAME": Username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "INWX_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "INWX_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation (default 360s)`) - ew.writeln(` - "INWX_SANDBOX": Activate the sandbox (boolean)`) - ew.writeln(` - "INWX_SHARED_SECRET": shared secret related to 2FA`) - ew.writeln(` - "INWX_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/inwx`) - - case "ionos": - // generated from: providers/dns/ionos/ionos.toml - ew.writeln(`Configuration for Ionos.`) - ew.writeln(`Code: 'ionos'`) - ew.writeln(`Since: 'v4.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "IONOS_API_KEY": API key '.' https://developer.hosting.ionos.com/docs/getstarted`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "IONOS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "IONOS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "IONOS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "IONOS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/ionos`) - - case "joker": - // generated from: providers/dns/joker/joker.toml - ew.writeln(`Configuration for Joker.`) - ew.writeln(`Code: 'joker'`) - ew.writeln(`Since: 'v2.6.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "JOKER_API_KEY": API key (only with DMAPI mode)`) - ew.writeln(` - "JOKER_API_MODE": 'DMAPI' or 'SVC'. DMAPI is for resellers accounts. (Default: DMAPI)`) - ew.writeln(` - "JOKER_PASSWORD": Joker.com password`) - ew.writeln(` - "JOKER_USERNAME": Joker.com username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "JOKER_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "JOKER_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "JOKER_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "JOKER_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/joker`) - - case "lightsail": - // generated from: providers/dns/lightsail/lightsail.toml - ew.writeln(`Configuration for Amazon Lightsail.`) - ew.writeln(`Code: 'lightsail'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AWS_ACCESS_KEY_ID": Access key ID`) - ew.writeln(` - "AWS_SECRET_ACCESS_KEY": Secret access key`) - ew.writeln(` - "DNS_ZONE": DNS zone`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "LIGHTSAIL_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "LIGHTSAIL_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/lightsail`) - - case "linode": - // generated from: providers/dns/linode/linode.toml - ew.writeln(`Configuration for Linode (v4).`) - ew.writeln(`Code: 'linode'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "LINODE_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "LINODE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "LINODE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "LINODE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "LINODE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/linode`) - - case "liquidweb": - // generated from: providers/dns/liquidweb/liquidweb.toml - ew.writeln(`Configuration for Liquid Web.`) - ew.writeln(`Code: 'liquidweb'`) - ew.writeln(`Since: 'v3.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "LIQUID_WEB_PASSWORD": Storm API Password`) - ew.writeln(` - "LIQUID_WEB_USERNAME": Storm API Username`) - ew.writeln(` - "LIQUID_WEB_ZONE": DNS Zone`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "LIQUID_WEB_HTTP_TIMEOUT": Maximum waiting time for the DNS records to be created (not verified)`) - ew.writeln(` - "LIQUID_WEB_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "LIQUID_WEB_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "LIQUID_WEB_TTL": The TTL of the TXT record used for the DNS challenge`) - ew.writeln(` - "LIQUID_WEB_URL": Storm API endpoint`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/liquidweb`) - - case "loopia": - // generated from: providers/dns/loopia/loopia.toml - ew.writeln(`Configuration for Loopia.`) - ew.writeln(`Code: 'loopia'`) - ew.writeln(`Since: 'v4.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "LOOPIA_API_PASSWORD": API password`) - ew.writeln(` - "LOOPIA_API_USER": API username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "LOOPIA_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "LOOPIA_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "LOOPIA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "LOOPIA_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/loopia`) - - case "luadns": - // generated from: providers/dns/luadns/luadns.toml - ew.writeln(`Configuration for LuaDNS.`) - ew.writeln(`Code: 'luadns'`) - ew.writeln(`Since: 'v3.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "LUADNS_API_TOKEN": API token`) - ew.writeln(` - "LUADNS_API_USERNAME": Username (your email)`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "LUADNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "LUADNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "LUADNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "LUADNS_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "LUADNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/luadns`) - - case "mydnsjp": - // generated from: providers/dns/mydnsjp/mydnsjp.toml - ew.writeln(`Configuration for MyDNS.jp.`) - ew.writeln(`Code: 'mydnsjp'`) - ew.writeln(`Since: 'v1.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "MYDNSJP_MASTER_ID": Master ID`) - ew.writeln(` - "MYDNSJP_PASSWORD": Password`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "MYDNSJP_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "MYDNSJP_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "MYDNSJP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "MYDNSJP_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/mydnsjp`) - - case "mythicbeasts": - // generated from: providers/dns/mythicbeasts/mythicbeasts.toml - ew.writeln(`Configuration for MythicBeasts.`) - ew.writeln(`Code: 'mythicbeasts'`) - ew.writeln(`Since: 'v0.3.7'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "MYTHICBEASTS_PASSWORD": Password`) - ew.writeln(` - "MYTHICBEASTS_USERNAME": User name`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "MYTHICBEASTS_API_ENDPOINT": The endpoint for the API (must implement v2)`) - ew.writeln(` - "MYTHICBEASTS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "MYTHICBEASTS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "MYTHICBEASTS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "MYTHICBEASTS_TTL": The TTL of the TXT record used for the DNS challenge`) - ew.writeln(` - "MYTHICBEASYS_AUTH_API_ENDPOINT": The endpoint for Mythic Beasts' Authentication`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/mythicbeasts`) - - case "namecheap": - // generated from: providers/dns/namecheap/namecheap.toml - ew.writeln(`Configuration for Namecheap.`) - ew.writeln(`Code: 'namecheap'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NAMECHEAP_API_KEY": API key`) - ew.writeln(` - "NAMECHEAP_API_USER": API user`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NAMECHEAP_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NAMECHEAP_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NAMECHEAP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NAMECHEAP_SANDBOX": Activate the sandbox (boolean)`) - ew.writeln(` - "NAMECHEAP_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/namecheap`) - - case "namedotcom": - // generated from: providers/dns/namedotcom/namedotcom.toml - ew.writeln(`Configuration for Name.com.`) - ew.writeln(`Code: 'namedotcom'`) - ew.writeln(`Since: 'v0.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NAMECOM_API_TOKEN": API token`) - ew.writeln(` - "NAMECOM_USERNAME": Username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NAMECOM_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NAMECOM_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NAMECOM_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NAMECOM_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/namedotcom`) - - case "namesilo": - // generated from: providers/dns/namesilo/namesilo.toml - ew.writeln(`Configuration for Namesilo.`) - ew.writeln(`Code: 'namesilo'`) - ew.writeln(`Since: 'v2.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NAMESILO_API_KEY": Client ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NAMESILO_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NAMESILO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation, it is better to set larger than 15m`) - ew.writeln(` - "NAMESILO_TTL": The TTL of the TXT record used for the DNS challenge, should be in [3600, 2592000]`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/namesilo`) - - case "netcup": - // generated from: providers/dns/netcup/netcup.toml - ew.writeln(`Configuration for Netcup.`) - ew.writeln(`Code: 'netcup'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NETCUP_API_KEY": API key`) - ew.writeln(` - "NETCUP_API_PASSWORD": API password`) - ew.writeln(` - "NETCUP_CUSTOMER_NUMBER": Customer number`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NETCUP_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NETCUP_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NETCUP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NETCUP_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/netcup`) - - case "netlify": - // generated from: providers/dns/netlify/netlify.toml - ew.writeln(`Configuration for Netlify.`) - ew.writeln(`Code: 'netlify'`) - ew.writeln(`Since: 'v3.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NETLIFY_TOKEN": Token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NETLIFY_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NETLIFY_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NETLIFY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NETLIFY_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/netlify`) - - case "nifcloud": - // generated from: providers/dns/nifcloud/nifcloud.toml - ew.writeln(`Configuration for NIFCloud.`) - ew.writeln(`Code: 'nifcloud'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NIFCLOUD_ACCESS_KEY_ID": Access key`) - ew.writeln(` - "NIFCLOUD_SECRET_ACCESS_KEY": Secret access key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NIFCLOUD_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NIFCLOUD_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NIFCLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NIFCLOUD_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/nifcloud`) - - case "njalla": - // generated from: providers/dns/njalla/njalla.toml - ew.writeln(`Configuration for Njalla.`) - ew.writeln(`Code: 'njalla'`) - ew.writeln(`Since: 'v4.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NJALLA_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NJALLA_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NJALLA_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NJALLA_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NJALLA_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/njalla`) - - case "ns1": - // generated from: providers/dns/ns1/ns1.toml - ew.writeln(`Configuration for NS1.`) - ew.writeln(`Code: 'ns1'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "NS1_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "NS1_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "NS1_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "NS1_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "NS1_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/ns1`) - - case "oraclecloud": - // generated from: providers/dns/oraclecloud/oraclecloud.toml - ew.writeln(`Configuration for Oracle Cloud.`) - ew.writeln(`Code: 'oraclecloud'`) - ew.writeln(`Since: 'v2.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "OCI_COMPARTMENT_OCID": Compartment OCID`) - ew.writeln(` - "OCI_PRIVKEY_FILE": Private key file`) - ew.writeln(` - "OCI_PRIVKEY_PASS": Private key password`) - ew.writeln(` - "OCI_PUBKEY_FINGERPRINT": Public key fingerprint`) - ew.writeln(` - "OCI_REGION": Region`) - ew.writeln(` - "OCI_TENANCY_OCID": Tenancy OCID`) - ew.writeln(` - "OCI_USER_OCID": User OCID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "OCI_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "OCI_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "OCI_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/oraclecloud`) - - case "otc": - // generated from: providers/dns/otc/otc.toml - ew.writeln(`Configuration for Open Telekom Cloud.`) - ew.writeln(`Code: 'otc'`) - ew.writeln(`Since: 'v0.4.1'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "OTC_DOMAIN_NAME": Domain name`) - ew.writeln(` - "OTC_IDENTITY_ENDPOINT": Identity endpoint URL`) - ew.writeln(` - "OTC_PASSWORD": Password`) - ew.writeln(` - "OTC_PROJECT_NAME": Project name`) - ew.writeln(` - "OTC_USER_NAME": User name`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "OTC_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "OTC_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "OTC_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "OTC_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/otc`) - - case "ovh": - // generated from: providers/dns/ovh/ovh.toml - ew.writeln(`Configuration for OVH.`) - ew.writeln(`Code: 'ovh'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "OVH_APPLICATION_KEY": Application key`) - ew.writeln(` - "OVH_APPLICATION_SECRET": Application secret`) - ew.writeln(` - "OVH_CONSUMER_KEY": Consumer key`) - ew.writeln(` - "OVH_ENDPOINT": Endpoint URL (ovh-eu or ovh-ca)`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "OVH_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "OVH_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "OVH_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "OVH_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/ovh`) - - case "pdns": - // generated from: providers/dns/pdns/pdns.toml - ew.writeln(`Configuration for PowerDNS.`) - ew.writeln(`Code: 'pdns'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "PDNS_API_KEY": API key`) - ew.writeln(` - "PDNS_API_URL": API URL`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "PDNS_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "PDNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "PDNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "PDNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/pdns`) - - case "rackspace": - // generated from: providers/dns/rackspace/rackspace.toml - ew.writeln(`Configuration for Rackspace.`) - ew.writeln(`Code: 'rackspace'`) - ew.writeln(`Since: 'v0.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "RACKSPACE_API_KEY": API key`) - ew.writeln(` - "RACKSPACE_USER": API user`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "RACKSPACE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "RACKSPACE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "RACKSPACE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "RACKSPACE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/rackspace`) - - case "regru": - // generated from: providers/dns/regru/regru.toml - ew.writeln(`Configuration for reg.ru.`) - ew.writeln(`Code: 'regru'`) - ew.writeln(`Since: 'v3.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "REGRU_PASSWORD": API password`) - ew.writeln(` - "REGRU_USERNAME": API username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "REGRU_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "REGRU_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "REGRU_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "REGRU_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/regru`) - - case "rfc2136": - // generated from: providers/dns/rfc2136/rfc2136.toml - ew.writeln(`Configuration for RFC2136.`) - ew.writeln(`Code: 'rfc2136'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "RFC2136_NAMESERVER": Network address in the form "host" or "host:port"`) - ew.writeln(` - "RFC2136_TSIG_ALGORITHM": TSIG algorithm. See [miekg/dns#tsig.go](https://github.com/miekg/dns/blob/master/tsig.go) for supported values. To disable TSIG authentication, leave the 'RFC2136_TSIG*' variables unset.`) - ew.writeln(` - "RFC2136_TSIG_KEY": Name of the secret key as defined in DNS server configuration. To disable TSIG authentication, leave the 'RFC2136_TSIG*' variables unset.`) - ew.writeln(` - "RFC2136_TSIG_SECRET": Secret key payload. To disable TSIG authentication, leave the' RFC2136_TSIG*' variables unset.`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "RFC2136_DNS_TIMEOUT": API request timeout`) - ew.writeln(` - "RFC2136_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "RFC2136_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "RFC2136_SEQUENCE_INTERVAL": Interval between iteration`) - ew.writeln(` - "RFC2136_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/rfc2136`) - - case "rimuhosting": - // generated from: providers/dns/rimuhosting/rimuhosting.toml - ew.writeln(`Configuration for RimuHosting.`) - ew.writeln(`Code: 'rimuhosting'`) - ew.writeln(`Since: 'v0.3.5'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "RIMUHOSTING_API_KEY": User API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "RIMUHOSTING_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "RIMUHOSTING_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "RIMUHOSTING_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "RIMUHOSTING_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/rimuhosting`) - - case "route53": - // generated from: providers/dns/route53/route53.toml - ew.writeln(`Configuration for Amazon Route 53.`) - ew.writeln(`Code: 'route53'`) - ew.writeln(`Since: 'v0.3.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "AWS_ACCESS_KEY_ID": Managed by the AWS client ('AWS_ACCESS_KEY_ID_FILE' is not supported)`) - ew.writeln(` - "AWS_HOSTED_ZONE_ID": Override the hosted zone ID`) - ew.writeln(` - "AWS_PROFILE": Managed by the AWS client ('AWS_PROFILE_FILE' is not supported)`) - ew.writeln(` - "AWS_REGION": Managed by the AWS client ('AWS_REGION_FILE' is not supported)`) - ew.writeln(` - "AWS_SDK_LOAD_CONFIG": Retrieve the region from the CLI config file ('AWS_SDK_LOAD_CONFIG_FILE' is not supported)`) - ew.writeln(` - "AWS_SECRET_ACCESS_KEY": Managed by the AWS client ('AWS_SECRET_ACCESS_KEY_FILE' is not supported)`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "AWS_MAX_RETRIES": The number of maximum returns the service will use to make an individual API request`) - ew.writeln(` - "AWS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "AWS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "AWS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/route53`) - - case "sakuracloud": - // generated from: providers/dns/sakuracloud/sakuracloud.toml - ew.writeln(`Configuration for Sakura Cloud.`) - ew.writeln(`Code: 'sakuracloud'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "SAKURACLOUD_ACCESS_TOKEN": Access token`) - ew.writeln(` - "SAKURACLOUD_ACCESS_TOKEN_SECRET": Access token secret`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "SAKURACLOUD_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "SAKURACLOUD_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "SAKURACLOUD_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "SAKURACLOUD_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/sakuracloud`) - - case "scaleway": - // generated from: providers/dns/scaleway/scaleway.toml - ew.writeln(`Configuration for Scaleway.`) - ew.writeln(`Code: 'scaleway'`) - ew.writeln(`Since: 'v3.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "SCALEWAY_API_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "SCALEWAY_API_VERSION": API version`) - ew.writeln(` - "SCALEWAY_BASE_URL": API endpoint URL`) - ew.writeln(` - "SCALEWAY_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "SCALEWAY_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "SCALEWAY_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "SCALEWAY_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/scaleway`) - - case "selectel": - // generated from: providers/dns/selectel/selectel.toml - ew.writeln(`Configuration for Selectel.`) - ew.writeln(`Code: 'selectel'`) - ew.writeln(`Since: 'v1.2.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "SELECTEL_API_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "SELECTEL_BASE_URL": API endpoint URL`) - ew.writeln(` - "SELECTEL_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "SELECTEL_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "SELECTEL_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "SELECTEL_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/selectel`) - - case "servercow": - // generated from: providers/dns/servercow/servercow.toml - ew.writeln(`Configuration for Servercow.`) - ew.writeln(`Code: 'servercow'`) - ew.writeln(`Since: 'v3.4.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "SERVERCOW_PASSWORD": API password`) - ew.writeln(` - "SERVERCOW_USERNAME": API username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "SERVERCOW_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "SERVERCOW_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "SERVERCOW_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "SERVERCOW_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/servercow`) - - case "stackpath": - // generated from: providers/dns/stackpath/stackpath.toml - ew.writeln(`Configuration for Stackpath.`) - ew.writeln(`Code: 'stackpath'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "STACKPATH_CLIENT_ID": Client ID`) - ew.writeln(` - "STACKPATH_CLIENT_SECRET": Client secret`) - ew.writeln(` - "STACKPATH_STACK_ID": Stack ID`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "STACKPATH_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "STACKPATH_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "STACKPATH_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/stackpath`) - - case "transip": - // generated from: providers/dns/transip/transip.toml - ew.writeln(`Configuration for TransIP.`) - ew.writeln(`Code: 'transip'`) - ew.writeln(`Since: 'v2.0.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "TRANSIP_ACCOUNT_NAME": Account name`) - ew.writeln(` - "TRANSIP_PRIVATE_KEY_PATH": Private key path`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "TRANSIP_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "TRANSIP_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "TRANSIP_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/transip`) - - case "vegadns": - // generated from: providers/dns/vegadns/vegadns.toml - ew.writeln(`Configuration for VegaDNS.`) - ew.writeln(`Code: 'vegadns'`) - ew.writeln(`Since: 'v1.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "SECRET_VEGADNS_KEY": API key`) - ew.writeln(` - "SECRET_VEGADNS_SECRET": API secret`) - ew.writeln(` - "VEGADNS_URL": API endpoint URL`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "VEGADNS_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "VEGADNS_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "VEGADNS_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/vegadns`) - - case "versio": - // generated from: providers/dns/versio/versio.toml - ew.writeln(`Configuration for Versio.[nl|eu|uk].`) - ew.writeln(`Code: 'versio'`) - ew.writeln(`Since: 'v2.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "VERSIO_PASSWORD": Basic authentication password`) - ew.writeln(` - "VERSIO_USERNAME": Basic authentication username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "VERSIO_ENDPOINT": The endpoint URL of the API Server`) - ew.writeln(` - "VERSIO_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "VERSIO_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "VERSIO_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "VERSIO_SEQUENCE_INTERVAL": Interval between iteration, default 60s`) - ew.writeln(` - "VERSIO_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/versio`) - - case "vscale": - // generated from: providers/dns/vscale/vscale.toml - ew.writeln(`Configuration for Vscale.`) - ew.writeln(`Code: 'vscale'`) - ew.writeln(`Since: 'v2.0.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "VSCALE_API_TOKEN": API token`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "VSCALE_BASE_URL": API endpoint URL`) - ew.writeln(` - "VSCALE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "VSCALE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "VSCALE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "VSCALE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/vscale`) - - case "vultr": - // generated from: providers/dns/vultr/vultr.toml - ew.writeln(`Configuration for Vultr.`) - ew.writeln(`Code: 'vultr'`) - ew.writeln(`Since: 'v0.3.1'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "VULTR_API_KEY": API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "VULTR_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "VULTR_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "VULTR_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "VULTR_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/vultr`) - - case "yandex": - // generated from: providers/dns/yandex/yandex.toml - ew.writeln(`Configuration for Yandex.`) - ew.writeln(`Code: 'yandex'`) - ew.writeln(`Since: 'v3.7.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "YANDEX_PDD_TOKEN": Basic authentication username`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "YANDEX_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "YANDEX_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "YANDEX_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "YANDEX_SEQUENCE_INTERVAL": Interval between iteration, default 60s`) - ew.writeln(` - "YANDEX_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/yandex`) - - case "zoneee": - // generated from: providers/dns/zoneee/zoneee.toml - ew.writeln(`Configuration for Zone.ee.`) - ew.writeln(`Code: 'zoneee'`) - ew.writeln(`Since: 'v2.1.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "ZONEEE_API_KEY": API key`) - ew.writeln(` - "ZONEEE_API_USER": API user`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "ZONEEE_ENDPOINT": API endpoint URL`) - ew.writeln(` - "ZONEEE_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "ZONEEE_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "ZONEEE_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "ZONEEE_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/zoneee`) - - case "zonomi": - // generated from: providers/dns/zonomi/zonomi.toml - ew.writeln(`Configuration for Zonomi.`) - ew.writeln(`Code: 'zonomi'`) - ew.writeln(`Since: 'v3.5.0'`) - ew.writeln() - - ew.writeln(`Credentials:`) - ew.writeln(` - "ZONOMI_API_KEY": User API key`) - ew.writeln() - - ew.writeln(`Additional Configuration:`) - ew.writeln(` - "ZONOMI_HTTP_TIMEOUT": API request timeout`) - ew.writeln(` - "ZONOMI_POLLING_INTERVAL": Time between DNS propagation check`) - ew.writeln(` - "ZONOMI_PROPAGATION_TIMEOUT": Maximum waiting time for DNS propagation`) - ew.writeln(` - "ZONOMI_TTL": The TTL of the TXT record used for the DNS challenge`) - - ew.writeln() - ew.writeln(`More information: https://go-acme.github.io/lego/dns/zonomi`) - - case "manual": - ew.writeln(`Solving the DNS-01 challenge using CLI prompt.`) - default: - return fmt.Errorf("%q is not yet supported", name) - } - - if ew.err != nil { - return fmt.Errorf("error: %w", ew.err) - } - - return w.Flush() -} diff --git a/common/legocmd/lego.go b/common/legocmd/lego.go deleted file mode 100644 index 71bca17..0000000 --- a/common/legocmd/lego.go +++ /dev/null @@ -1,190 +0,0 @@ -// Let's Encrypt client to go! -// CLI application for generating Let's Encrypt certificates using the ACME package. -package legocmd - -import ( - "errors" - "fmt" - "os" - "path" - "path/filepath" - "runtime" - "strings" - - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/cmd" -) - -var version = "dev" -var defaultPath string - -type LegoCMD struct { - cmdClient *cli.App -} - -func New() (*LegoCMD, error) { - app := cli.NewApp() - app.Name = "lego" - app.HelpName = "lego" - app.Usage = "Let's Encrypt client written in Go" - app.EnableBashCompletion = true - - app.Version = version - cli.VersionPrinter = func(c *cli.Context) { - fmt.Printf("lego version %s %s/%s\n", c.App.Version, runtime.GOOS, runtime.GOARCH) - } - - // Set default path to configPath/cert - var path string = "" - configPath := os.Getenv("XRAY_LOCATION_CONFIG") - if configPath != "" { - path = configPath - } else if cwd, err := os.Getwd(); err == nil { - path = cwd - } else { - path = "." - } - - defaultPath = filepath.Join(path, "cert") - - app.Flags = cmd.CreateFlags(defaultPath) - - app.Before = cmd.Before - - app.Commands = cmd.CreateCommands() - - lego := &LegoCMD{ - cmdClient: app, - } - - return lego, nil -} - -// DNSCert cert a domain using DNS API -func (l *LegoCMD) DNSCert(domain, email, provider string, DNSEnv map[string]string) (CertPath string, KeyPath string, err error) { - defer func() (string, string, error) { - // Handle any error - if r := recover(); r != nil { - switch x := r.(type) { - case string: - err = errors.New(x) - case error: - err = x - default: - err = errors.New("unknow panic") - } - return "", "", err - } - return CertPath, KeyPath, nil - }() - // Set Env for DNS configuration - for key, value := range DNSEnv { - os.Setenv(strings.ToUpper(key), value) - } - // First check if the certificate exists - CertPath, KeyPath, err = checkCertfile(domain) - if err == nil { - return CertPath, KeyPath, err - } - - argstring := fmt.Sprintf("lego -a -d %s -m %s --dns %s run", domain, email, provider) - err = l.cmdClient.Run(strings.Split(argstring, " ")) - if err != nil { - return "", "", err - } - CertPath, KeyPath, err = checkCertfile(domain) - if err != nil { - return "", "", err - } - return CertPath, KeyPath, nil -} - -// HTTPCert cert a domain using http methods -func (l *LegoCMD) HTTPCert(domain, email string) (CertPath string, KeyPath string, err error) { - defer func() (string, string, error) { - // Handle any error - if r := recover(); r != nil { - switch x := r.(type) { - case string: - err = errors.New(x) - case error: - err = x - default: - err = errors.New("unknow panic") - } - return "", "", err - } - return CertPath, KeyPath, nil - }() - // First check if the certificate exists - CertPath, KeyPath, err = checkCertfile(domain) - if err == nil { - return CertPath, KeyPath, err - } - argstring := fmt.Sprintf("lego -a -d %s -m %s --http run", domain, email) - err = l.cmdClient.Run(strings.Split(argstring, " ")) - - if err != nil { - return "", "", err - } - CertPath, KeyPath, err = checkCertfile(domain) - if err != nil { - return "", "", err - } - return CertPath, KeyPath, nil -} - -// RenewCert renew a domain cert -func (l *LegoCMD) RenewCert(domain, email, certMode, provider string, DNSEnv map[string]string) (CertPath string, KeyPath string, err error) { - var argstring string - defer func() (string, string, error) { - // Handle any error - if r := recover(); r != nil { - switch x := r.(type) { - case string: - err = errors.New(x) - case error: - err = x - default: - err = errors.New("unknow panic") - } - return "", "", err - } - return CertPath, KeyPath, nil - }() - if certMode == "http" { - argstring = fmt.Sprintf("lego -a -d %s -m %s --http renew --days 30", domain, email) - } else if certMode == "dns" { - // Set Env for DNS configuration - for key, value := range DNSEnv { - os.Setenv(key, value) - } - argstring = fmt.Sprintf("lego -a -d %s -m %s --dns %s renew --days 30", domain, email, provider) - } else { - return "", "", fmt.Errorf("Unsupport cert mode: %s", certMode) - } - err = l.cmdClient.Run(strings.Split(argstring, " ")) - - if err != nil { - return "", "", err - } - CertPath, KeyPath, err = checkCertfile(domain) - if err != nil { - return "", "", err - } - return CertPath, KeyPath, nil -} -func checkCertfile(domain string) (string, string, error) { - keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", domain)) - certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", domain)) - if _, err := os.Stat(keyPath); os.IsNotExist(err) { - return "", "", fmt.Errorf("Cert key failed: %s", domain) - } - if _, err := os.Stat(certPath); os.IsNotExist(err) { - return "", "", fmt.Errorf("Cert cert failed: %s", domain) - } - absKeyPath, _ := filepath.Abs(keyPath) - absCertPath, _ := filepath.Abs(certPath) - return absCertPath, absKeyPath, nil -} diff --git a/common/legocmd/lego_test.go b/common/legocmd/lego_test.go deleted file mode 100644 index 75a551f..0000000 --- a/common/legocmd/lego_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package legocmd_test - -import ( - "testing" - - "github.com/XrayR-project/XrayR/common/legocmd" -) - -func TestLegoClient(t *testing.T) { - _, err := legocmd.New() - if err != nil { - t.Error(err) - } -} - -func TestLegoDNSCert(t *testing.T) { - lego, err := legocmd.New() - if err != nil { - t.Error(err) - } - var ( - domain string = "node1.test.com" - email string = "test@gmail.com" - provider string = "alidns" - DNSEnv map[string]string - ) - DNSEnv = make(map[string]string) - DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa" - DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb" - certPath, keyPath, err := lego.DNSCert(domain, email, provider, DNSEnv) - if err != nil { - t.Error(err) - } - t.Log(certPath) - t.Log(keyPath) -} - -func TestLegoHTTPCert(t *testing.T) { - lego, err := legocmd.New() - if err != nil { - t.Error(err) - } - var ( - domain string = "node1.test.com" - email string = "test@gmail.com" - ) - certPath, keyPath, err := lego.HTTPCert(domain, email) - if err != nil { - t.Error(err) - } - t.Log(certPath) - t.Log(keyPath) -} - -func TestLegoRenewCert(t *testing.T) { - lego, err := legocmd.New() - if err != nil { - t.Error(err) - } - var ( - domain string = "node1.test.com" - email string = "test@gmail.com" - provider string = "alidns" - DNSEnv map[string]string - ) - DNSEnv = make(map[string]string) - DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa" - DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb" - certPath, keyPath, err := lego.RenewCert(domain, email, "dns", provider, DNSEnv) - if err != nil { - t.Error(err) - } - t.Log(certPath) - t.Log(keyPath) - - certPath, keyPath, err = lego.RenewCert(domain, email, "http", provider, DNSEnv) - if err != nil { - t.Error(err) - } - t.Log(certPath) - t.Log(keyPath) -} diff --git a/common/legocmd/log/log.go b/common/legocmd/log/log.go deleted file mode 100644 index 35d5c93..0000000 --- a/common/legocmd/log/log.go +++ /dev/null @@ -1,59 +0,0 @@ -package log - -import ( - "log" - "os" -) - -// Logger is an optional custom logger. -var Logger StdLogger = log.New(os.Stdout, "", log.LstdFlags) - -// StdLogger interface for Standard Logger. -type StdLogger interface { - Panic(args ...interface{}) - Fatalln(args ...interface{}) - Panicf(format string, args ...interface{}) - Print(args ...interface{}) - Println(args ...interface{}) - Printf(format string, args ...interface{}) -} - -// Panic writes a log entry. -// It uses Logger if not nil, otherwise it uses the default log.Logger. -func Panic(args ...interface{}) { - Logger.Panic(args...) -} - -// Panicf writes a log entry. -// It uses Logger if not nil, otherwise it uses the default log.Logger. -func Panicf(format string, args ...interface{}) { - Logger.Panicf(format, args...) -} - -// Print writes a log entry. -// It uses Logger if not nil, otherwise it uses the default log.Logger. -func Print(args ...interface{}) { - Logger.Print(args...) -} - -// Println writes a log entry. -// It uses Logger if not nil, otherwise it uses the default log.Logger. -func Println(args ...interface{}) { - Logger.Println(args...) -} - -// Printf writes a log entry. -// It uses Logger if not nil, otherwise it uses the default log.Logger. -func Printf(format string, args ...interface{}) { - Logger.Printf(format, args...) -} - -// Warnf writes a log entry. -func Warnf(format string, args ...interface{}) { - Printf("[WARN] "+format, args...) -} - -// Infof writes a log entry. -func Infof(format string, args ...interface{}) { - Printf("[INFO] "+format, args...) -} diff --git a/common/legocmd/cmd/account.go b/common/mylego/account.go similarity index 98% rename from common/legocmd/cmd/account.go rename to common/mylego/account.go index 73247c9..014e07f 100644 --- a/common/legocmd/cmd/account.go +++ b/common/mylego/account.go @@ -1,4 +1,4 @@ -package cmd +package mylego import ( "crypto" diff --git a/common/legocmd/cmd/accounts_storage.go b/common/mylego/accounts_storage.go similarity index 86% rename from common/legocmd/cmd/accounts_storage.go rename to common/mylego/accounts_storage.go index 3051a7d..1f9e698 100644 --- a/common/legocmd/cmd/accounts_storage.go +++ b/common/mylego/accounts_storage.go @@ -1,4 +1,4 @@ -package cmd +package mylego import ( "crypto" @@ -6,8 +6,7 @@ import ( "encoding/json" "encoding/pem" "errors" - "fmt" - "io/ioutil" + "log" "net/url" "os" "path/filepath" @@ -16,9 +15,7 @@ import ( "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/registration" - "github.com/urfave/cli" - - "github.com/XrayR-project/XrayR/common/legocmd/log" + "golang.org/x/crypto/acme" ) const ( @@ -66,20 +63,18 @@ type AccountsStorage struct { rootUserPath string keysPath string accountFilePath string - ctx *cli.Context } // NewAccountsStorage Creates a new AccountsStorage. -func NewAccountsStorage(ctx *cli.Context) *AccountsStorage { - // TODO: move to account struct? Currently MUST pass email. - email := getEmail(ctx) +func NewAccountsStorage(l *LegoCMD) *AccountsStorage { + email := l.C.Email - serverURL, err := url.Parse(ctx.GlobalString("server")) + serverURL, err := url.Parse(acme.LetsEncryptURL) if err != nil { log.Panic(err) } - rootPath := filepath.Join(ctx.GlobalString("path"), baseAccountsRootFolderName) + rootPath := filepath.Join(l.path, baseAccountsRootFolderName) serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host) accountsPath := filepath.Join(rootPath, serverPath) rootUserPath := filepath.Join(accountsPath, email) @@ -90,7 +85,6 @@ func NewAccountsStorage(ctx *cli.Context) *AccountsStorage { rootUserPath: rootUserPath, keysPath: filepath.Join(rootUserPath, baseKeysFolderName), accountFilePath: filepath.Join(rootUserPath, accountFileName), - ctx: ctx, } } @@ -122,11 +116,11 @@ func (s *AccountsStorage) Save(account *Account) error { return err } - return ioutil.WriteFile(s.accountFilePath, jsonBytes, filePerm) + return os.WriteFile(s.accountFilePath, jsonBytes, filePerm) } func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account { - fileBytes, err := ioutil.ReadFile(s.accountFilePath) + fileBytes, err := os.ReadFile(s.accountFilePath) if err != nil { log.Panicf("Could not load file for account %s: %v", s.userID, err) } @@ -140,7 +134,7 @@ func (s *AccountsStorage) LoadAccount(privateKey crypto.PrivateKey) *Account { account.key = privateKey if account.Registration == nil || account.Registration.Body.Status == "" { - reg, err := tryRecoverRegistration(s.ctx, privateKey) + reg, err := tryRecoverRegistration(privateKey) if err != nil { log.Panicf("Could not load account for %s. Registration is nil: %#v", s.userID, err) } @@ -207,7 +201,7 @@ func generatePrivateKey(file string, keyType certcrypto.KeyType) (crypto.Private } func loadPrivateKey(file string) (crypto.PrivateKey, error) { - keyBytes, err := ioutil.ReadFile(file) + keyBytes, err := os.ReadFile(file) if err != nil { return nil, err } @@ -224,11 +218,11 @@ func loadPrivateKey(file string) (crypto.PrivateKey, error) { return nil, errors.New("unknown private key type") } -func tryRecoverRegistration(ctx *cli.Context, privateKey crypto.PrivateKey) (*registration.Resource, error) { +func tryRecoverRegistration(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.GlobalString("server") - config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version) + config.CADirURL = acme.LetsEncryptURL + config.UserAgent = "lego-cli/dev" client, err := lego.NewClient(config) if err != nil { diff --git a/common/mylego/base.go b/common/mylego/base.go new file mode 100644 index 0000000..81f8429 --- /dev/null +++ b/common/mylego/base.go @@ -0,0 +1,163 @@ +package mylego + +import ( + "errors" + "fmt" + "os" + "path" + "path/filepath" + "strings" +) + +var defaultPath string + +func New(certConf *CertConfig) (*LegoCMD, error) { + // Set default path to configPath/cert + var p = "" + configPath := os.Getenv("V2RAY_LOCATION_CONFIG") + if configPath != "" { + p = configPath + } else if cwd, err := os.Getwd(); err == nil { + p = cwd + } else { + p = "." + } + + defaultPath = filepath.Join(p, "cert") + lego := &LegoCMD{ + C: certConf, + path: defaultPath, + } + + return lego, nil +} + +func (l *LegoCMD) getPath() string { + return l.path +} + +func (l *LegoCMD) getCertConfig() *CertConfig { + return l.C +} + +// DNSCert cert a domain using DNS API +func (l *LegoCMD) DNSCert() (CertPath string, KeyPath string, err error) { + defer func() (string, string, error) { + // Handle any error + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("unknown panic") + } + return "", "", err + } + return CertPath, KeyPath, nil + }() + + // Set Env for DNS configuration + for key, value := range l.C.DNSEnv { + os.Setenv(strings.ToUpper(key), value) + } + + // First check if the certificate exists + CertPath, KeyPath, err = checkCertFile(l.C.CertDomain) + if err == nil { + return CertPath, KeyPath, err + } + + err = l.Run() + if err != nil { + return "", "", err + } + CertPath, KeyPath, err = checkCertFile(l.C.CertDomain) + if err != nil { + return "", "", err + } + return CertPath, KeyPath, nil +} + +// HTTPCert cert a domain using http methods +func (l *LegoCMD) HTTPCert() (CertPath string, KeyPath string, err error) { + defer func() (string, string, error) { + // Handle any error + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("unknown panic") + } + return "", "", err + } + return CertPath, KeyPath, nil + }() + + // First check if the certificate exists + CertPath, KeyPath, err = checkCertFile(l.C.CertDomain) + if err == nil { + return CertPath, KeyPath, err + } + + err = l.Run() + if err != nil { + return "", "", err + } + + CertPath, KeyPath, err = checkCertFile(l.C.CertDomain) + if err != nil { + return "", "", err + } + + return CertPath, KeyPath, nil +} + +// RenewCert renew a domain cert +func (l *LegoCMD) RenewCert() (CertPath string, KeyPath string, ok bool, err error) { + defer func() (string, string, bool, error) { + // Handle any error + if r := recover(); r != nil { + switch x := r.(type) { + case string: + err = errors.New(x) + case error: + err = x + default: + err = errors.New("unknown panic") + } + return "", "", false, err + } + return CertPath, KeyPath, ok, nil + }() + + ok, err = l.Renew() + if err != nil { + return + } + + CertPath, KeyPath, err = checkCertFile(l.C.CertDomain) + if err != nil { + return + } + + return +} + +func checkCertFile(domain string) (string, string, error) { + keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", domain)) + certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", domain)) + if _, err := os.Stat(keyPath); os.IsNotExist(err) { + return "", "", fmt.Errorf("cert key failed: %s", domain) + } + if _, err := os.Stat(certPath); os.IsNotExist(err) { + return "", "", fmt.Errorf("cert cert failed: %s", domain) + } + absKeyPath, _ := filepath.Abs(keyPath) + absCertPath, _ := filepath.Abs(certPath) + return absCertPath, absKeyPath, nil +} diff --git a/common/legocmd/cmd/certs_storage.go b/common/mylego/certs_storage.go similarity index 74% rename from common/legocmd/cmd/certs_storage.go rename to common/mylego/certs_storage.go index 8d09ff7..b36956e 100644 --- a/common/legocmd/cmd/certs_storage.go +++ b/common/mylego/certs_storage.go @@ -1,22 +1,17 @@ -package cmd +package mylego import ( "bytes" "crypto/x509" "encoding/json" - "io/ioutil" + "log" "os" "path/filepath" - "strconv" "strings" - "time" "github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certificate" - "github.com/urfave/cli" "golang.org/x/net/idna" - - "github.com/XrayR-project/XrayR/common/legocmd/log" ) const ( @@ -24,7 +19,7 @@ const ( baseArchivesFolderName = "archives" ) -// CertificatesStorage a certificates storage. +// CertificatesStorage a certificates' storage. // // rootPath: // @@ -38,19 +33,14 @@ const ( // │ └── archived certificates directory // └── "path" option type CertificatesStorage struct { - rootPath string - archivePath string - pem bool - filename string // Deprecated + rootPath string + pem bool } // NewCertificatesStorage create a new certificates storage. -func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage { +func NewCertificatesStorage(path string) *CertificatesStorage { return &CertificatesStorage{ - rootPath: filepath.Join(ctx.GlobalString("path"), baseCertificatesFolderName), - archivePath: filepath.Join(ctx.GlobalString("path"), baseArchivesFolderName), - pem: ctx.GlobalBool("pem"), - filename: ctx.GlobalString("filename"), + rootPath: filepath.Join(path, baseCertificatesFolderName), } } @@ -61,13 +51,6 @@ func (s *CertificatesStorage) CreateRootFolder() { } } -func (s *CertificatesStorage) CreateArchiveFolder() { - err := createNonExistingFolder(s.archivePath) - if err != nil { - log.Panicf("Could not check/create path: %v", err) - } -} - func (s *CertificatesStorage) GetRootPath() string { return s.rootPath } @@ -144,7 +127,7 @@ func (s *CertificatesStorage) ExistsFile(domain, extension string) bool { } func (s *CertificatesStorage) ReadFile(domain, extension string) ([]byte, error) { - return ioutil.ReadFile(s.GetFileName(domain, extension)) + return os.ReadFile(s.GetFileName(domain, extension)) } func (s *CertificatesStorage) GetFileName(domain, extension string) string { @@ -163,36 +146,11 @@ func (s *CertificatesStorage) ReadCertificate(domain, extension string) ([]*x509 } func (s *CertificatesStorage) WriteFile(domain, extension string, data []byte) error { - var baseFileName string - if s.filename != "" { - baseFileName = s.filename - } else { - baseFileName = sanitizedDomain(domain) - } + var baseFileName = sanitizedDomain(domain) filePath := filepath.Join(s.rootPath, baseFileName+extension) - return ioutil.WriteFile(filePath, data, filePerm) -} - -func (s *CertificatesStorage) MoveToArchive(domain string) error { - matches, err := filepath.Glob(filepath.Join(s.rootPath, sanitizedDomain(domain)+".*")) - if err != nil { - return err - } - - for _, oldFile := range matches { - date := strconv.FormatInt(time.Now().Unix(), 10) - filename := date + "." + filepath.Base(oldFile) - newFile := filepath.Join(s.archivePath, filename) - - err = os.Rename(oldFile, newFile) - if err != nil { - return err - } - } - - return nil + return os.WriteFile(filePath, data, filePerm) } // sanitizedDomain Make sure no funny chars are in the cert names (like wildcards ;)). diff --git a/common/mylego/cmd_renew.go b/common/mylego/cmd_renew.go new file mode 100644 index 0000000..8d5471c --- /dev/null +++ b/common/mylego/cmd_renew.go @@ -0,0 +1,76 @@ +package mylego + +import ( + "crypto" + "crypto/x509" + "log" + "time" + + "github.com/go-acme/lego/v4/certcrypto" + "github.com/go-acme/lego/v4/certificate" + "github.com/go-acme/lego/v4/lego" +) + +func (l *LegoCMD) Renew() (bool, error) { + account, client := setup(NewAccountsStorage(l)) + setupChallenges(l, client) + + if account.Registration == nil { + log.Panicf("Account %s is not registered. Use 'run' to register a new account.\n", account.Email) + } + + return renewForDomains(l.C.CertDomain, client, NewCertificatesStorage(l.path)) +} + +func renewForDomains(domain string, client *lego.Client, certsStorage *CertificatesStorage) (bool, error) { + // 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") + if err != nil { + log.Panicf("Error while loading the certificate for domain %s\n\t%v", domain, err) + } + + cert := certificates[0] + + if !needRenewal(cert, domain, 30) { + return false, nil + } + + // This is just meant to be informal for the user. + timeLeft := cert.NotAfter.Sub(time.Now().UTC()) + log.Printf("[%s] acme: Trying renewal with %d hours remaining", domain, int(timeLeft.Hours())) + + certDomains := certcrypto.ExtractDomains(cert) + + var privateKey crypto.PrivateKey + request := certificate.ObtainRequest{ + Domains: certDomains, + PrivateKey: privateKey, + } + certRes, err := client.Certificate.Obtain(request) + if err != nil { + log.Panic(err) + } + + certsStorage.SaveResource(certRes) + + return true, nil +} + +func needRenewal(x509Cert *x509.Certificate, domain string, days int) bool { + if x509Cert.IsCA { + log.Panicf("[%s] Certificate bundle starts with a CA certificate", domain) + } + + if days >= 0 { + notAfter := int(time.Until(x509Cert.NotAfter).Hours() / 24.0) + if notAfter > days { + log.Printf("[%s] The certificate expires in %d days, the number of days defined to perform the renewal is %d: no renewal.", + domain, notAfter, days) + return false + } + } + + return true +} diff --git a/common/legocmd/cmd/cmd_renew_test.go b/common/mylego/cmd_renew_test.go similarity index 88% rename from common/legocmd/cmd/cmd_renew_test.go rename to common/mylego/cmd_renew_test.go index 0ad9526..fc37fe6 100644 --- a/common/legocmd/cmd/cmd_renew_test.go +++ b/common/mylego/cmd_renew_test.go @@ -1,4 +1,4 @@ -package cmd +package mylego import ( "crypto/x509" @@ -116,3 +116,19 @@ func Test_needRenewal(t *testing.T) { }) } } + +func merge(prevDomains, nextDomains []string) []string { + for _, next := range nextDomains { + var found bool + for _, prev := range prevDomains { + if prev == next { + found = true + break + } + } + if !found { + prevDomains = append(prevDomains, next) + } + } + return prevDomains +} diff --git a/common/mylego/cmd_run.go b/common/mylego/cmd_run.go new file mode 100644 index 0000000..480cde0 --- /dev/null +++ b/common/mylego/cmd_run.go @@ -0,0 +1,67 @@ +package mylego + +import ( + "fmt" + "log" + + "github.com/go-acme/lego/v4/certificate" + "github.com/go-acme/lego/v4/lego" + "github.com/go-acme/lego/v4/registration" +) + +const rootPathWarningMessage = `!!!! HEADS UP !!!! + +Your account credentials have been saved in your Let's Encrypt +configuration directory at "%s". + +You should make a secure backup of this folder now. This +configuration directory will also contain certificates and +private keys obtained from Let's Encrypt so making regular +backups of this folder is ideal. +` + +func (l *LegoCMD) Run() error { + accountsStorage := NewAccountsStorage(l) + + account, client := setup(accountsStorage) + setupChallenges(l, client) + + if account.Registration == nil { + reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true}) + if err != nil { + log.Panicf("Could not complete registration\n\t%v", err) + } + + account.Registration = reg + if err = accountsStorage.Save(account); err != nil { + log.Panic(err) + } + + fmt.Printf(rootPathWarningMessage, accountsStorage.GetRootPath()) + } + + certsStorage := NewCertificatesStorage(l.path) + certsStorage.CreateRootFolder() + + cert, err := obtainCertificate([]string{l.C.CertDomain}, client) + if err != nil { + // Make sure to return a non-zero exit code if ObtainSANCertificate returned at least one error. + // Due to us not returning partial certificate we can just exit here instead of at the end. + log.Panicf("Could not obtain certificates:\n\t%v", err) + } + + certsStorage.SaveResource(cert) + + return nil +} + +func obtainCertificate(domains []string, client *lego.Client) (*certificate.Resource, error) { + if len(domains) > 0 { + // obtain a certificate, generating a new private key + request := certificate.ObtainRequest{ + Domains: domains, + } + return client.Certificate.Obtain(request) + } + return nil, fmt.Errorf("not a valid domain") +} diff --git a/common/mylego/lego_test.go b/common/mylego/lego_test.go new file mode 100644 index 0000000..09e15e3 --- /dev/null +++ b/common/mylego/lego_test.go @@ -0,0 +1,87 @@ +package mylego_test + +import ( + "testing" + + "github.com/thank243/v2rayS/common/mylego" +) + +func TestLegoClient(t *testing.T) { + _, err := mylego.New(&mylego.CertConfig{}) + if err != nil { + t.Error(err) + } +} + +func TestLegoDNSCert(t *testing.T) { + lego, err := mylego.New(&mylego.CertConfig{ + CertDomain: "node1.test.com", + Provider: "alidns", + Email: "test@gmail.com", + DNSEnv: map[string]string{ + "ALICLOUD_ACCESS_KEY": "aaa", + "ALICLOUD_SECRET_KEY": "bbb", + }, + }, + ) + if err != nil { + t.Error(err) + } + + certPath, keyPath, err := lego.DNSCert() + if err != nil { + t.Error(err) + } + t.Log(certPath) + t.Log(keyPath) +} + +func TestLegoHTTPCert(t *testing.T) { + lego, err := mylego.New(&mylego.CertConfig{ + CertMode: "http", + CertDomain: "node1.test.com", + Email: "test@gmail.com", + }) + if err != nil { + t.Error(err) + } + + certPath, keyPath, err := lego.HTTPCert() + if err != nil { + t.Error(err) + } + t.Log(certPath) + t.Log(keyPath) +} + +func TestLegoRenewCert(t *testing.T) { + lego, err := mylego.New(&mylego.CertConfig{ + CertDomain: "node1.test.com", + Email: "test@gmail.com", + Provider: "alidns", + DNSEnv: map[string]string{ + "ALICLOUD_ACCESS_KEY": "aaa", + "ALICLOUD_SECRET_KEY": "bbb", + }, + }) + if err != nil { + t.Error(err) + } + lego.C.CertMode = "http" + certPath, keyPath, ok, err := lego.RenewCert() + if err != nil { + t.Error(err) + } + t.Log(certPath) + t.Log(keyPath) + t.Log(ok) + + lego.C.CertMode = "dns" + certPath, keyPath, ok, err = lego.RenewCert() + if err != nil { + t.Error(err) + } + t.Log(certPath) + t.Log(keyPath) + t.Log(ok) +} diff --git a/common/mylego/model.go b/common/mylego/model.go new file mode 100644 index 0000000..d6a3fad --- /dev/null +++ b/common/mylego/model.go @@ -0,0 +1,18 @@ +package mylego + +type CertConfig struct { + CertMode string `mapstructure:"CertMode"` // none, file, http, dns + VerifyClientCertificate bool `mapstructure:"VerifyClientCertificate"` + CertDomain string `mapstructure:"CertDomain"` + CertFile string `mapstructure:"CertFile"` + KeyFile string `mapstructure:"KeyFile"` + Provider string `mapstructure:"Provider"` // alidns, cloudflare, gandi, godaddy.... + Email string `mapstructure:"Email"` + DNSEnv map[string]string `mapstructure:"DNSEnv"` + RejectUnknownSni bool `mapstructure:"RejectUnknownSni"` +} + +type LegoCMD struct { + C *CertConfig + path string +} diff --git a/common/mylego/setup.go b/common/mylego/setup.go new file mode 100644 index 0000000..977315d --- /dev/null +++ b/common/mylego/setup.go @@ -0,0 +1,95 @@ +package mylego + +import ( + "log" + "os" + "time" + + "github.com/go-acme/lego/v4/certcrypto" + "github.com/go-acme/lego/v4/challenge/dns01" + "github.com/go-acme/lego/v4/challenge/http01" + "github.com/go-acme/lego/v4/challenge/tlsalpn01" + "github.com/go-acme/lego/v4/lego" + "github.com/go-acme/lego/v4/providers/dns" + "github.com/go-acme/lego/v4/registration" + "golang.org/x/crypto/acme" +) + +const filePerm os.FileMode = 0o600 + +func setup(accountsStorage *AccountsStorage) (*Account, *lego.Client) { + keyType := certcrypto.EC256 + privateKey := accountsStorage.GetPrivateKey(keyType) + + var account *Account + if accountsStorage.ExistsAccountFilePath() { + account = accountsStorage.LoadAccount(privateKey) + } else { + account = &Account{Email: accountsStorage.GetUserID(), key: privateKey} + } + + client := newClient(account, keyType) + + return account, client +} + +func newClient(acc registration.User, keyType certcrypto.KeyType) *lego.Client { + config := lego.NewConfig(acc) + config.CADirURL = acme.LetsEncryptURL + + config.Certificate = lego.CertificateConfig{ + KeyType: keyType, + Timeout: 30 * time.Second, + } + config.UserAgent = "lego-cli/dev" + + client, err := lego.NewClient(config) + if err != nil { + log.Panicf("Could not create client: %v", err) + } + + return client +} + +func createNonExistingFolder(path string) error { + if _, err := os.Stat(path); os.IsNotExist(err) { + return os.MkdirAll(path, 0o700) + } else if err != nil { + return err + } + return nil +} + +func setupChallenges(l *LegoCMD, client *lego.Client) { + switch l.C.CertMode { + case "http": + err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5001")) + if err != nil { + log.Panic(err) + } + case "tls": + err := client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5002")) + if err != nil { + log.Panic(err) + } + case "dns": + setupDNS(l.C.Provider, client) + default: + log.Panic("No challenge selected. You must specify at least one challenge: `http`, `tls`, `dns`.") + } +} + +func setupDNS(p string, client *lego.Client) { + provider, err := dns.NewDNSChallengeProviderByName(p) + if err != nil { + log.Panic(err) + } + + err = client.Challenge.SetDNS01Provider( + provider, + dns01.CondOption(true, dns01.AddDNSTimeout(10*time.Second)), + ) + if err != nil { + log.Panic(err) + } +} diff --git a/panel/config.go b/panel/config.go index 4743421..a9aa964 100644 --- a/panel/config.go +++ b/panel/config.go @@ -6,13 +6,13 @@ import ( ) type Config struct { - LogConfig *LogConfig `mapstructure:"Log"` - DnsConfigPath string `mapstructure:"DnsConfigPath"` - InboundConfigPath string `mapstructure:"InboundConfigPath"` - OutboundConfigPath string `mapstructure:"OutboundConfigPath"` - RouteConfigPath string `mapstructure:"RouteConfigPath"` - ConnetionConfig *ConnetionConfig `mapstructure:"ConnetionConfig"` - NodesConfig []*NodesConfig `mapstructure:"Nodes"` + LogConfig *LogConfig `mapstructure:"Log"` + DnsConfigPath string `mapstructure:"DnsConfigPath"` + InboundConfigPath string `mapstructure:"InboundConfigPath"` + OutboundConfigPath string `mapstructure:"OutboundConfigPath"` + RouteConfigPath string `mapstructure:"RouteConfigPath"` + ConnectionConfig *ConnectionConfig `mapstructure:"ConnectionConfig"` + NodesConfig []*NodesConfig `mapstructure:"Nodes"` } type NodesConfig struct { @@ -27,7 +27,7 @@ type LogConfig struct { ErrorPath string `mapstructure:"ErrorPath"` } -type ConnetionConfig struct { +type ConnectionConfig struct { Handshake uint32 `mapstructure:"handshake"` ConnIdle uint32 `mapstructure:"connIdle"` UplinkOnly uint32 `mapstructure:"uplinkOnly"` diff --git a/panel/defaultConfig.go b/panel/defaultConfig.go index 5a2e79b..8653664 100644 --- a/panel/defaultConfig.go +++ b/panel/defaultConfig.go @@ -10,8 +10,8 @@ func getDefaultLogConfig() *LogConfig { } } -func getDefaultConnetionConfig() *ConnetionConfig { - return &ConnetionConfig{ +func getDefaultConnectionConfig() *ConnectionConfig { + return &ConnectionConfig{ Handshake: 4, ConnIdle: 30, UplinkOnly: 2, diff --git a/panel/panel.go b/panel/panel.go index 874ebaa..9791901 100644 --- a/panel/panel.go +++ b/panel/panel.go @@ -123,7 +123,7 @@ func (p *Panel) loadCore(panelConfig *Config) *core.Instance { outBoundConfig = append(outBoundConfig, oc) } // Policy config - levelPolicyConfig := parseConnectionConfig(panelConfig.ConnetionConfig) + levelPolicyConfig := parseConnectionConfig(panelConfig.ConnectionConfig) corePolicyConfig := &conf.PolicyConfig{} corePolicyConfig.Levels = map[uint32]*conf.Policy{0: levelPolicyConfig} policyConfig, _ := corePolicyConfig.Build() @@ -219,11 +219,11 @@ func (p *Panel) Close() { return } -func parseConnectionConfig(c *ConnetionConfig) (policy *conf.Policy) { - connetionConfig := getDefaultConnetionConfig() +func parseConnectionConfig(c *ConnectionConfig) (policy *conf.Policy) { + connetionConfig := getDefaultConnectionConfig() if c != nil { if _, err := diff.Merge(connetionConfig, c, connetionConfig); err != nil { - log.Panicf("Read ConnetionConfig failed: %s", err) + log.Panicf("Read ConnectionConfig failed: %s", err) } } policy = &conf.Policy{ diff --git a/service/controller/config.go b/service/controller/config.go index d93843a..d1b7080 100644 --- a/service/controller/config.go +++ b/service/controller/config.go @@ -2,13 +2,14 @@ package controller import ( "github.com/XrayR-project/XrayR/common/limiter" + "github.com/XrayR-project/XrayR/common/mylego" ) type Config struct { ListenIP string `mapstructure:"ListenIP"` SendIP string `mapstructure:"SendIP"` UpdatePeriodic int `mapstructure:"UpdatePeriodic"` - CertConfig *CertConfig `mapstructure:"CertConfig"` + CertConfig *mylego.CertConfig `mapstructure:"CertConfig"` EnableDNS bool `mapstructure:"EnableDNS"` DNSType string `mapstructure:"DNSType"` DisableUploadTraffic bool `mapstructure:"DisableUploadTraffic"` @@ -29,17 +30,6 @@ type AutoSpeedLimitConfig struct { LimitDuration int `mapstructure:"LimitDuration"` // minute } -type CertConfig struct { - CertMode string `mapstructure:"CertMode"` // none, file, http, dns - RejectUnknownSni bool `mapstructure:"RejectUnknownSni"` - CertDomain string `mapstructure:"CertDomain"` - CertFile string `mapstructure:"CertFile"` - KeyFile string `mapstructure:"KeyFile"` - Provider string `mapstructure:"Provider"` // alidns, cloudflare, gandi, godaddy.... - Email string `mapstructure:"Email"` - DNSEnv map[string]string `mapstructure:"DNSEnv"` -} - type FallBackConfig struct { SNI string `mapstructure:"SNI"` Alpn string `mapstructure:"Alpn"` diff --git a/service/controller/controller.go b/service/controller/controller.go index 1f09b61..8320683 100644 --- a/service/controller/controller.go +++ b/service/controller/controller.go @@ -16,8 +16,8 @@ import ( "github.com/XrayR-project/XrayR/api" "github.com/XrayR-project/XrayR/app/mydispatcher" - "github.com/XrayR-project/XrayR/common/legocmd" "github.com/XrayR-project/XrayR/common/limiter" + "github.com/XrayR-project/XrayR/common/mylego" "github.com/XrayR-project/XrayR/common/serverstatus" ) @@ -221,12 +221,12 @@ func (c *Controller) nodeInfoMonitor() (err error) { // Check Cert if c.nodeInfo.EnableTLS && (c.config.CertConfig.CertMode == "dns" || c.config.CertConfig.CertMode == "http") { - lego, err := legocmd.New() + lego, err := mylego.New(c.config.CertConfig) if err != nil { log.Print(err) } // Xray-core supports the OcspStapling certification hot renew - _, _, err = lego.RenewCert(c.config.CertConfig.CertDomain, c.config.CertConfig.Email, c.config.CertConfig.CertMode, c.config.CertConfig.Provider, c.config.CertConfig.DNSEnv) + _, _, _, err = lego.RenewCert() if err != nil { log.Print(err) } diff --git a/service/controller/controller_test.go b/service/controller/controller_test.go index 0631cae..5b2a676 100644 --- a/service/controller/controller_test.go +++ b/service/controller/controller_test.go @@ -13,6 +13,7 @@ import ( "github.com/XrayR-project/XrayR/api" "github.com/XrayR-project/XrayR/api/sspanel" + "github.com/XrayR-project/XrayR/common/mylego" _ "github.com/XrayR-project/XrayR/main/distro/all" . "github.com/XrayR-project/XrayR/service/controller" ) @@ -46,7 +47,7 @@ func TestController(t *testing.T) { if err = server.Start(); err != nil { t.Errorf("Failed to start instance: %s", err) } - certConfig := &CertConfig{ + certConfig := &mylego.CertConfig{ CertMode: "http", CertDomain: "test.ss.tk", Provider: "alidns", diff --git a/service/controller/inboundbuilder.go b/service/controller/inboundbuilder.go index dd17c3b..3f7017e 100644 --- a/service/controller/inboundbuilder.go +++ b/service/controller/inboundbuilder.go @@ -1,4 +1,4 @@ -// Package generate the InbounderConfig used by add inbound +// Package controller Package generate the InboundConfig used by add inbound package controller import ( @@ -11,7 +11,7 @@ import ( "github.com/xtls/xray-core/infra/conf" "github.com/XrayR-project/XrayR/api" - "github.com/XrayR-project/XrayR/common/legocmd" + "github.com/XrayR-project/XrayR/common/mylego" ) // InboundBuilder build Inbound config for different protocol @@ -20,10 +20,10 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I // Build Listen IP address if nodeInfo.NodeType == "Shadowsocks-Plugin" { // Shdowsocks listen in 127.0.0.1 for safety - inboundDetourConfig.ListenOn = &conf.Address{net.ParseAddress("127.0.0.1")} + inboundDetourConfig.ListenOn = &conf.Address{Address: net.ParseAddress("127.0.0.1")} } else if config.ListenIP != "" { ipAddress := net.ParseAddress(config.ListenIP) - inboundDetourConfig.ListenOn = &conf.Address{ipAddress} + inboundDetourConfig.ListenOn = &conf.Address{Address: ipAddress} } // Build Port @@ -115,12 +115,12 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I NetworkList: []string{"tcp", "udp"}, } } else { - return nil, fmt.Errorf("Unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType) + return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType) } setting, err := json.Marshal(proxySetting) if err != nil { - return nil, fmt.Errorf("Marshal proxy %s config fialed: %s", nodeInfo.NodeType, err) + return nil, fmt.Errorf("marshal proxy %s config fialed: %s", nodeInfo.NodeType, err) } // Build streamSettings @@ -196,53 +196,53 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I return inboundDetourConfig.Build() } -func getCertFile(certConfig *CertConfig) (certFile string, keyFile string, err error) { +func getCertFile(certConfig *mylego.CertConfig) (certFile string, keyFile string, err error) { if certConfig.CertMode == "file" { if certConfig.CertFile == "" || certConfig.KeyFile == "" { - return "", "", fmt.Errorf("Cert file path or key file path not exist") + return "", "", fmt.Errorf("cert file path or key file path not exist") } return certConfig.CertFile, certConfig.KeyFile, nil } else if certConfig.CertMode == "dns" { - lego, err := legocmd.New() + lego, err := mylego.New(certConfig) if err != nil { return "", "", err } - certPath, keyPath, err := lego.DNSCert(certConfig.CertDomain, certConfig.Email, certConfig.Provider, certConfig.DNSEnv) + certPath, keyPath, err := lego.DNSCert() if err != nil { return "", "", err } return certPath, keyPath, err } else if certConfig.CertMode == "http" { - lego, err := legocmd.New() + lego, err := mylego.New(certConfig) if err != nil { return "", "", err } - certPath, keyPath, err := lego.HTTPCert(certConfig.CertDomain, certConfig.Email) + certPath, keyPath, err := lego.HTTPCert() if err != nil { return "", "", err } return certPath, keyPath, err } - return "", "", fmt.Errorf("Unsupported certmode: %s", certConfig.CertMode) + return "", "", fmt.Errorf("unsupported certmode: %s", certConfig.CertMode) } func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboundFallback, error) { if fallbackConfigs == nil { - return nil, fmt.Errorf("You must provide FallBackConfigs") + return nil, fmt.Errorf("you must provide FallBackConfigs") } vlessFallBacks := make([]*conf.VLessInboundFallback, len(fallbackConfigs)) for i, c := range fallbackConfigs { if c.Dest == "" { - return nil, fmt.Errorf("Dest is required for fallback fialed") + return nil, fmt.Errorf("dest is required for fallback fialed") } var dest json.RawMessage dest, err := json.Marshal(c.Dest) if err != nil { - return nil, fmt.Errorf("Marshal dest %s config fialed: %s", dest, err) + return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err) } vlessFallBacks[i] = &conf.VLessInboundFallback{ Name: c.SNI, @@ -257,20 +257,20 @@ func buildVlessFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.VLessInboun func buildTrojanFallbacks(fallbackConfigs []*FallBackConfig) ([]*conf.TrojanInboundFallback, error) { if fallbackConfigs == nil { - return nil, fmt.Errorf("You must provide FallBackConfigs") + return nil, fmt.Errorf("you must provide FallBackConfigs") } trojanFallBacks := make([]*conf.TrojanInboundFallback, len(fallbackConfigs)) for i, c := range fallbackConfigs { if c.Dest == "" { - return nil, fmt.Errorf("Dest is required for fallback fialed") + return nil, fmt.Errorf("dest is required for fallback fialed") } var dest json.RawMessage dest, err := json.Marshal(c.Dest) if err != nil { - return nil, fmt.Errorf("Marshal dest %s config fialed: %s", dest, err) + return nil, fmt.Errorf("marshal dest %s config fialed: %s", dest, err) } trojanFallBacks[i] = &conf.TrojanInboundFallback{ Name: c.SNI, diff --git a/service/controller/inboundbuilder_test.go b/service/controller/inboundbuilder_test.go index 5614d39..a6bc372 100644 --- a/service/controller/inboundbuilder_test.go +++ b/service/controller/inboundbuilder_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/XrayR-project/XrayR/api" + "github.com/XrayR-project/XrayR/common/mylego" . "github.com/XrayR-project/XrayR/service/controller" ) @@ -20,7 +21,7 @@ func TestBuildV2ray(t *testing.T) { EnableTLS: false, TLSType: "tls", } - certConfig := &CertConfig{ + certConfig := &mylego.CertConfig{ CertMode: "http", CertDomain: "test.test.tk", Provider: "alidns", @@ -51,7 +52,7 @@ func TestBuildTrojan(t *testing.T) { DNSEnv := make(map[string]string) DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa" DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb" - certConfig := &CertConfig{ + certConfig := &mylego.CertConfig{ CertMode: "dns", CertDomain: "trojan.test.tk", Provider: "alidns", @@ -83,7 +84,7 @@ func TestBuildSS(t *testing.T) { DNSEnv := make(map[string]string) DNSEnv["ALICLOUD_ACCESS_KEY"] = "aaa" DNSEnv["ALICLOUD_SECRET_KEY"] = "bbb" - certConfig := &CertConfig{ + certConfig := &mylego.CertConfig{ CertMode: "dns", CertDomain: "trojan.test.tk", Provider: "alidns",