Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions pkg/tlsutil/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ func (scg *SDKCertGenerator) GenerateCert(cr runtime.Object, service *v1.Service
if err != nil {
return nil, nil, nil, err
}
appSecret, err := getAppSecretInCluster(scg.KubeClient, ToAppSecretName(k, n, config.CertName), ns)
appSecretName := ToAppSecretName(k, n, config.CertName)
appSecret, err := getAppSecretInCluster(scg.KubeClient, appSecretName, ns)
if err != nil {
return nil, nil, nil, err
}
Expand All @@ -169,9 +170,29 @@ func (scg *SDKCertGenerator) GenerateCert(cr runtime.Object, service *v1.Service
} else if hasAppSecret && !hasCASecretAndConfigMap {
return nil, nil, nil, ErrCANotFound
} else if !hasAppSecret && hasCASecretAndConfigMap {
// TODO
caKey, err := parsePEMEncodedPrivateKey(caSecret.Data[TLSPrivateCAKeyKey])
if err != nil {
return nil, nil, nil, err
}
caCert, err := parsePEMEncodedCert([]byte(caConfigMap.Data[TLSCACertKey]))
if err != nil {
return nil, nil, nil, err
}
key, err := newPrivateKey()
if err != nil {
return nil, nil, nil, err
}
cert, err := newSignedCertificate(config, service, key, caCert, caKey)
if err != nil {
return nil, nil, nil, err
}
appSecret, err := scg.KubeClient.CoreV1().Secrets(ns).Create(toTLSSecret(key, cert, appSecretName, ns))
if err != nil {
return nil, nil, nil, err
}
return appSecret, caConfigMap, caSecret, nil
} else {
// TODO
// TODO: handle the case where both CA and Application TLS assets don't exist.
}
return nil, nil, nil, nil
}
Expand Down
17 changes: 17 additions & 0 deletions test/e2e/testdata/ca-csr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"L": "San Francisco",
"ST": "California",
"C": "USA"
}
],
"CN": "ca",
"ca": {
"expiry": "87600h"
}
}
21 changes: 21 additions & 0 deletions test/e2e/testdata/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDhDCCAmygAwIBAgIUJCpEclRVqfgYKUIyrk6m46BqH0EwDQYJKoZIhvcNAQEL
BQAwSDEMMAoGA1UEBhMDVVNBMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH
Ew1TYW4gRnJhbmNpc2NvMQswCQYDVQQDEwJjYTAeFw0xODA4MzAyMDEyMDBaFw0y
ODA4MjcyMDEyMDBaMEgxDDAKBgNVBAYTA1VTQTETMBEGA1UECBMKQ2FsaWZvcm5p
YTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzELMAkGA1UEAxMCY2EwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDwSnTyS56xvTRBNbkNNoYBfOJNGzSNCtF/
u2NrYUQW9YOCCceuhl8q4g8H6/+HTV9RlRiTAY7DSFSZUK/C3x4uFhY1emXjzgqT
Z19FKEKwkVhqo7XSkGrqb37U0vgdO2eyGWqVt2gS50wNimo4Z3HcfsziDtqFZpxb
9ZuCiWmGpnkx+NuH9Qq2LBHSdOHI+HWw7E/91ZAaTmW/QA9W9HvxKNC9pmFFBRtd
WDjGvHsTmpgPZ2Pce/jcJ6SAaO82KXM0ksW4LmaK4OTUPN+c3KODA/gSau77DNNG
bnjQ6CkyKKOfInGDVhpG57p+LuIbt724bCxmNRkvjYwrr+dEL4SpAgMBAAGjZjBk
MA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgECMB0GA1UdDgQWBBSN
6FinnI4qg4IeK9PGzzufD6usjDAfBgNVHSMEGDAWgBSN6FinnI4qg4IeK9PGzzuf
D6usjDANBgkqhkiG9w0BAQsFAAOCAQEAy6sn3xyNcQ/HzD1Ii7p4toc5qbgDONnq
9YkbIoNFxFj8DTQ86r6jcj94PnylIhBe1I1k70tVVal7nM+4wnNaTktAfiQN/mYJ
RyvMTXN6+Vsl93AeBMo7DIGElz2sL2EkOTct1QmTr7hr/3u4SfBvppFnxYqJKiI3
GX3V0kV1iuAllyHR787hkWq28LQ3WXtqnybAR23SMVtQNrHw1t1ia5eStK4Gbfl/
FN/BNwkV6i8Q/5B2obCUJWpzt4UqB4hXv3TmhYCeA8ddq7LYjjil11Ed21o95QyK
FooF2jEmda+zivmB/XKC+5+DfL00x0G1QqbME6ilGkpRx2gDFg03cg==
-----END CERTIFICATE-----
16 changes: 16 additions & 0 deletions test/e2e/testdata/ca.csr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICjTCCAXUCAQAwSDEMMAoGA1UEBhMDVVNBMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMQswCQYDVQQDEwJjYTCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAPBKdPJLnrG9NEE1uQ02hgF84k0bNI0K0X+7
Y2thRBb1g4IJx66GXyriDwfr/4dNX1GVGJMBjsNIVJlQr8LfHi4WFjV6ZePOCpNn
X0UoQrCRWGqjtdKQaupvftTS+B07Z7IZapW3aBLnTA2Kajhncdx+zOIO2oVmnFv1
m4KJaYameTH424f1CrYsEdJ04cj4dbDsT/3VkBpOZb9AD1b0e/Eo0L2mYUUFG11Y
OMa8exOamA9nY9x7+NwnpIBo7zYpczSSxbguZorg5NQ835zco4MD+BJq7vsM00Zu
eNDoKTIoo58icYNWGkbnun4u4hu3vbhsLGY1GS+NjCuv50QvhKkCAwEAAaAAMA0G
CSqGSIb3DQEBCwUAA4IBAQDDqdtWrOmptqpQNDG6nt1EW6KLwSPhZBx+wwGVpPtb
cXVSvjQkmIzK0G22XtDnIIix+D65hvFIPyVvKYVhDm5LhRvcguyRAV2SkrDlhBka
tZG03yvvUE4hbdWjJtk7CAUoKOZ1Sl47zdf0Rn1b/LZd9gQ6Ew08YRfdZ9VLQdOm
j/o6owGqIpU/dCaMZZ/8jzccmqt6QkiTSlyrA2ws38S0wcEsILp8vppLQc056Qiw
AcqwwUw1jp8omqozPCKir12gNjkWxLnZ56ka1PwUJr0cj8QYUqHC0q/xl2eNw2lU
W8qZn+2N43F3KvJ5BPUbuu+69G8EQhhMKHq69G6WSGhQ
-----END CERTIFICATE REQUEST-----
27 changes: 27 additions & 0 deletions test/e2e/testdata/ca.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA8Ep08kuesb00QTW5DTaGAXziTRs0jQrRf7tja2FEFvWDggnH
roZfKuIPB+v/h01fUZUYkwGOw0hUmVCvwt8eLhYWNXpl484Kk2dfRShCsJFYaqO1
0pBq6m9+1NL4HTtnshlqlbdoEudMDYpqOGdx3H7M4g7ahWacW/WbgolphqZ5Mfjb
h/UKtiwR0nThyPh1sOxP/dWQGk5lv0APVvR78SjQvaZhRQUbXVg4xrx7E5qYD2dj
3Hv43CekgGjvNilzNJLFuC5miuDk1DzfnNyjgwP4Emru+wzTRm540OgpMiijnyJx
g1YaRue6fi7iG7e9uGwsZjUZL42MK6/nRC+EqQIDAQABAoIBAAbaSL2ENJFjEPNv
IcjjriyqsBV82iHPlivrXyl3y6ZP+CEkQEKU6G/jpIQYUeA876P2+Y1vtO+Sx37b
0zdef5DW5mk+BVvay2hqwUfKnyRD8N6RrqTDo5jt9xMAtTy4LfvhR63fXiNz3zJf
qSnUoWWlZBhqTgcR5xGkTnwJiS3i0Vk9/xU1zNL7OZpSSSuefXuq2qQtG+Gayrps
KAp1essnKnNRyiQH2yOn3pXs5Mj+ytWCV7C9eL1TAg0ZSIjuV+S/CNpCHsVLv5p6
yj/CWjzV7NOhsdHoo5t1FsALhQaov0bb6hv96ZbTwkPoegr1SLQnYx63kOo//AmK
uCgZgxECgYEA/qmFoBlRNm2AJ/vRp0t6JoERF9LhsUWSYRmcSho2xG5fLwzSxCjR
YOxFEdZl3hzkH/rhY7+Vg6rOH5rhjL4hBKnrCkZcC88J7WCTI4mJDwTP/iViahAg
RVEvJ6T51qI8N1wojumuQIhbUmVcWiZA49QRC/5DqIgZ1lRDWycqTeUCgYEA8Y2b
mCI5zvjPci/1WBbPqA9ZDdbi4MmvO/RG+ik4RZnN7poxg2JU/Ta5RAFB1UY21bo8
JTiL2pRqLaGLi0HPEJEaS6K5a+9oK5tUtmJp6CgpnNiNmALUyaoXbg3lrv5ajo74
G94AZEIha0r9ReECvtk/sdsK1IgZaBtCIJ2Lj3UCgYEAjo+4DngdzqpeJAQEyfKm
3wdB2mRjlCmuWE1OAO3L2wsundg/5TA0hl2+DM5JGJ5z1rNLmduWh68G1QqPWYrW
URYOTiI1RScSF6EIvcwwvgejqFKlVVrRtfxMuZTRiCYqL5OX4OlQcy/ib63ulUj0
6pW9NUmR9ra6QBHL4yt5s0ECgYEAsAJpX/+AdAnkzuWXNqrYgTM9xtHP28/aOiuT
FHG4qS6bWcNNVNjv6NpZQO5RlCBnkHD1poF/lrQSclGGJuC7Cu1QZdCan8WA+FVk
8sjfNuUc/UbmVd+qQZAJJo5F0K9SORKAQ34Odv+g7ldkGekNYRdYTDa5u4e4S52h
H7bsnIkCgYAJZRkDWjhPhWX7hv9HcLcyW/yOe9tEys/2UoYBr+j3X0eraKR1+EUr
Xli+yuPBbRo5+bEzAXI/gbZGu3J6vZm0J9qHc1ybqLvcTcOweTBU7xs4aeJsSK5O
w0BnNOc/05hLf2Ow02ZlZBELMXpp1Y187+FKEmkwxTrgaGB3rZanVA==
-----END RSA PRIVATE KEY-----
13 changes: 13 additions & 0 deletions test/e2e/testdata/gencert.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"signing": {
"default": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
18 changes: 18 additions & 0 deletions test/e2e/testdata/gencert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

if ! [[ "$0" =~ "./gencert.sh" ]]; then
echo "must be run from 'testdata'"
exit 255
fi

if ! which cfssl; then
echo "cfssl is not installed"
exit 255
fi

cfssl gencert --initca=true ./ca-csr.json | cfssljson --bare ca -
mv ca.pem ca.crt
mv ca-key.pem ca.key
if which openssl >/dev/null; then
openssl x509 -in ca.crt -noout -text
fi
106 changes: 99 additions & 7 deletions test/e2e/tls_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package e2e

import (
"io/ioutil"
"reflect"
"testing"

Expand All @@ -27,32 +28,53 @@ import (

var (
// TLS test variables.
crKind = "Pod"
crName = "example-pod"
certName = "app-cert"

crKind = "Pod"
crName = "example-pod"
certName = "app-cert"
caConfigMapAndSecretName = tlsutil.ToCASecretAndConfigMapName(crKind, crName)
caConfigMap = &v1.ConfigMap{
appSecretName = tlsutil.ToAppSecretName(crKind, crName, certName)

caConfigMap *v1.ConfigMap
caSecret *v1.Secret
appSecret *v1.Secret

ccfg *tlsutil.CertConfig
)

// setup test variables.
func init() {
caCertBytes, err := ioutil.ReadFile("./testdata/ca.crt")
if err != nil {
panic(err)
}
caConfigMap = &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: caConfigMapAndSecretName,
},
Data: map[string]string{tlsutil.TLSCACertKey: string(caCertBytes)},
}

caKeyBytes, err := ioutil.ReadFile("./testdata/ca.key")
if err != nil {
panic(err)
}
caSecret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: caConfigMapAndSecretName,
},
Data: map[string][]byte{tlsutil.TLSPrivateCAKeyKey: caKeyBytes},
}

appSecret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: tlsutil.ToAppSecretName(crKind, crName, certName),
Name: appSecretName,
},
}

