diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index be2e4790d..5155337ee 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -7,8 +7,10 @@ package main import ( "context" + "crypto/tls" _ "embed" "fmt" + "net/http" "os" "strings" "time" @@ -25,7 +27,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/rest" + "k8s.io/client-go/transport" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" @@ -235,9 +237,23 @@ waitOnline: startlog.Infof("Startup complete, operator running") if shouldRunAuthProxy { - rt, err := rest.TransportFor(restConfig) + cfg, err := restConfig.TransportConfig() if err != nil { - startlog.Fatalf("could not get rest transport: %v", err) + startlog.Fatalf("could not get rest.TransportConfig(): %v", err) + } + + // Kubernetes uses SPDY for exec and port-forward, however SPDY is + // incompatible with HTTP/2; so disable HTTP/2 in the proxy. + tr := http.DefaultTransport.(*http.Transport).Clone() + tr.TLSClientConfig, err = transport.TLSConfigFor(cfg) + if err != nil { + startlog.Fatalf("could not get transport.TLSConfigFor(): %v", err) + } + tr.TLSNextProto = make(map[string]func(authority string, c *tls.Conn) http.RoundTripper) + + rt, err := transport.HTTPWrappersForConfig(cfg, tr) + if err != nil { + startlog.Fatalf("could not get rest.TransportConfig(): %v", err) } go runAuthProxy(s, rt, zlog.Named("auth-proxy").Infof) } diff --git a/cmd/k8s-operator/proxy.go b/cmd/k8s-operator/proxy.go index 11a71d94f..1a307a226 100644 --- a/cmd/k8s-operator/proxy.go +++ b/cmd/k8s-operator/proxy.go @@ -5,6 +5,7 @@ package main import ( "context" + "crypto/tls" "fmt" "log" "net/http" @@ -48,7 +49,7 @@ func (h *authProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { // // It never returns. func runAuthProxy(s *tsnet.Server, rt http.RoundTripper, logf logger.Logf) { - ln, err := s.ListenTLS("tcp", ":443") + ln, err := s.Listen("tcp", ":443") if err != nil { log.Fatalf("could not listen on :443: %v", err) } @@ -103,7 +104,17 @@ func runAuthProxy(s *tsnet.Server, rt http.RoundTripper, logf logger.Logf) { Transport: rt, }, } - if err := http.Serve(ln, ap); err != nil { + hs := &http.Server{ + // Kubernetes uses SPDY for exec and port-forward, however SPDY is + // incompatible with HTTP/2; so disable HTTP/2 in the proxy. + TLSConfig: &tls.Config{ + GetCertificate: lc.GetCertificate, + NextProtos: []string{"http/1.1"}, + }, + TLSNextProto: make(map[string]func(*http.Server, *tls.Conn, http.Handler)), + Handler: ap, + } + if err := hs.ServeTLS(ln, "", ""); err != nil { log.Fatalf("runAuthProxy: failed to serve %v", err) } }