Merge pull request #62 from dlorenc/certs

Fix certificate handling.
pull/63/head
dlorenc 2016-05-11 11:21:52 -10:00
commit 30b10f4fc7
6 changed files with 46 additions and 30 deletions

View File

@ -69,8 +69,8 @@ func runStart(cmd *cobra.Command, args []string) {
kubeHost = strings.Replace(kubeHost, ":2376", ":443", -1) kubeHost = strings.Replace(kubeHost, ":2376", ":443", -1)
fmt.Printf("Kubernetes is available at %s.\n", kubeHost) fmt.Printf("Kubernetes is available at %s.\n", kubeHost)
fmt.Println("Run this command to use the cluster: ") fmt.Println("Run this command to use the cluster: ")
fmt.Printf("kubectl config set-cluster minikube --server=%s --certificate-authority=$HOME/.minikube/ca.crt\n", kubeHost) fmt.Printf("kubectl config set-cluster minikube --server=%s --certificate-authority=$HOME/.minikube/apiserver.crt\n", kubeHost)
fmt.Println("kubectl config set-credentials minikube --client-certificate=$HOME/.minikube/kubecfg.crt --client-key=$HOME/.minikube/kubecfg.key") fmt.Println("kubectl config set-credentials minikube --client-certificate=$HOME/.minikube/apiserver.crt --client-key=$HOME/.minikube/apiserver.key")
fmt.Println("kubectl config set-context minikube --cluster=minikube --user=minikube") fmt.Println("kubectl config set-context minikube --cluster=minikube --user=minikube")
fmt.Println("kubectl config use-context minikube") fmt.Println("kubectl config use-context minikube")

View File

@ -98,10 +98,10 @@ func (lk LocalkubeServer) loadCert(path string) (*x509.Certificate, error) {
return x509.ParseCertificate(decoded.Bytes) return x509.ParseCertificate(decoded.Bytes)
} }
func (lk LocalkubeServer) shouldGenerateCerts(hostIP net.IP) bool { func (lk LocalkubeServer) shouldGenerateCerts(ips []net.IP) bool {
if !(util.CanReadFile(lk.GetPublicKeyCertPath()) && if !(util.CanReadFile(lk.GetPublicKeyCertPath()) &&
util.CanReadFile(lk.GetPrivateKeyCertPath())) { util.CanReadFile(lk.GetPrivateKeyCertPath())) {
fmt.Println("Regenerating certs because the files aren't readable.") fmt.Println("Regenerating certs because the files aren't readable")
return true return true
} }
@ -111,28 +111,43 @@ func (lk LocalkubeServer) shouldGenerateCerts(hostIP net.IP) bool {
return true return true
} }
certIPs := map[string]bool{}
for _, certIP := range cert.IPAddresses { for _, certIP := range cert.IPAddresses {
if certIP.Equal(hostIP) { certIPs[certIP.String()] = true
return false
} }
}
fmt.Printf( for _, ip := range ips {
"Regenerating certs because the IP didn't match. Got %s, expected %s", if _, ok := certIPs[ip.String()]; !ok {
cert.IPAddresses, hostIP) fmt.Println("Regenerating certs becase an IP is missing: ", ip)
return true return true
} }
}
return false
}
func (lk LocalkubeServer) GenerateCerts(hostIP net.IP) error { func (lk LocalkubeServer) GenerateCerts(hostIP net.IP) error {
if !lk.shouldGenerateCerts(hostIP) { ips := []net.IP{lk.ServiceClusterIPRange.IP, hostIP}
addrs, err := net.InterfaceAddrs()
if err != nil {
return err
}
for _, addr := range addrs {
ipnet, ok := addr.(*net.IPNet)
if !ok {
fmt.Println("Skipping: ", addr)
continue
}
ips = append(ips, ipnet.IP)
}
if !lk.shouldGenerateCerts(ips) {
fmt.Println("Using these existing certs: ", lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath()) fmt.Println("Using these existing certs: ", lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath())
return nil return nil
} }
fmt.Println("Creating cert with IPs: ", ips)
alternateIPs := []net.IP{lk.ServiceClusterIPRange.IP}
alternateDNS := []string{fmt.Sprintf("%s.%s", "kubernetes.default.svc", lk.DNSDomain), "kubernetes.default.svc", "kubernetes.default", "kubernetes"} alternateDNS := []string{fmt.Sprintf("%s.%s", "kubernetes.default.svc", lk.DNSDomain), "kubernetes.default.svc", "kubernetes.default", "kubernetes"}
if err := utilcrypto.GenerateSelfSignedCert(hostIP.String(), lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath(), alternateIPs, alternateDNS); err != nil { if err := utilcrypto.GenerateSelfSignedCert(hostIP.String(), lk.GetPublicKeyCertPath(), lk.GetPrivateKeyCertPath(), ips, alternateDNS); err != nil {
fmt.Println("Failed to create certs: ", err) fmt.Println("Failed to create certs: ", err)
return err return err
} }

View File

@ -26,7 +26,7 @@ import (
"k8s.io/minikube/pkg/minikube/tests" "k8s.io/minikube/pkg/minikube/tests"
) )
var testIP = net.ParseIP("1.2.3.4") var testIPs = []net.IP{net.ParseIP("1.2.3.4")}
func TestGenerateCerts(t *testing.T) { func TestGenerateCerts(t *testing.T) {
tempDir := tests.MakeTempDir() tempDir := tests.MakeTempDir()
@ -39,7 +39,7 @@ func TestGenerateCerts(t *testing.T) {
ServiceClusterIPRange: *ipRange, ServiceClusterIPRange: *ipRange,
} }
if err := lk.GenerateCerts(testIP); err != nil { if err := lk.GenerateCerts(testIPs[0]); err != nil {
t.Fatalf("Unexpected error generating certs: %s", err) t.Fatalf("Unexpected error generating certs: %s", err)
} }
@ -54,14 +54,14 @@ func TestGenerateCerts(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Error parsing cert: %s", err) t.Fatalf("Error parsing cert: %s", err)
} }
if !cert.IPAddresses[0].Equal(testIP) { if !cert.IPAddresses[0].Equal(testIPs[0]) {
t.Fatalf("IP mismatch: %s != %s.", cert.IPAddresses[0], testIP) t.Fatalf("IP mismatch: %s != %s.", cert.IPAddresses[0], testIPs[0])
} }
} }
func TestShouldGenerateCertsNoFiles(t *testing.T) { func TestShouldGenerateCertsNoFiles(t *testing.T) {
lk := LocalkubeServer{LocalkubeDirectory: "baddir"} lk := LocalkubeServer{LocalkubeDirectory: "baddir"}
if !lk.shouldGenerateCerts(testIP) { if !lk.shouldGenerateCerts(testIPs) {
t.Fatalf("No certs exist, we should generate.") t.Fatalf("No certs exist, we should generate.")
} }
} }
@ -72,7 +72,7 @@ func TestShouldGenerateCertsOneFile(t *testing.T) {
os.Mkdir(filepath.Join(tempDir, "certs"), 0777) os.Mkdir(filepath.Join(tempDir, "certs"), 0777)
ioutil.WriteFile(filepath.Join(tempDir, "certs", "apiserver.crt"), []byte(""), 0644) ioutil.WriteFile(filepath.Join(tempDir, "certs", "apiserver.crt"), []byte(""), 0644)
lk := LocalkubeServer{LocalkubeDirectory: tempDir} lk := LocalkubeServer{LocalkubeDirectory: tempDir}
if !lk.shouldGenerateCerts(testIP) { if !lk.shouldGenerateCerts(testIPs) {
t.Fatalf("Not all certs exist, we should generate.") t.Fatalf("Not all certs exist, we should generate.")
} }
} }
@ -85,7 +85,7 @@ func TestShouldGenerateCertsBadFiles(t *testing.T) {
ioutil.WriteFile(filepath.Join(tempDir, "certs", f), []byte(""), 0644) ioutil.WriteFile(filepath.Join(tempDir, "certs", f), []byte(""), 0644)
} }
lk := LocalkubeServer{LocalkubeDirectory: tempDir} lk := LocalkubeServer{LocalkubeDirectory: tempDir}
if !lk.shouldGenerateCerts(testIP) { if !lk.shouldGenerateCerts(testIPs) {
t.Fatalf("Certs are badly formatted, we should generate.") t.Fatalf("Certs are badly formatted, we should generate.")
} }
} }
@ -100,8 +100,9 @@ func TestShouldGenerateCertsMismatchedIP(t *testing.T) {
LocalkubeDirectory: tempDir, LocalkubeDirectory: tempDir,
ServiceClusterIPRange: *ipRange, ServiceClusterIPRange: *ipRange,
} }
lk.GenerateCerts(testIP) lk.GenerateCerts(testIPs[0])
if !lk.shouldGenerateCerts(net.ParseIP("4.3.2.1")) {
if !lk.shouldGenerateCerts([]net.IP{net.ParseIP("4.3.2.1")}) {
t.Fatalf("IPs don't match, we should generate.") t.Fatalf("IPs don't match, we should generate.")
} }
} }
@ -116,8 +117,8 @@ func TestShouldNotGenerateCerts(t *testing.T) {
LocalkubeDirectory: tempDir, LocalkubeDirectory: tempDir,
ServiceClusterIPRange: *ipRange, ServiceClusterIPRange: *ipRange,
} }
lk.GenerateCerts(testIP) lk.GenerateCerts(testIPs[0])
if lk.shouldGenerateCerts(testIP) { if lk.shouldGenerateCerts(testIPs) {
t.Fatalf("IPs match, we should not generate.") t.Fatalf("IPs match, we should not generate.")
} }
} }