ccfg = &tlsutil.CertConfig{
CertName: certName,
}
)
}

// TestBothAppAndCATLSAssetsExist ensures that when both application
// and CA TLS assets exist in the k8s cluster for a given cr,
Expand Down Expand Up @@ -142,3 +164,73 @@ func TestOnlyAppSecretExist(t *testing.T) {
t.Fatalf("expect %v, but got %v", tlsutil.ErrCANotFound.Error(), err.Error())
}
}

// TestOnlyCAExist ensures that at the case where only the CA exists in the cluster;
// GenerateCert can retrieve the CA and uses it to create a new application secret.
func TestOnlyCAExist(t *testing.T) {
f := framework.Global
ctx := f.NewTestCtx(t)
defer ctx.Cleanup(t)
namespace, err := ctx.GetNamespace()
if err != nil {
t.Fatal(err)
}

_, err = f.KubeClient.CoreV1().ConfigMaps(namespace).Create(caConfigMap)
if err != nil {
t.Fatal(err)
}
_, err = f.KubeClient.CoreV1().Secrets(namespace).Create(caSecret)
if err != nil {
t.Fatal(err)
}

cg := tlsutil.NewSDKCertGenerator(f.KubeClient)
// Use Pod as a dummy runtime object for the CR input of GenerateCert().
mCR := &v1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: crKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: crName,
Namespace: namespace,
},
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to make a helper for this, now or in a later PR, since we're using the dummy runtime object in all test cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I will do another round of refactoring after finishing all the test cases.

