diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index 8ce21bb9b3..079b2fee5f 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -57,11 +57,13 @@ func (ic *GenericController) syncSecret() { } glog.Infof("updating secret %v in the local store", key) ic.sslCertTracker.Update(key, cert) + ic.reloadRequired = true continue } glog.Infof("adding secret %v to the local store", key) ic.sslCertTracker.Add(key, cert) + ic.reloadRequired = true } } @@ -86,8 +88,8 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC var s *ingress.SSLCert if okcert && okkey { - glog.V(3).Infof("found certificate and private key, configuring %v as a TLS Secret", secretName) s, err = ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca) + glog.V(3).Infof("found certificate and private key, configuring %v as a TLS Secret (CN: %v)", secretName, s.CN) } else if ca != nil { glog.V(3).Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) s, err = ssl.AddCertAuth(nsSecName, ca) diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index ff9e0ba0a2..0b3577b0f4 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -42,6 +42,7 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/flowcontrol" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/ingress/core/pkg/ingress" "k8s.io/ingress/core/pkg/ingress/annotations/class" "k8s.io/ingress/core/pkg/ingress/annotations/healthcheck" @@ -113,8 +114,8 @@ type GenericController struct { // runningConfig contains the running configuration in the Backend runningConfig *ingress.Configuration - // configmapChanged indicates the configmap - configmapChanged bool + // reloadRequired indicates the configmap + reloadRequired bool } // Configuration contains all the settings required by an Ingress controller @@ -262,7 +263,7 @@ func newIngressController(config *Configuration) *GenericController { if mapKey == ic.cfg.ConfigMapName { glog.V(2).Infof("adding configmap %v to backend", mapKey) ic.cfg.Backend.SetConfig(upCmap) - ic.configmapChanged = true + ic.reloadRequired = true } }, UpdateFunc: func(old, cur interface{}) { @@ -272,7 +273,7 @@ func newIngressController(config *Configuration) *GenericController { if mapKey == ic.cfg.ConfigMapName { glog.V(2).Infof("updating configmap backend (%v)", mapKey) ic.cfg.Backend.SetConfig(upCmap) - ic.configmapChanged = true + ic.reloadRequired = true } // updates to configuration configmaps can trigger an update if mapKey == ic.cfg.ConfigMapName || mapKey == ic.cfg.TCPConfigMapName || mapKey == ic.cfg.UDPConfigMapName { @@ -419,7 +420,7 @@ func (ic *GenericController) syncIngress(key interface{}) error { PassthroughBackends: passUpstreams, } - if !ic.configmapChanged && (ic.runningConfig != nil && ic.runningConfig.Equal(&pcfg)) { + if !ic.reloadRequired && (ic.runningConfig != nil && ic.runningConfig.Equal(&pcfg)) { glog.V(3).Infof("skipping backend reload (no changes detected)") return nil } @@ -433,7 +434,7 @@ func (ic *GenericController) syncIngress(key interface{}) error { return err } - ic.configmapChanged = false + ic.reloadRequired = false glog.Infof("ingress backend successfully reloaded...") incReloadCount() setSSLExpireTime(servers) @@ -1018,55 +1019,52 @@ func (ic *GenericController) createServers(data []interface{}, } // only add a certificate if the server does not have one previously configured - // TODO: TLS without secret? - if len(ing.Spec.TLS) > 0 && servers[host].SSLCertificate == "" { - tlsSecretName := "" - found := false - for _, tls := range ing.Spec.TLS { - for _, tlsHost := range tls.Hosts { - if tlsHost == host { - tlsSecretName = tls.SecretName - found = true - break - } - } - } + if len(ing.Spec.TLS) == 0 || servers[host].SSLCertificate != "" { + continue + } - // the current ing.Spec.Rules[].Host doesn't have an entry at - // ing.Spec.TLS[].Hosts[], skipping to the next Rule - if !found { - continue + tlsSecretName := "" + found := false + for _, tls := range ing.Spec.TLS { + if sets.NewString(tls.Hosts...).Has(host) { + tlsSecretName = tls.SecretName + found = true + break } + } - // Current Host listed on ing.Spec.TLS[].Hosts[] - // but TLS[].SecretName is empty; using default cert - if tlsSecretName == "" { - servers[host].SSLCertificate = defaultPemFileName - servers[host].SSLPemChecksum = defaultPemSHA - continue - } + // the current ing.Spec.Rules[].Host doesn't have an entry at + // ing.Spec.TLS[].Hosts[] skipping to the next Rule + if !found { + continue + } - key := fmt.Sprintf("%v/%v", ing.Namespace, tlsSecretName) - bc, exists := ic.sslCertTracker.Get(key) - if exists { - cert := bc.(*ingress.SSLCert) - if isHostValid(host, cert) { - servers[host].SSLCertificate = cert.PemFileName - servers[host].SSLPemChecksum = cert.PemSHA - servers[host].SSLExpireTime = cert.ExpireTime - - if cert.ExpireTime.Before(time.Now().Add(240 * time.Hour)) { - glog.Warningf("ssl certificate for host %v is about to expire in 10 days", host) - } + if tlsSecretName == "" { + glog.Warningf("host %v is listed on tls section but secretName is empty. Using default cert", host) + servers[host].SSLCertificate = defaultPemFileName + servers[host].SSLPemChecksum = defaultPemSHA + continue + } - } else { - glog.Warningf("ssl certificate %v does not contain a common name for host %v", key, host) - } + key := fmt.Sprintf("%v/%v", ing.Namespace, tlsSecretName) + bc, exists := ic.sslCertTracker.Get(key) + if !exists { + glog.Infof("ssl certificate \"%v\" does not exist in local store", key) + continue + } - continue - } + cert := bc.(*ingress.SSLCert) + if !isHostValid(host, cert) { + glog.Warningf("ssl certificate %v does not contain a common name for host %v", key, host) + continue + } - glog.Infof("ssl certificate \"%v\" does not exist in local store", key) + servers[host].SSLCertificate = cert.PemFileName + servers[host].SSLPemChecksum = cert.PemSHA + servers[host].SSLExpireTime = cert.ExpireTime + + if cert.ExpireTime.Before(time.Now().Add(240 * time.Hour)) { + glog.Warningf("ssl certificate for host %v is about to expire in 10 days", host) } } } diff --git a/core/pkg/net/ssl/ssl.go b/core/pkg/net/ssl/ssl.go index 13e4b161b5..21a6d1a6ef 100644 --- a/core/pkg/net/ssl/ssl.go +++ b/core/pkg/net/ssl/ssl.go @@ -37,6 +37,7 @@ import ( "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/ingress/core/pkg/ingress" ) @@ -104,19 +105,27 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, return nil, err } - cn := []string{pemCert.Subject.CommonName} - if len(pemCert.DNSNames) > 0 { - cn = append(cn, pemCert.DNSNames...) + cn := sets.NewString(pemCert.Subject.CommonName) + for _, dns := range pemCert.DNSNames { + if !cn.Has(dns) { + cn.Insert(dns) + } } if len(pemCert.Extensions) > 0 { + glog.V(3).Info("parsing ssl certificate extensions") for _, ext := range getExtension(pemCert, oidExtensionSubjectAltName) { dns, _, _, err := parseSANExtension(ext.Value) if err != nil { glog.Warningf("unexpected error parsing certificate extensions: %v", err) continue } - cn = append(cn, dns...) + + for _, dns := range dns { + if !cn.Has(dns) { + cn.Insert(dns) + } + } } } @@ -155,7 +164,7 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, CAFileName: pemFileName, PemFileName: pemFileName, PemSHA: PemSHA1(pemFileName), - CN: cn, + CN: cn.List(), ExpireTime: pemCert.NotAfter, }, nil } @@ -163,7 +172,7 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert, return &ingress.SSLCert{ PemFileName: pemFileName, PemSHA: PemSHA1(pemFileName), - CN: cn, + CN: cn.List(), ExpireTime: pemCert.NotAfter, }, nil }