From 7a29af4d2cff1fdd986f7726e8a656055d33841e Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 1 Jul 2015 16:57:48 -0400 Subject: [PATCH] Add Subject Alt Names to self signed apiserver certs A cert from GCE shows: - IP Address:23.236.49.122 - IP Address:10.0.0.1 - DNS:kubernetes, - DNS:kubernetes.default - DNS:kubernetes.default.svc - DNS:kubernetes.default.svc.cluster.local - DNS:e2e-test-zml-master A similarly configured self signed cert shows: - IP Address:23.236.49.122 - IP Address:10.0.0.1 - DNS:kubernetes - DNS:kubernetes.default - DNS:kubernetes.default.svc So we are missing the fqdn kubernetes.default.svc.cluster.local. The apiserver does not even know the fqdn! it's defined entirely by the kubelet! We also do not have the cluster name certificate. This may be --cluster-name= argument to the apiserver but will take a bit more research. --- cmd/kube-apiserver/app/server.go | 2 +- cmd/kubelet/app/server.go | 2 +- pkg/master/master.go | 21 +++++++++++++-------- pkg/util/crypto.go | 11 ++++++++++- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 84ec8c2dab0..15921ce4bbf 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -449,7 +449,7 @@ func (s *APIServer) Run(_ []string) error { s.TLSCertFile = path.Join(s.CertDirectory, "apiserver.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "apiserver.key") // TODO (cjcullen): Is PublicAddress the right address to sign a cert with? - if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile); err != nil { + if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile, config.ServiceReadWriteIP); err != nil { glog.Errorf("Unable to generate self signed cert: %v", err) } else { glog.Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 1cd1362da1f..f4b97a07bb3 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -395,7 +395,7 @@ func (s *KubeletServer) InitializeTLS() (*kubelet.TLSOptions, error) { if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" { s.TLSCertFile = path.Join(s.CertDirectory, "kubelet.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "kubelet.key") - if err := util.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile); err != nil { + if err := util.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile, nil); err != nil { return nil, fmt.Errorf("unable to generate self signed cert: %v", err) } glog.V(4).Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) diff --git a/pkg/master/master.go b/pkg/master/master.go index ebc11888869..f07a7103618 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -147,6 +147,9 @@ type Config struct { // The range of IPs to be assigned to services with type=ClusterIP or greater ServiceClusterIPRange *net.IPNet + // The IP address for the master service (must be inside ServiceClusterIPRange + ServiceReadWriteIP net.IP + // The range of ports to be assigned to services with type=NodePort or greater ServiceNodePortRange util.PortRange @@ -245,6 +248,15 @@ func setDefaults(c *Config) { } c.ServiceClusterIPRange = serviceClusterIPRange } + if c.ServiceReadWriteIP == nil { + // Select the first valid IP from ServiceClusterIPRange to use as the master service IP. + serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) + if err != nil { + glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) + } + glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) + c.ServiceReadWriteIP = serviceReadWriteIP + } if c.ServiceNodePortRange.Size == 0 { // TODO: Currently no way to specify an empty range (do we need to allow this?) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) @@ -311,13 +323,6 @@ func New(c *Config) *Master { glog.Fatalf("master.New() called with config.KubeletClient == nil") } - // Select the first valid IP from serviceClusterIPRange to use as the master service IP. - serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) - if err != nil { - glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) - } - glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) - m := &Master{ serviceClusterIPRange: c.ServiceClusterIPRange, serviceNodePortRange: c.ServiceNodePortRange, @@ -343,7 +348,7 @@ func New(c *Config) *Master { externalHost: c.ExternalHost, clusterIP: c.PublicAddress, publicReadWritePort: c.ReadWritePort, - serviceReadWriteIP: serviceReadWriteIP, + serviceReadWriteIP: c.ServiceReadWriteIP, // TODO: serviceReadWritePort should be passed in as an argument, it may not always be 443 serviceReadWritePort: 443, diff --git a/pkg/util/crypto.go b/pkg/util/crypto.go index f312246bb57..eadb0424b18 100644 --- a/pkg/util/crypto.go +++ b/pkg/util/crypto.go @@ -38,7 +38,7 @@ import ( // The certificate will be created with file mode 0644. The key will be created with file mode 0600. // If the certificate or key files already exist, they will be overwritten. // Any parent directories of the certPath or keyPath will be created as needed with file mode 0755. -func GenerateSelfSignedCert(host, certPath, keyPath string) error { +func GenerateSelfSignedCert(host, certPath, keyPath string, ServiceReadWriteIP net.IP) error { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err @@ -63,6 +63,15 @@ func GenerateSelfSignedCert(host, certPath, keyPath string) error { template.DNSNames = append(template.DNSNames, host) } + if ServiceReadWriteIP != nil { + template.IPAddresses = append(template.IPAddresses, ServiceReadWriteIP) + } + // It would be nice to have the next line, but only the kubelets know the fqdn, the apiserver is clueless + // template.DNSNames = append(template.DNSNames, "kubernetes.default.svc.CLUSTER.DNS.NAME") + template.DNSNames = append(template.DNSNames, "kubernetes.default.svc") + template.DNSNames = append(template.DNSNames, "kubernetes.default") + template.DNSNames = append(template.DNSNames, "kubernetes") + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err