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