From d6f1990c7c0cf7bf17edf02b04a8a33e9a3da128 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Thu, 1 Jun 2017 13:24:40 +0200 Subject: [PATCH] apiserver: avoid resolving 'localhost' The golang stdlib resolve localhost first via the external DNS server, not via /etc/hosts. If your DNS resolve localhost., the API server won't start. Kubernetes-commit: 63cd572c74a40933d8e6928e084601810b724a81 --- pkg/server/BUILD | 1 + pkg/server/config_selfclient.go | 69 +++++----------------------- pkg/server/config_selfclient_test.go | 46 +++++++++++++++++++ 3 files changed, 59 insertions(+), 57 deletions(-) create mode 100644 pkg/server/config_selfclient_test.go diff --git a/pkg/server/BUILD b/pkg/server/BUILD index 29543a789..3faa3502d 100644 --- a/pkg/server/BUILD +++ b/pkg/server/BUILD @@ -11,6 +11,7 @@ load( go_test( name = "go_default_test", srcs = [ + "config_selfclient_test.go", "config_test.go", "genericapiserver_test.go", ], diff --git a/pkg/server/config_selfclient.go b/pkg/server/config_selfclient.go index a027b6076..5e37c1ad2 100644 --- a/pkg/server/config_selfclient.go +++ b/pkg/server/config_selfclient.go @@ -17,7 +17,6 @@ limitations under the License. package server import ( - "crypto/x509" "fmt" "net" @@ -55,41 +54,6 @@ func (s *SecureServingInfo) NewLoopbackClientConfig(token string, loopbackCert [ }, nil } -func trustedChain(chain []*x509.Certificate) bool { - intermediates := x509.NewCertPool() - for _, cert := range chain[1:] { - intermediates.AddCert(cert) - } - _, err := chain[0].Verify(x509.VerifyOptions{ - Intermediates: intermediates, - KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - }) - return err == nil -} - -func parseChain(bss [][]byte) ([]*x509.Certificate, error) { - var result []*x509.Certificate - for _, bs := range bss { - x509Cert, err := x509.ParseCertificate(bs) - if err != nil { - return nil, err - } - result = append(result, x509Cert) - } - - return result, nil -} - -func findCA(chain []*x509.Certificate) (*x509.Certificate, error) { - for _, cert := range chain { - if cert.IsCA { - return cert, nil - } - } - - return nil, fmt.Errorf("no certificate with CA:TRUE found in chain") -} - // LoopbackHostPort returns the host and port loopback REST clients should use // to contact the server. func LoopbackHostPort(bindAddress string) (string, string, error) { @@ -101,28 +65,19 @@ func LoopbackHostPort(bindAddress string) (string, string, error) { // Value is expected to be an IP or DNS name, not "0.0.0.0". if host == "0.0.0.0" { - // compare MaybeDefaultWithSelfSignedCerts which adds "localhost" to the cert as alternateDNS host = "localhost" + // Get ip of local interface, but fall back to "localhost". + // Note that "localhost" is resolved with the external nameserver first with Go's stdlib. + // So if localhost. resolves, we don't get a 127.0.0.1 as expected. + addrs, err := net.InterfaceAddrs() + if err == nil { + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && ipnet.IP.IsLoopback() { + host = ipnet.IP.String() + break + } + } + } } return host, port, nil } - -func certMatchesName(cert *x509.Certificate, name string) bool { - for _, certName := range cert.DNSNames { - if certName == name { - return true - } - } - - return false -} - -func certMatchesIP(cert *x509.Certificate, ip string) bool { - for _, certIP := range cert.IPAddresses { - if certIP.String() == ip { - return true - } - } - - return false -} diff --git a/pkg/server/config_selfclient_test.go b/pkg/server/config_selfclient_test.go new file mode 100644 index 000000000..d76e31f8e --- /dev/null +++ b/pkg/server/config_selfclient_test.go @@ -0,0 +1,46 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package server + +import ( + "strings" + "testing" +) + +func TestLoopbackHostPort(t *testing.T) { + host, port, err := LoopbackHostPort("1.2.3.4:443") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if host != "1.2.3.4" { + t.Fatalf("expected 1.2.3.4 as host, got %q", host) + } + if port != "443" { + t.Fatalf("expected 443 as port, got %q", port) + } + + host, port, err = LoopbackHostPort("0.0.0.0:443") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !strings.HasPrefix(host, "127.") { + t.Fatalf("expected host to start with 127., got %q", host) + } + if port != "443" { + t.Fatalf("expected 443 as port, got %q", port) + } +}