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:
parent
e053010e67
commit
882b348ff5
5 changed files with 360 additions and 0 deletions
89
e2e/suite/alibaba/alibaba.go
Normal file
89
e2e/suite/alibaba/alibaba.go
Normal 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
|
||||
}
|
88
e2e/suite/alibaba/provider.go
Normal file
88
e2e/suite/alibaba/provider.go
Normal 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())
|
||||
}
|
25
pkg/provider/alibaba/fake/fake.go
Normal file
25
pkg/provider/alibaba/fake/fake.go
Normal 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
|
||||
}
|
||||
}
|
|
@ -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
pkg/provider/alibaba/kms_test.go
Normal file
157
pkg/provider/alibaba/kms_test.go
Normal 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)
|
||||
}
|
Loading…
Reference in a new issue