Merge pull request #424 from aledbf/ca-auth

Manually sync secrets from certificate authentication annotations
This commit is contained in:
Manuel Alejandro de Brito Fontes 2017-03-13 19:17:00 -03:00 committed by GitHub
commit 448a42a67a
3 changed files with 55 additions and 12 deletions

View file

@ -17,8 +17,11 @@ limitations under the License.
package controller package controller
import ( import (
"fmt"
"github.com/golang/glog" "github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/ingress/core/pkg/ingress/annotations/auth" "k8s.io/ingress/core/pkg/ingress/annotations/auth"
@ -47,11 +50,13 @@ type extractorConfig interface {
} }
type annotationExtractor struct { type annotationExtractor struct {
annotations map[string]parser.IngressAnnotation secretResolver resolver.Secret
annotations map[string]parser.IngressAnnotation
} }
func newAnnotationExtractor(cfg extractorConfig) annotationExtractor { func newAnnotationExtractor(cfg extractorConfig) annotationExtractor {
return annotationExtractor{ return annotationExtractor{
cfg,
map[string]parser.IngressAnnotation{ map[string]parser.IngressAnnotation{
"BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg), "BasicDigestAuth": auth.NewParser(auth.AuthDirectory, cfg),
"ExternalAuth": authreq.NewParser(), "ExternalAuth": authreq.NewParser(),
@ -104,6 +109,7 @@ const (
healthCheck = "HealthCheck" healthCheck = "HealthCheck"
sslPassthrough = "SSLPassthrough" sslPassthrough = "SSLPassthrough"
sessionAffinity = "SessionAffinity" sessionAffinity = "SessionAffinity"
certificateAuth = "CertificateAuth"
) )
func (e *annotationExtractor) SecureUpstream(ing *extensions.Ingress) bool { 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) val, _ := e.annotations[sessionAffinity].Parse(ing)
return val.(*sessionaffinity.AffinityConfig) 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)
}

View file

@ -18,6 +18,7 @@ package controller
import ( import (
"fmt" "fmt"
"reflect"
"strings" "strings"
"time" "time"
@ -68,13 +69,18 @@ func (ic *GenericController) syncSecret(k interface{}) error {
} }
// create certificates and add or update the item in the store // create certificates and add or update the item in the store
_, exists = ic.sslCertTracker.Get(key) cur, exists := ic.sslCertTracker.Get(key)
if exists { 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) ic.sslCertTracker.Update(key, cert)
return nil 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) ic.sslCertTracker.Add(key, cert)
return nil return nil
} }
@ -100,13 +106,13 @@ 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) 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)
} 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)
} else { } 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 { if err != nil {
@ -122,10 +128,14 @@ func (ic *GenericController) getPemCertificate(secretName string) (*ingress.SSLC
func (ic *GenericController) secrReferenced(name, namespace string) bool { func (ic *GenericController) secrReferenced(name, namespace string) bool {
for _, ingIf := range ic.ingLister.Store.List() { for _, ingIf := range ic.ingLister.Store.List() {
ing := ingIf.(*extensions.Ingress) 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) { if ic.annotations.ContainsCertificateAuth(ing) {
return true str, _ := parser.GetStringAnnotation("ingress.kubernetes.io/auth-tls-secret", ing)
if str == fmt.Sprintf("%v/%v", namespace, name) {
return true
}
} }
if ing.Namespace != namespace { if ing.Namespace != namespace {
continue continue
} }

View file

@ -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.recorder.Eventf(addIng, api.EventTypeNormal, "CREATE", fmt.Sprintf("Ingress %s/%s", addIng.Namespace, addIng.Name))
ic.syncQueue.Enqueue(obj) 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{}) { DeleteFunc: func(obj interface{}) {
delIng := obj.(*extensions.Ingress) 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) ic.syncQueue.Enqueue(cur)
} }
}, },
@ -280,11 +293,11 @@ func newIngressController(config *Configuration) *GenericController {
&api.Endpoints{}, ic.cfg.ResyncPeriod, eventHandler) &api.Endpoints{}, ic.cfg.ResyncPeriod, eventHandler)
ic.secrLister.Store, ic.secrController = cache.NewInformer( 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) &api.Secret{}, ic.cfg.ResyncPeriod, secrEventHandler)
ic.mapLister.Store, ic.mapController = cache.NewInformer( 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) &api.ConfigMap{}, ic.cfg.ResyncPeriod, mapEventHandler)
ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer( ic.svcLister.Indexer, ic.svcController = cache.NewIndexerInformer(