Skip to content

Commit f907c81

Browse files
Merge branch 'master' into master
2 parents f3ba987 + b9447f0 commit f907c81

12 files changed

+183
-108
lines changed

docs/examples/aspnetapp.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ spec:
99
- image: "mcr.microsoft.com/dotnet/samples:aspnetapp"
1010
name: aspnetapp-image
1111
ports:
12-
- containerPort: 80
12+
- containerPort: 8080
1313
protocol: TCP
1414

1515
---
@@ -24,7 +24,7 @@ spec:
2424
ports:
2525
- protocol: TCP
2626
port: 80
27-
targetPort: 80
27+
targetPort: 8080
2828

2929
---
3030

pkg/k8scontext/context.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func NewContext(kubeClient kubernetes.Interface, crdClient versioned.Interface,
107107
informers: &informerCollection,
108108
ingressSecretsMap: utils.NewThreadsafeMultimap(),
109109
Caches: &cacheCollection,
110-
CertificateSecretStore: NewSecretStore(),
110+
CertificateSecretStore: NewSecretStore(kubeClient),
111111
Work: make(chan events.Event, workBuffer),
112112
CacheSynced: make(chan interface{}),
113113

pkg/k8scontext/handlers_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
v1 "k8s.io/api/core/v1"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414

15-
"github.com/onsi/ginkgo"
15+
"github.com/onsi/ginkgo/v2"
1616
. "github.com/onsi/gomega"
1717
"k8s.io/client-go/kubernetes"
1818
testclient "k8s.io/client-go/kubernetes/fake"

pkg/k8scontext/ingress_handlers_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"context"
1010
"time"
1111

12-
"github.com/onsi/ginkgo"
12+
"github.com/onsi/ginkgo/v2"
1313
. "github.com/onsi/gomega"
1414
v1 "k8s.io/api/core/v1"
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

pkg/k8scontext/k8scontext_suite_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Licensed under the MIT License. See License.txt in the project root for license information.
44
// --------------------------------------------------------------------------------------------
55

6+
//go:build unittest
67
// +build unittest
78

89
package k8scontext
@@ -11,7 +12,7 @@ import (
1112
"flag"
1213
"testing"
1314

14-
"github.com/onsi/ginkgo"
15+
"github.com/onsi/ginkgo/v2"
1516
"github.com/onsi/gomega"
1617
"k8s.io/klog/v2"
1718
)

pkg/k8scontext/k8scontext_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
"github.com/getlantern/deepcopy"
1414
"github.com/knative/pkg/apis/istio/v1alpha3"
15-
"github.com/onsi/ginkgo"
15+
"github.com/onsi/ginkgo/v2"
1616
. "github.com/onsi/gomega"
1717
v1 "k8s.io/api/core/v1"
1818
networking "k8s.io/api/networking/v1"
@@ -73,7 +73,6 @@ var _ = ginkgo.Describe("K8scontext", func() {
7373
}
7474
}
7575
case <-time.After(1 * time.Second):
76-
break
7776
}
7877

