diff --git a/pkg/secrets/k8s_secrets_storage/mocks/access_token.go b/pkg/secrets/clients/conjur/mocks/access_token.go similarity index 100% rename from pkg/secrets/k8s_secrets_storage/mocks/access_token.go rename to pkg/secrets/clients/conjur/mocks/access_token.go diff --git a/pkg/secrets/k8s_secrets_storage/mocks/conjur_secrets_retriever.go b/pkg/secrets/clients/conjur/mocks/conjur_secrets_retriever.go similarity index 51% rename from pkg/secrets/k8s_secrets_storage/mocks/conjur_secrets_retriever.go rename to pkg/secrets/clients/conjur/mocks/conjur_secrets_retriever.go index 3b52ff348..f0da82285 100644 --- a/pkg/secrets/k8s_secrets_storage/mocks/conjur_secrets_retriever.go +++ b/pkg/secrets/clients/conjur/mocks/conjur_secrets_retriever.go @@ -11,24 +11,45 @@ import ( aren't concerned with if some Conjur secrets have permissions and others don't. Our main priority is validating that those secrets with 'execute' permissions can be fetched. */ -var CanExecuteConjurVar bool -func RetrieveConjurSecrets(_ []byte, variableIDs []string) (map[string][]byte, error) { +type ConjurMockClient struct { + CanExecute bool + // TODO: CanExecute is really just used to assert on the presence of errors + // and should probably just be an optional error. + Database map[string]string +} + +func (c ConjurMockClient) RetrieveSecrets (_ []byte, variableIDs []string) (map[string][]byte, error) { conjurSecrets := make(map[string][]byte) - if !CanExecuteConjurVar { + if !c.CanExecute { return nil, errors.New("custom error") } for _, variableId := range variableIDs { // Check if the secret exists in the mock Conjur DB - if _, ok := MockConjurDB[variableId]; !ok { + variableData, ok := c.Database[variableId] + if !ok { return nil, errors.New("no_conjur_secret_error") } fullVariableId := fmt.Sprintf("account:variable:%s", variableId) - conjurSecrets[fullVariableId] = MockConjurDB[variableId] + conjurSecrets[fullVariableId] = []byte(variableData) } return conjurSecrets, nil } + +func NewConjurMockClient() ConjurMockClient { + database := map[string]string{ + "conjur_variable1": "conjur_secret1", + "conjur_variable2": "conjur_secret2", + "conjur_variable_empty_secret": "", + } + + return ConjurMockClient{ + CanExecute: true, + Database: database, + } +} + diff --git a/pkg/secrets/k8s_secrets_storage/mocks/conjur_db.go b/pkg/secrets/k8s_secrets_storage/mocks/conjur_db.go deleted file mode 100644 index 48896b839..000000000 --- a/pkg/secrets/k8s_secrets_storage/mocks/conjur_db.go +++ /dev/null @@ -1,4 +0,0 @@ -package mocks - -// Mocks a Conjur data base. Maps variable IDs to secrets -var MockConjurDB map[string][]byte diff --git a/pkg/secrets/k8s_secrets_storage/mocks/k8s_db.go b/pkg/secrets/k8s_secrets_storage/mocks/k8s_db.go deleted file mode 100644 index 91b2f94cb..000000000 --- a/pkg/secrets/k8s_secrets_storage/mocks/k8s_db.go +++ /dev/null @@ -1,36 +0,0 @@ -package mocks - -import "fmt" - -// Mocks a K8s database. Maps k8s secret names to mock K8s secrets. -var MockK8sDB map[string]map[string][]byte - -func CreateMockK8sSecret(dataEntries map[string]string) map[string][]byte { - secret := make(map[string][]byte) - secret["conjur-map"] = []byte(createConjurMapDataEntry(dataEntries)) - - return secret -} - -func createConjurMapDataEntry(dataEntries map[string]string) string { - // combine each key-value entry to "key:value" - index := 0 - entriesCombined := make([]string, len(dataEntries)) - for key, value := range dataEntries { - entry := fmt.Sprintf("\"%s\": \"%s\"", key, value) - entriesCombined[index] = entry - index++ - } - - // Add a comma between each pair of entries - numOfDataEntries := len(dataEntries) - dataEntriesCombined := entriesCombined[0] - for i := range entriesCombined { - if i < numOfDataEntries-1 { - dataEntriesCombined = fmt.Sprintf("%s, %s", dataEntriesCombined, entriesCombined[i+1]) - } - } - - // Wrap all the entries - return fmt.Sprintf("{%s}", dataEntriesCombined) -} diff --git a/pkg/secrets/k8s_secrets_storage/mocks/k8s_secrets_client.go b/pkg/secrets/k8s_secrets_storage/mocks/k8s_secrets_client.go index 26b194288..b387a2c91 100644 --- a/pkg/secrets/k8s_secrets_storage/mocks/k8s_secrets_client.go +++ b/pkg/secrets/k8s_secrets_storage/mocks/k8s_secrets_client.go @@ -3,33 +3,69 @@ package mocks import ( "errors" + "gopkg.in/yaml.v3" v1 "k8s.io/api/core/v1" ) -var CanGetK8sSecrets bool -var CanUpdateK8sSecrets bool +type KubeSecretsMockClient struct { + // Mocks a K8s database. Maps k8s secret names to mock K8s secrets. + Database map[string]map[string][]byte + // TODO: CanRetrieve and CanUpdate are really just used to assert on the presence of errors + // and should probably just be an optional error. + CanRetrieve bool + CanUpdate bool +} + +func NewKubeSecretsMockClient() KubeSecretsMockClient { + client := KubeSecretsMockClient{ + Database: map[string]map[string][]byte{}, + CanRetrieve: true, + CanUpdate: true, + } + + return client +} + +func (c KubeSecretsMockClient) AddSecret( + secretName string, + key string, + keyConjurPath string, +) { + conjurMap := map[string]string{ + key: keyConjurPath, + } + conjurMapBytes, err := yaml.Marshal(conjurMap) + if err != nil { + panic(err) + } + + c.Database[secretName] = map[string][]byte{ + "conjur-map": conjurMapBytes, + } +} -func RetrieveK8sSecret(_ string, secretName string) (*v1.Secret, error) { - if !CanGetK8sSecrets { +func (c KubeSecretsMockClient) RetrieveSecret(_ string, secretName string) (*v1.Secret, error) { + if !c.CanRetrieve { return nil, errors.New("custom error") } // Check if the secret exists in the mock K8s DB - if _, ok := MockK8sDB[secretName]; !ok { + secretData, ok := c.Database[secretName] + if !ok { return nil, errors.New("custom error") } return &v1.Secret{ - Data: MockK8sDB[secretName], + Data: secretData, }, nil } -func UpdateK8sSecret(_ string, secretName string, originalK8sSecret *v1.Secret, stringDataEntriesMap map[string][]byte) error { - if !CanUpdateK8sSecrets { +func (c KubeSecretsMockClient) UpdateSecret(_ string, secretName string, originalK8sSecret *v1.Secret, stringDataEntriesMap map[string][]byte) error { + if !c.CanUpdate { return errors.New("custom error") } - secretToUpdate := MockK8sDB[secretName] + secretToUpdate := c.Database[secretName] for key, value := range stringDataEntriesMap { secretToUpdate[key] = value } diff --git a/pkg/secrets/k8s_secrets_storage/provide_conjur_secrets_test.go b/pkg/secrets/k8s_secrets_storage/provide_conjur_secrets_test.go index 215f71e84..a690594d8 100644 --- a/pkg/secrets/k8s_secrets_storage/provide_conjur_secrets_test.go +++ b/pkg/secrets/k8s_secrets_storage/provide_conjur_secrets_test.go @@ -2,24 +2,24 @@ package k8s_secrets_storage import ( "fmt" - "reflect" "sort" "testing" . "github.com/smartystreets/goconvey/convey" "github.com/cyberark/secrets-provider-for-k8s/pkg/log/messages" - "github.com/cyberark/secrets-provider-for-k8s/pkg/secrets/k8s_secrets_storage/mocks" + secretsStorageMocks "github.com/cyberark/secrets-provider-for-k8s/pkg/secrets/k8s_secrets_storage/mocks" + conjurMocks "github.com/cyberark/secrets-provider-for-k8s/pkg/secrets/clients/conjur/mocks" ) func TestProvideConjurSecrets(t *testing.T) { Convey("getVariableIDsToRetrieve", t, func() { Convey("Given a non-empty pathMap", func() { - pathMap := make(map[string][]string) - - pathMap["account/var_path1"] = []string{"secret1:key1"} - pathMap["account/var_path2"] = []string{"secret1:key2"} + pathMap := map[string][]string{ + "account/var_path1": {"secret1:key1"}, + "account/var_path2": {"secret1:key2"}, + } variableIDsExpected := []string{"account/var_path1", "account/var_path2"} variableIDsActual, err := getVariableIDsToRetrieve(pathMap) @@ -31,13 +31,13 @@ func TestProvideConjurSecrets(t *testing.T) { // Sort actual and expected, because output order can change sort.Strings(variableIDsActual) sort.Strings(variableIDsExpected) - eq := reflect.DeepEqual(variableIDsActual, variableIDsExpected) - So(eq, ShouldEqual, true) + + So(variableIDsActual, ShouldResemble, variableIDsExpected) }) }) Convey("Given an empty pathMap", func() { - pathMap := make(map[string][]string) + pathMap := map[string][]string{} Convey("Raises an error that the map input is empty", func() { _, err := getVariableIDsToRetrieve(pathMap) @@ -48,18 +48,19 @@ func TestProvideConjurSecrets(t *testing.T) { Convey("updateK8sSecretsMapWithConjurSecrets", t, func() { Convey("Given one K8s secret with one Conjur secret", func() { - secret := []byte{'s', 'u', 'p', 'e', 'r'} - conjurSecrets := make(map[string][]byte) - conjurSecrets["account:variable:allowed/username"] = secret - - newDataEntriesMap := make(map[string][]byte) - newDataEntriesMap["username"] = []byte("allowed/username") + conjurSecrets := map[string][]byte{ + "account:variable:allowed/username": []byte("super"), + } - k8sSecretsMap := make(map[string]map[string][]byte) - k8sSecretsMap["mysecret"] = newDataEntriesMap + k8sSecretsMap := map[string]map[string][]byte{ + "mysecret": { + "username": []byte("allowed/username"), + }, + } - pathMap := make(map[string][]string) - pathMap["allowed/username"] = []string{"mysecret:username"} + pathMap := map[string][]string{ + "allowed/username": {"mysecret:username"}, + } k8sSecretsStruct := K8sSecretsMap{k8sSecretsMap, nil, pathMap} err := updateK8sSecretsMapWithConjurSecrets(&k8sSecretsStruct, conjurSecrets) @@ -69,25 +70,25 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Replaces secret variable IDs in k8sSecretsMap with their corresponding secret value", func() { - eq := reflect.DeepEqual(k8sSecretsStruct.K8sSecrets["mysecret"]["username"], []byte{'s', 'u', 'p', 'e', 'r'}) - So(eq, ShouldEqual, true) + So(k8sSecretsStruct.K8sSecrets["mysecret"]["username"], ShouldResemble, []byte("super")) }) }) Convey("Given 2 k8s secrets that need the same Conjur secret", func() { - secret := []byte{'s', 'u', 'p', 'e', 'r'} - conjurSecrets := make(map[string][]byte) - conjurSecrets["account:variable:allowed/username"] = secret - - dataEntriesMap := make(map[string][]byte) - dataEntriesMap["username"] = []byte("allowed/username") - - k8sSecretsMap := make(map[string]map[string][]byte) - k8sSecretsMap["secret"] = dataEntriesMap - k8sSecretsMap["another-secret"] = dataEntriesMap - - pathMap := make(map[string][]string) - pathMap["allowed/username"] = []string{"secret:username", "another-secret:username"} + conjurSecrets := map[string][]byte{ + "account:variable:allowed/username": []byte("super"), + } + dataEntriesMap := map[string][]byte{ + "username": []byte("allowed/username"), + } + k8sSecretsMap := map[string]map[string][]byte{ + "secret": dataEntriesMap, + "another-secret": dataEntriesMap, + } + + pathMap := map[string][]string{ + "allowed/username": {"secret:username", "another-secret:username"}, + } k8sSecretsStruct := K8sSecretsMap{k8sSecretsMap, nil, pathMap} err := updateK8sSecretsMapWithConjurSecrets(&k8sSecretsStruct, conjurSecrets) @@ -97,59 +98,53 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Replaces both Variable IDs in k8sSecretsMap to their corresponding secret values without errors", func() { - eq := reflect.DeepEqual(k8sSecretsStruct.K8sSecrets["secret"]["username"], secret) - So(eq, ShouldEqual, true) - - eq = reflect.DeepEqual(k8sSecretsStruct.K8sSecrets["another-secret"]["username"], secret) - So(eq, ShouldEqual, true) + secret := []byte("super") + So(k8sSecretsStruct.K8sSecrets["secret"]["username"], ShouldResemble, secret) + So(k8sSecretsStruct.K8sSecrets["another-secret"]["username"], ShouldResemble, secret) }) }) }) Convey("RetrieveRequiredK8sSecrets", t, func() { - mocks.CanGetK8sSecrets = true - Convey("Given an existing k8s secret that is mapped to an existing conjur secret", func() { - prepareMockDBs() + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret1", "secret_key", "conjur_variable1") - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") requiredSecrets := []string{"k8s_secret1"} - k8sSecretsMap, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + k8sSecretsMap, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Finishes without raising an error", func() { So(err, ShouldEqual, nil) }) Convey("Creates K8sSecrets map as expected", func() { - expectedK8sSecretsData := make(map[string][]byte) - expectedK8sSecretsData["data_key"] = []byte("conjur_variable1") - - expectedK8sSecrets := make(map[string]map[string][]byte) - expectedK8sSecrets["k8s_secret1"] = expectedK8sSecretsData + expectedK8sSecrets := map[string]map[string][]byte{ + "k8s_secret1": { + "secret_key": []byte("conjur_variable1"), + }, + } - eq := reflect.DeepEqual(k8sSecretsMap.K8sSecrets, expectedK8sSecrets) - So(eq, ShouldEqual, true) + So(k8sSecretsMap.K8sSecrets, ShouldResemble, expectedK8sSecrets) }) Convey("Creates PathMap map as expected", func() { - expectedPathMap := make(map[string][]string) - expectedPathMap["conjur_variable1"] = []string{fmt.Sprintf("%s:%s", "k8s_secret1", "data_key")} + expectedPathMap := map[string][]string{ + "conjur_variable1": {"k8s_secret1:secret_key"}, + } - eq := reflect.DeepEqual(k8sSecretsMap.PathMap, expectedPathMap) - So(eq, ShouldEqual, true) + So(k8sSecretsMap.PathMap, ShouldResemble, expectedPathMap) }) }) Convey("Given no 'get' permissions on the 'secrets' k8s resource", func() { - prepareMockDBs() + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.CanRetrieve = false + kubeMockClient.AddSecret("k8s_secret1", "secret_key", "conjur_variable1") - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") requiredSecrets := []string{"k8s_secret1"} - mocks.CanGetK8sSecrets = false - - _, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + _, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, messages.CSPFK020E) @@ -157,11 +152,11 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Given a non-existing k8s secret", func() { - prepareMockDBs() + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() requiredSecrets := []string{"non_existing"} - _, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + _, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, messages.CSPFK020E) @@ -169,15 +164,13 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Given a k8s secret without 'conjur-map'", func() { - prepareMockDBs() - - secretData := make(map[string][]byte) - secretData["not-conjur-map"] = []byte("some-data") - mocks.MockK8sDB["no_conjur_map_secret"] = secretData + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.Database["no_conjur_map_secret"] = map[string][]byte{ + "not-conjur-map": []byte("some-data"), + } requiredSecrets := []string{"no_conjur_map_secret"} - - _, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + _, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, fmt.Sprintf(messages.CSPFK028E, "no_conjur_map_secret")) @@ -185,15 +178,14 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Given a k8s secret with an empty 'conjur-map'", func() { - prepareMockDBs() - - secretData := make(map[string][]byte) - secretData["conjur-map"] = []byte("") - mocks.MockK8sDB["empty_conjur_map_secret"] = secretData + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.Database["empty_conjur_map_secret"] = map[string][]byte{ + "conjur-map": []byte(""), + } requiredSecrets := []string{"empty_conjur_map_secret"} - _, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + _, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, fmt.Sprintf(messages.CSPFK028E, "empty_conjur_map_secret")) @@ -201,15 +193,14 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Given a k8s secret with an invalid 'conjur-map'", func() { - prepareMockDBs() - - secretData := make(map[string][]byte) - secretData["conjur-map"] = []byte("key_with_no_value") - mocks.MockK8sDB["invalid_conjur_map_secret"] = secretData + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.Database["invalid_conjur_map_secret"] = map[string][]byte{ + "conjur-map": []byte("key_with_no_value"), + } requiredSecrets := []string{"invalid_conjur_map_secret"} - _, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + _, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, fmt.Sprintf(messages.CSPFK028E, "invalid_conjur_map_secret")) @@ -219,20 +210,18 @@ func TestProvideConjurSecrets(t *testing.T) { Convey("UpdateRequiredK8sSecrets", t, func() { Convey("Given no 'update' permissions on the 'secrets' k8s resource", func() { - prepareMockDBs() - - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.CanUpdate = false + kubeMockClient.AddSecret("k8s_secret1", "secret_key1", "conjur_variable1") requiredSecrets := []string{"k8s_secret1"} - mocks.CanUpdateK8sSecrets = false - - k8sSecretsMap, err := RetrieveRequiredK8sSecrets(mocks.RetrieveK8sSecret, "someNameSpace", requiredSecrets) + k8sSecretsMap, err := RetrieveRequiredK8sSecrets(kubeMockClient.RetrieveSecret, "someNameSpace", requiredSecrets) Convey("Finishes without raising an error", func() { So(err, ShouldEqual, nil) }) - err = UpdateRequiredK8sSecrets(mocks.UpdateK8sSecret, "someNameSpace", k8sSecretsMap) + err = UpdateRequiredK8sSecrets(kubeMockClient.UpdateSecret, "someNameSpace", k8sSecretsMap) Convey("Raises proper error", func() { So(err.Error(), ShouldEqual, messages.CSPFK022E) @@ -241,27 +230,23 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("run", t, func() { - var mockAccessToken mocks.MockAccessToken - - mocks.CanGetK8sSecrets = true - mocks.CanUpdateK8sSecrets = true + var mockAccessToken conjurMocks.MockAccessToken Convey("Given 2 k8s secrets that only one is required by the pod", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") - addK8sSecretToMockDB("k8s_secret2", "conjur_variable2") + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret1", "secret_key1", "conjur_variable1") + kubeMockClient.AddSecret("k8s_secret2", "secret_key2", "conjur_variable2") requiredSecrets := []string{"k8s_secret1"} - mocks.CanExecuteConjurVar = true - err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Finishes without raising an error", func() { @@ -269,31 +254,31 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Updates K8s secrets with their corresponding Conjur secrets", func() { - verifyK8sSecretValue("k8s_secret1", "conjur_secret1") + verifyK8sSecretValue(kubeMockClient, "k8s_secret1", "secret_key1", "conjur_secret1") + }) Convey("Does not updates other K8s secrets", func() { - actualK8sSecretDataValue := mocks.MockK8sDB["k8s_secret2"]["data_key"] + actualK8sSecretDataValue := kubeMockClient.Database["k8s_secret2"]["secretkkey1"] So(actualK8sSecretDataValue, ShouldEqual, nil) }) }) Convey("Given 2 k8s secrets that are required by the pod - each one has its own Conjur secret", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") - addK8sSecretToMockDB("k8s_secret2", "conjur_variable2") + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret1","secret_key1","conjur_variable1") + kubeMockClient.AddSecret("k8s_secret2", "secret_key2","conjur_variable2") requiredSecrets := []string{"k8s_secret1", "k8s_secret2"} - mocks.CanExecuteConjurVar = true - err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Finishes without raising an error", func() { @@ -301,27 +286,27 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Updates K8s secrets with their corresponding Conjur secrets", func() { - verifyK8sSecretValue("k8s_secret1", "conjur_secret1") - verifyK8sSecretValue("k8s_secret2", "conjur_secret2") + verifyK8sSecretValue(kubeMockClient, "k8s_secret1", "secret_key1", "conjur_secret1") + verifyK8sSecretValue(kubeMockClient, "k8s_secret2", "secret_key2", "conjur_secret2") }) }) Convey("Given 2 k8s secrets that are required by the pod - both have the same Conjur secret", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() - addK8sSecretToMockDB("k8s_secret1", "conjur_variable1") - addK8sSecretToMockDB("k8s_secret2", "conjur_variable1") - requiredSecrets := []string{"k8s_secret1", "k8s_secret2"} + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret1", "secret_key1", "conjur_variable1") + kubeMockClient.AddSecret("k8s_secret2", "secret_key2", "conjur_variable2") - mocks.CanExecuteConjurVar = true + requiredSecrets := []string{"k8s_secret1", "k8s_secret2"} err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Finishes without raising an error", func() { @@ -329,26 +314,26 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Updates K8s secrets with their corresponding Conjur secrets", func() { - verifyK8sSecretValue("k8s_secret1", "conjur_secret1") - verifyK8sSecretValue("k8s_secret2", "conjur_secret1") + verifyK8sSecretValue(kubeMockClient, "k8s_secret1", "secret_key1", "conjur_secret1") + verifyK8sSecretValue(kubeMockClient, "k8s_secret2", "secret_key2", "conjur_secret2") }) }) Convey("Given a k8s secret which is mapped to a non-existing conjur variable", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() - addK8sSecretToMockDB("k8s_secret1", "non_existing_conjur_variable") - requiredSecrets := []string{"k8s_secret1"} + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret1", "secret_key", "non_existing_conjur_variable") - mocks.CanExecuteConjurVar = true + requiredSecrets := []string{"k8s_secret1"} err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Raises proper error", func() { @@ -357,20 +342,19 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Given a k8s secret which is mapped to a conjur secret with an empty secret value", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() - addK8sSecretToMockDB("k8s_secret_with_empty_conjur_variable", "conjur_variable_empty_secret") + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret_with_empty_conjur_variable", "secret_key", "conjur_variable_empty_secret") requiredSecrets := []string{"k8s_secret_with_empty_conjur_variable"} - mocks.CanExecuteConjurVar = true - err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Finishes without raising an error", func() { @@ -378,26 +362,26 @@ func TestProvideConjurSecrets(t *testing.T) { }) Convey("Updates K8s secrets with their corresponding Conjur secrets", func() { - verifyK8sSecretValue("k8s_secret_with_empty_conjur_variable", "") + verifyK8sSecretValue(kubeMockClient, "k8s_secret_with_empty_conjur_variable", "secret_key", "") }) }) Convey("Given no 'execute' permissions on the conjur secret", func() { - prepareMockDBs() + conjurMockClient := conjurMocks.NewConjurMockClient() + // no execute privileges on the conjur secret + conjurMockClient.CanExecute = false - addK8sSecretToMockDB("k8s_secret_with_no_permission_conjur_variable", "no_execute_permission_conjur_secret") + kubeMockClient := secretsStorageMocks.NewKubeSecretsMockClient() + kubeMockClient.AddSecret("k8s_secret_with_no_permission_conjur_variable", "secret_key", "no_execute_permission_conjur_secret") requiredSecrets := []string{"k8s_secret_with_no_permission_conjur_variable"} - // no execute privileges on the conjur secret - mocks.CanExecuteConjurVar = false - err := run( - mocks.RetrieveK8sSecret, - mocks.UpdateK8sSecret, + kubeMockClient.RetrieveSecret, + kubeMockClient.UpdateSecret, "someNameSpace", requiredSecrets, mockAccessToken, - mocks.RetrieveConjurSecrets, + conjurMockClient.RetrieveSecrets, ) Convey("Raises proper error", func() { @@ -407,24 +391,13 @@ func TestProvideConjurSecrets(t *testing.T) { }) } -func prepareMockDBs() { - mocks.MockK8sDB = make(map[string]map[string][]byte) - - mocks.MockConjurDB = make(map[string][]byte) - mocks.MockConjurDB["conjur_variable1"] = []byte("conjur_secret1") - mocks.MockConjurDB["conjur_variable2"] = []byte("conjur_secret2") - mocks.MockConjurDB["conjur_variable_empty_secret"] = []byte("") -} - -func addK8sSecretToMockDB(secretName string, conjurVariable string) { - secretDataEntries := make(map[string]string) - secretDataEntries["data_key"] = conjurVariable - mocks.MockK8sDB[secretName] = mocks.CreateMockK8sSecret(secretDataEntries) -} - -func verifyK8sSecretValue(secretName string, value string) { - actualK8sSecretDataValue := mocks.MockK8sDB[secretName]["data_key"] +func verifyK8sSecretValue( + client secretsStorageMocks.KubeSecretsMockClient, + secretName string, + key string, + value string, +) { + actualK8sSecretDataValue := client.Database[secretName][key] expectedK8sSecretDataValue := []byte(value) - eq := reflect.DeepEqual(actualK8sSecretDataValue, expectedK8sSecretDataValue) - So(eq, ShouldEqual, true) + So(actualK8sSecretDataValue, ShouldResemble, expectedK8sSecretDataValue) }