-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
doc: add ACME (LetsEncrypt, etc) example docs to the standard library #17053
Comments
Like what I'm seeing so far! I wonder if the ACME configuration should be in a separate struct value -- do we want to tether the http.Server type to ACME concretely? One of the requests we've had in Caddy is to abstract the way certificates are In fact, thinking on these lines, it might be beneficial to drop down to the FWIW, In Caddy I found myself writing essentially a wrapper type over tls.Config that specifies all the ACME stuff and makes the GetCertificate callback, etc. It all happens within TLS (not just HTTPS), so how about an easy way to make an ACME-capable TLS listener that you pass into |
I've been moving all of my Go servers to use ACME (with letsencrypt) and I've been using Russ's letsencrypt package for now because it is so simple and easy. However, I've also contributed to the However, I don't like the use of fields in (as I was writing this, I noticed @mholt's comment which I 👍) |
This is super cool! With my Let's Encrypt hat on: One important thing to consider though is that currently neither the ACME spec nor the API implementation provided by Let's Encrypt should be considered completely stable. The Let's Encrypt API currently implements a amalgam of the four ACME RFC drafts which we colloquially refer to as Once |
👍🏻 |
I totally agree. But Go 1.8 isn't due until 2017 anyway. The timing might work out? But even Go 1.9 is acceptable, if that works out best timing-wse. |
Another Let's Encrypt developer here. Wrote out a post saying what @rolandshoemaker said about upcoming ACME changes, but he beat me to it! Also, ideally the design should encourage disk-based caching as much as possible. If Go programs are designed to issue on each startup, people will very quickly run into Let's Encrypt rate limits. I see that Lastly: This is great, and I'm super happy to see it. This is exactly the type of thing Let's Encrypt exists to enable. Thanks! |
@jsha, as I said in my first post, caching would automatic. There wouldn't even be an option to disable it. Only an option to change the directory it uses. |
Got it! I read too quickly. :-) |
As awesome as this sounds, I think this shouldn't be included in the standard library. I understand that people will say: it's about security, or other arguments, which, yes, are valid. But please consider this:
Considering proposals to include different useful things in the language or standard library have been shut down of over the course of years, I would like to know if this means a change in vision on how the standard library / language should evolve from here on out. Does it mean that I can raise a proposal for having |
I agree they're probably too stuttery. Being a listener is interesting, though. Maybe: package main
import (
"crypto/tls"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", websiteHandler)
var srv http.Server
log.Fatal(srv.Serve(&tls.ACMEListener{
Domain: "foo.com",
Provider: tls.LetsEncrypt,
AgreeTOS: tls.YesIAgreeTOS,
}))
} |
@bradfitz I like that. But now, I'm not sure if |
@dlsniper, the timing with regards to its draft status is discussed above. See comments from @rolandshoemaker and @jsha.
Yes. And maybe all we do here is add documentation examples on how to use autocert. Maybe that's enough. I'd like it to be even easier, though.
You can propose anything you like, but that discussion happened a long time ago and was already decided. If you insist on raising it again, please do it elsewhere and not in this issue. |
@nhooyr, I don't really want to add a new package, though. We already have https://golang.org/pkg/net/http/httputil/ though. Maybe that's a suitable location. |
@bradfitz That's better. I imagine the And maybe the And why not just |
@bradfitz actually, I meant the high level package https://godoc.org/golang.org/x/crypto/acme/autocert. |
So package main
import (
"crypto/acme"
"crypto/acme/autocert"
"crypto/tls"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", websiteHandler)
var srv http.Server
log.Fatal(srv.Serve(&autocert.Listener{
Domain: "foo.com",
Provider: acme.LetsEncrypt,
AgreeTOS: autocert.AcceptTOS,
}))
} I think it would fit in with autocert being the high level package for using acme. |
@mholt, I addressed my opinion on the default in my initial proposal text at top:
We could provide two LetsEncrypt constants for prod vs staging but I don't want to make LetsEncrypt be automatic. Depending on any specific organization (for-profit or otherwise) rubs me the wrong way. I want users to explicitly opt-in to it and know what's happening. (Or hopefully know what's happening by being curious what the line |
@mholt the acme package uses a callback to determine whether or not you agree to the TOS. the autocert package provides a convenient |
The only issue there is that you then have to import an external package to use it. |
@nhooyr, you can basically already do that. This proposal is about whether Go should come out of the box with ACME support, now that ACME is a thing. Go has always been very pro-easy-HTTPS, but ACME wasn't an option at the time when Go first came out. The question is whether we continue the tradition of promoting easy HTTPS. |
I already addressed that. See my original text at the top of this issue. |
Oops, you're right.
This makes sense. And I agree with this philosophy. But if you're going to provide a |
@bradfitz @mholt |
Sure. Or for all public, non-profit (or at least free) ones. I'd rather the user not have to provide a big ugly string. I'd like to keep the boilerplate as tidy as possible. |
Let's Encrypt created the ACME spec, but anybody can implement it. StartCom/StartSSL has announced they plan to use ACME: https://www.ietf.org/mail-archive/web/acme/current/msg01290.html So maybe there will be two. We'll see. |
The proposal would dramatically increase the amount of code net/http depends on. For that reason alone, I'd prefer to leave ACME support where it is and settle on clean, standard way to use it. I do not believe it is necessary for it to be in the standard repo for it to be easy to use. To put it another way, you have stated your goal of easy security, which I applaud, but there has not been sufficient study of the various ways to do that. |
@robpike, it's not much code, if that's the root of your argument. |
Does Go have a policy about the docs for the standard library including On Thu, Sep 15, 2016 at 2:07 PM, Russ Cox notifications@github.com wrote:
"I disapprove of what you say, but I will defend to the death your right to |
Stop sending these to me! torsdag 15 september 2016 skrev Brad Fitzpatrick notifications@github.com:
|
Allowing the cache implementation (not just directory) to be overridden seems essential to me. Eg, if you are running a binary that compiles this code in on many servers (either your actual app or a custom proxy) which do not share a disk you likely do not want them all to individually and separately talk to LetsEncrypt as that will quickly exhaust your rate limits. (Otherwise +1 on this general idea. We are a production user of github.com/hlandau/acme but hopefully this library provides similar support, or we can just keep using hlandau.) |
Wouldn't it make sense to have something like a Note: I'm not saying that the package shouldn't be included, just that it might be a good idea to have it in a way that makes it possible to swap implementation. |
Another argument for a separate listener vs http.Server: presumably you need to configure what domain you're requesting the cert for (vs getting a cert for whatever shows up in a Host header?) In the original snippet I guess the implication was that it derives that from Addr, but it's very common for a server to live behind a proxy and not listen on an interface that directly answers to the domain name for which the cert is needed. |
I should also add that if this is done as proposed, any other ACME implementation (and there are many) will almost certainly (and should) use |
Thanks everyone for the feedback. There's some good stuff in here. However, given the length of this thread and the unlikelihood that anybody's read it all, I think it's time to freeze this thread until it's time for any next step, which won't be at least 4-6 months probably. The plan at this point is just to implement more in |
Ping @bradfitz - We would like to see the documentation. |
CL https://golang.org/cl/39207 mentions this issue. |
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Now users can do 1-line LetsEncrypt HTTPS servers: log.Fatal(http.Serve(autocert.NewListener("example.com"), handler)) Updates golang/go#17053 Change-Id: I13fcd3985ebf6bc97a7524cceeb7641cf1b66b22 Reviewed-on: https://go-review.googlesource.com/39207 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Vaghin <ddos@google.com>
Thanks to @crhym3, we now have a suitably-licensed & CLA-clean ACME implementation in https://godoc.org/golang.org/x/crypto/acme (and a high-level package in https://godoc.org/golang.org/x/crypto/acme/autocert).
I'd like to consider privately vendoring that into Go 1.8 and making HTTPS even easier.
I'd like a complete user program with automatic HTTPS certs to look something like:
Misc notes:
ACMEFoo
names are placeholders. Maybe they'd deserve their own struct.ACMEServer
would be required as the opt-in, and we wouldn't make LetsEncrypt be automatic or preferred, but we would add a constantconst LetsEncrypt = "https://acme-v01.api.letsencrypt.org/directory"
like theacme
package has.ACMEAgreeTOS
would be required for now. The ACME protocol requires a TOS agreement because the CAB Forum requires cert issuers to have a legal relationship with the people getting certs or something. It's mostly a formality, but we shouldn't make it automatically say "yes" either, even though I don't think LetsEncrypt themselves care. Maybe we could export the https://godoc.org/golang.org/x/crypto/acme#AcceptTOS func in thenet/http
package to reduce the boilerplate.ACMEEmail
is optional. If provided, your ACME cert provider can keep you updated on problems or changes.golang.org/x/crypto/acme/autocert
package yourself. This is analogous to the HTTP/2 situation where common HTTP/2 is provided automatically, but weird uses require importing the guts.srv.ListenAndServeTLS("", "")
is already valid for the past few releases, since 6a208ef for net/http: Server.ListenAndServeTLS not compatible with tls.Config.GetCertificate #14268 requested by @willchan specifically for LetsEncrypt stuff. It's a little ugly but works. Maybe we could provide instead a new method or option which also listens on an cleartext port 80 and redirects HTTP to HTTPS, optionally with a HSTS header.My goal is for HTTPS to be dead simple out of the box.
Thoughts?
/cc @adg @broady @campoy @quentinmit @rsc @robpike @ianlancetaylor @mholt @crhym3
The text was updated successfully, but these errors were encountered: