2016-02-08 00:59:03 +00:00
// Let's Encrypt client to go!
// CLI application for generating Let's Encrypt certificates using the ACME package.
2015-06-08 00:36:07 +00:00
package main
import (
2016-03-18 00:32:24 +00:00
"fmt"
2015-06-08 00:36:07 +00:00
"os"
2015-06-12 21:34:49 +00:00
"path"
2016-01-09 01:13:13 +00:00
"strings"
2016-03-18 00:32:24 +00:00
"text/tabwriter"
2015-06-08 00:36:07 +00:00
2016-07-13 19:03:47 +00:00
"github.com/urfave/cli"
2018-05-27 21:55:19 +00:00
"github.com/xenolf/lego/acme"
2018-05-27 22:08:23 +00:00
"github.com/xenolf/lego/log"
2015-06-08 00:36:07 +00:00
)
2016-01-09 01:13:13 +00:00
var gittag string
2015-06-08 00:36:07 +00:00
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
2017-09-26 14:13:47 +00:00
version := "0.4.1"
2016-01-09 01:13:13 +00:00
if strings . HasPrefix ( gittag , "v" ) {
version = gittag
}
app . Version = version
2015-06-08 00:36:07 +00:00
2015-12-30 22:01:21 +00:00
acme . UserAgent = "lego/" + app . Version
2016-05-16 17:01:51 +00:00
defaultPath := ""
2015-06-12 21:34:49 +00:00
cwd , err := os . Getwd ( )
2016-05-16 17:01:51 +00:00
if err == nil {
defaultPath = path . Join ( cwd , ".lego" )
}
app . Before = func ( c * cli . Context ) error {
if c . GlobalString ( "path" ) == "" {
2018-05-27 22:08:23 +00:00
log . Fatal ( "Could not determine current working directory. Please pass --path." )
2016-05-16 17:01:51 +00:00
}
return nil
2015-06-12 21:34:49 +00:00
}
2015-06-08 00:36:07 +00:00
app . Commands = [ ] cli . Command {
{
Name : "run" ,
2015-09-27 12:50:45 +00:00
Usage : "Register an account, then create and install a certificate" ,
2015-06-08 00:36:07 +00:00
Action : run ,
2016-02-26 01:57:16 +00:00
Flags : [ ] cli . Flag {
cli . BoolFlag {
2016-02-27 09:46:13 +00:00
Name : "no-bundle" ,
2016-02-26 01:57:16 +00:00
Usage : "Do not create a certificate bundle by adding the issuers certificate to the new certificate." ,
} ,
2016-10-27 09:22:10 +00:00
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." ,
} ,
2016-02-26 01:57:16 +00:00
} ,
2015-06-08 00:36:07 +00:00
} ,
{
2015-09-27 12:50:45 +00:00
Name : "revoke" ,
Usage : "Revoke a certificate" ,
Action : revoke ,
2015-06-08 00:36:07 +00:00
} ,
2015-10-18 22:42:04 +00:00
{
Name : "renew" ,
Usage : "Renew a certificate" ,
Action : renew ,
2015-12-06 21:35:52 +00:00
Flags : [ ] cli . Flag {
cli . IntFlag {
2015-12-24 08:57:09 +00:00
Name : "days" ,
2015-12-06 21:35:52 +00:00
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." ,
} ,
2016-02-26 01:57:16 +00:00
cli . BoolFlag {
2016-02-27 09:46:13 +00:00
Name : "no-bundle" ,
2016-02-26 01:57:16 +00:00
Usage : "Do not create a certificate bundle by adding the issuers certificate to the new certificate." ,
} ,
2016-10-27 09:22:10 +00:00
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." ,
} ,
2015-12-06 21:35:52 +00:00
} ,
2015-10-18 22:42:04 +00:00
} ,
2016-03-18 00:32:24 +00:00
{
Name : "dnshelp" ,
Usage : "Shows additional help for the --dns global option" ,
Action : dnshelp ,
} ,
2015-06-08 00:36:07 +00:00
}
app . Flags = [ ] cli . Flag {
cli . StringSliceFlag {
Name : "domains, d" ,
2017-09-25 20:29:31 +00:00
Usage : "Add a domain to the process. Can be specified multiple times." ,
2015-06-08 00:36:07 +00:00
} ,
2016-02-12 01:02:00 +00:00
cli . StringFlag {
Name : "csr, c" ,
Usage : "Certificate signing request filename, if an external CSR is to be used" ,
} ,
2015-06-08 00:36:07 +00:00
cli . StringFlag {
Name : "server, s" ,
2015-12-03 18:37:54 +00:00
Value : "https://acme-v01.api.letsencrypt.org/directory" ,
2015-06-08 00:36:07 +00:00
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." ,
} ,
2016-02-15 02:51:59 +00:00
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." ,
} ,
2018-05-30 00:05:57 +00:00
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." ,
} ,
2016-01-27 01:01:39 +00:00
cli . StringFlag {
Name : "key-type, k" ,
Value : "rsa2048" ,
Usage : "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384" ,
2015-06-08 00:36:07 +00:00
} ,
cli . StringFlag {
2015-06-12 21:34:49 +00:00
Name : "path" ,
Usage : "Directory to use for storing the data" ,
Value : defaultPath ,
2015-06-08 00:36:07 +00:00
} ,
2015-12-05 21:01:08 +00:00
cli . StringSliceFlag {
2015-12-27 17:30:04 +00:00
Name : "exclude, x" ,
2018-02-02 19:22:33 +00:00
Usage : "Explicitly disallow solvers by name from being used. Solvers: \"http-01\", \"tls-sni-01\", \"dns-01\",." ,
2015-12-27 17:30:04 +00:00
} ,
2016-02-10 11:19:29 +00:00
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" ,
} ,
2016-10-24 09:03:18 +00:00
cli . StringSliceFlag {
Name : "memcached-host" ,
Usage : "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts." ,
} ,
2015-12-27 17:30:04 +00:00
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" ,
2015-12-27 17:30:04 +00:00
} ,
2016-01-30 01:40:57 +00:00
cli . StringFlag {
2016-03-18 00:32:24 +00:00
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
} ,
2016-05-19 16:52:44 +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." ,
} ,
2016-08-19 09:27:26 +00:00
cli . StringSliceFlag {
Name : "dns-resolvers" ,
2018-01-15 21:11:42 +00:00
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." ,
2016-08-19 09:27:26 +00:00
} ,
2016-06-19 05:55:15 +00:00
cli . BoolFlag {
Name : "pem" ,
Usage : "Generate a .pem file by concatanating the .key and .crt files together." ,
} ,
2015-06-08 00:36:07 +00:00
}
2016-05-14 15:11:26 +00:00
err = app . Run ( os . Args )
if err != nil {
log . Fatal ( err )
}
2015-06-08 00:36:07 +00:00
}
2016-03-18 00:32:24 +00:00
2016-05-12 17:52:59 +00:00
func dnshelp ( c * cli . Context ) error {
2016-03-18 00:32:24 +00:00
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 )
2016-11-20 01:40:51 +00:00
fmt . Fprintln ( w , "\tazure:\tAZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, AZURE_RESOURCE_GROUP" )
2016-10-12 00:42:20 +00:00
fmt . Fprintln ( w , "\tauroradns:\tAURORA_USER_ID, AURORA_KEY, AURORA_ENDPOINT" )
2018-04-03 02:50:15 +00:00
fmt . Fprintln ( w , "\tbluecat:\tBLUECAT_SERVER_URL, BLUECAT_USER_NAME, BLUECAT_PASSWORD, BLUECAT_CONFIG_NAME, BLUECAT_DNS_VIEW" )
2018-02-02 19:41:35 +00:00
fmt . Fprintln ( w , "\tcloudxns:\tCLOUDXNS_API_KEY, CLOUDXNS_SECRET_KEY" )
2016-03-18 00:32:24 +00:00
fmt . Fprintln ( w , "\tcloudflare:\tCLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY" )
fmt . Fprintln ( w , "\tdigitalocean:\tDO_AUTH_TOKEN" )
2017-04-05 18:28:06 +00:00
fmt . Fprintln ( w , "\tdnsimple:\tDNSIMPLE_EMAIL, DNSIMPLE_OAUTH_TOKEN" )
2016-06-28 21:00:05 +00:00
fmt . Fprintln ( w , "\tdnsmadeeasy:\tDNSMADEEASY_API_KEY, DNSMADEEASY_API_SECRET" )
2018-04-02 14:02:54 +00:00
fmt . Fprintln ( w , "\tduckdns:\tDUCKDNS_TOKEN" )
2016-11-07 07:37:57 +00:00
fmt . Fprintln ( w , "\texoscale:\tEXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT" )
2016-03-18 00:32:24 +00:00
fmt . Fprintln ( w , "\tgandi:\tGANDI_API_KEY" )
2018-02-02 19:22:33 +00:00
fmt . Fprintln ( w , "\tgandiv5:\tGANDIV5_API_KEY" )
2017-07-17 19:40:57 +00:00
fmt . Fprintln ( w , "\tgcloud:\tGCE_PROJECT, GCE_SERVICE_ACCOUNT_FILE" )
2018-03-31 14:33:48 +00:00
fmt . Fprintln ( w , "\tglesys:\tGLESYS_API_USER, GLESYS_API_KEY" )
2016-08-29 19:37:19 +00:00
fmt . Fprintln ( w , "\tlinode:\tLINODE_API_KEY" )
2018-02-18 15:27:58 +00:00
fmt . Fprintln ( w , "\tlightsail:\tAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, DNS_ZONE" )
2016-03-18 00:32:24 +00:00
fmt . Fprintln ( w , "\tmanual:\tnone" )
fmt . Fprintln ( w , "\tnamecheap:\tNAMECHEAP_API_USER, NAMECHEAP_API_KEY" )
2018-03-14 17:43:09 +00:00
fmt . Fprintln ( w , "\tnamedotcom:\tNAMECOM_USERNAME, NAMECOM_API_TOKEN" )
2016-11-04 09:29:14 +00:00
fmt . Fprintln ( w , "\trackspace:\tRACKSPACE_USER, RACKSPACE_API_KEY" )
2016-03-18 00:32:24 +00:00
fmt . Fprintln ( w , "\trfc2136:\tRFC2136_TSIG_KEY, RFC2136_TSIG_SECRET,\n\t\tRFC2136_TSIG_ALGORITHM, RFC2136_NAMESERVER" )
2017-07-17 19:50:53 +00:00
fmt . Fprintln ( w , "\troute53:\tAWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_HOSTED_ZONE_ID" )
2016-03-18 02:30:21 +00:00
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" )
2016-06-16 19:11:19 +00:00
fmt . Fprintln ( w , "\tovh:\tOVH_ENDPOINT, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY" )
2016-08-19 07:07:18 +00:00
fmt . Fprintln ( w , "\tpdns:\tPDNS_API_KEY, PDNS_API_URL" )
2016-11-14 10:41:37 +00:00
fmt . Fprintln ( w , "\tdnspod:\tDNSPOD_API_KEY" )
2017-07-19 22:54:35 +00:00
fmt . Fprintln ( w , "\totc:\tOTC_USER_NAME, OTC_PASSWORD, OTC_PROJECT_NAME, OTC_DOMAIN_NAME, OTC_IDENTITY_ENDPOINT" )
2018-03-27 14:10:38 +00:00
fmt . Fprintln ( w , "\texec:\tEXEC_PATH" )
2016-03-18 00:32:24 +00:00
w . Flush ( )
fmt . Println ( `
For a more detailed explanation of a DNS provider ' s credential variables ,
please consult their online documentation . ` )
2016-05-12 17:52:59 +00:00
return nil
2016-03-18 00:32:24 +00:00
}