Implement flag always-enable-tls

This commit is contained in:
Yves Peter 2017-08-09 21:49:52 +02:00
parent 36cf018a71
commit f825445b2d
3 changed files with 145 additions and 64 deletions

View file

@ -131,6 +131,7 @@ type Configuration struct {
// optional
UDPConfigMapName string
DefaultSSLCertificate string
AlwaysEnableTLS bool
DefaultHealthzURL string
DefaultIngressClass string
// optional
@ -1065,76 +1066,80 @@ func (ic *GenericController) createServers(data []interface{},
},
}, SSLPassthrough: sslpt}
}
}
// configure default location and SSL
for _, ingIf := range data {
ing := ingIf.(*extensions.Ingress)
if !class.IsValid(ing, ic.cfg.IngressClass, ic.cfg.DefaultIngressClass) {
continue
}
for _, rule := range ing.Spec.Rules {
host := rule.Host
if host == "" {
host = defServerName
}
// only add a certificate if the server does not have one previously configured
if len(ing.Spec.TLS) == 0 || servers[host].SSLCertificate != "" {
continue
}
tlsSecretName := ""
found := false
for _, tls := range ing.Spec.TLS {
if sets.NewString(tls.Hosts...).Has(host) {
tlsSecretName = tls.SecretName
found = true
break
}
}
// the current ing.Spec.Rules[].Host doesn't have an entry at
// ing.Spec.TLS[].Hosts[] skipping to the next Rule
if !found {
continue
}
if tlsSecretName == "" {
glog.V(3).Infof("host %v is listed on tls section but secretName is empty. Using default cert", host)
servers[host].SSLCertificate = defaultPemFileName
servers[host].SSLPemChecksum = defaultPemSHA
continue
}
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
}
cert := bc.(*ingress.SSLCert)
err = cert.Certificate.VerifyHostname(host)
if err != nil {
glog.Warningf("ssl certificate %v does not contain a Common Name or Subject Alternative Name for host %v", key, host)
continue
}
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)
}
}
ic.configureTLSforIng(ing, servers, defaultPemFileName, defaultPemSHA)
}
return servers
}
func (ic *GenericController) configureTLSforIng(ing *extensions.Ingress, servers map[string]*ingress.Server, defaultPemFileName string, defaultPemSHA string) {
for _, rule := range ing.Spec.Rules {
host := rule.Host
if host == "" {
host = defServerName
}
// only add a certificate if the server does not have one previously configured
if servers[host].SSLCertificate != "" {
continue
}
tlsForHost := getTLSForHost(ing.Spec.TLS, host)
if tlsForHost == nil && ic.cfg.AlwaysEnableTLS {
glog.V(3).Infof("no tls host defined for %v but EnforceTLS is true. Using default cert", host)
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 tlsForHost == nil {
continue
}
if tlsForHost.SecretName == "" {
glog.V(3).Infof("host %v is listed on tls section but secretName is empty. Using default cert", host)
servers[host].SSLCertificate = defaultPemFileName
servers[host].SSLPemChecksum = defaultPemSHA
continue
}
key := fmt.Sprintf("%v/%v", ing.Namespace, tlsForHost.SecretName)
bc, exists := ic.sslCertTracker.Get(key)
if !exists {
glog.Infof("ssl certificate \"%v\" does not exist in local store", key)
continue
}
cert := bc.(*ingress.SSLCert)
err := cert.Certificate.VerifyHostname(host)
if err != nil {
glog.Warningf("ssl certificate %v does not contain a Common Name or Subject Alternative Name for host %v", key, host)
continue
}
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)
}
}
}
func getTLSForHost(ingressTLS []extensions.IngressTLS, host string) *extensions.IngressTLS {
for _, tls := range ingressTLS {
if sets.NewString(tls.Hosts...).Has(host) {
return &tls
}
}
return nil
}
// getEndpoints returns a list of <endpoint ip>:<port> for a given service/target port combination.
func (ic *GenericController) getEndpoints(
s *api.Service,

View file

@ -0,0 +1,72 @@
package controller
import (
"testing"
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/ingress/core/pkg/ingress"
)
func buildGenericControllerForCertTest() *GenericController {
return &GenericController{
cfg: &Configuration{},
}
}
func buildTestIngressRuleForCertTest() extensions.Ingress {
return extensions.Ingress{
Spec: extensions.IngressSpec{
Rules: []extensions.IngressRule{
extensions.IngressRule{
Host: "hostWithTLS",
},
extensions.IngressRule{
Host: "hostWithoutTLS",
},
},
TLS: []extensions.IngressTLS{
extensions.IngressTLS{
Hosts: []string{"hostWithTLS"},
},
},
},
}
}
func buildTestServersForCertTest() map[string]*ingress.Server {
return map[string]*ingress.Server{
"hostWithTLS": &ingress.Server{
Hostname: "hostWithTLS",
},
"hostWithoutTLS": &ingress.Server{
Hostname: "hostWithoutTLS",
},
}
}
func TestConfigureTLSforIng(t *testing.T) {
ic := buildGenericControllerForCertTest()
testIng := buildTestIngressRuleForCertTest()
testServers := buildTestServersForCertTest()
defaultPemFileName := "defaultPemFileName"
defaultPemSHA := "defaultPemSHA"
ic.configureTLSforIng(&testIng, testServers, defaultPemFileName, defaultPemSHA)
if testServers["hostWithTLS"].SSLCertificate != defaultPemFileName {
t.Errorf("SSLCertificate set to %s instead of %s", testServers["hostWithTLS"].SSLCertificate, defaultPemFileName)
}
if testServers["hostWithoutTLS"].SSLCertificate != "" {
t.Errorf("SSLCertificate set to %s instead of being empty", testServers["hostWithoutTLS"].SSLCertificate)
}
ic.cfg.AlwaysEnableTLS = true
ic.configureTLSforIng(&testIng, testServers, defaultPemFileName, defaultPemSHA)
if testServers["hostWithTLS"].SSLCertificate != defaultPemFileName {
t.Errorf("SSLCertificate set to %s instead of %s", testServers["hostWithTLS"].SSLCertificate, defaultPemFileName)
}
if testServers["hostWithoutTLS"].SSLCertificate != defaultPemFileName {
t.Errorf("SSLCertificate set to %s instead of %s", testServers["hostWithoutTLS"].SSLCertificate, defaultPemFileName)
}
}

View file

@ -78,6 +78,9 @@ func NewIngressController(backend ingress.Controller) *GenericController {
defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
that contains a SSL certificate to be used as default for a HTTPS catch-all server`)
defAlwaysEnableTLS = flags.Bool("always-enable-tls", false, `Enable tls using the default-ssl-certificate even if no tls section is defined
for the ingress.`)
defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
the URL to be used as health check inside in the default server in NGINX.`)
@ -171,6 +174,7 @@ func NewIngressController(backend ingress.Controller) *GenericController {
TCPConfigMapName: *tcpConfigMapName,
UDPConfigMapName: *udpConfigMapName,
DefaultSSLCertificate: *defSSLCertificate,
AlwaysEnableTLS: *defAlwaysEnableTLS,
DefaultHealthzURL: *defHealthzURL,
PublishService: *publishSvc,
Backend: backend,