From c992ce309ce9cafab31ebce940aab7080a7d64d4 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 2 Apr 2020 22:07:34 -0700 Subject: [PATCH 1/2] Reject bad CNs that will prevent the secret from being saved. --- factory/gen.go | 22 +++++++++++++++++++++- listener.go | 2 +- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/factory/gen.go b/factory/gen.go index 7256693..ddd5b6d 100644 --- a/factory/gen.go +++ b/factory/gen.go @@ -10,10 +10,12 @@ import ( "encoding/hex" "encoding/pem" "net" + "regexp" "sort" "strings" "github.com/rancher/dynamiclistener/cert" + "github.com/sirupsen/logrus" v1 "k8s.io/api/core/v1" ) @@ -23,11 +25,16 @@ const ( hashKey = "listener.cattle.io/hash" ) +var ( + cnRegexp = regexp.MustCompile("^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$") +) + type TLS struct { CACert *x509.Certificate CAKey crypto.Signer CN string Organization []string + FilterCN func(...string) []string } func cns(secret *v1.Secret) (cns []string) { @@ -76,11 +83,20 @@ func (t *TLS) Refresh(secret *v1.Secret) (*v1.Secret, error) { return secret, err } +func (t *TLS) Filter(cn ...string) []string { + if t.FilterCN == nil { + return cn + } + return t.FilterCN(cn...) +} + func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) { var ( err error ) + cn = t.Filter(cn...) + if !NeedsUpdate(0, secret, cn...) { return secret, false, nil } @@ -132,7 +148,11 @@ func populateCN(secret *v1.Secret, cn ...string) *v1.Secret { secret.Annotations = map[string]string{} } for _, cn := range cn { - secret.Annotations[cnPrefix+cn] = cn + if cnRegexp.MatchString(cn) { + secret.Annotations[cnPrefix+cn] = cn + } else { + logrus.Errorf("dropping invalid CN: %s", cn) + } } return secret } diff --git a/listener.go b/listener.go index 2d61de4..c6e9369 100644 --- a/listener.go +++ b/listener.go @@ -205,7 +205,7 @@ func (l *listener) Accept() (net.Conn, error) { if !strings.Contains(host, ":") { if err := l.updateCert(host); err != nil { - logrus.Infof("failed to create TLS cert for: %s", host) + logrus.Infof("failed to create TLS cert for: %s, %v", host, err) } } From 4bac3f291f87e2cee1c69ebc2b966671df2ce222 Mon Sep 17 00:00:00 2001 From: Darren Shepherd Date: Thu, 2 Apr 2020 22:08:36 -0700 Subject: [PATCH 2/2] Add ability to confirm adding new CNs --- listener.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/listener.go b/listener.go index c6e9369..389a4b6 100644 --- a/listener.go +++ b/listener.go @@ -25,6 +25,7 @@ type TLSFactory interface { Refresh(secret *v1.Secret) (*v1.Secret, error) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) Merge(target *v1.Secret, additional *v1.Secret) (*v1.Secret, bool, error) + Filter(cn ...string) []string } type SetFactory interface { @@ -48,6 +49,7 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c CAKey: caKey, CN: config.CN, Organization: config.Organization, + FilterCN: config.FilterCN, }, Listener: l, storage: &nonNil{storage: storage}, @@ -97,6 +99,7 @@ type Config struct { MaxSANs int ExpirationDaysCheck int CloseConnOnCertChange bool + FilterCN func(...string) []string } type listener struct { @@ -259,6 +262,11 @@ func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, } func (l *listener) updateCert(cn ...string) error { + cn = l.factory.Filter(cn...) + if len(cn) == 0 { + return nil + } + l.RLock() defer l.RUnlock()