Browse Source

Table driven test with anonymous functions implemented.
The NewClient tests were kept as they were.

Sebastian Gomez 4 years ago
parent
commit
385caa156f

+ 27 - 164
pkg/provider/azure/keyvault/fake/fake.go

@@ -17,188 +17,51 @@ import (
 	"context"
 
 	"github.com/Azure/azure-sdk-for-go/profiles/latest/keyvault/keyvault"
-	"github.com/google/uuid"
-	mock "github.com/stretchr/testify/mock"
 )
 
-type secretData struct {
-	item           keyvault.SecretItem
-	secretVersions map[string]keyvault.SecretBundle
-	lastVersion    string
+type AzureMockClient struct {
+	getKey             func(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error)
+	getSecret          func(ctx context.Context, vaultBaseURL string, secretName string, secretVersion string) (result keyvault.SecretBundle, err error)
+	getSecretsComplete func(ctx context.Context, vaultBaseURL string, maxresults *int32) (result keyvault.SecretListResultIterator, err error)
+	getCertificate     func(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (result keyvault.CertificateBundle, err error)
 }
 
-type keyData struct {
-	item        keyvault.KeyItem
-	keyVersions map[string]keyvault.KeyBundle
-	lastVersion string
+func (mc *AzureMockClient) GetSecret(ctx context.Context, vaultBaseURL string, secretName string, secretVersion string) (result keyvault.SecretBundle, err error) {
+	return mc.getSecret(ctx, vaultBaseURL, secretName, secretVersion)
 }
 
-type AzureMock struct {
-	mock.Mock
-	knownSecrets map[string]map[string]*secretData
-	knownKeys    map[string]map[string]*keyData
+func (mc *AzureMockClient) GetCertificate(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (result keyvault.CertificateBundle, err error) {
+	return mc.getCertificate(ctx, vaultBaseURL, certificateName, certificateVersion)
 }
 
-func (m *AzureMock) AddSecret(vaultBaseURL, secretName, secretContent string, enabled bool) string {
-	uid := uuid.NewString()
-	m.AddSecretWithVersion(vaultBaseURL, secretName, uid, secretContent, enabled)
-	return uid
+func (mc *AzureMockClient) GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error) {
+	return mc.getKey(ctx, vaultBaseURL, keyName, keyVersion)
 }
 
-func (m *AzureMock) AddSecretWithVersion(vaultBaseURL, secretName, secretVersion, secretContent string, enabled bool) {
-	if m.knownSecrets == nil {
-		m.knownSecrets = make(map[string]map[string]*secretData)
-	}
-	if m.knownSecrets[vaultBaseURL] == nil {
-		m.knownSecrets[vaultBaseURL] = make(map[string]*secretData)
-	}
-
-	secretItemID := vaultBaseURL + secretName
-	secretBundleID := secretItemID + "/" + secretVersion
-
-	if m.knownSecrets[vaultBaseURL][secretName] == nil {
-		m.knownSecrets[vaultBaseURL][secretName] = &secretData{
-			item:           newValidSecretItem(secretItemID, enabled),
-			secretVersions: make(map[string]keyvault.SecretBundle),
-		}
-	} else {
-		m.knownSecrets[vaultBaseURL][secretName].item.Attributes.Enabled = &enabled
-	}
-	m.knownSecrets[vaultBaseURL][secretName].secretVersions[secretVersion] = newValidSecretBundle(secretBundleID, secretContent)
-	m.knownSecrets[vaultBaseURL][secretName].lastVersion = secretVersion
-}
-
-func newValidSecretBundle(secretBundleID, secretContent string) keyvault.SecretBundle {
-	return keyvault.SecretBundle{
-		Value: &secretContent,
-		ID:    &secretBundleID,
-	}
-}
-
-func newValidSecretItem(secretItemID string, enabled bool) keyvault.SecretItem {
-	return keyvault.SecretItem{
-		ID:         &secretItemID,
-		Attributes: &keyvault.SecretAttributes{Enabled: &enabled},
-	}
-}
-
-func (m *AzureMock) ExpectsGetSecret(ctx context.Context, vaultBaseURL, secretName, secretVersion string) {
-	data := m.knownSecrets[vaultBaseURL][secretName]
-	version := secretVersion
-	if version == "" {
-		version = data.lastVersion
-	}
-	returnValue := data.secretVersions[version]
-	m.On("GetSecret", ctx, vaultBaseURL, secretName, secretVersion).Return(returnValue, nil)
+func (mc *AzureMockClient) GetSecretsComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) (result keyvault.SecretListResultIterator, err error) {
+	return mc.getSecretsComplete(ctx, vaultBaseURL, maxresults)
 }
 
-func (m *AzureMock) ExpectsGetSecretsComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) {
-	secretMap := m.knownSecrets[vaultBaseURL]
-	secretItems := make([]keyvault.SecretItem, len(secretMap))
-	i := 0
-	for _, value := range secretMap {
-		secretItems[i] = value.item
-		i++
-	}
-	firstPage := keyvault.SecretListResult{
-		Value:    &secretItems,
-		NextLink: nil,
-	}
-	returnValue := keyvault.NewSecretListResultIterator(keyvault.NewSecretListResultPage(firstPage, func(context.Context, keyvault.SecretListResult) (keyvault.SecretListResult, error) {
-		return keyvault.SecretListResult{}, nil
-	}))
-	m.On("GetSecretsComplete", ctx, vaultBaseURL, maxresults).Return(returnValue, nil)
-}
-
-func (m *AzureMock) AddKey(vaultBaseURL, keyName string, key *keyvault.JSONWebKey, enabled bool) string {
-	uid := uuid.NewString()
-	m.AddKeyWithVersion(vaultBaseURL, keyName, uid, key, enabled)
-	return uid
-}
-
-func (m *AzureMock) AddKeyWithVersion(vaultBaseURL, keyName, keyVersion string, key *keyvault.JSONWebKey, enabled bool) {
-	if m.knownKeys == nil {
-		m.knownKeys = make(map[string]map[string]*keyData)
-	}
-	if m.knownKeys[vaultBaseURL] == nil {
-		m.knownKeys[vaultBaseURL] = make(map[string]*keyData)
-	}
-
-	keyItemID := vaultBaseURL + keyName
-
-	if m.knownKeys[vaultBaseURL][keyName] == nil {
-		m.knownKeys[vaultBaseURL][keyName] = &keyData{
-			item:        newValidKeyItem(keyItemID, enabled),
-			keyVersions: make(map[string]keyvault.KeyBundle),
+func (mc *AzureMockClient) WithValue(serviceUrl string, secretName string, secretVersion string, apiOutput keyvault.SecretBundle, err error) {
+	if mc != nil {
+		mc.getSecret = func(ctx context.Context, serviceUrl string, secretName string, secretVersion string) (result keyvault.SecretBundle, retErr error) {
+			return apiOutput, err
 		}
-	} else {
-		m.knownKeys[vaultBaseURL][keyName].item.Attributes.Enabled = &enabled
-	}
-	m.knownKeys[vaultBaseURL][keyName].keyVersions[keyVersion] = newValidKeyBundle(key)
-	m.knownKeys[vaultBaseURL][keyName].lastVersion = keyVersion
-}
-
-func newValidKeyBundle(key *keyvault.JSONWebKey) keyvault.KeyBundle {
-	return keyvault.KeyBundle{
-		Key: key,
 	}
 }
 
-func newValidKeyItem(keyItemID string, enabled bool) keyvault.KeyItem {
-	return keyvault.KeyItem{
-		Kid:        &keyItemID,
-		Attributes: &keyvault.KeyAttributes{Enabled: &enabled},
-	}
-}
-
-func (m *AzureMock) ExpectsGetKey(ctx context.Context, vaultBaseURL, keyName, keyVersion string) {
-	data := m.knownKeys[vaultBaseURL][keyName]
-	version := keyVersion
-	if version == "" {
-		version = data.lastVersion
+func (mc *AzureMockClient) WithKey(serviceUrl string, secretName string, secretVersion string, apiOutput keyvault.KeyBundle, err error) {
+	if mc != nil {
+		mc.getKey = func(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, retErr error) {
+			return apiOutput, err
+		}
 	}
-	returnValue := data.keyVersions[version]
-	m.On("GetKey", ctx, vaultBaseURL, keyName, keyVersion).Return(returnValue, nil)
 }
 
-func (m *AzureMock) ExpectsGetKeysComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) {
-	keyMap := m.knownKeys[vaultBaseURL]
-	keyItems := make([]keyvault.KeyItem, len(keyMap))
-	i := 0
-	for _, value := range keyMap {
-		keyItems[i] = value.item
-		i++
-	}
-	firstPage := keyvault.KeyListResult{
-		Value:    &keyItems,
-		NextLink: nil,
+func (mc *AzureMockClient) WithCertificate(serviceUrl string, secretName string, secretVersion string, apiOutput keyvault.CertificateBundle, err error) {
+	if mc != nil {
+		mc.getCertificate = func(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.CertificateBundle, retErr error) {
+			return apiOutput, err
+		}
 	}
-	returnValue := keyvault.NewKeyListResultIterator(keyvault.NewKeyListResultPage(firstPage, func(context.Context, keyvault.KeyListResult) (keyvault.KeyListResult, error) {
-		return keyvault.KeyListResult{}, nil
-	}))
-	m.On("GetKeysComplete", ctx, vaultBaseURL, maxresults).Return(returnValue, nil)
-}
-
-func (m *AzureMock) GetKey(ctx context.Context, vaultBaseURL, keyName, keyVersion string) (result keyvault.KeyBundle, err error) {
-	args := m.Called(ctx, vaultBaseURL, keyName, keyVersion)
-	return args.Get(0).(keyvault.KeyBundle), args.Error(1)
-}
-
-func (m *AzureMock) GetSecret(ctx context.Context, vaultBaseURL, secretName, secretVersion string) (result keyvault.SecretBundle, err error) {
-	args := m.Called(ctx, vaultBaseURL, secretName, secretVersion)
-	return args.Get(0).(keyvault.SecretBundle), args.Error(1)
-}
-func (m *AzureMock) GetCertificate(ctx context.Context, vaultBaseURL, certificateName, certificateVersion string) (result keyvault.CertificateBundle, err error) {
-	args := m.Called(ctx, vaultBaseURL, certificateName, certificateVersion)
-	return args.Get(0).(keyvault.CertificateBundle), args.Error(1)
-}
-
-func (m *AzureMock) GetSecretsComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) (result keyvault.SecretListResultIterator, err error) {
-	args := m.Called(ctx, vaultBaseURL, maxresults)
-	return args.Get(0).(keyvault.SecretListResultIterator), args.Error(1)
-}
-
-func (m *AzureMock) GetKeysComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) (result keyvault.KeyListResultIterator, err error) {
-	args := m.Called(ctx, vaultBaseURL, maxresults)
-	return args.Get(0).(keyvault.KeyListResultIterator), args.Error(1)
 }

+ 5 - 8
pkg/provider/azure/keyvault/keyvault.go

@@ -27,9 +27,10 @@ import (
 	"k8s.io/apimachinery/pkg/types"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
+	"github.com/external-secrets/external-secrets/pkg/provider"
+
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 	smmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
-	"github.com/external-secrets/external-secrets/pkg/provider"
 	"github.com/external-secrets/external-secrets/pkg/provider/schema"
 )
 
@@ -37,9 +38,6 @@ const (
 	defaultObjType = "secret"
 )
 
-// Provider satisfies the provider interface.
-type Provider struct{}
-
 // interface to keyvault.BaseClient.
 type SecretClient interface {
 	GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error)
@@ -48,7 +46,6 @@ type SecretClient interface {
 	GetCertificate(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (result keyvault.CertificateBundle, err error)
 }
 
-// Azure satisfies the provider.SecretsClient interface.
 type Azure struct {
 	kube       client.Client
 	store      esv1alpha1.GenericStore
@@ -58,13 +55,13 @@ type Azure struct {
 }
 
 func init() {
-	schema.Register(&Provider{}, &esv1alpha1.SecretStoreProvider{
+	schema.Register(&Azure{}, &esv1alpha1.SecretStoreProvider{
 		AzureKV: &esv1alpha1.AzureKVProvider{},
 	})
 }
 
 // NewClient constructs a new secrets client based on the provided store.
-func (p *Provider) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube client.Client, namespace string) (provider.SecretsClient, error) {
+func (p *Azure) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube client.Client, namespace string) (provider.SecretsClient, error) {
 	return newClient(ctx, store, kube, namespace)
 }
 
@@ -122,7 +119,7 @@ func (a *Azure) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretData
 		}
 		return *secretResp.Cer, nil
 	case "key":
-		// returns a KeyBundla that contains a jwk
+		// returns a KeyBundle that contains a jwk
 		// azure kv returns only public keys
 		// see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#KeyBundle
 		keyResp, err := basicClient.GetKey(context.Background(), a.vaultURL, secretName, version)

+ 257 - 84
pkg/provider/azure/keyvault/keyvault_test.go

@@ -15,28 +15,72 @@ limitations under the License.
 package keyvault
 
 import (
-	context "context"
+	"context"
 	"encoding/json"
+	"fmt"
+	"reflect"
+	"strings"
 	"testing"
 
-	"github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
 	tassert "github.com/stretchr/testify/assert"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
 
+	"github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
+
 	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
 	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	fake "github.com/external-secrets/external-secrets/pkg/provider/azure/keyvault/fake"
 	"github.com/external-secrets/external-secrets/pkg/provider/schema"
 )
 
-func newAzure() (Azure, *fake.AzureMock) {
-	azureMock := &fake.AzureMock{}
-	testAzure := Azure{
-		baseClient: azureMock,
-		vaultURL:   "https://local.vault/",
+type secretManagerTestCase struct {
+	mockClient     *fake.AzureMockClient
+	secretName     string
+	secretVersion  string
+	serviceUrl     string
+	ref            *esv1alpha1.ExternalSecretDataRemoteRef
+	apiErr         error
+	secretOutput   keyvault.SecretBundle
+	keyOutput      keyvault.KeyBundle
+	certOutput     keyvault.CertificateBundle
+	expectError    string
+	expectedSecret string
+	// for testing secretmap
+	expectedData map[string][]byte
+}
+
+func makeValidSecretManagerTestCase() *secretManagerTestCase {
+	secretString := "Hello World!"
+	smtc := secretManagerTestCase{
+		mockClient:     &fake.AzureMockClient{},
+		secretName:     "MySecret",
+		secretVersion:  "",
+		ref:            makeValidRef(),
+		secretOutput:   keyvault.SecretBundle{Value: &secretString},
+		serviceUrl:     "",
+		apiErr:         nil,
+		expectError:    "",
+		expectedSecret: secretString,
+		expectedData:   map[string][]byte{},
+	}
+
+	smtc.mockClient.WithValue(smtc.serviceUrl, smtc.secretName, smtc.secretVersion, smtc.secretOutput, smtc.apiErr)
+
+	return &smtc
+}
+
+func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
+	smtc := makeValidSecretManagerTestCase()
+	for _, fn := range tweaks {
+		fn(smtc)
 	}
-	return testAzure, azureMock
+
+	smtc.mockClient.WithValue(smtc.serviceUrl, smtc.secretName, smtc.secretVersion, smtc.secretOutput, smtc.apiErr)
+	smtc.mockClient.WithKey(smtc.serviceUrl, smtc.secretName, smtc.secretVersion, smtc.keyOutput, smtc.apiErr)
+	smtc.mockClient.WithCertificate(smtc.serviceUrl, smtc.secretName, smtc.secretVersion, smtc.certOutput, smtc.apiErr)
+
+	return smtc
 }
 
 func TestNewClientNoCreds(t *testing.T) {
@@ -88,99 +132,228 @@ const (
 	jwkPubEC  = `{"kid":"https://example.vault.azure.net/keys/ec-p-521/e3d0e9c179b54988860c69c6ae172c65","kty":"EC","key_ops":["sign","verify"],"crv":"P-521","x":"AedOAtb7H7Oz1C_cPKI_R4CN_eai5nteY6KFW07FOoaqgQfVCSkQDK22fCOiMT_28c8LZYJRsiIFz_IIbQUW7bXj","y":"AOnchHnmBphIWXvanmMAmcCDkaED6ycW8GsAl9fQ43BMVZTqcTkJYn6vGnhn7MObizmkNSmgZYTwG-vZkIg03HHs"}`
 )
 
-func TestGetKey(t *testing.T) {
-	testAzure, azureMock := newAzure()
-	ctx := context.Background()
-
-	tbl := []struct {
-		name   string
-		kvName string
-		jwk    *keyvault.JSONWebKey
-		out    string
-	}{
-		{
-			name:   "test public rsa key",
-			kvName: "my-rsa",
-			jwk:    newKVJWK([]byte(jwkPubRSA)),
-			out:    jwkPubRSA,
-		},
-		{
-			name:   "test public ec key",
-			kvName: "my-ec",
-			jwk:    newKVJWK([]byte(jwkPubEC)),
-			out:    jwkPubEC,
-		},
+func newKVJWK(b []byte) *keyvault.JSONWebKey {
+	var key keyvault.JSONWebKey
+	err := json.Unmarshal(b, &key)
+	if err != nil {
+		panic(err)
 	}
+	return &key
+}
 
-	for _, row := range tbl {
-		t.Run(row.name, func(t *testing.T) {
-			azureMock.AddKey(testAzure.vaultURL, row.kvName, row.jwk, true)
-			azureMock.ExpectsGetKey(ctx, testAzure.vaultURL, row.kvName, "")
+// test the sm<->azurekv interface
+// make sure correct values are passed and errors are handled accordingly.
+func TestAzureKeyVaultSecretManagerGetSecret(t *testing.T) {
+	secretString := "changedvalue"
+	secretCertificate := "certificate_value"
 
-			rf := esv1alpha1.ExternalSecretDataRemoteRef{
-				Key: "key/" + row.kvName,
-			}
-			secret, err := testAzure.GetSecret(ctx, rf)
-			azureMock.AssertExpectations(t)
-			tassert.Nil(t, err, "the return err should be nil")
-			tassert.Equal(t, []byte(row.out), secret)
-		})
+	// good case
+	setSecretString := func(smtc *secretManagerTestCase) {
+		smtc.expectedSecret = secretString
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &secretString,
+		}
 	}
-}
 
-func TestGetSecretWithVersion(t *testing.T) {
-	testAzure, azureMock := newAzure()
-	ctx := context.Background()
-	version := "v1"
+	setSecretStringWithVersion := func(smtc *secretManagerTestCase) {
+		smtc.expectedSecret = secretString
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &secretString,
+		}
+		smtc.ref.Version = "v1"
+		smtc.secretVersion = smtc.ref.Version
+	}
 
-	rf := esv1alpha1.ExternalSecretDataRemoteRef{
-		Key:     "testName",
-		Version: version,
+	setSecretWithProperty := func(smtc *secretManagerTestCase) {
+		jsonString := `{"Name": "External", "LastName": "Secret"}`
+		smtc.expectedSecret = "External"
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &jsonString,
+		}
+		smtc.ref.Property = "Name"
 	}
-	azureMock.AddSecretWithVersion(testAzure.vaultURL, "testName", version, "My Secret", true)
-	azureMock.ExpectsGetSecret(ctx, testAzure.vaultURL, "testName", version)
 
-	secret, err := testAzure.GetSecret(ctx, rf)
-	azureMock.AssertExpectations(t)
-	tassert.Nil(t, err, "the return err should be nil")
-	tassert.Equal(t, []byte("My Secret"), secret)
+	badSecretWithProperty := func(smtc *secretManagerTestCase) {
+		jsonString := `{"Name": "External", "LastName": "Secret"}`
+		smtc.expectedSecret = ""
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &jsonString,
+		}
+		smtc.ref.Property = "Age"
+		smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Property, smtc.ref.Key)
+		smtc.apiErr = fmt.Errorf(smtc.expectError)
+	}
+
+	// // good case: key set
+	setPubRSAKey := func(smtc *secretManagerTestCase) {
+		smtc.secretName = "key/keyname"
+		smtc.expectedSecret = jwkPubRSA
+		smtc.keyOutput = keyvault.KeyBundle{
+			Key: newKVJWK([]byte(jwkPubRSA)),
+		}
+		smtc.ref.Key = smtc.secretName
+	}
+
+	// // good case: key set
+	setPubECKey := func(smtc *secretManagerTestCase) {
+		smtc.secretName = "key/keyname"
+		smtc.expectedSecret = jwkPubEC
+		smtc.keyOutput = keyvault.KeyBundle{
+			Key: newKVJWK([]byte(jwkPubEC)),
+		}
+		smtc.ref.Key = smtc.secretName
+	}
+
+	// // good case: key set
+	setCertificate := func(smtc *secretManagerTestCase) {
+		byteArrString := []byte(secretCertificate)
+		smtc.secretName = "cert/certname"
+		smtc.expectedSecret = secretCertificate
+		smtc.certOutput = keyvault.CertificateBundle{
+			Cer: &byteArrString,
+		}
+		smtc.ref.Key = smtc.secretName
+	}
+
+	badSecretType := func(smtc *secretManagerTestCase) {
+		smtc.secretName = "name"
+		smtc.expectedSecret = ""
+		smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName)
+		smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
+	}
+
+	successCases := []*secretManagerTestCase{
+		makeValidSecretManagerTestCase(),
+		makeValidSecretManagerTestCaseCustom(setSecretString),
+		makeValidSecretManagerTestCaseCustom(setSecretStringWithVersion),
+		makeValidSecretManagerTestCaseCustom(setSecretWithProperty),
+		makeValidSecretManagerTestCaseCustom(badSecretWithProperty),
+		makeValidSecretManagerTestCaseCustom(setPubRSAKey),
+		makeValidSecretManagerTestCaseCustom(setPubECKey),
+		makeValidSecretManagerTestCaseCustom(setCertificate),
+		makeValidSecretManagerTestCaseCustom(badSecretType),
+	}
+
+	sm := Azure{}
+	for k, v := range successCases {
+		sm.baseClient = 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 TestGetSecretWithoutVersion(t *testing.T) {
-	testAzure, azureMock := newAzure()
-	ctx := context.Background()
+func TestAzureKeyVaultSecretManagerGetSecretMap(t *testing.T) {
+	secretString := "changedvalue"
+	secretCertificate := "certificate_value"
 
-	rf := esv1alpha1.ExternalSecretDataRemoteRef{
-		Key: "testName",
+	badSecretString := func(smtc *secretManagerTestCase) {
+		smtc.expectedSecret = secretString
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &secretString,
+		}
+		smtc.expectError = "error unmarshalling json data: invalid character 'c' looking for beginning of value"
 	}
-	azureMock.AddSecret(testAzure.vaultURL, "testName", "My Secret", true)
-	azureMock.ExpectsGetSecret(ctx, testAzure.vaultURL, "testName", "")
 
-	secret, err := testAzure.GetSecret(ctx, rf)
-	azureMock.AssertExpectations(t)
-	tassert.Nil(t, err, "the return err should be nil")
-	tassert.Equal(t, []byte("My Secret"), secret)
+	setSecretJson := func(smtc *secretManagerTestCase) {
+		jsonString := `{"Name": "External", "LastName": "Secret"}`
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &jsonString,
+		}
+		smtc.expectedData["Name"] = []byte("External")
+		smtc.expectedData["LastName"] = []byte("Secret")
+	}
+
+	setSecretJsonWithProperty := func(smtc *secretManagerTestCase) {
+		jsonString := `{"Name": "External", "LastName": "Secret", "Address": { "Street": "Myroad st.", "CP": "J4K4T4" } }`
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &jsonString,
+		}
+		smtc.ref.Property = "Address"
+
+		smtc.expectedData["Street"] = []byte("Myroad st.")
+		smtc.expectedData["CP"] = []byte("J4K4T4")
+	}
+
+	badSecretWithProperty := func(smtc *secretManagerTestCase) {
+		jsonString := `{"Name": "External", "LastName": "Secret"}`
+		smtc.expectedSecret = ""
+		smtc.secretOutput = keyvault.SecretBundle{
+			Value: &jsonString,
+		}
+		smtc.ref.Property = "Age"
+		smtc.expectError = fmt.Sprintf("property %s does not exist in key %s", smtc.ref.Property, smtc.ref.Key)
+		smtc.apiErr = fmt.Errorf(smtc.expectError)
+	}
+
+	badPubRSAKey := func(smtc *secretManagerTestCase) {
+		smtc.secretName = "key/keyname"
+		smtc.expectedSecret = jwkPubRSA
+		smtc.keyOutput = keyvault.KeyBundle{
+			Key: newKVJWK([]byte(jwkPubRSA)),
+		}
+		smtc.ref.Key = smtc.secretName
+		smtc.expectError = "cannot get use dataFrom to get key secret"
+	}
+
+	badCertificate := func(smtc *secretManagerTestCase) {
+		byteArrString := []byte(secretCertificate)
+		smtc.secretName = "cert/certname"
+		smtc.expectedSecret = secretCertificate
+		smtc.certOutput = keyvault.CertificateBundle{
+			Cer: &byteArrString,
+		}
+		smtc.ref.Key = smtc.secretName
+		smtc.expectError = "cannot get use dataFrom to get certificate secret"
+	}
+
+	badSecretType := func(smtc *secretManagerTestCase) {
+		smtc.secretName = "name"
+		smtc.expectedSecret = ""
+		smtc.expectError = fmt.Sprintf("unknown Azure Keyvault object Type for %s", smtc.secretName)
+		smtc.ref.Key = fmt.Sprintf("dummy/%s", smtc.secretName)
+	}
+
+	successCases := []*secretManagerTestCase{
+		makeValidSecretManagerTestCaseCustom(badSecretString),
+		makeValidSecretManagerTestCaseCustom(setSecretJson),
+		makeValidSecretManagerTestCaseCustom(setSecretJsonWithProperty),
+		makeValidSecretManagerTestCaseCustom(badSecretWithProperty),
+		makeValidSecretManagerTestCaseCustom(badPubRSAKey),
+		makeValidSecretManagerTestCaseCustom(badCertificate),
+		makeValidSecretManagerTestCaseCustom(badSecretType),
+	}
+
+	sm := Azure{}
+	for k, v := range successCases {
+		sm.baseClient = 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 TestGetSecretMap(t *testing.T) {
-	testAzure, azureMock := newAzure()
-	ctx := context.Background()
-	rf := esv1alpha1.ExternalSecretDataRemoteRef{
-		Key: "testName",
+func ErrorContains(out error, want string) bool {
+	if out == nil {
+		return want == ""
 	}
-	azureMock.AddSecret(testAzure.vaultURL, "testName", "{\"username\": \"user1\", \"pass\": \"123\"}", true)
-	azureMock.ExpectsGetSecret(ctx, testAzure.vaultURL, "testName", "")
-	secretMap, err := testAzure.GetSecretMap(ctx, rf)
-	azureMock.AssertExpectations(t)
-	tassert.Nil(t, err, "the return err should be nil")
-	tassert.Equal(t, secretMap, map[string][]byte{"username": []byte("user1"), "pass": []byte("123")})
+	if want == "" {
+		return false
+	}
+	return strings.Contains(out.Error(), want)
 }
 
-func newKVJWK(b []byte) *keyvault.JSONWebKey {
-	var key keyvault.JSONWebKey
-	err := json.Unmarshal(b, &key)
-	if err != nil {
-		panic(err)
+func makeValidRef() *esv1alpha1.ExternalSecretDataRemoteRef {
+	return &esv1alpha1.ExternalSecretDataRemoteRef{
+		Key:     "test-secret",
+		Version: "default",
 	}
-	return &key
 }