Only support SSL dynamic mode

This commit is contained in:
Manuel Alejandro de Brito Fontes 2019-08-13 17:14:55 -04:00
parent 333d9fd48d
commit 80bd481abb
No known key found for this signature in database
GPG key ID: 786136016A8BA02A
40 changed files with 415 additions and 709 deletions

View file

@ -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
}

View file

@ -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
}

View file

@ -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),