mirror of
https://github.com/rancher/dynamiclistener.git
synced 2025-09-02 13:44:26 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e425269f0e | ||
|
401fafb7e6 | ||
|
bad953b9f0 | ||
|
8ebd77f8a4 | ||
|
fdf983a935 | ||
|
7b5997cee9 | ||
|
42d72c2ef2 | ||
|
d2b7e2aaa6 | ||
|
a30741bb53 | ||
|
4df376813d | ||
|
9b92d13bcb | ||
|
5e81b14c1f |
15
.drone.yml
Normal file
15
.drone.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
|
||||
kind: pipeline
|
||||
name: fossa
|
||||
|
||||
steps:
|
||||
- name: fossa
|
||||
image: rancher/drone-fossa:latest
|
||||
settings:
|
||||
api_key:
|
||||
from_secret: FOSSA_API_KEY
|
||||
when:
|
||||
instance:
|
||||
- drone-publish.rancher.io
|
||||
|
35
cert/cert.go
35
cert/cert.go
@@ -33,7 +33,9 @@ import (
|
||||
"math"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -64,11 +66,16 @@ type AltNames struct {
|
||||
IPs []net.IP
|
||||
}
|
||||
|
||||
// NewPrivateKey creates an RSA private key
|
||||
func NewPrivateKey() (*rsa.PrivateKey, error) {
|
||||
// NewRSAPrivateKey creates an RSA private key
|
||||
func NewRSAPrivateKey() (*rsa.PrivateKey, error) {
|
||||
return rsa.GenerateKey(cryptorand.Reader, rsaKeySize)
|
||||
}
|
||||
|
||||
// NewPrivateKey creates an RSA private key
|
||||
func NewPrivateKey() (*ecdsa.PrivateKey, error) {
|
||||
return ecdsa.GenerateKey(elliptic.P256Sm2(), cryptorand.Reader)
|
||||
}
|
||||
|
||||
// NewSelfSignedCACert creates a CA certificate
|
||||
func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
|
||||
now := time.Now()
|
||||
@@ -109,11 +116,18 @@ func NewSignedCert(cfg Config, key crypto.Signer, caCert *x509.Certificate, caKe
|
||||
if len(cfg.Usages) == 0 {
|
||||
return nil, errors.New("must specify at least one ExtKeyUsage")
|
||||
}
|
||||
var expiresAt time.Duration
|
||||
expiresAt := duration365d
|
||||
if cfg.ExpiresAt > 0 {
|
||||
expiresAt = time.Duration(cfg.ExpiresAt)
|
||||
} else {
|
||||
expiresAt = duration365d
|
||||
envExpirationDays := os.Getenv("CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS")
|
||||
if envExpirationDays != "" {
|
||||
if envExpirationDaysInt, err := strconv.Atoi(envExpirationDays); err != nil {
|
||||
logrus.Infof("[NewSignedCert] expiration days from ENV (%s) could not be converted to int (falling back to default value: %d)", envExpirationDays, expiresAt)
|
||||
} else {
|
||||
expiresAt = time.Hour * 24 * time.Duration(envExpirationDaysInt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
certTmpl := x509.Certificate{
|
||||
@@ -144,7 +158,7 @@ func NewSignedCert(cfg Config, key crypto.Signer, caCert *x509.Certificate, caKe
|
||||
|
||||
// MakeEllipticPrivateKeyPEM creates an ECDSA private key
|
||||
func MakeEllipticPrivateKeyPEM() ([]byte, error) {
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), cryptorand.Reader)
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256Sm2(), cryptorand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -195,7 +209,7 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
|
||||
maxAge = 100 * time.Hour * 24 * 365 // 100 years fixtures
|
||||
}
|
||||
|
||||
caKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
|
||||
caKey, err := NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -223,7 +237,7 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
priv, err := rsa.GenerateKey(cryptorand.Reader, 2048)
|
||||
priv, err := NewPrivateKey()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -266,7 +280,12 @@ func GenerateSelfSignedCertKeyWithFixtures(host string, alternateIPs []net.IP, a
|
||||
|
||||
// Generate key
|
||||
keyBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(&keyBuffer, &pem.Block{Type: RSAPrivateKeyBlockType, Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil {
|
||||
privBuf, err := x509.MarshalECPrivateKey(priv)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := pem.Encode(&keyBuffer, &pem.Block{Type: ECPrivateKeyBlockType, Bytes: privBuf}); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
|
39
cert/cert_test.go
Normal file
39
cert/cert_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package cert
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateAndReadCert(t *testing.T) {
|
||||
kFile := "service.key"
|
||||
defer os.Remove(kFile)
|
||||
key, err := NewPrivateKey()
|
||||
if err != nil {
|
||||
t.Errorf("failed to create private key: %v", err)
|
||||
}
|
||||
|
||||
if err := WriteKey(kFile, EncodePrivateKeyPEM(key)); err != nil {
|
||||
t.Errorf("failed to encode private key to pem: %v", err)
|
||||
}
|
||||
|
||||
keyR, err := PrivateKeyFromFile(kFile)
|
||||
if err != nil {
|
||||
t.Errorf("failed to load private key from file: %v", err)
|
||||
}
|
||||
|
||||
switch k := keyR.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
fmt.Println("loaded back ecdsa private key")
|
||||
default:
|
||||
t.Errorf("load back a wrong private key %v", k)
|
||||
}
|
||||
|
||||
buf := EncodePrivateKeyPEM(key)
|
||||
_, err = ParsePrivateKeyPEM(buf)
|
||||
if err != nil {
|
||||
t.Errorf("failed to parse private key from pem: %v", err)
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package cert
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
cryptorand "crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
@@ -60,8 +61,11 @@ func MakeCSRFromTemplate(privateKey interface{}, template *x509.CertificateReque
|
||||
|
||||
func sigType(privateKey interface{}) x509.SignatureAlgorithm {
|
||||
// Customize the signature for RSA keys, depending on the key size
|
||||
if privateKey, ok := privateKey.(*rsa.PrivateKey); ok {
|
||||
keySize := privateKey.N.BitLen()
|
||||
switch privK := privateKey.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
return x509.ECDSAWithSHA256
|
||||
case *rsa.PrivateKey:
|
||||
keySize := privK.N.BitLen()
|
||||
switch {
|
||||
case keySize >= 4096:
|
||||
return x509.SHA512WithRSA
|
||||
|
25
cert/pem.go
25
cert/pem.go
@@ -41,7 +41,7 @@ const (
|
||||
)
|
||||
|
||||
// EncodePublicKeyPEM returns PEM-encoded public data
|
||||
func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) {
|
||||
func EncodePublicKeyPEM(key interface{}) ([]byte, error) {
|
||||
der, err := x509.MarshalPKIXPublicKey(key)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
@@ -54,12 +54,25 @@ func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) {
|
||||
}
|
||||
|
||||
// EncodePrivateKeyPEM returns PEM-encoded private key data
|
||||
func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte {
|
||||
block := pem.Block{
|
||||
Type: RSAPrivateKeyBlockType,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(key),
|
||||
func EncodePrivateKeyPEM(key interface{}) []byte {
|
||||
var block *pem.Block
|
||||
switch privKey := key.(type) {
|
||||
case *ecdsa.PrivateKey:
|
||||
derBytes, _ := x509.MarshalECPrivateKey(privKey)
|
||||
block = &pem.Block{
|
||||
Type: ECPrivateKeyBlockType,
|
||||
Bytes: derBytes,
|
||||
}
|
||||
case *rsa.PrivateKey:
|
||||
block = &pem.Block{
|
||||
Type: RSAPrivateKeyBlockType,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(privKey),
|
||||
}
|
||||
}
|
||||
return pem.EncodeToMemory(&block)
|
||||
if block != nil {
|
||||
return pem.EncodeToMemory(block)
|
||||
}
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
// EncodeCertPEM returns PEM-endcoded certificate data
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/dynamiclistener/cert"
|
||||
)
|
||||
@@ -16,7 +17,7 @@ func GenCA() (*x509.Certificate, crypto.Signer, error) {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
caCert, err := NewSelfSignedCACert(caKey, "dynamiclistener-ca", "dynamiclistener-org")
|
||||
caCert, err := NewSelfSignedCACert(caKey, fmt.Sprintf("dynamiclistener-ca@%d", time.Now().Unix()), "dynamiclistener-org")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/dynamiclistener/cert"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -32,11 +33,12 @@ var (
|
||||
)
|
||||
|
||||
type TLS struct {
|
||||
CACert *x509.Certificate
|
||||
CAKey crypto.Signer
|
||||
CN string
|
||||
Organization []string
|
||||
FilterCN func(...string) []string
|
||||
CACert *x509.Certificate
|
||||
CAKey crypto.Signer
|
||||
CN string
|
||||
Organization []string
|
||||
FilterCN func(...string) []string
|
||||
ExpirationDaysCheck int
|
||||
}
|
||||
|
||||
func cns(secret *v1.Secret) (cns []string) {
|
||||
@@ -72,7 +74,8 @@ func collectCNs(secret *v1.Secret) (domains []string, ips []net.IP, err error) {
|
||||
|
||||
// Merge combines the SAN lists from the target and additional Secrets, and
|
||||
// returns a potentially modified Secret, along with a bool indicating if the
|
||||
// returned Secret is not the same as the target Secret.
|
||||
// returned Secret is not the same as the target Secret. Secrets with expired
|
||||
// certificates will never be returned.
|
||||
//
|
||||
// If the merge would not add any CNs to the additional Secret, the additional
|
||||
// Secret is returned, to allow for certificate rotation/regeneration.
|
||||
@@ -93,17 +96,17 @@ func (t *TLS) Merge(target, additional *v1.Secret) (*v1.Secret, bool, error) {
|
||||
|
||||
// if the additional secret already has all the CNs, use it in preference to the
|
||||
// current one. This behavior is required to allow for renewal or regeneration.
|
||||
if !NeedsUpdate(0, additional, mergedCNs...) {
|
||||
if !NeedsUpdate(0, additional, mergedCNs...) && !t.IsExpired(additional) {
|
||||
return additional, true, nil
|
||||
}
|
||||
|
||||
// if the target secret already has all the CNs, continue using it. The additional
|
||||
// cert had only a subset of the current CNs, so nothing needs to be added.
|
||||
if !NeedsUpdate(0, target, mergedCNs...) {
|
||||
if !NeedsUpdate(0, target, mergedCNs...) && !t.IsExpired(target) {
|
||||
return target, false, nil
|
||||
}
|
||||
|
||||
// neither cert currently has all the necessary CNs; generate a new one.
|
||||
// neither cert currently has all the necessary CNs or is unexpired; generate a new one.
|
||||
return t.generateCert(target, mergedCNs...)
|
||||
}
|
||||
|
||||
@@ -154,6 +157,10 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
|
||||
secret = &v1.Secret{}
|
||||
}
|
||||
|
||||
if err := t.Verify(secret); err != nil {
|
||||
logrus.Warnf("unable to verify existing certificate: %v - signing operation may change certificate issuer", err)
|
||||
}
|
||||
|
||||
secret = populateCN(secret, cn...)
|
||||
|
||||
privateKey, err := getPrivateKey(secret)
|
||||
@@ -171,7 +178,7 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
certBytes, keyBytes, err := Marshal(newCert, privateKey)
|
||||
keyBytes, certBytes, err := MarshalChain(privateKey, newCert, t.CACert)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -187,6 +194,44 @@ func (t *TLS) generateCert(secret *v1.Secret, cn ...string) (*v1.Secret, bool, e
|
||||
return secret, true, nil
|
||||
}
|
||||
|
||||
func (t *TLS) IsExpired(secret *v1.Secret) bool {
|
||||
certsPem := secret.Data[v1.TLSCertKey]
|
||||
if len(certsPem) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
certificates, err := cert.ParseCertsPEM(certsPem)
|
||||
if err != nil || len(certificates) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
expirationDays := time.Duration(t.ExpirationDaysCheck) * time.Hour * 24
|
||||
return time.Now().Add(expirationDays).After(certificates[0].NotAfter)
|
||||
}
|
||||
|
||||
func (t *TLS) Verify(secret *v1.Secret) error {
|
||||
certsPem := secret.Data[v1.TLSCertKey]
|
||||
if len(certsPem) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
certificates, err := cert.ParseCertsPEM(certsPem)
|
||||
if err != nil || len(certificates) == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
verifyOpts := x509.VerifyOptions{
|
||||
Roots: x509.NewCertPool(),
|
||||
KeyUsages: []x509.ExtKeyUsage{
|
||||
x509.ExtKeyUsageAny,
|
||||
},
|
||||
}
|
||||
verifyOpts.Roots.AddCert(t.CACert)
|
||||
|
||||
_, err = certificates[0].Verify(verifyOpts)
|
||||
return err
|
||||
}
|
||||
|
||||
func (t *TLS) newCert(domains []string, ips []net.IP, privateKey crypto.Signer) (*x509.Certificate, error) {
|
||||
return NewSignedCert(privateKey, t.CACert, t.CAKey, t.CN, t.Organization, domains, ips)
|
||||
}
|
||||
@@ -250,14 +295,33 @@ func getPrivateKey(secret *v1.Secret) (crypto.Signer, error) {
|
||||
return NewPrivateKey()
|
||||
}
|
||||
|
||||
// MarshalChain returns given key and certificates as byte slices.
|
||||
func MarshalChain(privateKey crypto.Signer, certs ...*x509.Certificate) (keyBytes, certChainBytes []byte, err error) {
|
||||
keyBytes, err = cert.MarshalPrivateKeyToPEM(privateKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
for _, cert := range certs {
|
||||
if cert != nil {
|
||||
certBlock := pem.Block{
|
||||
Type: CertificateBlockType,
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
certChainBytes = append(certChainBytes, pem.EncodeToMemory(&certBlock)...)
|
||||
}
|
||||
}
|
||||
return keyBytes, certChainBytes, nil
|
||||
}
|
||||
|
||||
// Marshal returns the given cert and key as byte slices.
|
||||
func Marshal(x509Cert *x509.Certificate, privateKey crypto.Signer) ([]byte, []byte, error) {
|
||||
func Marshal(x509Cert *x509.Certificate, privateKey crypto.Signer) (certBytes, keyBytes []byte, err error) {
|
||||
certBlock := pem.Block{
|
||||
Type: CertificateBlockType,
|
||||
Bytes: x509Cert.Raw,
|
||||
}
|
||||
|
||||
keyBytes, err := cert.MarshalPrivateKeyToPEM(privateKey)
|
||||
keyBytes, err = cert.MarshalPrivateKeyToPEM(privateKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
51
listener.go
51
listener.go
@@ -7,7 +7,6 @@ import (
|
||||
"crypto/x509"
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -45,14 +44,18 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c
|
||||
if config.TLSConfig == nil {
|
||||
config.TLSConfig = &tls.Config{}
|
||||
}
|
||||
if config.ExpirationDaysCheck == 0 {
|
||||
config.ExpirationDaysCheck = 90
|
||||
}
|
||||
|
||||
dynamicListener := &listener{
|
||||
factory: &factory.TLS{
|
||||
CACert: caCert,
|
||||
CAKey: caKey,
|
||||
CN: config.CN,
|
||||
Organization: config.Organization,
|
||||
FilterCN: allowDefaultSANs(config.SANs, config.FilterCN),
|
||||
CACert: caCert,
|
||||
CAKey: caKey,
|
||||
CN: config.CN,
|
||||
Organization: config.Organization,
|
||||
FilterCN: allowDefaultSANs(config.SANs, config.FilterCN),
|
||||
ExpirationDaysCheck: config.ExpirationDaysCheck,
|
||||
},
|
||||
Listener: l,
|
||||
storage: &nonNil{storage: storage},
|
||||
@@ -82,10 +85,6 @@ func NewListener(l net.Listener, storage TLSStorage, caCert *x509.Certificate, c
|
||||
}
|
||||
}
|
||||
|
||||
if config.ExpirationDaysCheck == 0 {
|
||||
config.ExpirationDaysCheck = 30
|
||||
}
|
||||
|
||||
tlsListener := tls.NewListener(dynamicListener.WrapExpiration(config.ExpirationDaysCheck), dynamicListener.tlsConfig)
|
||||
|
||||
return tlsListener, dynamicListener.cacheHandler(), nil
|
||||
@@ -163,15 +162,15 @@ type listener struct {
|
||||
func (l *listener) WrapExpiration(days int) net.Listener {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
// busy-wait for certificate preload to complete
|
||||
// loop on short sleeps until certificate preload completes
|
||||
for l.cert == nil {
|
||||
runtime.Gosched()
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
|
||||
for {
|
||||
wait := 6 * time.Hour
|
||||
if err := l.checkExpiration(days); err != nil {
|
||||
logrus.Errorf("failed to check and renew dynamic cert: %v", err)
|
||||
logrus.Errorf("dynamiclistener %s: failed to check and renew dynamic cert: %v", l.Addr(), err)
|
||||
// Don't go into short retry loop if we're using a static (user-provided) cert.
|
||||
// We will still check and print an error every six hours until the user updates the secret with
|
||||
// a cert that is not about to expire. Hopefully this will prompt them to take action.
|
||||
@@ -263,12 +262,18 @@ func (l *listener) Accept() (net.Conn, error) {
|
||||
l.init.Do(func() {
|
||||
if len(l.sans) > 0 {
|
||||
if err := l.updateCert(l.sans...); err != nil {
|
||||
logrus.Errorf("failed to update cert with configured SANs: %v", err)
|
||||
logrus.Errorf("dynamiclistener %s: failed to update cert with configured SANs: %v", l.Addr(), err)
|
||||
return
|
||||
}
|
||||
if _, err := l.loadCert(nil); err != nil {
|
||||
logrus.Errorf("failed to preload certificate: %v", err)
|
||||
}
|
||||
}
|
||||
if cert, err := l.loadCert(nil); err != nil {
|
||||
logrus.Errorf("dynamiclistener %s: failed to preload certificate: %v", l.Addr(), err)
|
||||
} else if cert == nil {
|
||||
// This should only occur on the first startup when no SANs are configured in the listener config, in which
|
||||
// case no certificate can be created, as dynamiclistener will not create certificates until at least one IP
|
||||
// or DNS SAN is set. It will also occur when using the Kubernetes storage without a local File cache.
|
||||
// For reliable serving of requests, callers should configure a local cache and/or a default set of SANs.
|
||||
logrus.Warnf("dynamiclistener %s: no cached certificate available for preload - deferring certificate load until storage initialization or first client request", l.Addr())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -284,14 +289,12 @@ func (l *listener) Accept() (net.Conn, error) {
|
||||
|
||||
host, _, err := net.SplitHostPort(addr.String())
|
||||
if err != nil {
|
||||
logrus.Errorf("failed to parse network %s: %v", addr.Network(), err)
|
||||
logrus.Errorf("dynamiclistener %s: failed to parse connection local address %s: %v", l.Addr(), addr, err)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
if !strings.Contains(host, ":") {
|
||||
if err := l.updateCert(host); err != nil {
|
||||
logrus.Errorf("failed to update cert with listener address: %v", err)
|
||||
}
|
||||
if err := l.updateCert(host); err != nil {
|
||||
logrus.Errorf("dynamiclistener %s: failed to update cert with connection local address: %v", l.Addr(), err)
|
||||
}
|
||||
|
||||
if l.conns != nil {
|
||||
@@ -338,7 +341,7 @@ func (l *listener) getCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate,
|
||||
newConn := hello.Conn
|
||||
if hello.ServerName != "" {
|
||||
if err := l.updateCert(hello.ServerName); err != nil {
|
||||
logrus.Errorf("failed to update cert with TLS ServerName: %v", err)
|
||||
logrus.Errorf("dynamiclistener %s: failed to update cert with TLS ServerName: %v", l.Addr(), err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -455,7 +458,7 @@ func (l *listener) cacheHandler() http.Handler {
|
||||
}
|
||||
|
||||
if err := l.updateCert(h); err != nil {
|
||||
logrus.Errorf("failed to update cert with HTTP request Host header: %v", err)
|
||||
logrus.Errorf("dynamiclistener %s: failed to update cert with HTTP request Host header: %v", l.Addr(), err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -56,7 +56,7 @@ func createAndStoreClientCert(secrets v1controller.SecretClient, namespace strin
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certPem, keyPem, err := factory.Marshal(cert, key)
|
||||
keyPem, certPem, err := factory.MarshalChain(key, cert, caCert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -69,6 +69,8 @@ type storage struct {
|
||||
}
|
||||
|
||||
func (s *storage) SetFactory(tls dynamiclistener.TLSFactory) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.tls = tls
|
||||
}
|
||||
|
||||
@@ -109,7 +111,9 @@ func (s *storage) init(secrets v1controller.SecretController) {
|
||||
// local storage was empty, try to populate it
|
||||
secret, err := s.secrets.Get(s.namespace, s.name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to init Kubernetes secret: %v", err)
|
||||
if !errors.IsNotFound(err) {
|
||||
logrus.Warnf("Failed to init Kubernetes secret: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ func (s *storage) targetSecret() (*v1.Secret, error) {
|
||||
}
|
||||
|
||||
func (s *storage) saveInK8s(secret *v1.Secret) (*v1.Secret, error) {
|
||||
if !s.controllerHasSynced() {
|
||||
if !s.initComplete() {
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
@@ -206,9 +210,14 @@ func (s *storage) Update(secret *v1.Secret) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isConflictOrAlreadyExists(err error) bool {
|
||||
return errors.IsConflict(err) || errors.IsAlreadyExists(err)
|
||||
}
|
||||
|
||||
func (s *storage) update(secret *v1.Secret) (err error) {
|
||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
secret, err = s.saveInK8s(secret)
|
||||
var newSecret *v1.Secret
|
||||
err = retry.OnError(retry.DefaultRetry, isConflictOrAlreadyExists, func() error {
|
||||
newSecret, err = s.saveInK8s(secret)
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -219,14 +228,11 @@ func (s *storage) update(secret *v1.Secret) (err error) {
|
||||
// Only hold the lock while updating underlying storage
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.storage.Update(secret)
|
||||
return s.storage.Update(newSecret)
|
||||
}
|
||||
|
||||
func (s *storage) controllerHasSynced() bool {
|
||||
func (s *storage) initComplete() bool {
|
||||
s.RLock()
|
||||
defer s.RUnlock()
|
||||
if s.secrets == nil {
|
||||
return false
|
||||
}
|
||||
return s.secrets.Informer().HasSynced()
|
||||
return s.secrets != nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user