go-acme / lego Goto Github PK
View Code? Open in Web Editor NEWLet's Encrypt/ACME client and library written in Go
Home Page: https://go-acme.github.io/lego/
License: MIT License
Let's Encrypt/ACME client and library written in Go
Home Page: https://go-acme.github.io/lego/
License: MIT License
I have a situation where the server receiving the certificate has a proxy which serves many servers in front of it (letsencrypt/acme-spec#222).
I need a way for the server behind the proxy to inform the proxy that it would like to respond to SNI requests matching <challenge1>.<challenge2>.acme.invalid
.
My initial suggestion was that the format of the challenge should be changed to <challenge1>.<challenge2>.<sub.domain.tld>.acme.invalid
(ietf-wg-acme/acme#23), but that was decided to be a non-optimal solution.
The next-best solution I can come up with is that the client should make a hook available to expose the challenge and and perform any necessary work to ensure that the response to the challenge can be received.
I'm trying to revoke a certificate using the private key of the host/server. I load the certificate's PEM-encoded bytes from a file (and confirmed that that works), and when I do client.RevokeCertificate(certBytes)
, I get this error:
2015/10/20 23:33:12 The server returned an error while trying to revoke the certificate.
{"type":"urn:acme:error:malformed","detail":"No such certificate"}
The client is created not necessarily with the same email address as was used to obtain the certificate originally. How can I use the server's private key instead to revoke the cert?
Hi Legoers. I've been so impressed with Lego after discovering it a couple of days ago that I made a short tutorial describing my setup to try to help others. You can find it here:
https://github.com/xi2/lego/wiki/A-100%25-automated-Lego-setup-for-Go-web-servers
Sorry for creating a Github issue, but there doesn't seem to be pull requests for the wiki?
Is the tutorial worth adding the wiki? I didn't want to just dump it on there as that seemed a bit rude. If it's not the right sort of thing then I will probably stick it on my blog so that's OK too and there'd be no offence caused. :)
Best wishes
This is another question/clarification.
From reading the entire README, my understanding is that lego
only needs to use port 443 by default, unless you use a custom port, then you need to forward 443 to that.
From https://www.guyrutenberg.com/2015/11/07/getting-started-with-lets-encrypt-tutorial/:
The next step is to issue the certificate and prove to Let’s Encrypt that you have some control over the domain. The client supports two methods to perform the validation. The first one is the standalone server. It works by setting up a webserver on port 443, and responding to a challenge from the Let’s Encrypt servers. However, if you already have your own web-server running on port 443 (the default for TLS/SSL), you would have to temporarily shut it down.
Which seems to confirm that idea.
However, commit c4add3c says:
Assumes the
lego
binary has permission to bind to ports 80 and 443.
This is the only mention of port 80 that I see in the README.
Is that accurate? Does it actually need both 80 and 443 (meaning I need to temporarily stop whatever's running on both 80 and 443 when running lego
)? Or does it only need 443, and mentioning port 80 is unintended? /cc @mholt
Whatever the answer is, I think it would be helpful to cover in a little more detail that given ports need to be available temporarily while lego
is running, and that you need to shutdown something else that might be running there. Just to let people know that it's normal procedure (and maybe suggest alternatives, etc.).
Thanks again, this project is great!
Usually when I call acme.GetOCSPForCert and pass in the PEM-encoded certificate bundle, I get this error:
asn1: syntax error: sequence truncated
This is on a 32-bit Windows VM. Here is the cert bundle - (from happy hacker fake CA):
-----BEGIN CERTIFICATE-----
MIIE4zCCA8ugAwIBAgITAPrCvQf6blNjag6FSzlxf3ZqtTANBgkqhkiG9w0BAQsF
ADAfMR0wGwYDVQQDDBRoYXBweSBoYWNrZXIgZmFrZSBDQTAeFw0xNTExMTgwMjA0
MDBaFw0xNjAyMTYwMjA0MDBaMBoxGDAWBgNVBAMTD2ZpbmVycGl4ZWxzLmNvbTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM0RTYoqnUWbeOzXrItwPxhx
Tq7zxlwj9BW3KJ07NjDpCjWWTYMB4bF0O3ipoVYzxkz/8Fd20yml8NbN+s/ajtR/
bKt1VoHersPu5Zt6sIT0BjcJrhvTUtGMnPHoKntP9Zya3aP0rTfC5+u8uzDtz+M3
636MzhcrciT1YH4ssewvhmqQnKJg27lhkRuTI300ffMzaphY4mqdmrMJN7iNwIca
XUwedz6f/SWTb6czCES4rRb4NFGfmxkdxCzrJ1bfpYrLtjYT6BodPb3yNA5C5G51
wbcHABpSI8+GuPr347Nj8aPwSfFuIdbWmigXWT0g26WesZWkfdq4nbgx5MGRx30C
AwEAAaOCAhswggIXMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD
AQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU/HnLxTMWmlG7JSKi
tti92ApIDqQwHwYDVR0jBBgwFoAU+3hPEvlgFYMsnxd/NBmzLjbqQYkweAYIKwYB
BQUHAQEEbDBqMDMGCCsGAQUFBzABhidodHRwOi8vb2NzcC5zdGFnaW5nLXgxLmxl
dHNlbmNyeXB0Lm9yZy8wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9jZXJ0LnN0YWdpbmct
eDEubGV0c2VuY3J5cHQub3JnLzAaBgNVHREEEzARgg9maW5lcnBpeGVscy5jb20w
ggEABgNVHSAEgfgwgfUwCgYGZ4EMAQIBMAAwgeYGCysGAQQBgt8TAQEBMIHWMCYG
CCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUH
AgIwgZ4MgZtUaGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9u
IGJ5IFJlbHlpbmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGgg
dGhlIENlcnRpZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNy
eXB0Lm9yZy9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEABQOe88NEmuig
dWSpxUDThdEwlGXmo3V+JUuBpepojlBoPxI/lNn3iIFvPTM2pB384ZSDQ0LeIgW3
LoVws10zSEx1jFDzJmqdFv7K+/7pHmUXDEsH+KiwbTyAaawM+uoNL4P0lCqI0g7H
j3YgPBMWHZ+8udLBxbRvqjQC8RT0mUXZl2PdQbYo4/MnauCq21BAsUieCkTNz84w
hizziDazIhOnxY1U+F12uH/8n619Gm530y5MBaavLXWsrTTYfN4r8kEt3mTplXlW
UXJr1KMHxARHFIUQopKfd25vjzJyHIhJqF6tEeJgVvSdfqH08IfRUQ1wYMHLJ2ks
hmTQWMs2Mg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDETCCAfmgAwIBAgIJAJzxkS6o1QkIMA0GCSqGSIb3DQEBCwUAMB8xHTAbBgNV
BAMMFGhhcHB5IGhhY2tlciBmYWtlIENBMB4XDTE1MDQwNzIzNTAzOFoXDTI1MDQw
NDIzNTAzOFowHzEdMBsGA1UEAwwUaGFwcHkgaGFja2VyIGZha2UgQ0EwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCCkd5mgXFErJ3F2M0E9dw+Ta/md5i
8TDId01HberAApqmydG7UZYF3zLTSzNjlNSOmtybvrSGUnZ9r9tSQcL8VM6WUOM8
tnIpiIjEA2QkBycMwvRmZ/B2ltPdYs/R9BqNwO1g18GDZrHSzUYtNKNeFI6Glamj
7GK2Vr0SmiEamlNIR5ktAFsEErzf/d4jCF7sosMsJpMCm1p58QkP4LHLShVLXDa8
BMfVoI+ipYcA08iNUFkgW8VWDclIDxcysa0psDDtMjX3+4aPkE/cefmP+1xOfUuD
HOGV8XFynsP4EpTfVOZr0/g9gYQ7ZArqXX7GTQkFqduwPm/w5qxSPTarAgMBAAGj
UDBOMB0GA1UdDgQWBBT7eE8S+WAVgyyfF380GbMuNupBiTAfBgNVHSMEGDAWgBT7
eE8S+WAVgyyfF380GbMuNupBiTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUA
A4IBAQAd9Da+Zv+TjMv7NTAmliqnWHY6d3UxEZN3hFEJ58IQVHbBZVZdW7zhRktB
vR05Kweac0HJeK91TKmzvXl21IXLvh0gcNLU/uweD3no/snfdB4OoFompljThmgl
zBqiqWoKBJQrLCA8w5UB+ReomRYd/EYXF/6TAfzm6hr//Xt5mPiUHPdvYt75lMAo
vRxLSbF8TSQ6b7BYxISWjPgFASNNqJNHEItWsmQMtAjjwzb9cs01XH9pChVAWn9L
oeMKa+SlHSYrWG93+EcrIH/dGU76uNOiaDzBSKvaehG53h25MHuO1anNICJvZovW
rFo4Uv1EnkKJm3vJFe50eJGhEKlx
-----END CERTIFICATE-----
Sometimes it works though. For example, I just re-ran the client for the same hostname (after deleting the cert file from last time) and had it issue a new certificate, then checking the OCSP status again showed no errors. Status was 0 (Good).
issuerBytes, err := ioutil.ReadAll(resp.Body)
allows an an attacker in a network MiTM position to exhaust the memory of any application using lego and cause a runtime panic by holding the previously opened TCP connection open and forging garbage data. The call the ioutil.ReadAll ensures that the application will consume the garbage data until it runs out of memory.
Thanks for lego, it's awesome!
When I use the DNS challenge to request a cert for a FQDN that's a CNAME, I get the following. Assume iamacname.example.com is a CNAME for www.example.com
2016/02/01 13:06:25 [INFO][iamacname.example.com] acme: Obtaining bundled SAN certificate
2016/02/01 13:06:25 [INFO][iamacname.example.com] acme: Trying to solve DNS-01
2016/02/01 13:06:25 [INFO] acme: Please create the following TXT record in your DNS zone:
2016/02/01 13:06:25 [INFO] acme: _acme-challenge.iamacname.example.com. 120 IN TXT "U4BJAr7Mg1x2BSdYWeCDLvWSYPkj14XR3uohxan1_RU"
2016/02/01 13:06:25 [INFO] acme: Press 'Enter' when you are done
2016/02/01 13:06:25 [INFO] acme: You can now remove this TXT record from your DNS zone:
2016/02/01 13:06:25 [INFO] acme: _acme-challenge.iamacname.example.com. 120 IN TXT "..."
panic: interface conversion: dns.RR is *dns.CNAME, not *dns.SOA
goroutine 1 [running]:
github.com/xenolf/lego/acme.checkDNS(0x7ffcb3f28514, 0x13, 0xc820424690, 0x24, 0xc820424690)
/home/happy/x/src/github.com/xenolf/lego/acme/dns_challenge.go:82 +0x355
github.com/xenolf/lego/acme.(*dnsChallenge).Solve(0xc82011c240, 0x0, 0x0, 0xc820432180, 0x6, 0xc820432190, 0x7, 0xc8203500e0, 0x68, 0xc8204240c0, ...)
/home/happy/x/src/github.com/xenolf/lego/acme/dns_challenge.go:65 +0x5a6
github.com/xenolf/lego/acme.(*Client).solveChallenges(0xc820126080, 0xc82000a300, 0x1, 0x1, 0xc82000a300)
/home/happy/x/src/github.com/xenolf/lego/acme/client.go:369 +0x250
github.com/xenolf/lego/acme.(*Client).ObtainCertificate(0xc820126080, 0xc820013990, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/home/happy/x/src/github.com/xenolf/lego/acme/client.go:227 +0x25b
main.run(0xc8200dc240)
/home/happy/x/src/github.com/xenolf/lego/cli_handlers.go:174 +0x173f
github.com/codegangsta/cli.Command.Run(0x9412b0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9dbd80, 0x3a, 0x0, ...)
/home/happy/x/src/github.com/codegangsta/cli/command.go:163 +0x131d
github.com/codegangsta/cli.(*App).Run(0xc82008fe60, 0xc82000a0c0, 0xc, 0xc, 0x0, 0x0)
/home/happy/x/src/github.com/codegangsta/cli/app.go:179 +0x1169
main.main()
/home/happy/x/src/github.com/xenolf/lego/cli.go:126 +0x106f
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/lib/go/src/runtime/asm_amd64.s:1696 +0x1
goroutine 9 [IO wait]:
net.runtime_pollWait(0x7f8f324ee000, 0x72, 0xc820012270)
/usr/lib/go/src/runtime/netpoll.go:157 +0x60
net.(*pollDesc).Wait(0xc820128060, 0x72, 0x0, 0x0)
/usr/lib/go/src/net/fd_poll_runtime.go:73 +0x3a
net.(*pollDesc).WaitRead(0xc820128060, 0x0, 0x0)
/usr/lib/go/src/net/fd_poll_runtime.go:78 +0x36
net.(*netFD).Read(0xc820128000, 0xc82031c000, 0x800, 0x800, 0x0, 0x7f8f34652050, 0xc820012270)
/usr/lib/go/src/net/fd_unix.go:232 +0x23a
net.(*conn).Read(0xc820030080, 0xc82031c000, 0x800, 0x800, 0x0, 0x0, 0x0)
/usr/lib/go/src/net/net.go:172 +0xe4
crypto/tls.(*block).readFromUntil(0xc8201123f0, 0x7f8f34656b50, 0xc820030080, 0x5, 0x0, 0x0)
/usr/lib/go/src/crypto/tls/conn.go:455 +0xcc
crypto/tls.(*Conn).readRecord(0xc8200d4840, 0xa14117, 0x0, 0x0)
/usr/lib/go/src/crypto/tls/conn.go:540 +0x2d1
crypto/tls.(*Conn).Read(0xc8200d4840, 0xc820188000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/lib/go/src/crypto/tls/conn.go:901 +0x167
net/http.noteEOFReader.Read(0x7f8f34663308, 0xc8200d4840, 0xc8200e67e8, 0xc820188000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
/usr/lib/go/src/net/http/transport.go:1370 +0x67
net/http.(*noteEOFReader).Read(0xc82044a700, 0xc820188000, 0x1000, 0x1000, 0x0, 0x0, 0x0)
<autogenerated>:126 +0xd0
bufio.(*Reader).fill(0xc8203ecfc0)
/usr/lib/go/src/bufio/bufio.go:97 +0x1e9
bufio.(*Reader).Peek(0xc8203ecfc0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/lib/go/src/bufio/bufio.go:132 +0xcc
net/http.(*persistConn).readLoop(0xc8200e6790)
/usr/lib/go/src/net/http/transport.go:876 +0xf7
created by net/http.(*Transport).dialConn
/usr/lib/go/src/net/http/transport.go:685 +0xc78
goroutine 10 [select]:
net/http.(*persistConn).writeLoop(0xc8200e6790)
/usr/lib/go/src/net/http/transport.go:1009 +0x40c
created by net/http.(*Transport).dialConn
/usr/lib/go/src/net/http/transport.go:686 +0xc9d
Continued from my comments in #2:
$ lego --email="[email protected]" --domains="example.com" --dns="route53" --exclude="http-01" --exclude="tls-sni-01" run
2016/01/29 23:06:03 [INFO][example.com] acme: Obtaining bundled SAN certificate
2016/01/29 23:06:03 [INFO][example.com] acme: Could not find solver for: http-01
2016/01/29 23:06:03 [INFO][example.com] acme: Could not find solver for: tls-sni-01
2016/01/29 23:06:03 [INFO] acme: Trying to solve DNS-01
2016/01/29 23:06:04 [example.com] Could not obtain certificates
Error presenting token Request failed, got status code: 400. Response: <?xml version="1.0"?>
<ErrorResponse xmlns="https://route53.amazonaws.com/doc/2013-04-01/"><Error><Type>Sender</Type><Code>InvalidChangeBatch</Code><Message>Invalid Resource Record: FATAL problem: InvalidTXTRDATA encountered at hcpTWGxkPEGUMxJMPsXtsPE0TSflliWqAKH1FJ8crvg</Message></Error><RequestId>REDACTED</RequestId></ErrorResponse>
This is with lego built from source at commit 031c5b5 (HEAD as of right now).
I don't know if this is feasible or not as I have not too much experience with letsencrypt.
Would it be possible to have some kind of 'autorenew' command which renews all certificates it finds in the lego directory which require renewal within a given period of days (preferable configurable)?
So one has just to schedule a daily cronjob which calls autorenew. Failures should then be outputted to stderr and exit with != 0, so that it's easy to send a failure notice email just in case.
It seems the server can return typed error responses alike:
HTTP/1.1 403 Forbidden
Server: nginx
Content-Type: application/problem+json
Content-Length: 90
Replay-Nonce: BImpOtZwyWj0msQvumDms8FPPheeyA-dpljvm86upH4
Expires: Wed, 28 Oct 2015 14:21:10 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Wed, 28 Oct 2015 14:21:10 GMT
Connection: close
{"type":"urn:acme:error:unauthorized","detail":"Error creating new authz :: Syntax error"}
It would be great if the client could return those error messages to stdout instead of just outputting The server did not provide enough information to proceed.
. That particular error was returned because I tried to use --domains localhost
.
The HTTP requests that contain a JWS should have the application/jose+json
Content-Type
as described in the JSON Web Signature (JWS) RFC.
To make NewClient easier to use and more customizable, I propose the following usage:
challengeTypes := acme.ChallengeHTTP | acme.ChallengeTLSSNI | acme.ChallengeDNS
client, err := acme.NewClient(dirURL, user, keyBits, challengeTypes)
// err check
// the client could have exported fields to allow it to be customized, for example:
client.HTTPChallengeServer = myServer // or whatever
client.HTTPChallengePort = optPort // instead of passing it into NewClient, which feels weird for just one challenge type
// any other customizations here, like challenge priorities:
client.ChallengePriority = []acme.ChallengeType{acme.ChallengeHTTP, acme.ChallengeTLSSNI}
// ^ although I'm not sure if the bitmask above should be mutually exclusive with priorities...
Basically, change the last argument of NewClient to be a bitmask (maybe? depends on how challenge priorities is implemented) and allow the *Client to be customized after its construction.
Hi. Firstly, thank you for making lego. It's working great for me. This is not a bug report, but merely a suggestion.
When I go looking for Go stuff my first try is normally to type the thing I am looking for into godoc.org (e.g. "lets encrypt" or "acme"). I actually did this twice over the last couple of months and failed to notice lego. I eventually found it a day or two ago via a blog post.
This could be easily remedied by adding single line package comments as discussed at https://golang.org/doc/effective_go.html#commentary for github.com/xenolf/lego and github.com/xenolf/lego/acme. I can't believe I'm the only one looking on godoc.org before looking elsewhere!
Best wishes and thanks again for lego.
Previously created a certificate:
lego --domains example.com --domains www.example.com [email protected] --path /etc/ssl/letsencrypt run
Then, tried to renew the certificate:
lego --domains example.com --domains www.example.com [email protected] run
2015/12/15 08:29:36 [INFO] acme: [example.com] Trying renewal with 2015 hours remaining
2015/12/15 08:29:36 [INFO] acme: Obtaining bundled certificates for example.com
2015/12/15 08:29:36 [INFO] acme: Trying to solve HTTP-01
2015/12/15 08:29:37 [INFO] Served key authentication
2015/12/15 08:29:38 The server validated our request
2015/12/15 08:29:38 [INFO] acme: Validations succeeded; requesting certificates
2015/12/15 08:29:40 [INFO] acme: Requesting issuer cert from https://acme-v01.api.letsencrypt.org/acme/issuer-cert
2015/12/15 08:29:41 [example.com] Server responded with a certificate.
2015/12/15 08:29:41 Error while loading the certificate for domain www.example.com
open /etc/ssl/letsencrypt/certificates/www.example.com.crt: no such file or directory
Result is a certificate without the correct Subject Alternate Names:
X509v3 Subject Alternative Name:
DNS:example.com
X509v3 Certificate Policies:
Policy: 2.23.140.1.2.1
Policy: 1.3.6.1.4.1.44947.1.1.1
CPS: http://cps.letsencrypt.org
User Notice:
Explicit Text: This Certificate may only be relied upon by Relying Parties and only in accordance with the Certificate Policy found at https://letsencrypt.org/repository/
Currently there are none... add some!
Hello,
I'm guessing the current releases are built with go 1.6 which attempts to use http/2 which doesn't currently work with the lets encrypt production servers. Given that go 1.6 has not yet been released, it seems like the released binaries should be built with 1.5 to fix this issue.
The existing "simpleHttp" and "dvsni" challenges are insecure, and Let's Encrypt will be disabling them in the near future. In order to keep working, lego will need to implement the "http-01" or "tls-sni-01" challenges.
See this issue from the official Let's Encrypt client:
certbot/certbot#914
Do you plan to implement webroot authenticator? ACME challenge file can be written to a directory, while another webserver (eg. nginx) is configured to read from it.
Not only it allows to run the client LE application as non-root user, it is also possible to run multiple cert requests at once, because it doesn't block any incoming port.
Caddy gives back a single failure message:
2015/12/06 03:51:44 [blog.coolaj86.com] failed to get certificate: The server could not validate our request.
while the python client gives back very detailed (and varied) error messages:
Failed authorization procedure. blog.coolaj86.com (tls-sni-01): urn:acme:error:unknownHost :: The server could not resolve a domain name :: No IPv4 addresses found for blog.coolaj86.com
Asking over at certbot/certbot#1855 as to how they pass error messages.
Calling ./lego
shows you some information, including the installed version. Currently it displays the wrong version (master
still shows 0.1.0 while 0.1.1 is released)
Not a huge deal, I was just a little confused at first :)
Example:
$ ./lego --email="[email protected]" --server="http://192.168.0.200:4000/directory" --http --domains="test1.com" run
Outputs
2016/01/17 18:42:46 Please specify --domains or -d
The real problem is that --http should be --http=":80" but the error is ununsual.
If you want me to fix this I can build a "pull" request.
Add the ability for renewal of issued certificates to the CLI as well as the library.
I'd like to be able to run lego --dns=foo --domains=totally.legit.biz dns-test
, which would:
foo
DNS provider to create a _acme-challenge.totally.legit.biz
record with a unique value for testing._acme-challenge.totally.legit.biz
to report that value just like a normal DNS challenge, preferably with extra log output so I can see what it's doing.This would allow users to test and troubleshoot their configuration without either a) pestering live ACME services or b) launching their own local ACME service for testing.
This would be safe to do even if someone else is concurrently answering challenges for the same name because identically-named TXT records can coexist and DNS-01 requires only one of them to match:
To validate a DNS challenge, the server performs the following steps:
1. Compute the SHA-256 digest of the key authorization
2. Query for TXT records under the validation domain name
3. Verify that the contents of one of the TXT records matches the
digest value
Hi sorry if this is more of a stupid error by me, but I can't get lego to work on my server.
Running letsencryt-auto works and creates certificates:
/opt/letsencrypt/letsencrypt-auto --agree-dev-preview --server https://acme-v01.api.letsencrypt.org/directory auth -d sub.mydomain.com--standalone
Running lego:
./Go/bin/lego --domains=sub.mydomain.com -B 4096 --email="[email protected]" --port 10443 -s "https://acme-v01.api.letsencrypt.org/" run
gets me:
2015/11/20 16:24:52 [INFO] acme: Obtaining bundled SAN certificate for mydomain.com
2015/11/20 16:24:53 [INFO] acme: Trying to solve HTTP-01
2015/11/20 16:24:54 [mydomain.com] Could not obtain certificates
The server could not validate our request.
Can you help me out here? I even tried the add-tls-sni-challenge
branch, but with the same results.
Hello,
Do you have plan to implement ECC account key and ECC certificate ?
Hi there!
I updated to 0.2 today, and my bundled certificate can no longer be aquired.
sudo /home/ansible/lego --exclude "tls-sni-01" --domains="git.example.com" --domains="cd.example.com" --domains="registry.staging.example.com" --domains="chat.staging.example.com" >
2016/01/11 14:30:45 [INFO][git.example.com, cd.example.com, registry.staging.example.com, chat.staging.example.com, accounts.staging.example.com] acme: Obtaining bundled SAN certif>
2016/01/11 14:30:46 [INFO][git.example.com] acme: Trying to solve HTTP-01
2016/01/11 14:30:48 [INFO][git.example.com] Served key authentication
2016/01/11 14:30:49 [INFO][git.example.com] The server validated our request
2016/01/11 14:30:49 [INFO][cd.example.com] acme: Could not find solver for: tls-sni-01
2016/01/11 14:30:49 [INFO][cd.example.com] acme: Trying to solve HTTP-01
2016/01/11 14:30:49 [INFO][registry.staging.example.com] acme: Could not find solver for: tls-sni-01
2016/01/11 14:30:49 [INFO][registry.staging.example.com] acme: Trying to solve HTTP-01
2016/01/11 14:30:49 [INFO][chat.staging.example.com] acme: Could not find solver for: tls-sni-01
2016/01/11 14:30:49 [INFO][chat.staging.example.com] acme: Trying to solve HTTP-01
2016/01/11 14:30:49 [INFO][accounts.staging.example.com] acme: Trying to solve HTTP-01
2016/01/11 14:30:49 [cd.example.com] Could not obtain certificates
Could not start HTTP server for challenge -> listen tcp 0.0.0.0:9999: bind: address already in use
2016/01/11 14:30:49 [registry.staging.example.com] Could not obtain certificates
Could not start HTTP server for challenge -> listen tcp 0.0.0.0:9999: bind: address already in use
2016/01/11 14:30:49 [chat.staging.example.com] Could not obtain certificates
Could not start HTTP server for challenge -> listen tcp 0.0.0.0:9999: bind: address already in use
2016/01/11 14:30:49 [accounts.staging.example.com] Could not obtain certificates
Could not start HTTP server for challenge -> listen tcp 0.0.0.0:9999: bind: address already in use
it seems to try to start one server for every domain parameter.
Earlier it created one bundled certificate with only one webserver.
hi there, just tried to renew my bundled certificate, but it always drops my SAN.
Tested with one --domains parameter that contained only the main certificate domain and also one test with all --domains parameter.
Tested versions: master and 0.2
Command to check:
openssl x509 -noout -text -in /etc/ssl/letsencrypt/certificate
I think it'd be very helpful to have a section that covers how to install lego
from source. In the README, I could only see that binary releases are available. If I want to build from source, is that supported?
I assume it would be just go get -u github.com/xenolf/lego
, but without a section like https://github.com/shurcooL/binstale#installation, I find it hard to be confident.
Leaving this out makes me worry that building from source is not recommended/not supported. Is that the case?
Had to hardcode a 5 sec sleep after creating the TXT record because of frequent errors:
acme: Error 0 - urn:acme:error:connection - DNS problem: NXDOMAIN looking up TXT for _acme-challenge.xxxx.xxxx.com
We need to tweak DNS check here a bit: https://github.com/xenolf/lego/blob/master/acme/dns_challenge.go#L70
We should not rely on the SOA record content. This gives us only the master server of the zone - which might not even be part of the NS record that recursive resolvers query to find the nameserers. Boulder uses unbound for that purpose (letsencrypt/boulder#1112 (comment)).
So the record might well be available at the master server when we query it, but this does not mean that the record has (already) been propagated to the actual nameservers that Boulders recursive resolver will query. We should therefore lookup the NS record and use the nameservers listed therein. Maybe query them all.
I am a go developer and am running servers on google compute and AWS.
I saw the python client and how it kind of integrates with Apache. Nice for Apache users but useless for me.
Is there some docs yet regarding using this go based client ?
Can i participate in testing domains and wildcard domains ? I would like to try this out for our development environments now.
Hi. I'm not sure if this is a bug or not, but if not it might be worth documenting somewhere if it isn't.
My setup is that I wanted to run lego on a non-standard port (using the --http flag) and have http-01 acme challenges forwarded to lego from my two web servers.
My first attempt at doing so was to add 302 http redirects but for some reason the Let's Encrypt validation servers just wouldn't play ball (even though everyone on the net says http redirects works fine). This was nothing to do with lego, but I just thought I'd mention it.
Having failed at that I decided to use httputil.ReverseProxy from the Go standard library to send on the challenges. This worked great with my first web server which has a single domain name on the certificate. However my second web server, which has a SAN Multi-Domain certificate, failed. The first domain on the certificate validated fine with Let's Encrypt's servers, but the second did not whith lego returning an acme "404" error.
After a bit of head scratching I turned off re-use of TCP connections between different HTTP requests in the transport of the reverse proxy by setting DisableKeepAlives in the transport to true. Then everything worked perfectly! :)
Anyway, I just thought I'd let you guys know in case it was of interest.
When certificate generation fails, the client still exits with code 0:
user@host:~$ ./lego --domains=<redacted> -B 4096 -m <redacted> --path=/etc/ssl/letsencrypt --port=9999 run
2015/12/07 15:02:40 [INFO] acme: Obtaining bundled SAN certificate for <redacted>
2015/12/07 15:02:40 [INFO] acme: Trying to solve HTTP-01
2015/12/07 15:02:41 [<redacted>] Could not obtain certificates
The server could not validate our request.
user@host:~$ echo $?
0
This makes checking for errors in the certificate generation process unnecessarily difficult.
Hi there!
I upgraded to v0.1 and now I am getting this error:
2015/12/04 10:10:14 Could not create client:decode directory: invalid character '<' looking for beginning of value
I am using the following parameters:
lego --domains=mydomain.de -B 4096 --email="[email protected]" -s "https://acme-v01.api.letsencrypt.org/" --path=/var/container/nginx/newcert/ --port 9999 run
Did something change? I tried using the existing keys and creating new ones, the error is still the same.
Thanks!
lego --email "[email protected]" -d nella.org -d blog.nella.org run
2015/12/13 00:17:21 [INFO] acme: Registering account for [email protected]
2015/12/13 00:17:21 [DEBUG] {"resource":"new-reg","contact":["mailto:[email protected]"]}
2015/12/13 00:17:21 Could not complete registration
acme: Error 400 - urn:acme:error:malformed - Unable to read/verify body :: Parse error reading JWS
The "DEBUG" line is something I added to dump the jsonBytes to see if they looked right.
My copy of lego is from c4add3c
Howdy, friendly lego devs!
Just wanted to let you know that the long-term location for a convenient Boulder testing site is https://acme-staging.api.letsencrypt.org/acme/new-reg , and that ACME has been updated: https://datatracker.ietf.org/doc/draft-barnes-acme/
(note - corrected URI to go live this week)
If you want to ping me in #letsencrypt on freenode, I'm jcj_moz.
Cheers, and keep up the good work. 👍
To piggyback off the excellent PR #38, it might be nice to see DigitalOcean support for the dns-01 challenge as well... I'll eventually do it but somebody else might beat me to it.
This may or may not be something that one want to support, but I thought I could ask.
By NAT port support I mean having the ability to run with another parameter defining the public port which the Let's Encrypt server should query against. I imagine something like this.
./lego [other params...] --port=80 --natport=8888
Where lego
would be listening on 80 in the local machine but tell the Let's Encrypt server to connect to 8888.
Pending Let's Encrypts's IPv6 support (IPv6-only hosts), I guess bootstrapping off a magic IPv4 DNS forwarder is going to be a problem...
/* .../lego/acme/dns_challenge.go */
func checkDNS(domain, fqdn string) bool {
// check if the expected DNS entry was created. If not wait for some time and try again.
m := new(dns.Msg)
m.SetQuestion(domain+".", dns.TypeSOA)
c := new(dns.Client)
in, _, err := c.Exchange(m, "8.8.8.8:53") // <= ouch
if err != nil {
return false
}
// ...
There are systems out there that let only certain DNS forwarders through their firewalls (to mitigate cache poison attacks etc), so maybe it would be an idea to provide a configurable forwarder?
den@abdim:lego$ git log -1
commit 5992793edd44b2adbf095c1bc70245bb2a440b2c
Author: xenolf <[email protected]>
Date: Fri Jan 22 02:25:27 2016 +0100
Refactor DNS precheck
den@abdim:lego$ go version
go version go1.5.3 linux/386
den@abdim:lego$ go build
# github.com/xenolf/lego/acme
acme/dns_challenge_route53.go:66: constant 9223372036854775807 overflows int
When we cannot run an ACME client on the target server a "manual" mode for the http-01
and tls-sni-01
challenges would be helpful.
Adding --manual
flag to run
command can be a solution imho.
Btw, Let's Encrypt client has a plugin for this.
Could not create client:decode directory: json: cannot unmarshal number into Go value of type acme.directory
Caddy errored out with this, but lego does the same:
gthomas@tequila:/home/gthomas$ sudo chpst -u www-data:ssl-cert /home/gthomas/bin/lego --path /var/www/.caddy/letsencrypt --server https://acme-v01.api.letsencrypt.org/directory --email [email protected] run
2015/11/10 18:04:13 No key found for account [email protected]. Generating a 2048 bit key.
2015/11/10 18:04:14 Saved key to /var/www/.caddy/letsencrypt/accounts/acme-v01.api.letsencrypt.org/[email protected]/keys/[email protected]
2015/11/10 18:04:15 Could not create client:decode directory: json: cannot unmarshal number into Go value of type acme.directory
Idea?
The logic of the --days parameter seems reversed to me:
if int(expTime.Sub(time.Now()).Hours() / 24.0) <= c.Int("days") {
return
}
This appears to renew the certificate only if it is NOT about to expire.
Is this the behaviour intended, or a typo?
Currently new private keys are generated for every certificate request - even for renewals.
This is a problem for websites using Public Key Pinning (HPKP).
There should be --reuse-key
flag for renew
action that will use the private key of the current certificate to generate the CSR.
I'm very possibly missing something, but I'm trying this running on a cloud server with a floating IP. I have set up DNS to resolve to this floating IP & then trying to do domain validation. This tries to bind to the IP that the domain resolves to which ends up with
Could not start HTTPS server for challenge -> listen tcp <IP>:5001: bind: cannot assign requested address
which is understandable because that IP is a floating IP, not bound to the host interfaces.
How about just listening on requested port rather than trying to use the requested domain IP?
It would be really nice that multiple --domains
arguments would generate a single certificate (SAN) like the python client instead of generating a single certificate for each --domain
argument.
Currently only stubbed out.
It would be good - perhaps optionally? - if failure to verify a domain name could try again using a different challenge (whichever challenges are not excluded by the user) to maximize the chances of getting a certificate.
I know we've talked about this before and is on the roadmap already, but just documenting this here so we don't forget.
lego
could grow indefinitely by supporting every DNS provider API ever made, but this seems less than ideal (#100). I'd like to discuss how to move DNS providers out of the lego
executable.
It is fortunate that DNS-01 has a very small surface area in terms of what functions are required. There's basically just two operations:
_acme-challenge.whatever IN TXT "abc123"
lego
can monitor the authoritative DNS servers to watch and wait for success, so communication from the DNS provider back to lego
can be as little as just signaling failure.
Go limits the mechanisms by which external code can interact with a project like lego
. The most straightforward mechanism is to launch a child process and interact with it, and based on my understanding of the requirements, I think that model would work fine:
lego
does everything ACME-related, ultimately deciding that it needs to create _acme-challenge.whatever IN TXT "abc123"
.lego
, having been invoked with --dns=foo
, spawns lego-dns-foo "_acme-challenge.whatever" "abc123"
, passing on its environment variables.lego-dns-foo
uses FOO_USERNAME
and FOO_PASSWORD
to create the record indicated by its arguments, then waits.lego
spins and waits for a) _acme-challenge.whatever
to show the correct value, b) lego-dns-foo
to exit, or c) some configurable timeout.lego
sees _acme-challenge.whatever
get created and proceeds in its ACME dance, yielding a completed challenge and a certificate for whatever
.lego
no longer needs _acme-challenge.whatever
, and indicates this by closing lego-dns-foo
's stdin.lego-dns-foo
sees its stdin close, removes the record, and terminates successfully.This scheme avoids unnecessary complexity (it's simple enough that a provider could be implemented with a shell script) and platform dependence (i.e. signals don't really port well to Windows). lego-dns-foo
could communicate back by printing to stdout/stderr and by exiting with a failure code, which seems like it's enough.
Some negatives of this approach are:
lego-dns-foo
doesn't get run until late in the operation, which means DNS-related configuration errors aren't detected until late in the operation. This could be mitigated by launching lego-dns-foo
with no arguments before doing anything else (i.e. "don't actually create any records, but do fail immediately if you would fail immediately"), or by adding a separate dns-test
function which creates a TXT record and verifies its content outside an ACME exchange (#110).go get github.com/xenolf/lego
becomes insufficient. (That's sort of the point, though.) Would it be okay to make users say go get github.com/xenolf/lego-dns-foo
? Do we want users to have a kitchen sink option?Thoughts?
I sweat dependency trees, and really enjoy light libraries. One of the initial appeals to me of lego
over hlandau/acme
was how light this project was in terms of dependencies to accomplish what i needed. ❤️
Unfortunately, with the current code structure, the addition of support for multiple DNS providers to solve the dns-01
challenge has increased the dependency tree 🙈.
To import github.com/hlandau/acme
the current dependency tree you need to support is
$ go list -f '{{join .Deps "\n"}}' | xargs go list -f '{{if not .Standard}}{{.ImportPath}}{{end}}'
github.com/crackcomm/cloudflare
github.com/miekg/dns
github.com/mitchellh/goamz/aws
github.com/mitchellh/goamz/route53
github.com/square/go-jose
github.com/square/go-jose/cipher
github.com/vaughan0/go-ini
github.com/weppos/dnsimple-go/dnsimple
golang.org/x/crypto/ocsp
golang.org/x/crypto/sha3
golang.org/x/net/context
Of these, I'd love to skip 6 of them (vaughan0/go-ini
is a sub dependency of mitchellh/goamz/route53
), so I'd like to propose two options for refactoring the code structure to make these dependencies separate from the main acme
package.
a) Move all providers
into a single xenolf/lego/providers
package
b) Move per-challenge pacakges (ie: xenolf/lego/providers/dns01
xenolf/lego/providers/http01
etc)
c) move to per-provider packages (ie: xenolf/lego/providers/dns/cloudflare
, xenolf/lego/providers/dnsimple
, ...)
d) some combination of the above?
(Note: i'm proposing structure, not specific naming). Since i personally don't care about the DNS providers, 2 and 3 are equal for me. I imagine others might feel differently, and the ideal case might change when more options w/ dependencies are added (like say #28).
The key is that the acme
package doesn't import these packages (because that makes them all a dependency), the cli code would import them and set them as appropriate on the Client
. Depending on the approach, the default http and tls-sni providers may or may not be moved.
thoughts @xenolf ?
After pulling the latest tonight, I get this:
2015/10/17 21:08:01 [caddy.dev] The server returned an unexpected status code 200.
Then the program exits.
Based on logs, it seems to happen just after everything is done and the web server (not the lego one, but the one I'm getting the certs for) is already started. I suspect, though I am not sure, the behavior comes from caa6e78. None of the other changes tonight seem like they would cause this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.