1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

WiP: e2e and unit tests

This commit is contained in:
Elsa Chelala 2021-08-18 09:40:57 -04:00
parent e053010e67
commit 882b348ff5
5 changed files with 360 additions and 0 deletions

View file

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

View file

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

View file

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

View file

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

View file

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