mirror of
https://github.com/k3s-io/k3s.git
synced 2024-06-07 19:41:36 +00:00
Merge pull request #2053 from brandond/update_dynamiclistener
Update dynamiclistener
This commit is contained in:
commit
c8282f4939
2
go.mod
2
go.mod
@ -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
4
go.sum
@ -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=
|
||||||
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
vendor/github.com/rancher/dynamiclistener/factory/ca.go
generated
vendored
24
vendor/github.com/rancher/dynamiclistener/factory/ca.go
generated
vendored
@ -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)
|
||||||
|
}
|
||||||
|
57
vendor/github.com/rancher/dynamiclistener/factory/gen.go
generated
vendored
57
vendor/github.com/rancher/dynamiclistener/factory/gen.go
generated
vendored
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
vendor/github.com/rancher/dynamiclistener/go.mod
generated
vendored
1
vendor/github.com/rancher/dynamiclistener/go.mod
generated
vendored
@ -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
|
||||||
)
|
)
|
||||||
|
219
vendor/github.com/rancher/dynamiclistener/listener.go
generated
vendored
219
vendor/github.com/rancher/dynamiclistener/listener.go
generated
vendored
@ -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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
4
vendor/github.com/rancher/dynamiclistener/redirect.go
generated
vendored
4
vendor/github.com/rancher/dynamiclistener/redirect.go
generated
vendored
@ -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)
|
||||||
|
1
vendor/github.com/rancher/dynamiclistener/storage/file/file.go
generated
vendored
1
vendor/github.com/rancher/dynamiclistener/storage/file/file.go
generated
vendored
@ -39,4 +39,3 @@ func (s *storage) Update(secret *v1.Secret) error {
|
|||||||
|
|
||||||
return json.NewEncoder(f).Encode(secret)
|
return json.NewEncoder(f).Encode(secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
59
vendor/github.com/rancher/dynamiclistener/storage/kubernetes/ca.go
generated
vendored
Normal file
59
vendor/github.com/rancher/dynamiclistener/storage/kubernetes/ca.go
generated
vendored
Normal 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
|
||||||
|
}
|
28
vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go
generated
vendored
28
vendor/github.com/rancher/dynamiclistener/storage/kubernetes/controller.go
generated
vendored
@ -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
2
vendor/modules.txt
vendored
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user