7978
if len(exists) == len(resourceList) {

pkg/k8scontext/secrets_handlers.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ import (
1818

1919
// secret resource handlers
2020
func (h handlers) secretAdd(obj interface{}) {
21-
sec := obj.(*v1.Secret)
21+
sec, ok := obj.(*v1.Secret)
22+
if !ok {
23+
klog.Error("error decoding object, invalid type")
24+
return
25+
}
26+
2227
if _, exists := namespacesToIgnore[sec.Namespace]; exists {
2328
return
2429
}
@@ -42,7 +47,12 @@ func (h handlers) secretAdd(obj interface{}) {
4247
}
4348

4449
func (h handlers) secretUpdate(oldObj, newObj interface{}) {
45-
sec := newObj.(*v1.Secret)
50+
sec, ok := newObj.(*v1.Secret)
51+
if !ok {
52+
klog.Error("error decoding object, invalid type")
53+
return
54+
}
55+
4656
if _, exists := namespacesToIgnore[sec.Namespace]; exists {
4757
return
4858
}
@@ -70,6 +80,11 @@ func (h handlers) secretUpdate(oldObj, newObj interface{}) {
7080

7181
func (h handlers) secretDelete(obj interface{}) {
7282
sec, ok := obj.(*v1.Secret)
83+
if !ok {
84+
klog.Error("error decoding object, invalid type")
85+
return
86+
}
87+
7388
if _, exists := namespacesToIgnore[sec.Namespace]; exists {
7489
return
7590
}

pkg/k8scontext/secrets_handlers_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
v1 "k8s.io/api/core/v1"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414

15-
"github.com/onsi/ginkgo"
15+
"github.com/onsi/ginkgo/v2"
1616
. "github.com/onsi/gomega"
1717
"k8s.io/client-go/kubernetes"
1818
testclient "k8s.io/client-go/kubernetes/fake"

pkg/k8scontext/secretstore.go

+34-10
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,18 @@ package k8scontext
77

88
import (
99
"bytes"
10+
"context"
1011
"os"
1112
"os/exec"
1213
"sync"
1314

1415
v1 "k8s.io/api/core/v1"
16+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
"k8s.io/client-go/kubernetes"
1518
"k8s.io/client-go/tools/cache"
1619

1720
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/controllererrors"
18-
)
19-
20-
const (
21-
recognizedSecretType = "kubernetes.io/tls"
22-
tlsKey = "tls.key"
23-
tlsCrt = "tls.crt"
21+
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/utils"
2422
)
2523

2624
// SecretsKeeper is the interface definition for secret store
@@ -33,13 +31,15 @@ type SecretsKeeper interface {
3331
// SecretsStore maintains a cache of the deployment secrets.
3432
type SecretsStore struct {
3533
conversionSync sync.Mutex
34+
Client kubernetes.Interface
3635
Cache cache.ThreadSafeStore
3736
}
3837

3938
// NewSecretStore creates a new SecretsKeeper object
40-
func NewSecretStore() SecretsKeeper {
39+
func NewSecretStore(client kubernetes.Interface) SecretsKeeper {
4140
return &SecretsStore{
42-
Cache: cache.NewThreadSafeStore(cache.Indexers{}, cache.Indices{}),
41+
Cache: cache.NewThreadSafeStore(cache.Indexers{}, cache.Indices{}),
42+
Client: client,
4343
}
4444
}
4545

@@ -50,9 +50,33 @@ func (s *SecretsStore) GetPfxCertificate(secretKey string) []byte {
5050
return cert
5151
}
5252
}
53+
54+
if cert, err := s.GetFromCluster(secretKey); err == nil {
55+
return cert
56+
}
5357
return nil
5458
}
5559

60+
func (s *SecretsStore) GetFromCluster(secretKey string) ([]byte, error) {
61+
secretNamespace, secretName, err := utils.ParseNamespacedName(secretKey)
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
secret, err := s.Client.CoreV1().Secrets(secretNamespace).Get(context.Background(), secretName, metav1.GetOptions{})
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
if err := s.ConvertSecret(secretKey, secret); err != nil {
72+
return nil, err
73+
}
74+
75+
certInterface, _ := s.Cache.Get(secretKey)
76+
cert, _ := certInterface.([]byte)
77+
return cert, nil
78+
}
79+
5680
func (s *SecretsStore) delete(secretKey string) {
5781
s.conversionSync.Lock()
5882
defer s.conversionSync.Unlock()
@@ -66,14 +90,14 @@ func (s *SecretsStore) ConvertSecret(secretKey string, secret *v1.Secret) error
6690
defer s.conversionSync.Unlock()
6791

6892
// check if this is a secret with the correct type
69-
if secret.Type != recognizedSecretType {
93+
if secret.Type != v1.SecretTypeTLS {
7094
return controllererrors.NewErrorf(
7195
controllererrors.ErrorUnknownSecretType,
7296
"secret [%v] is not type kubernetes.io/tls", secretKey,
7397
)
7498
}
7599

76-
if len(secret.Data[tlsKey]) == 0 || len(secret.Data[tlsCrt]) == 0 {
100+
if len(secret.Data[v1.TLSCertKey]) == 0 || len(secret.Data[v1.TLSPrivateKeyKey]) == 0 {
77101
return controllererrors.NewErrorf(
78102
controllererrors.ErrorMalformedSecret,
79103
"secret [%v] is malformed, tls.key or tls.crt is not defined", secretKey,

pkg/k8scontext/secretstore_test.go

+40-24
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,58 @@
66
package k8scontext
77

88
import (
9-
"github.com/onsi/ginkgo"
9+
"github.com/onsi/ginkgo/v2"
1010
. "github.com/onsi/gomega"
1111
v1 "k8s.io/api/core/v1"
12+
"k8s.io/client-go/kubernetes"
13+
testclient "k8s.io/client-go/kubernetes/fake"
1214

1315
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/controllererrors"
1416
"github.com/Azure/application-gateway-kubernetes-ingress/pkg/tests"
1517
)
1618

1719
var _ = ginkgo.Describe("Testing K8sContext.SecretStore", func() {
18-
secretsStore := NewSecretStore()
19-
ginkgo.Context("Test ConvertSecret function", func() {
20-
secret := v1.Secret{}
21-
ginkgo.It("Should have returned an error - unrecognized type of secret", func() {
22-
err := secretsStore.ConvertSecret("someKey", &secret)
23-
Expect(err.(*controllererrors.Error).Code).To(Equal(controllererrors.ErrorUnknownSecretType))
24-
})
25-
ginkgo.It("", func() {
26-
malformed := secret
27-
malformed.Type = recognizedSecretType
28-
err := secretsStore.ConvertSecret("someKey", &malformed)
29-
Expect(err.(*controllererrors.Error).Code).To(Equal(controllererrors.ErrorMalformedSecret))
30-
})
31-
ginkgo.It("", func() {
32-
malformed := secret
33-
malformed.Type = recognizedSecretType
34-
malformed.Data = make(map[string][]byte)
35-
malformed.Data[tlsKey] = []byte("X")
36-
malformed.Data[tlsCrt] = []byte("Y")
37-
err := secretsStore.ConvertSecret("someKey", &malformed)
38-
Expect(err.(*controllererrors.Error).Code).To(Equal(controllererrors.ErrorExportingWithOpenSSL))
39-
})
40-
ginkgo.It("", func() {
20+
secretsStore := NewSecretStore(nil)
21+
22+
ginkgo.DescribeTable("when converting certificate to PFX",
23+
func(secret *v1.Secret, expectedError controllererrors.ErrorCode) {
24+
err := secretsStore.ConvertSecret("someKey", secret)
25+
Expect(err.(*controllererrors.Error).Code).To(Equal(expectedError))
26+
},
27+
ginkgo.Entry("no type in secret", &v1.Secret{}, controllererrors.ErrorUnknownSecretType),
28+
ginkgo.Entry("unrecognized type of secret", &v1.Secret{Type: v1.SecretTypeOpaque}, controllererrors.ErrorUnknownSecretType),
29+
ginkgo.Entry("malformed data", &v1.Secret{Type: v1.SecretTypeTLS, Data: map[string][]byte{}}, controllererrors.ErrorMalformedSecret),
30+
ginkgo.Entry("invalid data", &v1.Secret{Type: v1.SecretTypeTLS, Data: map[string][]byte{
31+
v1.TLSCertKey: []byte("X"),
32+
v1.TLSPrivateKeyKey: []byte("X"),
33+
}}, controllererrors.ErrorExportingWithOpenSSL),
34+
)
35+
36+
ginkgo.When("certificate gets stored", func() {
37+
ginkgo.It("should be retrivable with the secret key", func() {
4138
err := secretsStore.ConvertSecret("someKey", tests.NewSecretTestFixture())
4239
Expect(err).ToNot(HaveOccurred())
4340
actual := secretsStore.GetPfxCertificate("someKey")
4441
Expect(len(actual)).To(BeNumerically(">", 0))
4542
})
4643
})
44+
45+
ginkgo.When("certificate is no cached", func() {
46+
ginkgo.It("should get it from the api-server", func() {
47+
secret := tests.NewSecretTestFixture()
48+
var client kubernetes.Interface = testclient.NewSimpleClientset(secret)
49+
secretsStore := NewSecretStore(client)
50+
51+
actual := secretsStore.GetPfxCertificate(secret.Namespace + "/" + secret.Name)
52+
Expect(len(actual)).To(BeNumerically(">", 0))
53+
})
54+
55+
ginkgo.It("should return nil if secret does not exist", func() {
56+
var client kubernetes.Interface = testclient.NewSimpleClientset()
57+
secretsStore := NewSecretStore(client)
58+
59+
actual := secretsStore.GetPfxCertificate("someKey")
60+
Expect(actual).To(BeNil())
61+
})
62+
})
4763
})

pkg/utils/utils.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"crypto/md5"
1010
"encoding/json"
1111
"fmt"
12-
"os"
1312
"math/rand"
13+
"os"
1414
"strings"
1515
"time"
1616

@@ -97,3 +97,11 @@ func RemoveDuplicateStrings(list []string) []string {
9797

9898
return result
9999
}
100+
101+
func ParseNamespacedName(namespacedName string) (string, string, error) {
102+
split := strings.Split(namespacedName, "/")
103+
if len(split) != 2 {
104+
return "", "", fmt.Errorf("invalid namespaced name %s", namespacedName)
105+
}
106+
return split[0], split[1], nil
107+
}

0 commit comments

Comments
 (0)