Simplify handling of ssl certificates

This commit is contained in:
Manuel de Brito Fontes 2017-07-12 13:31:15 -04:00
parent 26fccdc48b
commit 14a02d128c
3 changed files with 66 additions and 57 deletions

View file

@ -57,11 +57,13 @@ func (ic *GenericController) syncSecret() {
} }
glog.Infof("updating secret %v in the local store", key) glog.Infof("updating secret %v in the local store", key)
ic.sslCertTracker.Update(key, cert) ic.sslCertTracker.Update(key, cert)
ic.reloadRequired = true
continue continue
} }
glog.Infof("adding secret %v to the local store", key) glog.Infof("adding secret %v to the local store", key)
ic.sslCertTracker.Add(key, cert) ic.sslCertTracker.Add(key, cert)
ic.reloadRequired = true
} }
} }
@ -86,8 +88,8 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC
var s *ingress.SSLCert var s *ingress.SSLCert
if okcert && okkey { 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) 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 { } else if ca != nil {
glog.V(3).Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName) glog.V(3).Infof("found only ca.crt, configuring %v as an Certificate Authentication secret", secretName)
s, err = ssl.AddCertAuth(nsSecName, ca) s, err = ssl.AddCertAuth(nsSecName, ca)

View file

@ -42,6 +42,7 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/ingress/core/pkg/ingress" "k8s.io/ingress/core/pkg/ingress"
"k8s.io/ingress/core/pkg/ingress/annotations/class" "k8s.io/ingress/core/pkg/ingress/annotations/class"
"k8s.io/ingress/core/pkg/ingress/annotations/healthcheck" "k8s.io/ingress/core/pkg/ingress/annotations/healthcheck"
@ -113,8 +114,8 @@ type GenericController struct {
// runningConfig contains the running configuration in the Backend // runningConfig contains the running configuration in the Backend
runningConfig *ingress.Configuration runningConfig *ingress.Configuration
// configmapChanged indicates the configmap // reloadRequired indicates the configmap
configmapChanged bool reloadRequired bool
} }
// Configuration contains all the settings required by an Ingress controller // Configuration contains all the settings required by an Ingress controller
@ -262,7 +263,7 @@ func newIngressController(config *Configuration) *GenericController {
if mapKey == ic.cfg.ConfigMapName { if mapKey == ic.cfg.ConfigMapName {
glog.V(2).Infof("adding configmap %v to backend", mapKey) glog.V(2).Infof("adding configmap %v to backend", mapKey)
ic.cfg.Backend.SetConfig(upCmap) ic.cfg.Backend.SetConfig(upCmap)
ic.configmapChanged = true ic.reloadRequired = true
} }
}, },
UpdateFunc: func(old, cur interface{}) { UpdateFunc: func(old, cur interface{}) {
@ -272,7 +273,7 @@ func newIngressController(config *Configuration) *GenericController {
if mapKey == ic.cfg.ConfigMapName { if mapKey == ic.cfg.ConfigMapName {
glog.V(2).Infof("updating configmap backend (%v)", mapKey) glog.V(2).Infof("updating configmap backend (%v)", mapKey)
ic.cfg.Backend.SetConfig(upCmap) ic.cfg.Backend.SetConfig(upCmap)
ic.configmapChanged = true ic.reloadRequired = true
} }
// updates to configuration configmaps can trigger an update // updates to configuration configmaps can trigger an update
if mapKey == ic.cfg.ConfigMapName || mapKey == ic.cfg.TCPConfigMapName || mapKey == ic.cfg.UDPConfigMapName { 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, 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)") glog.V(3).Infof("skipping backend reload (no changes detected)")
return nil return nil
} }
@ -433,7 +434,7 @@ func (ic *GenericController) syncIngress(key interface{}) error {
return err return err
} }
ic.configmapChanged = false ic.reloadRequired = false
glog.Infof("ingress backend successfully reloaded...") glog.Infof("ingress backend successfully reloaded...")
incReloadCount() incReloadCount()
setSSLExpireTime(servers) setSSLExpireTime(servers)
@ -1018,29 +1019,28 @@ func (ic *GenericController) createServers(data []interface{},
} }
// only add a certificate if the server does not have one previously configured // 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 != "" {
if len(ing.Spec.TLS) > 0 && servers[host].SSLCertificate == "" { continue
}
tlsSecretName := "" tlsSecretName := ""
found := false found := false
for _, tls := range ing.Spec.TLS { for _, tls := range ing.Spec.TLS {
for _, tlsHost := range tls.Hosts { if sets.NewString(tls.Hosts...).Has(host) {
if tlsHost == host {
tlsSecretName = tls.SecretName tlsSecretName = tls.SecretName
found = true found = true
break break
} }
} }
}
// the current ing.Spec.Rules[].Host doesn't have an entry at // the current ing.Spec.Rules[].Host doesn't have an entry at
// ing.Spec.TLS[].Hosts[], skipping to the next Rule // ing.Spec.TLS[].Hosts[] skipping to the next Rule
if !found { if !found {
continue continue
} }
// Current Host listed on ing.Spec.TLS[].Hosts[]
// but TLS[].SecretName is empty; using default cert
if tlsSecretName == "" { 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].SSLCertificate = defaultPemFileName
servers[host].SSLPemChecksum = defaultPemSHA servers[host].SSLPemChecksum = defaultPemSHA
continue continue
@ -1048,9 +1048,17 @@ func (ic *GenericController) createServers(data []interface{},
key := fmt.Sprintf("%v/%v", ing.Namespace, tlsSecretName) key := fmt.Sprintf("%v/%v", ing.Namespace, tlsSecretName)
bc, exists := ic.sslCertTracker.Get(key) bc, exists := ic.sslCertTracker.Get(key)
if exists { if !exists {
glog.Infof("ssl certificate \"%v\" does not exist in local store", key)
continue
}
cert := bc.(*ingress.SSLCert) cert := bc.(*ingress.SSLCert)
if isHostValid(host, cert) { if !isHostValid(host, cert) {
glog.Warningf("ssl certificate %v does not contain a common name for host %v", key, host)
continue
}
servers[host].SSLCertificate = cert.PemFileName servers[host].SSLCertificate = cert.PemFileName
servers[host].SSLPemChecksum = cert.PemSHA servers[host].SSLPemChecksum = cert.PemSHA
servers[host].SSLExpireTime = cert.ExpireTime servers[host].SSLExpireTime = cert.ExpireTime
@ -1058,16 +1066,6 @@ func (ic *GenericController) createServers(data []interface{},
if cert.ExpireTime.Before(time.Now().Add(240 * time.Hour)) { 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) glog.Warningf("ssl certificate for host %v is about to expire in 10 days", host)
} }
} else {
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)
}
} }
} }