appSvc := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "app-service",
Namespace: namespace,
},
}
appSecret, _, _, err := cg.GenerateCert(mCR, appSvc, ccfg)
if err != nil {
t.Fatal(err)
}

// check if appSecret has the correct fields.
if appSecretName != appSecret.Name {
t.Fatalf("expect the secret name %v, but got %v", appSecretName, appSecret.Name)
}
if namespace != appSecret.Namespace {
t.Fatalf("expect the secret namespace %v, but got %v", namespace, appSecret.Namespace)
}
if v1.SecretTypeTLS != appSecret.Type {
t.Fatalf("expect the secret type %v, but got %v", v1.SecretTypeTLS, appSecret.Type)
}
if _, ok := appSecret.Data[v1.TLSCertKey]; !ok {
t.Fatalf("expect the secret to have the data field %v, but got none", v1.TLSCertKey)
}
if _, ok := appSecret.Data[v1.TLSPrivateKeyKey]; !ok {
t.Fatalf("expect the secret to have the data field %v, but got none", v1.TLSPrivateKeyKey)
}

// check if appSecret exists in k8s cluster.
appSecretFromCluster, err := f.KubeClient.CoreV1().Secrets(namespace).Get(appSecretName, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
// check if appSecret returned from GenerateCert is the same as the one that exists in the k8s.
if !reflect.DeepEqual(appSecret, appSecretFromCluster) {
t.Fatalf("expect %+v, but got %+v", appSecret, appSecretFromCluster)
}
}