Merge pull request #2053 from brandond/update_dynamiclistener

Update dynamiclistener
This commit is contained in:
Brad Davidson 2020-08-04 14:48:47 -07:00 committed by GitHub
commit c8282f4939
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 361 additions and 45 deletions

2
go.mod
View File

@ -95,7 +95,7 @@ require (
github.com/opencontainers/runc v1.0.0-rc10 github.com/opencontainers/runc v1.0.0-rc10
github.com/opencontainers/selinux v1.3.1-0.20190929122143-5215b1806f52 github.com/opencontainers/selinux v1.3.1-0.20190929122143-5215b1806f52
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/rancher/dynamiclistener v0.2.0 github.com/rancher/dynamiclistener v0.2.1-0.20200418023342-52ede5ec9234
github.com/rancher/helm-controller v0.6.3 github.com/rancher/helm-controller v0.6.3
github.com/rancher/kine v0.4.0 github.com/rancher/kine v0.4.0
github.com/rancher/remotedialer v0.2.0 github.com/rancher/remotedialer v0.2.0

4
go.sum
View File

@ -620,8 +620,8 @@ github.com/rancher/cri v1.3.0-k3s.6 h1:jeom53pNYUJHlZBHpax8vpQeBoW19vSVGAQn9jPyI
github.com/rancher/cri v1.3.0-k3s.6/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY= github.com/rancher/cri v1.3.0-k3s.6/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
github.com/rancher/cri-tools v1.18.0-k3s1 h1:pLYthxpSu6k3Up9tNAMA0MK2ERqB6FC1sZQPRSW1qSg= github.com/rancher/cri-tools v1.18.0-k3s1 h1:pLYthxpSu6k3Up9tNAMA0MK2ERqB6FC1sZQPRSW1qSg=
github.com/rancher/cri-tools v1.18.0-k3s1/go.mod h1:Ij/GWNRcEDP6zVN6eQpvN/s0nhuJVtPQFy7RAdl+Wu8= github.com/rancher/cri-tools v1.18.0-k3s1/go.mod h1:Ij/GWNRcEDP6zVN6eQpvN/s0nhuJVtPQFy7RAdl+Wu8=
github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk= github.com/rancher/dynamiclistener v0.2.1-0.20200418023342-52ede5ec9234 h1:wZ1Zh7fI7B9hfZw9Ouhz7171CZKu6XffM3ysUhhO6i0=
github.com/rancher/dynamiclistener v0.2.0/go.mod h1:fs/dxyNcB3YT6W9fVz4bDGfhmSQS17QQup6BIcGF++s= github.com/rancher/dynamiclistener v0.2.1-0.20200418023342-52ede5ec9234/go.mod h1:9WusTANoiRr8cDWCTtf5txieulezHbpv4vhLADPp0zU=
github.com/rancher/flannel v0.12.0-k3s1 h1:P23dWSk/9mGT1x2rDWW9JXNrF/0kjftiHwMau/+ZLGM= github.com/rancher/flannel v0.12.0-k3s1 h1:P23dWSk/9mGT1x2rDWW9JXNrF/0kjftiHwMau/+ZLGM=
github.com/rancher/flannel v0.12.0-k3s1/go.mod h1:zQ/9Uhaw0yV4Wh6ljVwHVT1x5KuhenZA+6L8lRzOJEY= github.com/rancher/flannel v0.12.0-k3s1/go.mod h1:zQ/9Uhaw0yV4Wh6ljVwHVT1x5KuhenZA+6L8lRzOJEY=
github.com/rancher/go-powershell v0.0.0-20200701182037-6845e6fcfa79 h1:UeC0rjrIel8hHz92cdVN09Cm4Hz+BhsPP/ZvQnPOr58= github.com/rancher/go-powershell v0.0.0-20200701182037-6845e6fcfa79 h1:UeC0rjrIel8hHz92cdVN09Cm4Hz+BhsPP/ZvQnPOr58=

View File

@ -33,12 +33,13 @@ func (c *Cluster) newListener(ctx context.Context) (net.Listener, http.Handler,
return dynamiclistener.NewListener(tcp, storage, cert, key, dynamiclistener.Config{ return dynamiclistener.NewListener(tcp, storage, cert, key, dynamiclistener.Config{
CN: version.Program, CN: version.Program,
Organization: []string{version.Program}, Organization: []string{version.Program},
TLSConfig: tls.Config{ TLSConfig: &tls.Config{
ClientAuth: tls.RequestClientCert, ClientAuth: tls.RequestClientCert,
MinVersion: c.config.TLSMinVersion, MinVersion: c.config.TLSMinVersion,
CipherSuites: c.config.TLSCipherSuites, CipherSuites: c.config.TLSCipherSuites,
}, },
SANs: append(c.config.SANs, "localhost", "kubernetes", "kubernetes.default", "kubernetes.default.svc."+c.config.ClusterDomain), SANs: append(c.config.SANs, "localhost", "kubernetes", "kubernetes.default", "kubernetes.default.svc."+c.config.ClusterDomain),
ExpirationDaysCheck: 90,
}) })
} }

