diff --git a/core/pkg/ingress/controller/annotations.go b/core/pkg/ingress/controller/annotations.go index c0727dd87a..5a8beeadfa 100644 --- a/core/pkg/ingress/controller/annotations.go +++ b/core/pkg/ingress/controller/annotations.go @@ -17,8 +17,11 @@ limitations under the License. package controller import ( + "fmt" + "github.com/golang/glog" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/ingress/core/pkg/ingress/annotations/auth" @@ -47,11 +50,13 @@ type extractorConfig interface { } type annotationExtractor struct { - annotations map[string]parser.IngressAnnotation + secretResolver resolver.Secret + annotations map[string]parser.IngressAnnotation } func newAnnotationExtractor(cfg extractorConfig) annotationExtractor { return annotationExtractor{ + cfg, map[string]parser.IngressAnnotation{ "BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg), "ExternalAuth": authreq.NewParser(), @@ -104,6 +109,7 @@ const ( healthCheck = "HealthCheck" sslPassthrough = "SSLPassthrough" sessionAffinity = "SessionAffinity" + certificateAuth = "CertificateAuth" ) func (e *annotationExtractor) SecureUpstream(ing *extensions.Ingress) bool { @@ -125,3 +131,17 @@ func (e *annotationExtractor) SessionAffinity(ing *extensions.Ingress) *sessiona val, _ := e.annotations[sessionAffinity].Parse(ing) return val.(*sessionaffinity.AffinityConfig) } + +func (e *annotationExtractor) ContainsCertificateAuth(ing *extensions.Ingress) bool { + val, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + return val != "" +} + +func (e *annotationExtractor) CertificateAuthSecret(ing *extensions.Ingress) (*api.Secret, error) { + val, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + if val == "" { + return nil, fmt.Errorf("ingress rule %v/%v does not contains the auth-tls-secret annotation", ing.Namespace, ing.Name) + } + + return e.secretResolver.GetSecret(val) +} diff --git a/core/pkg/ingress/controller/backend_ssl.go b/core/pkg/ingress/controller/backend_ssl.go index f67ff4743b..7b7cbc7fd4 100644 --- a/core/pkg/ingress/controller/backend_ssl.go +++ b/core/pkg/ingress/controller/backend_ssl.go @@ -18,6 +18,7 @@ package controller import ( "fmt" + "reflect" "strings" "time" @@ -68,13 +69,18 @@ func (ic *GenericController) syncSecret(k interface{}) error { } // create certificates and add or update the item in the store - _, exists = ic.sslCertTracker.Get(key) + cur, exists := ic.sslCertTracker.Get(key) if exists { - glog.V(3).Infof("updating secret %v/%v in the store ", sec.Namespace, sec.Name) + s := cur.(*ingress.SSLCert) + if reflect.DeepEqual(s, cert) { + // no need to update + return nil + } + glog.V(3).Infof("updating secret %v/%v in the store", sec.Namespace, sec.Name) ic.sslCertTracker.Update(key, cert) return nil } - glog.V(3).Infof("adding secret %v/%v to the store ", sec.Namespace, sec.Name) + glog.V(3).Infof("adding secret %v/%v to the store", sec.Namespace, sec.Name) ic.sslCertTracker.Add(key, cert) return nil } @@ -100,13 +106,13 @@ 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) + glog.V(3).Infof("found certificate and private key, configuring %v as a TLS Secret", secretName) s, err = ssl.AddOrUpdateCertAndKey(nsSecName, cert, key, ca) } 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) } else { - return nil, fmt.Errorf("No keypair or CA cert could be found in %v", secretName) + return nil, fmt.Errorf("ko keypair or CA cert could be found in %v", secretName) } if err != nil { @@ -122,10 +128,14 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC func (ic *GenericController) secrReferenced(name, namespace string) bool { for _, ingIf := range ic.ingLister.Store.List() { ing := ingIf.(*extensions.Ingress) - str, err := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) - if err == nil && str == fmt.Sprintf("%v/%v", namespace, name) { - return true + + if ic.annotations.ContainsCertificateAuth(ing) { + str, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing) + if str == fmt.Sprintf("%v/%v", namespace, name) { + return true + } } + if ing.Namespace != namespace { continue } diff --git a/core/pkg/ingress/controller/controller.go b/core/pkg/ingress/controller/controller.go index b1c2607c76..2a9c692b37 100644 --- a/core/pkg/ingress/controller/controller.go +++ b/core/pkg/ingress/controller/controller.go @@ -170,6 +170,12 @@ func newIngressController(config *Configuration) *GenericController { } ic.recorder.Eventf(addIng, api.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name)) ic.syncQueue.Enqueue(obj) + if ic.annotations.ContainsCertificateAuth(addIng) { + s, err := ic.annotations.CertificateAuthSecret(addIng) + if err == nil { + ic.syncSecret(fmt.Sprintf("%v/%v", s.Namespace, s.Name)) + } + } }, DeleteFunc: func(obj interface{}) { delIng := obj.(*extensions.Ingress) @@ -209,6 +215,13 @@ func newIngressController(config *Configuration) *GenericController { }() } } + if ic.annotations.ContainsCertificateAuth(upIng) { + s, err := ic.annotations.CertificateAuthSecret(upIng) + if err == nil { + ic.syncSecret(fmt.Sprintf("%v/%v", s.Namespace, s.Name)) + } + } + ic.syncQueue.Enqueue(cur) } }, @@ -280,11 +293,11 @@ func newIngressController(config *Configuration) *GenericController { &api.Endpoints{}, ic.cfg.ResyncPeriod, eventHandler) ic.secrLister.Store, ic.secrController = cache.NewInformer( - cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "secrets", ic.cfg.Namespace, fields.Everything()), + cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "secrets", api.NamespaceAll, fields.Everything()), &api.Secret{}, ic.cfg.ResyncPeriod, secrEventHandler) ic.mapLister.Store, ic.mapController = cache.NewInformer( - cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", ic.cfg.Namespace, fields.Everything()), + cache.NewListWatchFromClient(ic.cfg.Client.Core().RESTClient(), "configmaps", api.NamespaceAll, fields.Everything()), &api.ConfigMap{}, ic.cfg.ResyncPeriod, mapEventHandler) ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer(