golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.68k stars 17.62k forks source link

crypto/tls: add (*tls.Conn).HandshakeContext and add context to ClientHelloInfo and CertificateRequestInfo #32406

Closed johanbrandhorst closed 3 years ago

johanbrandhorst commented 5 years ago

Proposal

I propose an unexported context.Context field is added to the ClientHelloInfo and CertificateRequestInfo crypto/tls types. We should also add a Context() context.Context method to these types to access this context. Further, we should add a new method, HandshakeContext(context.Context) error to the tls.Conn struct, which will be used to propagate a context down the handshake call stack. The existing Handshake() error would call to the new method with a context.Background() context.

Standard library uses of (*tls.Conn).Handshake() should be moved over to the new method, where appropriate. For example, it is not clear that it is appropriate to change the existing Read and Write methods on the *tls.Conn to use the new handshake method, but in (*net/http.Server).serve, it is clear that moving to the new function would enhance the request lifetime control in the function.

The context.Context provided to HandshakeContext would only be used for cancellation of the handshake itself, and once the handshake has completed, cancelling the context will have no effect. This is in line with the predecent set by (*net.Dialer).DialContext.

Motivation

In recent Go releases, we've been able to use the handy GetCertificate and GetClientCertificate methods of the *tls.Config to dynamically control certificate management in Go apps. This is fantastic, and has lead to things like https://godoc.org/golang.org/x/crypto/acme/autocert and https://github.com/johanbrandhorst/certify which are somewhat unique to the Go ecosystem.

Unfortunately, one glaring omission from the API is a connection context for cancellation and request scoped variable propagation. This means users have to implement custom timeouts or block their TLS connections forever in case of problems. It also means powerful observability tools like tracing and metrics that make use of the context cannot be used.

Interaction with net/http

net/http.Server provide BaseContext, which is used to set a global context for the duration of (*http.Server).Serve, and ConnContext, which is used on every new connection. The context passed to (*tls.Conn).HandshakeContext would necessarily be a child of these contexts, as the existing Handshake call is made after these contexts are created. See

johanbrandhorst commented 4 years ago

I've updated the CL with your suggestion, shall we move any more comments to the CL?

johanbrandhorst commented 3 years ago

Friendly bump, should I open a new CL? Unfortunately the emails from that CL all start with DO NOT REVIEW even though I've since changed the title :joy:.

rsc commented 3 years ago

I'm not sure what exactly is the state of this proposal. It sounds like https://github.com/golang/go/issues/32406#issuecomment-712117269 is the most recent statement of the changes. Does anyone object to those?

FiloSottile commented 3 years ago

Yes, I think those are the final proposed changes. The rest is just implementation work, I think. I have no objections.

@johanbrandhorst no need for a new CL, we're just bandwidth constrained on reviews because the freeze is close.

rsc commented 3 years ago

Based on the discussion above, then, this seems like a likely accept.

gopherbot commented 3 years ago

Change https://golang.org/cl/268197 mentions this issue: http2: use (*tls.Conn).HandshakeContext in dialTLS

FiloSottile commented 3 years ago

Ah I thought this was already approved. Reopening to finish the process. We can revert if it's not approved.

gopherbot commented 3 years ago

Change https://golang.org/cl/269217 mentions this issue: crypto/tls: test HandshakeContext context hiearchy

rsc commented 3 years ago

No change in consensus, so accepted. But we should probably wait for Go 1.17.

gopherbot commented 3 years ago

Change https://golang.org/cl/269697 mentions this issue: crypto/tls: revert "crypto/tls: add HandshakeContext method to Conn"

FiloSottile commented 3 years ago

No change in consensus, so accepted. But we should probably wait for Go 1.17.

@rsc The CL went though plenty of review cycles and landed in time for the freeze, do you mean we should revert it?

johanbrandhorst commented 3 years ago

Friendliest of bumps, this is in an inbetween state between done and reverted at this time.

johanbrandhorst commented 3 years ago

Friendly bump, this is still in an in between state (http2 changes were never merged). @rsc we need a decision here.

rsc commented 3 years ago

Please revert. And in the future, please don't start landing changes before the proposal is accepted. Thanks!

FiloSottile commented 3 years ago

And in the future, please don't start landing changes before the proposal is accepted.

That was my fault, sorry @johanbrandhorst!

johanbrandhorst commented 3 years ago

This will be reverted in https://go-review.googlesource.com/c/go/+/269697

mvdan commented 3 years ago

before the proposal is accepted

As someone just following the thread, I'm confused; I thought it was already accepted?

If what is meant is that the changes were landed for 1.16 when they should have waited for 1.17, that makes more sense.

rsc commented 3 years ago

There was definitely some confusion about what was and was not subject to the proposal approval, but the current state is that only half the changes are done right now, very late in the freeze, so we should back them out and get everything in for Go 1.17.

gopherbot commented 3 years ago

Change https://golang.org/cl/278992 mentions this issue: api/go1.16: remove crypto/tls APIs that are moved to Go 1.17

gopherbot commented 3 years ago

Change https://golang.org/cl/295370 mentions this issue: crypto/tls: add HandshakeContext method to Conn

gopherbot commented 3 years ago

Change https://golang.org/cl/295173 mentions this issue: http2: use (*tls.Conn).HandshakeContext in dialTLS

FiloSottile commented 3 years ago

Reopening to track http2 landing.

johanbrandhorst commented 3 years ago

I think we can close this now 🎉. Thanks everyone involved for helping me get this in, it took longer than we hoped but here we are! Special thanks to @FiloSottile for all the reviews and comments. Also @katiehockman @bradfitz @bcmills for helping at various stages. I'm really excited for 1.17!

dmitshur commented 3 years ago

Reopening to track http2 landing.

If this refers to pulling in CL 295173 into net/http, that has happened in CL 315831. (Please reopen if I missed something.)

Thank you @johanbrandhorst and everyone else for your patience on working through this, and congratulations on getting this in!