Only support SSL dynamic mode
This commit is contained in:
parent
333d9fd48d
commit
80bd481abb
40 changed files with 415 additions and 709 deletions
|
|
@ -17,17 +17,20 @@ limitations under the License.
|
|||
package store
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/net/ssl"
|
||||
)
|
||||
|
||||
|
|
@ -39,7 +42,6 @@ func (s *k8sStore) syncSecret(key string) {
|
|||
|
||||
klog.V(3).Infof("Syncing Secret %q", key)
|
||||
|
||||
// TODO: getPemCertificate should not write to disk to avoid unnecessary overhead
|
||||
cert, err := s.getPemCertificate(key)
|
||||
if err != nil {
|
||||
if !isErrSecretForAuth(err) {
|
||||
|
|
@ -92,6 +94,7 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
if cert == nil {
|
||||
return nil, fmt.Errorf("key 'tls.crt' missing from Secret %q", secretName)
|
||||
}
|
||||
|
||||
if key == nil {
|
||||
return nil, fmt.Errorf("key 'tls.key' missing from Secret %q", secretName)
|
||||
}
|
||||
|
|
@ -101,15 +104,16 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
return nil, fmt.Errorf("unexpected error creating SSL Cert: %v", err)
|
||||
}
|
||||
|
||||
if !ngx_config.EnableDynamicCertificates || len(ca) > 0 {
|
||||
err = ssl.StoreSSLCertOnDisk(s.filesystem, nsSecName, sslCert)
|
||||
if len(ca) > 0 {
|
||||
path, err := ssl.StoreSSLCertOnDisk(nsSecName, sslCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while storing certificate and key: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ca) > 0 {
|
||||
err = ssl.ConfigureCACertWithCertAndKey(s.filesystem, nsSecName, ca, sslCert)
|
||||
sslCert.CAFileName = path
|
||||
sslCert.CASHA = file.SHA1(path)
|
||||
|
||||
err = ssl.ConfigureCACertWithCertAndKey(nsSecName, ca, sslCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring CA certificate: %v", err)
|
||||
}
|
||||
|
|
@ -120,14 +124,13 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
msg += " and authentication"
|
||||
}
|
||||
klog.V(3).Info(msg)
|
||||
|
||||
} else if len(ca) > 0 {
|
||||
sslCert, err = ssl.CreateCACert(ca)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unexpected error creating SSL Cert: %v", err)
|
||||
}
|
||||
|
||||
err = ssl.ConfigureCACert(s.filesystem, nsSecName, ca, sslCert)
|
||||
err = ssl.ConfigureCACert(nsSecName, ca, sslCert)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error configuring CA certificate: %v", err)
|
||||
}
|
||||
|
|
@ -135,7 +138,6 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
// makes this secret in 'syncSecret' to be used for Certificate Authentication
|
||||
// this does not enable Certificate Authentication
|
||||
klog.V(3).Infof("Configuring Secret %q for TLS authentication", secretName)
|
||||
|
||||
} else {
|
||||
if auth != nil {
|
||||
return nil, ErrSecretForAuth
|
||||
|
|
@ -147,6 +149,21 @@ func (s *k8sStore) getPemCertificate(secretName string) (*ingress.SSLCert, error
|
|||
sslCert.Name = secret.Name
|
||||
sslCert.Namespace = secret.Namespace
|
||||
|
||||
hasher := sha1.New()
|
||||
hasher.Write(sslCert.Certificate.Raw)
|
||||
|
||||
sslCert.PemSHA = hex.EncodeToString(hasher.Sum(nil))
|
||||
|
||||
// the default SSL certificate needs to be present on disk
|
||||
if secretName == s.defaultSSLCertificate {
|
||||
path, err := ssl.StoreSSLCertOnDisk(nsSecName, sslCert)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "storing default SSL Certificate")
|
||||
}
|
||||
|
||||
sslCert.PemFileName = path
|
||||
}
|
||||
|
||||
return sslCert, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,9 +152,9 @@ func (e NotExistsError) Error() string {
|
|||
|
||||
// Run initiates the synchronization of the informers against the API server.
|
||||
func (i *Informer) Run(stopCh chan struct{}) {
|
||||
go i.Secret.Run(stopCh)
|
||||
go i.Endpoint.Run(stopCh)
|
||||
go i.Service.Run(stopCh)
|
||||
go i.Secret.Run(stopCh)
|
||||
go i.ConfigMap.Run(stopCh)
|
||||
go i.Pod.Run(stopCh)
|
||||
|
||||
|
|
@ -165,6 +165,7 @@ func (i *Informer) Run(stopCh chan struct{}) {
|
|||
i.Service.HasSynced,
|
||||
i.Secret.HasSynced,
|
||||
i.ConfigMap.HasSynced,
|
||||
i.Pod.HasSynced,
|
||||
) {
|
||||
runtime.HandleError(fmt.Errorf("timed out waiting for caches to sync"))
|
||||
}
|
||||
|
|
@ -208,8 +209,6 @@ type k8sStore struct {
|
|||
// secret in the annotations.
|
||||
secretIngressMap ObjectRefMap
|
||||
|
||||
filesystem file.Filesystem
|
||||
|
||||
// updateCh
|
||||
updateCh *channels.RingChannel
|
||||
|
||||
|
|
@ -229,7 +228,6 @@ func New(
|
|||
namespace, configmap, tcp, udp, defaultSSLCertificate string,
|
||||
resyncPeriod time.Duration,
|
||||
client clientset.Interface,
|
||||
fs file.Filesystem,
|
||||
updateCh *channels.RingChannel,
|
||||
pod *k8s.PodInfo,
|
||||
disableCatchAll bool) Storer {
|
||||
|
|
@ -238,7 +236,6 @@ func New(
|
|||
informers: &Informer{},
|
||||
listers: &Lister{},
|
||||
sslStore: NewSSLCertTracker(),
|
||||
filesystem: fs,
|
||||
updateCh: updateCh,
|
||||
backendConfig: ngx_config.NewDefault(),
|
||||
syncSecretMu: &sync.Mutex{},
|
||||
|
|
@ -494,6 +491,7 @@ func New(
|
|||
}
|
||||
store.syncIngress(ing)
|
||||
}
|
||||
|
||||
updateCh.In() <- Event{
|
||||
Type: DeleteEvent,
|
||||
Obj: obj,
|
||||
|
|
@ -813,7 +811,7 @@ func (s *k8sStore) GetAuthCertificate(name string) (*resolver.AuthSSLCert, error
|
|||
return &resolver.AuthSSLCert{
|
||||
Secret: name,
|
||||
CAFileName: cert.CAFileName,
|
||||
PemSHA: cert.PemSHA,
|
||||
CASHA: cert.CASHA,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,8 @@ import (
|
|||
"k8s.io/client-go/tools/cache"
|
||||
"sigs.k8s.io/controller-runtime/pkg/envtest"
|
||||
|
||||
"k8s.io/ingress-nginx/internal/file"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/k8s"
|
||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||
)
|
||||
|
|
@ -87,7 +85,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -96,7 +93,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -167,7 +163,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -176,7 +171,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -317,7 +311,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -326,7 +319,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -423,7 +415,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -432,7 +423,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -512,7 +502,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -521,7 +510,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -623,7 +611,6 @@ func TestStore(t *testing.T) {
|
|||
}
|
||||
}(updateCh)
|
||||
|
||||
fs := newFS(t)
|
||||
storer := New(
|
||||
ns,
|
||||
fmt.Sprintf("%v/config", ns),
|
||||
|
|
@ -632,7 +619,6 @@ func TestStore(t *testing.T) {
|
|||
"",
|
||||
10*time.Minute,
|
||||
clientSet,
|
||||
fs,
|
||||
updateCh,
|
||||
pod,
|
||||
false)
|
||||
|
|
@ -701,39 +687,6 @@ func TestStore(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("error creating secret: %v", err)
|
||||
}
|
||||
|
||||
t.Run("should exists a secret in the local store and filesystem", func(t *testing.T) {
|
||||
ngx_config.EnableDynamicCertificates = false
|
||||
defer func() { ngx_config.EnableDynamicCertificates = true }()
|
||||
|
||||
err := framework.WaitForSecretInNamespace(clientSet, ns, name)
|
||||
if err != nil {
|
||||
t.Errorf("error waiting for secret: %v", err)
|
||||
}
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
pemFile := fmt.Sprintf("%v/%v-%v.pem", file.DefaultSSLDirectory, ns, name)
|
||||
err = framework.WaitForFileInFS(pemFile, fs)
|
||||
if err != nil {
|
||||
t.Errorf("error waiting for file to exist on the file system: %v", err)
|
||||
}
|
||||
|
||||
secretName := fmt.Sprintf("%v/%v", ns, name)
|
||||
sslCert, err := storer.GetLocalSSLCert(secretName)
|
||||
if err != nil {
|
||||
t.Errorf("error reading local secret %v: %v", secretName, err)
|
||||
}
|
||||
|
||||
if sslCert == nil {
|
||||
t.Errorf("expected a secret but none returned")
|
||||
}
|
||||
|
||||
pemSHA := file.SHA1(pemFile)
|
||||
if sslCert.PemSHA != pemSHA {
|
||||
t.Errorf("SHA of secret on disk differs from local secret store (%v != %v)", pemSHA, sslCert.PemSHA)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// test add ingress with secret it doesn't exists and then add secret
|
||||
|
|
@ -821,22 +774,9 @@ func deleteIngress(ingress *networking.Ingress, clientSet kubernetes.Interface,
|
|||
t.Logf("Ingress %+v deleted", ingress)
|
||||
}
|
||||
|
||||
func newFS(t *testing.T) file.Filesystem {
|
||||
fs, err := file.NewFakeFS()
|
||||
if err != nil {
|
||||
t.Fatalf("error creating filesystem: %v", err)
|
||||
}
|
||||
return fs
|
||||
}
|
||||
|
||||
// newStore creates a new mock object store for tests which do not require the
|
||||
// use of Informers.
|
||||
func newStore(t *testing.T) *k8sStore {
|
||||
fs, err := file.NewFakeFS()
|
||||
if err != nil {
|
||||
t.Fatalf("error: %v", err)
|
||||
}
|
||||
|
||||
pod := &k8s.PodInfo{
|
||||
Name: "ingress-1",
|
||||
Namespace: v1.NamespaceDefault,
|
||||
|
|
@ -853,7 +793,6 @@ func newStore(t *testing.T) *k8sStore {
|
|||
Pod: PodLister{cache.NewStore(cache.MetaNamespaceKeyFunc)},
|
||||
},
|
||||
sslStore: NewSSLCertTracker(),
|
||||
filesystem: fs,
|
||||
updateCh: channels.NewRingChannel(10),
|
||||
syncSecretMu: new(sync.Mutex),
|
||||
backendConfigMu: new(sync.RWMutex),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue