Skip to content

Commit 0f60da8

Browse files
authored
Merge pull request #450 from fanminshi/tls_impl
pkg/tlsutil: impl none of the CA and App TLS assets are found
2 parents 408e756 + 7481c9f commit 0f60da8

File tree

2 files changed

+142
-68
lines changed

2 files changed

+142
-68
lines changed

pkg/tlsutil/tls.go

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ func (scg *SDKCertGenerator) GenerateCert(cr runtime.Object, service *v1.Service
157157
if err != nil {
158158
return nil, nil, nil, err
159159
}
160-
caSecret, caConfigMap, err := getCASecretAndConfigMapInCluster(scg.KubeClient, ToCASecretAndConfigMapName(k, n), ns)
160+
caSecretAndConfigMapName := ToCASecretAndConfigMapName(k, n)
161+
caSecret, caConfigMap, err := getCASecretAndConfigMapInCluster(scg.KubeClient, caSecretAndConfigMapName, ns)
161162
if err != nil {
162163
return nil, nil, nil, err
163164
}
@@ -186,15 +187,44 @@ func (scg *SDKCertGenerator) GenerateCert(cr runtime.Object, service *v1.Service
186187
if err != nil {
187188
return nil, nil, nil, err
188189
}
189-
appSecret, err := scg.KubeClient.CoreV1().Secrets(ns).Create(toTLSSecret(key, cert, appSecretName, ns))
190+
appSecret, err := scg.KubeClient.CoreV1().Secrets(ns).Create(toTLSSecret(key, cert, appSecretName))
190191
if err != nil {
191192
return nil, nil, nil, err
192193
}
193194
return appSecret, caConfigMap, caSecret, nil
194195
} else {
195-
// TODO: handle the case where both CA and Application TLS assets don't exist.
196+
// case: both CA and Application TLS assets don't exist.
197+
caKey, err := newPrivateKey()
198+
if err != nil {
199+
return nil, nil, nil, err
200+
}
201+
caCert, err := newSelfSignedCACertificate(caKey)
202+
if err != nil {
203+
return nil, nil, nil, err
204+
}
205+
caSecret, caConfigMap := toCASecretAndConfigmap(caKey, caCert, caSecretAndConfigMapName)
206+
caSecret, err = scg.KubeClient.CoreV1().Secrets(ns).Create(caSecret)
207+
if err != nil {
208+
return nil, nil, nil, err
209+
}
210+
caConfigMap, err = scg.KubeClient.CoreV1().ConfigMaps(ns).Create(caConfigMap)
211+
if err != nil {
212+
return nil, nil, nil, err
213+
}
214+
key, err := newPrivateKey()
215+
if err != nil {
216+
return nil, nil, nil, err
217+
}
218+
cert, err := newSignedCertificate(config, service, key, caCert, caKey)
219+
if err != nil {
220+
return nil, nil, nil, err
221+
}
222+
appSecret, err := scg.KubeClient.CoreV1().Secrets(ns).Create(toTLSSecret(key, cert, appSecretName))
223+
if err != nil {
224+
return nil, nil, nil, err
225+
}
226+
return appSecret, caConfigMap, caSecret, nil
196227
}
197-
return nil, nil, nil, nil
198228
}
199229