View File

@ -33,11 +33,11 @@ import (
) )
const ( const (
remotePath = "/srv/kubernetes/certs" remotePath = "/var/lib/localkube/certs"
) )
var ( var (
certs = []string{"ca.crt", "kubecfg.key", "kubecfg.crt"} certs = []string{"apiserver.crt", "apiserver.key"}
) )
// StartHost starts a host VM. // StartHost starts a host VM.
@ -161,7 +161,7 @@ func GetCreds(h sshAble) error {
for _, cert := range certs { for _, cert := range certs {
remoteCertPath := filepath.Join(remotePath, cert) remoteCertPath := filepath.Join(remotePath, cert)
localCertPath := filepath.Join(localPath, cert) localCertPath := filepath.Join(localPath, cert)
data, err := h.RunSSHCommand(fmt.Sprintf("cat %s", remoteCertPath)) data, err := h.RunSSHCommand(fmt.Sprintf("sudo cat %s", remoteCertPath))
if err != nil { if err != nil {
return err return err
} }

View File

@ -283,7 +283,7 @@ func TestGetHostStatus(t *testing.T) {
func TestGetCreds(t *testing.T) { func TestGetCreds(t *testing.T) {
m := make(map[string]string) m := make(map[string]string)
for _, cert := range certs { for _, cert := range certs {
m[fmt.Sprintf("cat %s/%s", remotePath, cert)] = cert m[fmt.Sprintf("sudo cat %s/%s", remotePath, cert)] = cert
} }
h := mockHost{CommandOutput: m} h := mockHost{CommandOutput: m}

View File

@ -54,7 +54,7 @@ func GenerateSelfSignedCert(host, certPath, keyPath string, alternateIPs []net.I
NotAfter: time.Now().Add(time.Hour * 24 * 365), NotAfter: time.Now().Add(time.Hour * 24 * 365),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true, BasicConstraintsValid: true,
IsCA: true, IsCA: true,
} }