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:
parent
df4801fa4e
commit
d6f1990c7c
|
@ -11,6 +11,7 @@ load(
|
||||||
go_test(
|
go_test(
|
||||||
name = "go_default_test",
|
name = "go_default_test",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"config_selfclient_test.go",
|
||||||
"config_test.go",
|
"config_test.go",
|
||||||
"genericapiserver_test.go",
|
"genericapiserver_test.go",
|
||||||
],
|
],
|
||||||
|
|
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
@ -55,41 +54,6 @@ func (s *SecureServingInfo) NewLoopbackClientConfig(token string, loopbackCert [
|
||||||
}, nil
|
}, 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
|
// LoopbackHostPort returns the host and port loopback REST clients should use
|
||||||
// to contact the server.
|
// to contact the server.
|
||||||
func LoopbackHostPort(bindAddress string) (string, string, error) {
|
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".
|
// Value is expected to be an IP or DNS name, not "0.0.0.0".
|
||||||
if host == "0.0.0.0" {
|
if host == "0.0.0.0" {
|
||||||
// compare MaybeDefaultWithSelfSignedCerts which adds "localhost" to the cert as alternateDNS
|
|
||||||
host = "localhost"
|
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
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue