Browse Source

WiP: e2e and unit tests

Elsa Chelala 4 years ago
parent
commit
882b348ff5

+ 89 - 0
e2e/suite/alibaba/alibaba.go

@@ -0,0 +1,89 @@
+package alibaba
+
+import (
+
+	// nolint
+	. "github.com/onsi/ginkgo"
+	// nolint
+	. "github.com/onsi/ginkgo/extensions/table"
+
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/e2e/suite/common"
+)
+
+var _ = Describe("[alibaba] ", func() {
+	f := framework.New("eso-alibaba")
+
+	DescribeTable("sync secrets",
+		framework.TableFunc(f,
+			newVaultProvider(f)),
+		// uses token auth
+		compose("with token auth", f, common.JSONDataFromSync, useTokenAuth),
+		compose("with token auth", f, common.JSONDataWithProperty, useTokenAuth),
+		compose("with token auth", f, common.JSONDataWithTemplate, useTokenAuth),
+		compose("with token auth", f, common.DataPropertyDockerconfigJSON, useTokenAuth),
+		// use cert auth
+		compose("with cert auth", f, common.JSONDataFromSync, useCertAuth),
+		compose("with cert auth", f, common.JSONDataWithProperty, useCertAuth),
+		compose("with cert auth", f, common.JSONDataWithTemplate, useCertAuth),
+		compose("with cert auth", f, common.DataPropertyDockerconfigJSON, useCertAuth),
+		// use approle auth
+		compose("with appRole auth", f, common.JSONDataFromSync, useApproleAuth),
+		compose("with appRole auth", f, common.JSONDataWithProperty, useApproleAuth),
+		compose("with appRole auth", f, common.JSONDataWithTemplate, useApproleAuth),
+		compose("with appRole auth", f, common.DataPropertyDockerconfigJSON, useApproleAuth),
+		// use v1 provider
+		compose("with v1 kv provider", f, common.JSONDataFromSync, useV1Provider),
+		compose("with v1 kv provider", f, common.JSONDataWithProperty, useV1Provider),
+		compose("with v1 kv provider", f, common.JSONDataWithTemplate, useV1Provider),
+		compose("with v1 kv provider", f, common.DataPropertyDockerconfigJSON, useV1Provider),
+		// use jwt provider
+		compose("with jwt provider", f, common.JSONDataFromSync, useJWTProvider),
+		compose("with jwt provider", f, common.JSONDataWithProperty, useJWTProvider),
+		compose("with jwt provider", f, common.JSONDataWithTemplate, useJWTProvider),
+		compose("with jwt provider", f, common.DataPropertyDockerconfigJSON, useJWTProvider),
+		// use kubernetes provider
+		compose("with kubernetes provider", f, common.JSONDataFromSync, useKubernetesProvider),
+		compose("with kubernetes provider", f, common.JSONDataWithProperty, useKubernetesProvider),
+		compose("with kubernetes provider", f, common.JSONDataWithTemplate, useKubernetesProvider),
+		compose("with kubernetes provider", f, common.DataPropertyDockerconfigJSON, useKubernetesProvider),
+	)
+})
+
+func compose(descAppend string, f *framework.Framework, fn func(f *framework.Framework) (string, func(*framework.TestCase)), tweaks ...func(*framework.TestCase)) TableEntry {
+	desc, tfn := fn(f)
+	tweaks = append(tweaks, tfn)
+	te := Entry(desc + " " + descAppend)
+
+	// need to convert []func to []interface{}
+	ifs := make([]interface{}, len(tweaks))
+	for i := 0; i < len(tweaks); i++ {
+		ifs[i] = tweaks[i]
+	}
+	te.Parameters = ifs
+	return te
+}
+
+func useTokenAuth(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = tc.Framework.Namespace.Name
+}
+
+func useCertAuth(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = certAuthProviderName
+}
+
+func useApproleAuth(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = appRoleAuthProviderName
+}
+
+func useV1Provider(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = kvv1ProviderName
+}
+
+func useJWTProvider(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = jwtProviderName
+}
+
+func useKubernetesProvider(tc *framework.TestCase) {
+	tc.ExternalSecret.Spec.SecretStoreRef.Name = kubernetesProviderName
+}

+ 88 - 0
e2e/suite/alibaba/provider.go

@@ -0,0 +1,88 @@
+package alibaba
+
+import (
+	"context"
+
+	//nolint
+	. "github.com/onsi/ginkgo"
+
+	//nolint
+	. "github.com/onsi/gomega"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+	"github.com/external-secrets/external-secrets/e2e/framework"
+	"github.com/external-secrets/external-secrets/pkg/provider/alibaba"
+)
+
+type alibabaProvider struct {
+	url       string
+	client    *alibaba.KeyManagementService
+	framework *framework.Framework
+}
+
+const (
+	certAuthProviderName    = "cert-auth-provider"
+	appRoleAuthProviderName = "app-role-provider"
+	kvv1ProviderName        = "kv-v1-provider"
+	jwtProviderName         = "jwt-provider"
+	kubernetesProviderName  = "kubernetes-provider"
+)
+
+func newAlibabaProvider(f *framework.Framework) *alibabaProvider {
+	prov := &alibabaProvider{
+		framework: f,
+	}
+	BeforeEach(prov.BeforeEach)
+	return prov
+}
+
+// CreateSecret creates a secret in both kv v1 and v2 provider.
+func (s *alibabaProvider) CreateSecret(key, val string) {
+}
+
+func (s *alibabaProvider) DeleteSecret(key string) {
+	_, err := s.client.DeleteSecret("")
+	Expect(err).ToNot(HaveOccurred())
+}
+
+func (s *alibabaProvider) BeforeEach() {
+	//Creating an Alibaba secret
+	alibabaCreds := &v1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "provider-secret",
+			Namespace: s.framework.Namespace.Name,
+		},
+		StringData: map[string]string{
+			//secret
+		},
+	}
+	err := s.framework.CRClient.Create(context.Background(), alibabaCreds)
+	Expect(err).ToNot(HaveOccurred())
+
+	//Creating Alibaba secret store
+	secretStore := &esv1alpha1.SecretStore{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      s.framework.Namespace.Name,
+			Namespace: s.framework.Namespace.Name,
+		},
+		Spec: esv1alpha1.SecretStoreSpec{
+			Provider: &esv1alpha1.SecretStoreProvider{
+				Alibaba: &esv1alpha1.AlibabaProvider{
+					Auth: &esv1alpha1.AlibabaAuth{
+						SecretRef: esv1alpha1.AlibabaAuthSecretRef{
+							AccessKeyID: esmeta.SecretKeySelector{
+								Name: "external-secret",
+								Key:  "",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+	err = s.framework.CRClient.Create(context.Background(), secretStore)
+	Expect(err).ToNot(HaveOccurred())
+}

+ 25 - 0
pkg/provider/alibaba/fake/fake.go

@@ -0,0 +1,25 @@
+package fake
+
+import (
+	"fmt"
+
+	kmssdk "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
+	"github.com/google/go-cmp/cmp"
+)
+
+type AlibabaMockClient struct {
+	getSecretValue func(request *kmssdk.GetSecretValueRequest) (response *kmssdk.GetSecretValueResponse, err error)
+}
+
+func (mc *AlibabaMockClient) GetSecretValue(*kmssdk.GetSecretValueRequest) (result *kmssdk.GetSecretValueResponse, err error) {
+	return mc.getSecretValue(&kmssdk.GetSecretValueRequest{})
+}
+
+func (sm *AlibabaMockClient) WithValue(in *kmssdk.GetSecretValueRequest, val *kmssdk.GetSecretValueResponse, err error) {
+	sm.getSecretValue = func(paramIn *kmssdk.GetSecretValueRequest) (*kmssdk.GetSecretValueResponse, error) {
+		if !cmp.Equal(paramIn, in) {
+			return nil, fmt.Errorf("unexpected test argument")
+		}
+		return val, err
+	}
+}

+ 1 - 0
pkg/provider/alibaba/kms.go

@@ -37,6 +37,7 @@ const (
 
 	errAlibabaClient                           = "cannot setup new Alibaba client: %w"
 	errAlibabaCredSecretName                   = "invalid Alibaba SecretStore resource: missing Alibaba APIKey"
+	errUninitalizedAlibabaProvider             = "provider Alibaba is not initialized"
 	errInvalidClusterStoreMissingAKIDNamespace = "invalid ClusterStore, missing  AccessKeyID namespace"
 	errInvalidClusterStoreMissingSKNamespace   = "invalid ClusterStore, missing namespace"
 	errFetchSAKSecret                          = "could not fetch AccessSecretKey secret: %w"

+ 157 - 0
pkg/provider/alibaba/kms_test.go

@@ -0,0 +1,157 @@
+package alibaba
+
+import (
+	"context"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+
+	kmssdk "github.com/aliyun/alibaba-cloud-sdk-go/services/kms"
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	fakesm "github.com/external-secrets/external-secrets/pkg/provider/alibaba/fake"
+)
+
+type keyManagementServiceTestCase struct {
+	mockClient     *fakesm.AlibabaMockClient
+	apiInput       *kmssdk.GetSecretValueRequest
+	apiOutput      *kmssdk.GetSecretValueResponse
+	ref            *esv1alpha1.ExternalSecretDataRemoteRef
+	projectID      string
+	apiErr         error
+	expectError    string
+	expectedSecret string
+	keyID     []byte
+	accessKey []byte
+	// for testing secretmap
+	expectedData map[string]string
+}
+
+func makeValidKMSTestCase() *keyManagementServiceTestCase {
+	kmstc := keyManagementServiceTestCase{
+		mockClient:     &fakesm.AlibabaMockClient{},
+		apiInput:       makeValidAPIInput(),
+		ref:            makeValidRef(),
+		apiOutput:      makeValidAPIOutput(),
+		projectID:      "default",
+		apiErr:         nil,
+		expectError:    "",
+		expectedSecret: "",
+		expectedData:   make(map[string]string),
+	}
+	kmstc.mockClient.WithValue(kmstc.apiInput, kmstc.apiOutput, kmstc.apiErr)
+	return &kmstc
+}
+
+func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
+	return &esv1alpha1.ExternalSecretDataRemoteRef{
+		Key:     "/baz",
+		Version: "default",
+	}
+}
+
+func makeValidAPIInput() *kmssdk.GetSecretValueRequest {
+	return &kmssdk.GetSecretValueRequest{
+		SecretName: "projects/default/secrets//baz/versions/default",
+	}
+}
+
+func makeValidAPIOutput() *kmssdk.GetSecretValueResponse {
+	return &kmssdk.GetSecretValueResponse{}
+}
+
+func makeValidKMSTestCaseCustom(tweaks ...func(smtc *keyManagementServiceTestCase)) *keyManagementServiceTestCase {
+	kmstc := makeValidKMSTestCase()
+	for _, fn := range tweaks {
+		fn(kmstc)
+	}
+	kmstc.mockClient.WithValue(kmstc.apiInput, kmstc.apiOutput, kmstc.apiErr)
+	return kmstc
+}
+
+var setAPIErr = func(smtc *keyManagementServiceTestCase) {
+	smtc.apiErr = fmt.Errorf("oh no")
+	smtc.expectError = "oh no"
+}
+
+var setNilMockClient = func(smtc *keyManagementServiceTestCase) {
+	smtc.mockClient = nil
+	smtc.expectError = errUninitalizedAlibabaProvider
+}
+
+func TestAlibabaKMSGetSecret(t *testing.T) {
+	secretData := make(map[string]interface{})
+	secretValue := "changedvalue"
+	secretData["payload"] = secretValue
+	// good case: default version is set
+	// key is passed in, output is sent back
+	setSecretString := func(kmstc *keyManagementServiceTestCase) {
+	}
+
+	// good case: custom version set
+	setCustomKey := func(smtc *keyManagementServiceTestCase) {
+	}
+
+	successCases := []*keyManagementServiceTestCase{
+		makeValidKMSTestCase(),
+		makeValidKMSTestCaseCustom(setSecretString),
+		makeValidKMSTestCaseCustom(setCustomKey),
+		makeValidKMSTestCaseCustom(setAPIErr),
+		makeValidKMSTestCaseCustom(setNilMockClient),
+	}
+
+	sm := KeyManagementService{}
+	for k, v := range successCases {
+		sm.Client = v.mockClient
+		out, err := sm.GetSecret(context.Background(), *v.ref)
+		if !ErrorContains(err, v.expectError) {
+			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
+		}
+		if string(out) != v.expectedSecret {
+			t.Errorf("[%d] unexpected secret: expected %s, got %s", k, v.expectedSecret, string(out))
+		}
+	}
+}
+
+func TestGetSecretMap(t *testing.T) {
+	// good case: default version & deserialization
+	setDeserialization := func(smtc *keyManagementServiceTestCase) {
+		smtc.apiOutput.SecretData = (`{"foo":"bar"}`)
+		smtc.expectedData["foo"] = "bar"
+	}
+
+	// bad case: invalid json
+	setInvalidJSON := func(smtc *keyManagementServiceTestCase) {
+		smtc.apiOutput.SecretData = aws.String(`-----------------`)
+		pstc.expectError = "unable to unmarshal secret"
+	}
+
+	successCases := []*keyManagementServiceTestCase{
+		makeValidKMSTestCaseCustom(setDeserialization),
+		makeValidKMSTestCaseCustom(setInvalidJSON),
+		makeValidKMSTestCaseCustom(setNilMockClient),
+		makeValidKMSTestCaseCustom(setAPIErr),
+	}
+
+	sm := KeyManagementService{}
+	for k, v := range successCases {
+		sm.Client = v.mockClient
+		out, err := sm.GetSecretMap(context.Background(), *v.ref)
+		if !ErrorContains(err, v.expectError) {
+			t.Errorf("[%d] unexpected error: %s, expected: '%s'", k, err.Error(), v.expectError)
+		}
+		if err == nil && !reflect.DeepEqual(out, v.expectedData) {
+			t.Errorf("[%d] unexpected secret data: expected %#v, got %#v", k, v.expectedData, out)
+		}
+	}
+}
+
+func ErrorContains(out error, want string) bool {
+	if out == nil {
+		return want == ""
+	}
+	if want == "" {
+		return false
+	}
+	return strings.Contains(out.Error(), want)
+}