View file

@ -37,6 +37,7 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/ingress/core/pkg/ingress" "k8s.io/ingress/core/pkg/ingress"
) )
@ -104,19 +105,27 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert,
return nil, err return nil, err
} }
cn := []string{pemCert.Subject.CommonName} cn := sets.NewString(pemCert.Subject.CommonName)
if len(pemCert.DNSNames) > 0 { for _, dns := range pemCert.DNSNames {
cn = append(cn, pemCert.DNSNames...) if !cn.Has(dns) {
cn.Insert(dns)
}
} }
if len(pemCert.Extensions) > 0 { if len(pemCert.Extensions) > 0 {
glog.V(3).Info("parsing ssl certificate extensions")
for _, ext := range getExtension(pemCert, oidExtensionSubjectAltName) { for _, ext := range getExtension(pemCert, oidExtensionSubjectAltName) {
dns, _, _, err := parseSANExtension(ext.Value) dns, _, _, err := parseSANExtension(ext.Value)
if err != nil { if err != nil {
glog.Warningf("unexpected error parsing certificate extensions: %v", err) glog.Warningf("unexpected error parsing certificate extensions: %v", err)
continue 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, CAFileName: pemFileName,
PemFileName: pemFileName, PemFileName: pemFileName,
PemSHA: PemSHA1(pemFileName), PemSHA: PemSHA1(pemFileName),
CN: cn, CN: cn.List(),
ExpireTime: pemCert.NotAfter, ExpireTime: pemCert.NotAfter,
}, nil }, nil
} }
@ -163,7 +172,7 @@ func AddOrUpdateCertAndKey(name string, cert, key, ca []byte) (*ingress.SSLCert,
return &ingress.SSLCert{ return &ingress.SSLCert{
PemFileName: pemFileName, PemFileName: pemFileName,
PemSHA: PemSHA1(pemFileName), PemSHA: PemSHA1(pemFileName),
CN: cn, CN: cn.List(),
ExpireTime: pemCert.NotAfter, ExpireTime: pemCert.NotAfter,
}, nil }, nil
} }