apiserver: avoid resolving 'localhost'

The golang stdlib resolve localhost first via the external DNS server,
not via /etc/hosts. If your DNS resolve localhost.<search-domain>, the
API server won't start.

Kubernetes-commit: 63cd572c74a40933d8e6928e084601810b724a81
This commit is contained in:
Dr. Stefan Schimanski 2017-06-01 13:24:40 +02:00 committed by Kubernetes Publisher
parent df4801fa4e
commit d6f1990c7c
3 changed files with 59 additions and 57 deletions

View File

@ -11,6 +11,7 @@ load(
go_test(
name = "go_default_test",
srcs = [
"config_selfclient_test.go",
"config_test.go",
"genericapiserver_test.go",
],

View File

@ -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.<yoursearchdomain> 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
}

View File

@ -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)
}
}