blob: bf09161c9fcb545ed41135101ad0b93aae76f752 [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 "fmt"
21 "net"
22
23 restclient "k8s.io/client-go/rest"
24)
25
26// LoopbackClientServerNameOverride is passed to the apiserver from the loopback client in order to
27// select the loopback certificate via SNI if TLS is used.
28const LoopbackClientServerNameOverride = "apiserver-loopback-client"
29
30func (s *SecureServingInfo) NewLoopbackClientConfig(token string, loopbackCert []byte) (*restclient.Config, error) {
31 if s == nil || (s.Cert == nil && len(s.SNICerts) == 0) {
32 return nil, nil
33 }
34
35 host, port, err := LoopbackHostPort(s.Listener.Addr().String())
36 if err != nil {
37 return nil, err
38 }
39
40 return &restclient.Config{
41 // Increase QPS limits. The client is currently passed to all admission plugins,
42 // and those can be throttled in case of higher load on apiserver - see #22340 and #22422
43 // for more details. Once #22422 is fixed, we may want to remove it.
44 QPS: 50,
45 Burst: 100,
46 Host: "https://" + net.JoinHostPort(host, port),
47 BearerToken: token,
48 // override the ServerName to select our loopback certificate via SNI. This name is also
49 // used by the client to compare the returns server certificate against.
50 TLSClientConfig: restclient.TLSClientConfig{
51 ServerName: LoopbackClientServerNameOverride,
52 CAData: loopbackCert,
53 },
54 }, nil
55}
56
57// LoopbackHostPort returns the host and port loopback REST clients should use
58// to contact the server.
59func LoopbackHostPort(bindAddress string) (string, string, error) {
60 host, port, err := net.SplitHostPort(bindAddress)
61 if err != nil {
62 // should never happen
63 return "", "", fmt.Errorf("invalid server bind address: %q", bindAddress)
64 }
65
66 // Value is expected to be an IP or DNS name, not "0.0.0.0".
67 if host == "0.0.0.0" || host == "::" {
68 host = "localhost"
69 // Get ip of local interface, but fall back to "localhost".
70 // Note that "localhost" is resolved with the external nameserver first with Go's stdlib.
71 // So if localhost.<yoursearchdomain> resolves, we don't get a 127.0.0.1 as expected.
72 addrs, err := net.InterfaceAddrs()
73 if err == nil {
74 for _, address := range addrs {
75 if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsLoopback() {
76 host = ipnet.IP.String()
77 break
78 }
79 }
80 }
81 }
82 return host, port, nil
83}