200230
func verifyConfig(config *CertConfig) error {
@@ -276,15 +306,10 @@ func toKindNameNamespace(cr runtime.Object) (string, string, string, error) {
276306

277307
// toTLSSecret returns a client/server "kubernetes.io/tls" secret.
278308
// TODO: add owner ref.
279-
func toTLSSecret(key *rsa.PrivateKey, cert *x509.Certificate, name, namespace string) *v1.Secret {
309+
func toTLSSecret(key *rsa.PrivateKey, cert *x509.Certificate, name string) *v1.Secret {
280310
return &v1.Secret{
281-
TypeMeta: metav1.TypeMeta{
282-
Kind: "Secret",
283-
APIVersion: "v1",
284-
},
285311
ObjectMeta: metav1.ObjectMeta{
286-
Name: name,
287-
Namespace: namespace,
312+
Name: name,
288313
},
289314
Data: map[string][]byte{
290315
v1.TLSPrivateKeyKey: encodePrivateKeyPEM(key),
@@ -295,30 +320,20 @@ func toTLSSecret(key *rsa.PrivateKey, cert *x509.Certificate, name, namespace st
295320
}
296321

297322
// TODO: add owner ref.
298-
func toCASecretAndConfigmap(key *rsa.PrivateKey, cert *x509.Certificate, name, namespace string) (*v1.ConfigMap, *v1.Secret) {
299-
return &v1.ConfigMap{
300-
TypeMeta: metav1.TypeMeta{
301-
Kind: "ConfigMap",
302-
APIVersion: "v1",
303-
},
323+
func toCASecretAndConfigmap(key *rsa.PrivateKey, cert *x509.Certificate, name string) (*v1.Secret, *v1.ConfigMap) {
324+
return &v1.Secret{
304325
ObjectMeta: metav1.ObjectMeta{
305-
Name: name,
306-
Namespace: namespace,
326+
Name: name,
307327
},
308-
Data: map[string]string{
309-
TLSCACertKey: string(encodeCertificatePEM(cert)),
310-
},
311-
}, &v1.Secret{
312-
TypeMeta: metav1.TypeMeta{
313-
Kind: "Secret",
314-
APIVersion: "v1",
328+
Data: map[string][]byte{
329+
TLSPrivateCAKeyKey: encodePrivateKeyPEM(key),
315330
},
331+
}, &v1.ConfigMap{
316332
ObjectMeta: metav1.ObjectMeta{
317-
Name: name,
318-
Namespace: namespace,
333+
Name: name,
319334
},
320-
Data: map[string][]byte{
321-
TLSPrivateCAKeyKey: encodePrivateKeyPEM(key),
335+
Data: map[string]string{
336+
TLSCACertKey: string(encodeCertificatePEM(cert)),
322337
},
323338
}
324339
}

test/e2e/tls_util_test.go

Lines changed: 97 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"k8s.io/api/core/v1"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/runtime"
2728
)
2829

2930
var (
@@ -104,17 +105,7 @@ func TestBothAppAndCATLSAssetsExist(t *testing.T) {
104105
}
105106

106107
cg := tlsutil.NewSDKCertGenerator(f.KubeClient)
107-
// Use Pod as a dummy runtime object for the CR input of GenerateCert().
108-
mCR := &v1.Pod{
109-
TypeMeta: metav1.TypeMeta{
110-
Kind: crKind,
111-
},
112-
ObjectMeta: metav1.ObjectMeta{
113-
Name: crName,
114-
Namespace: namespace,
115-
},
116-
}
117-
actualAppSecret, actualCaConfigMap, actualCaSecret, err := cg.GenerateCert(mCR, nil, ccfg)
108+
actualAppSecret, actualCaConfigMap, actualCaSecret, err := cg.GenerateCert(newDummyCR(namespace), nil, ccfg)
118109
if err != nil {
119110
t.Fatal(err)
120111
}
@@ -146,17 +137,7 @@ func TestOnlyAppSecretExist(t *testing.T) {
146137
}
147138

148139
cg := tlsutil.NewSDKCertGenerator(f.KubeClient)
149-
// Use Pod as a dummy runtime object for the CR input of GenerateCert().
150-
mCR := &v1.Pod{
151-
TypeMeta: metav1.TypeMeta{
152-
Kind: crKind,
153-
},
154-
ObjectMeta: metav1.ObjectMeta{
155-
Name: crName,
156-
Namespace: namespace,
157-
},
158-
}
159-
_, _, _, err = cg.GenerateCert(mCR, nil, ccfg)
140+
_, _, _, err = cg.GenerateCert(newDummyCR(namespace), nil, ccfg)
160141
if err == nil {
161142
t.Fatal("expect error, but got none")
162143
}
@@ -186,27 +167,83 @@ func TestOnlyCAExist(t *testing.T) {
186167
}
187168

188169
cg := tlsutil.NewSDKCertGenerator(f.KubeClient)
189-
// Use Pod as a dummy runtime object for the CR input of GenerateCert().
190-
mCR := &v1.Pod{
191-
TypeMeta: metav1.TypeMeta{
192-
Kind: crKind,
193-
},
194-
ObjectMeta: metav1.ObjectMeta{
195-
Name: crName,
196-
Namespace: namespace,
197-
},
170+
appSecret, _, _, err := cg.GenerateCert(newDummyCR(namespace), newAppSvc(namespace), ccfg)
171+
if err != nil {
172+
t.Fatal(err)
198173
}
199-
appSvc := &v1.Service{
200-
ObjectMeta: metav1.ObjectMeta{
201-
Name: "app-service",
202-
Namespace: namespace,
203-
},
174+
175+
verifyAppSecret(t, appSecret, namespace)
176+
}
177+
178+
// TestNoneOfCaAndAppSecretExist ensures that when none of the CA and Application TLS assets
179+
// exist, GenerateCert() creates both and put them into the k8s cluster.
180+
func TestNoneOfCaAndAppSecretExist(t *testing.T) {
181+
f := framework.Global
182+
ctx := f.NewTestCtx(t)
183+
defer ctx.Cleanup(t)
184+
namespace, err := ctx.GetNamespace()
185+
if err != nil {
186+
t.Fatal(err)
204187
}
205-
appSecret, _, _, err := cg.GenerateCert(mCR, appSvc, ccfg)
188+
189+
cg := tlsutil.NewSDKCertGenerator(f.KubeClient)
190+
appSecret, caConfigMap, caSecret, err := cg.GenerateCert(newDummyCR(namespace), newAppSvc(namespace), ccfg)
206191
if err != nil {
207192
t.Fatal(err)
208193
}
209194

195+
verifyAppSecret(t, appSecret, namespace)
196+
verifyCaConfigMap(t, caConfigMap, namespace)
197+
verifyCASecret(t, caSecret, namespace)
198+
}
199+
200+
func verifyCASecret(t *testing.T, caSecret *v1.Secret, namespace string) {
201+
// check if caConfigMap has the correct fields.
202+
if caConfigMapAndSecretName != caSecret.Name {
203+
t.Fatalf("expect the ca config name %v, but got %v", caConfigMapAndSecretName, caConfigMap.Name)
204+
}
205+
if namespace != caSecret.Namespace {
206+
t.Fatalf("expect the ca config namespace %v, but got %v", namespace, appSecret.Namespace)
207+
}
208+
if _, ok := caSecret.Data[tlsutil.TLSPrivateCAKeyKey]; !ok {
209+
t.Fatalf("expect the ca config to have the data field %v, but got none", tlsutil.TLSPrivateCAKeyKey)
210+
}
211+
212+
// check if caConfigMap exists in k8s cluster.
213+
caSecretFromCluster, err := framework.Global.KubeClient.CoreV1().Secrets(namespace).Get(caConfigMapAndSecretName, metav1.GetOptions{})
214+
if err != nil {
215+
t.Fatal(err)
216+
}
217+
// check if caSecret returned from GenerateCert is the same as the one that exists in the k8s.
218+
if !reflect.DeepEqual(caSecret, caSecretFromCluster) {
219+
t.Fatalf("expect %+v, but got %+v", caSecret, caSecretFromCluster)
220+
}
221+
}
222+
223+
func verifyCaConfigMap(t *testing.T, caConfigMap *v1.ConfigMap, namespace string) {
224+
// check if caConfigMap has the correct fields.
225+
if caConfigMapAndSecretName != caConfigMap.Name {
226+
t.Fatalf("expect the ca config name %v, but got %v", caConfigMapAndSecretName, caConfigMap.Name)
227+
}
228+
if namespace != caConfigMap.Namespace {
229+
t.Fatalf("expect the ca config namespace %v, but got %v", namespace, appSecret.Namespace)
230+
}
231+
if _, ok := caConfigMap.Data[tlsutil.TLSCACertKey]; !ok {
232+
t.Fatalf("expect the ca config to have the data field %v, but got none", tlsutil.TLSCACertKey)
233+
}
234+
235+
// check if caConfigMap exists in k8s cluster.
236+
caConfigMapFromCluster, err := framework.Global.KubeClient.CoreV1().ConfigMaps(namespace).Get(caConfigMapAndSecretName, metav1.GetOptions{})
237+
if err != nil {
238+
t.Fatal(err)
239+
}
240+
// check if caConfigMap returned from GenerateCert is the same as the one that exists in the k8s.
241+
if !reflect.DeepEqual(caConfigMap, caConfigMapFromCluster) {
242+
t.Fatalf("expect %+v, but got %+v", caConfigMap, caConfigMapFromCluster)
243+
}
244+
}
245+
246+
func verifyAppSecret(t *testing.T, appSecret *v1.Secret, namespace string) {
210247
// check if appSecret has the correct fields.
211248
if appSecretName != appSecret.Name {
212249
t.Fatalf("expect the secret name %v, but got %v", appSecretName, appSecret.Name)
@@ -225,7 +262,7 @@ func TestOnlyCAExist(t *testing.T) {
225262
}
226263

227264
// check if appSecret exists in k8s cluster.
228-
appSecretFromCluster, err := f.KubeClient.CoreV1().Secrets(namespace).Get(appSecretName, metav1.GetOptions{})
265+
appSecretFromCluster, err := framework.Global.KubeClient.CoreV1().Secrets(namespace).Get(appSecretName, metav1.GetOptions{})
229266
if err != nil {
230267
t.Fatal(err)
231268
}
@@ -234,3 +271,25 @@ func TestOnlyCAExist(t *testing.T) {
234271
t.Fatalf("expect %+v, but got %+v", appSecret, appSecretFromCluster)
235272
}
236273
}
274+
275+
// newDummyCR returns a dummy runtime object for the CR input of GenerateCert().
276+
func newDummyCR(namespace string) runtime.Object {
277+
return &v1.Pod{
278+
TypeMeta: metav1.TypeMeta{
279+
Kind: crKind,
280+
},
281+
ObjectMeta: metav1.ObjectMeta{
282+
Name: crName,
283+
Namespace: namespace,
284+
},
285+
}
286+
}
287+
288+
func newAppSvc(namespace string) *v1.Service {
289+
return &v1.Service{
290+
ObjectMeta: metav1.ObjectMeta{
291+
Name: "app-service",
292+
Namespace: namespace,
293+
},
294+
}
295+
}

0 commit comments

Comments
 (0)