Matthias Andreas Benkard | 832a54e | 2019-01-29 09:27:38 +0100 | [diff] [blame^] | 1 | /* |
| 2 | Copyright 2016 The Kubernetes Authors. |
| 3 | |
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | you may not use this file except in compliance with the License. |
| 6 | You may obtain a copy of the License at |
| 7 | |
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | |
| 10 | Unless required by applicable law or agreed to in writing, software |
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | See the License for the specific language governing permissions and |
| 14 | limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package server |
| 18 | |
| 19 | import ( |
| 20 | "context" |
| 21 | "crypto/tls" |
| 22 | "crypto/x509" |
| 23 | "fmt" |
| 24 | "net" |
| 25 | "net/http" |
| 26 | "strings" |
| 27 | "time" |
| 28 | |
| 29 | "github.com/golang/glog" |
| 30 | "golang.org/x/net/http2" |
| 31 | |
| 32 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" |
| 33 | "k8s.io/apimachinery/pkg/util/validation" |
| 34 | ) |
| 35 | |
| 36 | const ( |
| 37 | defaultKeepAlivePeriod = 3 * time.Minute |
| 38 | ) |
| 39 | |
| 40 | // serveSecurely runs the secure http server. It fails only if certificates cannot |
| 41 | // be loaded or the initial listen call fails. The actual server loop (stoppable by closing |
| 42 | // stopCh) runs in a go routine, i.e. serveSecurely does not block. |
| 43 | func (s *SecureServingInfo) Serve(handler http.Handler, shutdownTimeout time.Duration, stopCh <-chan struct{}) error { |
| 44 | if s.Listener == nil { |
| 45 | return fmt.Errorf("listener must not be nil") |
| 46 | } |
| 47 | |
| 48 | secureServer := &http.Server{ |
| 49 | Addr: s.Listener.Addr().String(), |
| 50 | Handler: handler, |
| 51 | MaxHeaderBytes: 1 << 20, |
| 52 | TLSConfig: &tls.Config{ |
| 53 | NameToCertificate: s.SNICerts, |
| 54 | // Can't use SSLv3 because of POODLE and BEAST |
| 55 | // Can't use TLSv1.0 because of POODLE and BEAST using CBC cipher |
| 56 | // Can't use TLSv1.1 because of RC4 cipher usage |
| 57 | MinVersion: tls.VersionTLS12, |
| 58 | // enable HTTP2 for go's 1.7 HTTP Server |
| 59 | NextProtos: []string{"h2", "http/1.1"}, |
| 60 | }, |
| 61 | } |
| 62 | |
| 63 | if s.MinTLSVersion > 0 { |
| 64 | secureServer.TLSConfig.MinVersion = s.MinTLSVersion |
| 65 | } |
| 66 | if len(s.CipherSuites) > 0 { |
| 67 | secureServer.TLSConfig.CipherSuites = s.CipherSuites |
| 68 | } |
| 69 | |
| 70 | if s.Cert != nil { |
| 71 | secureServer.TLSConfig.Certificates = []tls.Certificate{*s.Cert} |
| 72 | } |
| 73 | |
| 74 | // append all named certs. Otherwise, the go tls stack will think no SNI processing |
| 75 | // is necessary because there is only one cert anyway. |
| 76 | // Moreover, if ServerCert.CertFile/ServerCert.KeyFile are not set, the first SNI |
| 77 | // cert will become the default cert. That's what we expect anyway. |
| 78 | for _, c := range s.SNICerts { |
| 79 | secureServer.TLSConfig.Certificates = append(secureServer.TLSConfig.Certificates, *c) |
| 80 | } |
| 81 | |
| 82 | if s.ClientCA != nil { |
| 83 | // Populate PeerCertificates in requests, but don't reject connections without certificates |
| 84 | // This allows certificates to be validated by authenticators, while still allowing other auth types |
| 85 | secureServer.TLSConfig.ClientAuth = tls.RequestClientCert |
| 86 | // Specify allowed CAs for client certificates |
| 87 | secureServer.TLSConfig.ClientCAs = s.ClientCA |
| 88 | } |
| 89 | |
| 90 | if s.HTTP2MaxStreamsPerConnection > 0 { |
| 91 | http2.ConfigureServer(secureServer, &http2.Server{ |
| 92 | MaxConcurrentStreams: uint32(s.HTTP2MaxStreamsPerConnection), |
| 93 | }) |
| 94 | } |
| 95 | |
| 96 | glog.Infof("Serving securely on %s", secureServer.Addr) |
| 97 | return RunServer(secureServer, s.Listener, shutdownTimeout, stopCh) |
| 98 | } |
| 99 | |
| 100 | // RunServer listens on the given port if listener is not given, |
| 101 | // then spawns a go-routine continuously serving |
| 102 | // until the stopCh is closed. This function does not block. |
| 103 | // TODO: make private when insecure serving is gone from the kube-apiserver |
| 104 | func RunServer( |
| 105 | server *http.Server, |
| 106 | ln net.Listener, |
| 107 | shutDownTimeout time.Duration, |
| 108 | stopCh <-chan struct{}, |
| 109 | ) error { |
| 110 | if ln == nil { |
| 111 | return fmt.Errorf("listener must not be nil") |
| 112 | } |
| 113 | |
| 114 | // Shutdown server gracefully. |
| 115 | go func() { |
| 116 | <-stopCh |
| 117 | ctx, cancel := context.WithTimeout(context.Background(), shutDownTimeout) |
| 118 | server.Shutdown(ctx) |
| 119 | cancel() |
| 120 | }() |
| 121 | |
| 122 | go func() { |
| 123 | defer utilruntime.HandleCrash() |
| 124 | |
| 125 | var listener net.Listener |
| 126 | listener = tcpKeepAliveListener{ln.(*net.TCPListener)} |
| 127 | if server.TLSConfig != nil { |
| 128 | listener = tls.NewListener(listener, server.TLSConfig) |
| 129 | } |
| 130 | |
| 131 | err := server.Serve(listener) |
| 132 | |
| 133 | msg := fmt.Sprintf("Stopped listening on %s", ln.Addr().String()) |
| 134 | select { |
| 135 | case <-stopCh: |
| 136 | glog.Info(msg) |
| 137 | default: |
| 138 | panic(fmt.Sprintf("%s due to error: %v", msg, err)) |
| 139 | } |
| 140 | }() |
| 141 | |
| 142 | return nil |
| 143 | } |
| 144 | |
| 145 | type NamedTLSCert struct { |
| 146 | TLSCert tls.Certificate |
| 147 | |
| 148 | // names is a list of domain patterns: fully qualified domain names, possibly prefixed with |
| 149 | // wildcard segments. |
| 150 | Names []string |
| 151 | } |
| 152 | |
| 153 | // getNamedCertificateMap returns a map of *tls.Certificate by name. It's is |
| 154 | // suitable for use in tls.Config#NamedCertificates. Returns an error if any of the certs |
| 155 | // cannot be loaded. Returns nil if len(certs) == 0 |
| 156 | func GetNamedCertificateMap(certs []NamedTLSCert) (map[string]*tls.Certificate, error) { |
| 157 | // register certs with implicit names first, reverse order such that earlier trump over the later |
| 158 | byName := map[string]*tls.Certificate{} |
| 159 | for i := len(certs) - 1; i >= 0; i-- { |
| 160 | if len(certs[i].Names) > 0 { |
| 161 | continue |
| 162 | } |
| 163 | cert := &certs[i].TLSCert |
| 164 | |
| 165 | // read names from certificate common names and DNS names |
| 166 | if len(cert.Certificate) == 0 { |
| 167 | return nil, fmt.Errorf("empty SNI certificate, skipping") |
| 168 | } |
| 169 | x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) |
| 170 | if err != nil { |
| 171 | return nil, fmt.Errorf("parse error for SNI certificate: %v", err) |
| 172 | } |
| 173 | cn := x509Cert.Subject.CommonName |
| 174 | if cn == "*" || len(validation.IsDNS1123Subdomain(strings.TrimPrefix(cn, "*."))) == 0 { |
| 175 | byName[cn] = cert |
| 176 | } |
| 177 | for _, san := range x509Cert.DNSNames { |
| 178 | byName[san] = cert |
| 179 | } |
| 180 | // intentionally all IPs in the cert are ignored as SNI forbids passing IPs |
| 181 | // to select a cert. Before go 1.6 the tls happily passed IPs as SNI values. |
| 182 | } |
| 183 | |
| 184 | // register certs with explicit names last, overwriting every of the implicit ones, |
| 185 | // again in reverse order. |
| 186 | for i := len(certs) - 1; i >= 0; i-- { |
| 187 | namedCert := &certs[i] |
| 188 | for _, name := range namedCert.Names { |
| 189 | byName[name] = &certs[i].TLSCert |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | return byName, nil |
| 194 | } |
| 195 | |
| 196 | // tcpKeepAliveListener sets TCP keep-alive timeouts on accepted |
| 197 | // connections. It's used by ListenAndServe and ListenAndServeTLS so |
| 198 | // dead TCP connections (e.g. closing laptop mid-download) eventually |
| 199 | // go away. |
| 200 | // |
| 201 | // Copied from Go 1.7.2 net/http/server.go |
| 202 | type tcpKeepAliveListener struct { |
| 203 | *net.TCPListener |
| 204 | } |
| 205 | |
| 206 | func (ln tcpKeepAliveListener) Accept() (net.Conn, error) { |
| 207 | tc, err := ln.AcceptTCP() |
| 208 | if err != nil { |
| 209 | return nil, err |
| 210 | } |
| 211 | tc.SetKeepAlive(true) |
| 212 | tc.SetKeepAlivePeriod(defaultKeepAlivePeriod) |
| 213 | return tc, nil |
| 214 | } |