View File

@ -59,16 +59,7 @@ func loadCA() (*x509.Certificate, crypto.Signer, error) {
return LoadCerts("./certs/ca.pem", "./certs/ca.key") return LoadCerts("./certs/ca.pem", "./certs/ca.key")
} }
func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, error) { func LoadCA(caPem, caKey []byte) (*x509.Certificate, crypto.Signer, error) {
caPem, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, nil, err
}
caKey, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, nil, err
}
key, err := cert.ParsePrivateKeyPEM(caKey) key, err := cert.ParsePrivateKeyPEM(caKey)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -85,3 +76,16 @@ func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, erro
return cert, signer, nil return cert, signer, nil
} }
func LoadCerts(certFile, keyFile string) (*x509.Certificate, crypto.Signer, error) {
caPem, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, nil, err
}
caKey, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, nil, err
}
return LoadCA(caPem, caKey)
}

View File

@ -10,27 +10,37 @@ import (
"encoding/hex" "encoding/hex"
"encoding/pem" "encoding/pem"
"net" "net"
"regexp"
"sort" "sort"
"strings" "strings"
"github.com/rancher/dynamiclistener/cert" "github.com/rancher/dynamiclistener/cert"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
) )
const ( const (
cnPrefix = "listener.cattle.io/cn-" cnPrefix = "listener.cattle.io/cn-"
static = "listener.cattle.io/static" Static = "listener.cattle.io/static"
hashKey = "listener.cattle.io/hash" hashKey = "listener.cattle.io/hash"
) )
var (
cnRegexp = regexp.MustCompile("^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$")
)
type TLS struct { type TLS struct {
CACert *x509.Certificate CACert *x509.Certificate
CAKey crypto.Signer CAKey crypto.Signer
CN string CN string
Organization []string Organization []string
FilterCN func(...string) []string
} }
func cns(secret *v1.Secret) (cns []string) { func cns(secret *v1.Secret) (cns []string) {
if secret == nil {
return nil
}
for k, v := range secret.Annotations { for k, v := range secret.Annotations {
if strings.HasPrefix(k, cnPrefix) { if strings.HasPrefix(k, cnPrefix) {
cns = append(cns, v) cns = append(cns, v)
@ -61,8 +71,23 @@ func collectCNs(secret *v1.Secret) (domains []string, ips []net.IP, hash string,
return return
} }
func (t *TLS) Merge(secret, other *v1.Secret) (*v1.Secret, bool, error) { func (t *TLS) Merge(target, additional *v1.Secret) (*v1.Secret, bool, error) {
return t.AddCN(secret, cns(other)...) return t.AddCN(target, cns(additional)...)
}
func (t *TLS) Refresh(secret *v1.Secret) (*v1.Secret, error) {
cns := cns(secret)
secret = secret.DeepCopy()
secret.Annotations = map[string]string{}
secret, _, err := t.AddCN(secret, cns...)
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) { func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) {
@ -70,10 +95,17 @@ func (t *TLS) AddCN(secret *v1.Secret, cn ...string) (*v1.Secret, bool, error) {
err error err error
) )
if !NeedsUpdate(secret, cn...) { cn = t.Filter(cn...)
if !NeedsUpdate(0, secret, cn...) {
return secret, false, nil return secret, false, nil
} }
secret = secret.DeepCopy()
if secret == nil {
secret = &v1.Secret{}
}
secret = populateCN(secret, cn...) secret = populateCN(secret, cn...)
privateKey, err := getPrivateKey(secret) privateKey, err := getPrivateKey(secret)
@ -116,18 +148,29 @@ func populateCN(secret *v1.Secret, cn ...string) *v1.Secret {
secret.Annotations = map[string]string{} secret.Annotations = map[string]string{}
} }
for _, cn := range cn { 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 return secret
} }
func NeedsUpdate(secret *v1.Secret, cn ...string) bool { func NeedsUpdate(maxSANs int, secret *v1.Secret, cn ...string) bool {
if secret.Annotations[static] == "true" { if secret == nil {
return true
}
if secret.Annotations[Static] == "true" {
return false return false
} }
for _, cn := range cn { for _, cn := range cn {
if secret.Annotations[cnPrefix+cn] == "" { if secret.Annotations[cnPrefix+cn] == "" {
if maxSANs > 0 && len(cns(secret)) >= maxSANs {
return false
}
return true return true
} }
} }

View File

@ -6,6 +6,7 @@ require (
github.com/rancher/wrangler v0.1.4 github.com/rancher/wrangler v0.1.4
github.com/rancher/wrangler-api v0.2.0 github.com/rancher/wrangler-api v0.2.0
github.com/sirupsen/logrus v1.4.1 github.com/sirupsen/logrus v1.4.1
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b
k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d
) )

View File

@ -1,6 +1,7 @@
package dynamiclistener package dynamiclistener
import ( import (
"context"
"crypto" "crypto"
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
@ -8,6 +9,7 @@ import (
"net/http" "net/http"
"strings" "strings"
"sync" "sync"
"time"
"github.com/rancher/dynamiclistener/factory" "github.com/rancher/dynamiclistener/factory"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
@ -19,15 +21,15 @@ type TLSStorage interface {
Update(secret *v1.Secret) error Update(secret *v1.Secret) error
} }
type SetFactory interface { type TLSFactory interface {
SetFactory(tls *factory.TLS) 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 Config struct { type SetFactory interface {
CN string SetFactory(tls TLSFactory)
Organization []string
TLSConfig tls.Config
SANs []string
} }
func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, caKey crypto.Signer, config Config) (net.Listener, http.Handler, error) { func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, caKey crypto.Signer, config Config) (net.Listener, http.Handler, error) {
@ -37,6 +39,9 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c
if len(config.Organization) == 0 { if len(config.Organization) == 0 {
config.Organization = []string{"dynamic"} config.Organization = []string{"dynamic"}
} }
if config.TLSConfig == nil {
config.TLSConfig = &tls.Config{}
}
dynamicListener := &listener{ dynamicListener := &listener{
factory: &factory.TLS{ factory: &factory.TLS{
@ -44,34 +49,169 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c
CAKey: caKey, CAKey: caKey,
CN: config.CN, CN: config.CN,
Organization: config.Organization, Organization: config.Organization,
FilterCN: allowDefaultSANs(config.SANs, config.FilterCN),
}, },
Listener: l, Listener: l,
storage: &nonNil{storage: storage}, storage: &nonNil{storage: storage},
sans: config.SANs, sans: config.SANs,
maxSANs: config.MaxSANs,
tlsConfig: config.TLSConfig, tlsConfig: config.TLSConfig,
} }
if dynamicListener.tlsConfig == nil {
dynamicListener.tlsConfig = &tls.Config{}
}
dynamicListener.tlsConfig.GetCertificate = dynamicListener.getCertificate dynamicListener.tlsConfig.GetCertificate = dynamicListener.getCertificate
if config.CloseConnOnCertChange {
if len(dynamicListener.tlsConfig.Certificates) == 0 {
dynamicListener.tlsConfig.NextProtos = []string{"http/1.1"}
}
dynamicListener.conns = map[int]*closeWrapper{}
}
if setter, ok := storage.(SetFactory); ok { if setter, ok := storage.(SetFactory); ok {
setter.SetFactory(dynamicListener.factory) setter.SetFactory(dynamicListener.factory)
} }
return tls.NewListener(dynamicListener, &dynamicListener.tlsConfig), dynamicListener.cacheHandler(), nil if config.ExpirationDaysCheck == 0 {
config.ExpirationDaysCheck = 30
}
tlsListener := tls.NewListener(dynamicListener.WrapExpiration(config.ExpirationDaysCheck), dynamicListener.tlsConfig)
return tlsListener, dynamicListener.cacheHandler(), nil
}
func allowDefaultSANs(sans []string, next func(...string) []string) func(...string) []string {
if next == nil {
return nil
} else if len(sans) == 0 {
return next
}
sanMap := map[string]bool{}
for _, san := range sans {
sanMap[san] = true
}
return func(s ...string) []string {
var (
good []string
unknown []string
)
for _, s := range s {
if sanMap[s] {
good = append(good, s)
} else {
unknown = append(unknown, s)
}
}
return append(good, next(unknown...)...)
}
}
type cancelClose struct {
cancel func()
net.Listener
}
func (c *cancelClose) Close() error {
c.cancel()
return c.Listener.Close()
}
type Config struct {
CN string
Organization []string
TLSConfig *tls.Config
SANs []string
MaxSANs int
ExpirationDaysCheck int
CloseConnOnCertChange bool
FilterCN func(...string) []string
} }
type listener struct { type listener struct {
sync.RWMutex sync.RWMutex
net.Listener net.Listener
factory *factory.TLS conns map[int]*closeWrapper
connID int
connLock sync.Mutex
factory TLSFactory
storage TLSStorage storage TLSStorage
version string version string
tlsConfig tls.Config tlsConfig *tls.Config
cert *tls.Certificate cert *tls.Certificate
sans []string sans []string
maxSANs int
init sync.Once init sync.Once
} }
func (l *listener) WrapExpiration(days int) net.Listener {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(5 * time.Minute)
for {
wait := 6 * time.Hour
if err := l.checkExpiration(days); err != nil {
logrus.Errorf("failed to check and refresh dynamic cert: %v", err)
wait = 5 + time.Minute
}
select {
case <-ctx.Done():
return
case <-time.After(wait):
}
}
}()
return &cancelClose{
cancel: cancel,
Listener: l,
}
}
func (l *listener) checkExpiration(days int) error {
l.Lock()
defer l.Unlock()
if days == 0 {
return nil
}
if l.cert == nil {
return nil
}
secret, err := l.storage.Get()
if err != nil {
return err
}
cert, err := tls.X509KeyPair(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
if err != nil {
return err
}
certParsed, err := x509.ParseCertificate(cert.Certificate[0])
if err != nil {
return err
}
if time.Now().UTC().Add(time.Hour * 24 * time.Duration(days)).After(certParsed.NotAfter) {
secret, err := l.factory.Refresh(secret)
if err != nil {
return err
}
return l.storage.Update(secret)
}
return nil
}
func (l *listener) Accept() (net.Conn, error) { func (l *listener) Accept() (net.Conn, error) {
l.init.Do(func() { l.init.Do(func() {
if len(l.sans) > 0 { if len(l.sans) > 0 {
@ -97,13 +237,49 @@ func (l *listener) Accept() (net.Conn, error) {
if !strings.Contains(host, ":") { if !strings.Contains(host, ":") {
if err := l.updateCert(host); err != nil { 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)
} }
} }
if l.conns != nil {
conn = l.wrap(conn)
}
return conn, nil return conn, nil
} }
func (l *listener) wrap(conn net.Conn) net.Conn {
l.connLock.Lock()
defer l.connLock.Unlock()
l.connID++
wrapper := &closeWrapper{
Conn: conn,
id: l.connID,
l: l,
}
l.conns[l.connID] = wrapper
return wrapper
}
type closeWrapper struct {
net.Conn
id int
l *listener
}
func (c *closeWrapper) close() error {
delete(c.l.conns, c.id)
return c.Conn.Close()
}
func (c *closeWrapper) Close() error {
c.l.connLock.Lock()
defer c.l.connLock.Unlock()
return c.close()
}
func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) { func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
if hello.ServerName != "" { if hello.ServerName != "" {
if err := l.updateCert(hello.ServerName); err != nil { if err := l.updateCert(hello.ServerName); err != nil {
@ -115,6 +291,11 @@ func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
} }
func (l *listener) updateCert(cn ...string) error { func (l *listener) updateCert(cn ...string) error {
cn = l.factory.Filter(cn...)
if len(cn) == 0 {
return nil
}
l.RLock() l.RLock()
defer l.RUnlock() defer l.RUnlock()
@ -123,7 +304,7 @@ func (l *listener) updateCert(cn ...string) error {
return err return err
} }
if !factory.NeedsUpdate(secret, cn...) { if !factory.NeedsUpdate(l.maxSANs, secret, cn...) {
return nil return nil
} }
@ -143,6 +324,13 @@ func (l *listener) updateCert(cn ...string) error {
} }
// clear version to force cert reload // clear version to force cert reload
l.version = "" l.version = ""
if l.conns != nil {
l.connLock.Lock()
for _, conn := range l.conns {
_ = conn.close()
}
l.connLock.Unlock()
}
} }
return nil return nil
@ -179,6 +367,7 @@ func (l *listener) loadCert() (*tls.Certificate, error) {
} }
l.cert = &cert l.cert = &cert
l.version = secret.ResourceVersion
return l.cert, nil return l.cert, nil
} }
@ -191,6 +380,12 @@ func (l *listener) cacheHandler() http.Handler {
ip := net.ParseIP(h) ip := net.ParseIP(h)
if len(ip) > 0 { if len(ip) > 0 {
for _, v := range req.Header["User-Agent"] {
if strings.Contains(strings.ToLower(v), "mozilla") {
return
}
}
l.updateCert(h) l.updateCert(h)
} }
}) })

View File

@ -11,8 +11,10 @@ import (
func HTTPRedirect(next http.Handler) http.Handler { func HTTPRedirect(next http.Handler) http.Handler {
return http.HandlerFunc( return http.HandlerFunc(
func(rw http.ResponseWriter, r *http.Request) { func(rw http.ResponseWriter, r *http.Request) {
if r.Header.Get("x-Forwarded-Proto") == "https" || if r.TLS != nil ||
r.Header.Get("x-Forwarded-Proto") == "https" ||
r.Header.Get("x-Forwarded-Proto") == "wss" || r.Header.Get("x-Forwarded-Proto") == "wss" ||
strings.HasPrefix(r.URL.Path, "/.well-known/") ||
strings.HasPrefix(r.URL.Path, "/ping") || strings.HasPrefix(r.URL.Path, "/ping") ||
strings.HasPrefix(r.URL.Path, "/health") { strings.HasPrefix(r.URL.Path, "/health") {
next.ServeHTTP(rw, r) next.ServeHTTP(rw, r)

View File

@ -39,4 +39,3 @@ func (s *storage) Update(secret *v1.Secret) error {
return json.NewEncoder(f).Encode(secret) return json.NewEncoder(f).Encode(secret)
} }

View File

@ -0,0 +1,59 @@
package kubernetes
import (
"crypto"
"crypto/x509"
"github.com/rancher/dynamiclistener/factory"
v1controller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func LoadOrGenCA(secrets v1controller.SecretClient, namespace, name string) (*x509.Certificate, crypto.Signer, error) {
secret, err := getSecret(secrets, namespace, name)
if err != nil {
return nil, nil, err
}
return factory.LoadCA(secret.Data[v1.TLSCertKey], secret.Data[v1.TLSPrivateKeyKey])
}
func getSecret(secrets v1controller.SecretClient, namespace, name string) (*v1.Secret, error) {
s, err := secrets.Get(namespace, name, metav1.GetOptions{})
if !errors.IsNotFound(err) {
return s, err
}
if err := createAndStore(secrets, namespace, name); err != nil {
return nil, err
}
return secrets.Get(namespace, name, metav1.GetOptions{})
}
func createAndStore(secrets v1controller.SecretClient, namespace string, name string) error {
ca, cert, err := factory.GenCA()
if err != nil {
return err
}
certPem, keyPem, err := factory.Marshal(ca, cert)
if err != nil {
return err
}
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string][]byte{
v1.TLSCertKey: certPem,
v1.TLSPrivateKeyKey: keyPem,
},
Type: v1.SecretTypeTLS,
}
secrets.Create(secret)
return nil
}

View File

@ -6,19 +6,28 @@ import (
"time" "time"
"github.com/rancher/dynamiclistener" "github.com/rancher/dynamiclistener"
"github.com/rancher/dynamiclistener/factory"
"github.com/rancher/wrangler-api/pkg/generated/controllers/core" "github.com/rancher/wrangler-api/pkg/generated/controllers/core"
v1controller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1" v1controller "github.com/rancher/wrangler-api/pkg/generated/controllers/core/v1"
"github.com/rancher/wrangler/pkg/start" "github.com/rancher/wrangler/pkg/start"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )
type CoreGetter func() *core.Factory type CoreGetter func() *core.Factory
func Load(ctx context.Context, secrets v1controller.SecretController, namespace, name string, backing dynamiclistener.TLSStorage) dynamiclistener.TLSStorage {
storage := &storage{
name: name,
namespace: namespace,
storage: backing,
ctx: ctx,
}
storage.init(secrets)
return storage
}
func New(ctx context.Context, core CoreGetter, namespace, name string, backing dynamiclistener.TLSStorage) dynamiclistener.TLSStorage { func New(ctx context.Context, core CoreGetter, namespace, name string, backing dynamiclistener.TLSStorage) dynamiclistener.TLSStorage {
storage := &storage{ storage := &storage{
name: name, name: name,
@ -55,10 +64,10 @@ type storage struct {
storage dynamiclistener.TLSStorage storage dynamiclistener.TLSStorage
secrets v1controller.SecretClient secrets v1controller.SecretClient
ctx context.Context ctx context.Context
tls *factory.TLS tls dynamiclistener.TLSFactory
} }
func (s *storage) SetFactory(tls *factory.TLS) { func (s *storage) SetFactory(tls dynamiclistener.TLSFactory) {
s.tls = tls s.tls = tls
} }
@ -122,7 +131,7 @@ func (s *storage) saveInK8s(secret *v1.Secret) (*v1.Secret, error) {
} }
if existing, err := s.storage.Get(); err == nil && s.tls != nil { if existing, err := s.storage.Get(); err == nil && s.tls != nil {
if newSecret, updated, err := s.tls.Merge(secret, existing); err == nil && updated { if newSecret, updated, err := s.tls.Merge(existing, secret); err == nil && updated {
secret = newSecret secret = newSecret
} }
} }
@ -132,9 +141,12 @@ func (s *storage) saveInK8s(secret *v1.Secret) (*v1.Secret, error) {
return nil, err return nil, err
} }
if equality.Semantic.DeepEqual(targetSecret.Annotations, secret.Annotations) && if newSecret, updated, err := s.tls.Merge(targetSecret, secret); err != nil {
equality.Semantic.DeepEqual(targetSecret.Data, secret.Data) { return nil, err
return secret, nil } else if !updated {
return newSecret, nil
} else {
secret = newSecret
} }
targetSecret.Annotations = secret.Annotations targetSecret.Annotations = secret.Annotations

2
vendor/modules.txt vendored
View File

@ -717,7 +717,7 @@ github.com/prometheus/procfs/xfs
# github.com/rakelkar/gonetsh v0.0.0-20190930180311-e5c5ffe4bdf0 # github.com/rakelkar/gonetsh v0.0.0-20190930180311-e5c5ffe4bdf0
github.com/rakelkar/gonetsh/netroute github.com/rakelkar/gonetsh/netroute
github.com/rakelkar/gonetsh/netsh github.com/rakelkar/gonetsh/netsh
# github.com/rancher/dynamiclistener v0.2.0 # github.com/rancher/dynamiclistener v0.2.1-0.20200418023342-52ede5ec9234
github.com/rancher/dynamiclistener github.com/rancher/dynamiclistener
github.com/rancher/dynamiclistener/cert github.com/rancher/dynamiclistener/cert
github.com/rancher/dynamiclistener/factory github.com/rancher/dynamiclistener/factory