lego/cli.go

207 lines
5.8 KiB
Go
Raw Normal View History

// Let's Encrypt client to go!
// CLI application for generating Let's Encrypt certificates using the ACME package.
package main
import (
"fmt"
"log"
"os"
"path"
2016-01-09 01:13:13 +00:00
"strings"
"text/tabwriter"
"github.com/codegangsta/cli"
"github.com/xenolf/lego/acme"
)
// Logger is used to log errors; if nil, the default log.Logger is used.
var Logger *log.Logger
// logger is an helper function to retrieve the available logger
func logger() *log.Logger {
if Logger == nil {
Logger = log.New(os.Stderr, "", log.LstdFlags)
}
return Logger
}
2016-01-09 01:13:13 +00:00
var gittag string
func main() {
app := cli.NewApp()
app.Name = "lego"
2016-03-23 18:12:47 +00:00
app.Usage = "Let's Encrypt client written in Go"
2016-01-09 01:13:13 +00:00
2016-03-23 18:12:47 +00:00
version := "0.3.0"
2016-01-09 01:13:13 +00:00
if strings.HasPrefix(gittag, "v") {
version = gittag
}
app.Version = version
acme.UserAgent = "lego/" + app.Version
defaultPath := ""
cwd, err := os.Getwd()
if err == nil {
defaultPath = path.Join(cwd, ".lego")
}
app.Before = func(c *cli.Context) error {
if c.GlobalString("path") == "" {
logger().Fatal("Could not determine current working directory. Please pass --path.")
}
return nil
}
app.Commands = []cli.Command{
{
Name: "run",
2015-09-27 12:50:45 +00:00
Usage: "Register an account, then create and install a certificate",
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.",
},
},
},
{
2015-09-27 12:50:45 +00:00
Name: "revoke",
Usage: "Revoke a certificate",
Action: revoke,
},
2015-10-18 22:42:04 +00:00
{
Name: "renew",
Usage: "Renew a certificate",
Action: renew,
Flags: []cli.Flag{
cli.IntFlag{
2015-12-24 08:57:09 +00:00
Name: "days",
Value: 0,
Usage: "The number of days left on a certificate to renew it.",
},
2016-01-08 09:14:41 +00:00
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.",
},
},
2015-10-18 22:42:04 +00:00
},
{
Name: "dnshelp",
Usage: "Shows additional help for the --dns global option",
Action: dnshelp,
},
}
app.Flags = []cli.Flag{
cli.StringSliceFlag{
Name: "domains, d",
Usage: "Add domains to the process",
},
cli.StringFlag{
Name: "csr, c",
Usage: "Certificate signing request filename, if an external CSR is to be used",
},
cli.StringFlag{
Name: "server, s",
Value: "https://acme-v01.api.letsencrypt.org/directory",
Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.",
},
cli.StringFlag{
Name: "email, m",
Usage: "Email used for registration and recovery contact.",
},
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: "key-type, k",
Value: "rsa2048",
Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384",
},
cli.StringFlag{
Name: "path",
Usage: "Directory to use for storing the data",
Value: defaultPath,
},
cli.StringSliceFlag{
Name: "exclude, x",
Usage: "Explicitly disallow solvers by name from being used. Solvers: \"http-01\", \"tls-sni-01\".",
},
cli.StringFlag{
Name: "webroot",
Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge",
},
cli.StringFlag{
2016-01-08 07:05:07 +00:00
Name: "http",
Usage: "Set the port and interface to use for HTTP based challenges to listen on. Supported: interface:port or :port",
},
cli.StringFlag{
2016-01-08 07:05:07 +00:00
Name: "tls",
Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port",
},
2016-01-30 01:40:57 +00:00
cli.StringFlag{
Name: "dns",
Usage: "Solve a DNS challenge using the specified provider. Disables all other challenges. Run 'lego dnshelp' for help on usage.",
2016-01-30 01:40:57 +00:00
},
cli.IntFlag{
Name: "http-timeout",
Usage: "Set the HTTP timeout value to a specific value in seconds. The default is 10 seconds.",
},
2016-05-25 03:22:09 +00:00
cli.IntFlag{
Name: "dns-timeout",
Usage: "Set the DNS timeout value to a specific value in seconds. The default is 10 seconds.",
},
cli.BoolFlag{
Name: "pem",
Usage: "Generate a .pem file by concatanating the .key and .crt files together.",
},
}
2016-05-14 15:11:26 +00:00
err = app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
}
func dnshelp(c *cli.Context) error {
fmt.Printf(
`Credentials for DNS providers must be passed through environment variables.
Here is an example bash command using the CloudFlare DNS provider:
$ CLOUDFLARE_EMAIL=foo@bar.com \
CLOUDFLARE_API_KEY=b9841238feb177a84330febba8a83208921177bffe733 \
lego --dns cloudflare --domains www.example.com --email me@bar.com run
`)
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
fmt.Fprintln(w, "Valid providers and their associated credential environment variables:")
fmt.Fprintln(w)
fmt.Fprintln(w, "\tcloudflare:\tCLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY")
fmt.Fprintln(w, "\tdigitalocean:\tDO_AUTH_TOKEN")
fmt.Fprintln(w, "\tdnsimple:\tDNSIMPLE_EMAIL, DNSIMPLE_API_KEY")
fmt.Fprintln(w, "\tgandi:\tGANDI_API_KEY")
fmt.Fprintln(w, "\tgcloud:\tGCE_PROJECT")
fmt.Fprintln(w, "\tmanual:\tnone")
fmt.Fprintln(w, "\tnamecheap:\tNAMECHEAP_API_USER, NAMECHEAP_API_KEY")
fmt.Fprintln(w, "\trfc2136:\tRFC2136_TSIG_KEY, RFC2136_TSIG_SECRET,\n\t\tRFC2136_TSIG_ALGORITHM, RFC2136_NAMESERVER")
fmt.Fprintln(w, "\troute53:\tAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION")
fmt.Fprintln(w, "\tdyn:\tDYN_CUSTOMER_NAME, DYN_USER_NAME, DYN_PASSWORD")
2016-03-20 23:23:37 +00:00
fmt.Fprintln(w, "\tvultr:\tVULTR_API_KEY")
w.Flush()
fmt.Println(`
For a more detailed explanation of a DNS provider's credential variables,
please consult their online documentation.`)
return nil
}