blob: 7cfc103821253683ef8191b06bc12c57a0f2b372 [file] [log] [blame]
Matthias Andreas Benkard832a54e2019-01-29 09:27:38 +01001/*
2Copyright 2016 The Kubernetes Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package server
18
19import (
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
36const (
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.
43func (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
104func 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
145type 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
156func 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
202type tcpKeepAliveListener struct {
203 *net.TCPListener
204}
205
206func (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}