Browse Source

Merge pull request #1083 from external-secrets/beach-team

Implement ValidateStore for Gitlab and Oracle providers
paul-the-alien[bot] 4 years ago
parent
commit
ff7e9f90f3

+ 19 - 0
pkg/provider/gitlab/gitlab.go

@@ -237,5 +237,24 @@ func (g *Gitlab) Validate() (esv1beta1.ValidationResult, error) {
 }
 
 func (g *Gitlab) ValidateStore(store esv1beta1.GenericStore) error {
+	storeSpec := store.GetSpec()
+	gitlabSpec := storeSpec.Provider.Gitlab
+	accessToken := gitlabSpec.Auth.SecretRef.AccessToken
+	err := utils.ValidateSecretSelector(store, accessToken)
+	if err != nil {
+		return err
+	}
+
+	if gitlabSpec.ProjectID == "" {
+		return fmt.Errorf("projectID cannot be empty")
+	}
+
+	if accessToken.Key == "" {
+		return fmt.Errorf("accessToken.key cannot be empty")
+	}
+
+	if accessToken.Name == "" {
+		return fmt.Errorf("accessToken.name cannot be empty")
+	}
 	return nil
 }

+ 79 - 0
pkg/provider/gitlab/gitlab_test.go

@@ -24,9 +24,16 @@ import (
 	gitlab "github.com/xanzy/go-gitlab"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	fakegitlab "github.com/external-secrets/external-secrets/pkg/provider/gitlab/fake"
 )
 
+const (
+	project  = "my-Project"
+	username = "user-name"
+	userkey  = "user-key"
+)
+
 type secretManagerTestCase struct {
 	mockClient               *fakegitlab.GitlabMockClient
 	apiInputProjectID        string
@@ -230,3 +237,75 @@ func ErrorContains(out error, want string) bool {
 	}
 	return strings.Contains(out.Error(), want)
 }
+
+type storeModifier func(*esv1beta1.SecretStore) *esv1beta1.SecretStore
+
+func makeSecretStore(projectID string, fn ...storeModifier) *esv1beta1.SecretStore {
+	store := &esv1beta1.SecretStore{
+		Spec: esv1beta1.SecretStoreSpec{
+			Provider: &esv1beta1.SecretStoreProvider{
+				Gitlab: &esv1beta1.GitlabProvider{
+					Auth:      esv1beta1.GitlabAuth{},
+					ProjectID: projectID,
+				},
+			},
+		},
+	}
+	for _, f := range fn {
+		store = f(store)
+	}
+	return store
+}
+
+func withAccessToken(name, key string, namespace *string) storeModifier {
+	return func(store *esv1beta1.SecretStore) *esv1beta1.SecretStore {
+		store.Spec.Provider.Gitlab.Auth.SecretRef.AccessToken = v1.SecretKeySelector{
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
+type ValidateStoreTestCase struct {
+	store *esv1beta1.SecretStore
+	err   error
+}
+
+func TestValidateStore(t *testing.T) {
+	namespace := "my-namespace"
+	testCases := []ValidateStoreTestCase{
+		{
+			store: makeSecretStore(""),
+			err:   fmt.Errorf("projectID cannot be empty"),
+		},
+		{
+			store: makeSecretStore(project, withAccessToken("", userkey, nil)),
+			err:   fmt.Errorf("accessToken.name cannot be empty"),
+		},
+		{
+			store: makeSecretStore(project, withAccessToken(username, "", nil)),
+			err:   fmt.Errorf("accessToken.key cannot be empty"),
+		},
+		{
+			store: makeSecretStore(project, withAccessToken("userName", "userKey", &namespace)),
+			err:   fmt.Errorf("namespace not allowed with namespaced SecretStore"),
+		},
+		{
+			store: makeSecretStore(project, withAccessToken("userName", "userKey", nil)),
+			err:   nil,
+		},
+	}
+	p := Gitlab{}
+	for _, tc := range testCases {
+		err := p.ValidateStore(tc.store)
+		if tc.err != nil && err != nil && err.Error() != tc.err.Error() {
+			t.Errorf("test failed! want %v, got %v", tc.err, err)
+		} else if tc.err == nil && err != nil {
+			t.Errorf("want nil got err %v", err)
+		} else if tc.err != nil && err == nil {
+			t.Errorf("want err %v got nil", tc.err)
+		}
+	}
+}

+ 57 - 0
pkg/provider/oracle/oracle.go

@@ -228,6 +228,63 @@ func (vms *VaultManagementService) Validate() (esv1beta1.ValidationResult, error
 }
 
 func (vms *VaultManagementService) ValidateStore(store esv1beta1.GenericStore) error {
+	storeSpec := store.GetSpec()
+	oracleSpec := storeSpec.Provider.Oracle
+
+	vault := oracleSpec.Vault
+	if vault == "" {
+		return fmt.Errorf("vault cannot be empty")
+	}
+
+	region := oracleSpec.Region
+	if region == "" {
+		return fmt.Errorf("region cannot be empty")
+	}
+
+	auth := oracleSpec.Auth
+	if auth == nil {
+		return nil
+	}
+
+	user := oracleSpec.Auth.User
+	if user == "" {
+		return fmt.Errorf("user cannot be empty")
+	}
+
+	tenant := oracleSpec.Auth.Tenancy
+	if tenant == "" {
+		return fmt.Errorf("tenant cannot be empty")
+	}
+	privateKey := oracleSpec.Auth.SecretRef.PrivateKey
+
+	if privateKey.Name == "" {
+		return fmt.Errorf("privateKey.name cannot be empty")
+	}
+
+	if privateKey.Key == "" {
+		return fmt.Errorf("privateKey.key cannot be empty")
+	}
+
+	err := utils.ValidateSecretSelector(store, privateKey)
+	if err != nil {
+		return err
+	}
+
+	fingerprint := oracleSpec.Auth.SecretRef.Fingerprint
+
+	if fingerprint.Name == "" {
+		return fmt.Errorf("fingerprint.name cannot be empty")
+	}
+
+	if fingerprint.Key == "" {
+		return fmt.Errorf("fingerprint.key cannot be empty")
+	}
+
+	err = utils.ValidateSecretSelector(store, fingerprint)
+	if err != nil {
+		return err
+	}
+
 	return nil
 }
 

+ 125 - 0
pkg/provider/oracle/oracle_test.go

@@ -23,9 +23,19 @@ import (
 	utilpointer "k8s.io/utils/pointer"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
+	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
 	fakeoracle "github.com/external-secrets/external-secrets/pkg/provider/oracle/fake"
 )
 
+const (
+	vaultOCID  = "vault-OCID"
+	region     = "some-region"
+	tenant     = "a-tenant"
+	userOCID   = "user-OCID"
+	secretKey  = "key"
+	secretName = "name"
+)
+
 type vaultTestCase struct {
 	mockClient     *fakeoracle.OracleMockClient
 	apiInput       *secrets.GetSecretBundleByNameRequest
@@ -177,3 +187,118 @@ func ErrorContains(out error, want string) bool {
 	}
 	return strings.Contains(out.Error(), want)
 }
+
+type storeModifier func(*esv1beta1.SecretStore) *esv1beta1.SecretStore
+
+func makeSecretStore(vault, region string, fn ...storeModifier) *esv1beta1.SecretStore {
+	store := &esv1beta1.SecretStore{
+		Spec: esv1beta1.SecretStoreSpec{
+			Provider: &esv1beta1.SecretStoreProvider{
+				Oracle: &esv1beta1.OracleProvider{
+					Vault:  vault,
+					Region: region,
+				},
+			},
+		},
+	}
+
+	for _, f := range fn {
+		store = f(store)
+	}
+	return store
+}
+func withSecretAuth(user, tenancy string) storeModifier {
+	return func(store *esv1beta1.SecretStore) *esv1beta1.SecretStore {
+		store.Spec.Provider.Oracle.Auth = &esv1beta1.OracleAuth{
+			User:    user,
+			Tenancy: tenancy,
+		}
+		return store
+	}
+}
+func withPrivateKey(name, key string, namespace *string) storeModifier {
+	return func(store *esv1beta1.SecretStore) *esv1beta1.SecretStore {
+		store.Spec.Provider.Oracle.Auth.SecretRef.PrivateKey = v1.SecretKeySelector{
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+func withFingerprint(name, key string, namespace *string) storeModifier {
+	return func(store *esv1beta1.SecretStore) *esv1beta1.SecretStore {
+		store.Spec.Provider.Oracle.Auth.SecretRef.Fingerprint = v1.SecretKeySelector{
+			Name:      name,
+			Key:       key,
+			Namespace: namespace,
+		}
+		return store
+	}
+}
+
+type ValidateStoreTestCase struct {
+	store *esv1beta1.SecretStore
+	err   error
+}
+
+func TestValidateStore(t *testing.T) {
+	namespace := "my-namespace"
+	testCases := []ValidateStoreTestCase{
+		{
+			store: makeSecretStore("", region),
+			err:   fmt.Errorf("vault cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, ""),
+			err:   fmt.Errorf("region cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth("", tenant)),
+			err:   fmt.Errorf("user cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, "")),
+			err:   fmt.Errorf("tenant cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey("", secretKey, nil)),
+			err:   fmt.Errorf("privateKey.name cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey(secretName, secretKey, &namespace)),
+			err:   fmt.Errorf("namespace not allowed with namespaced SecretStore"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey(secretName, "", nil)),
+			err:   fmt.Errorf("privateKey.key cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey(secretName, secretKey, nil), withFingerprint("", secretKey, nil)),
+			err:   fmt.Errorf("fingerprint.name cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey(secretName, secretKey, nil), withFingerprint(secretName, secretKey, &namespace)),
+			err:   fmt.Errorf("namespace not allowed with namespaced SecretStore"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region, withSecretAuth(userOCID, tenant), withPrivateKey(secretName, secretKey, nil), withFingerprint(secretName, "", nil)),
+			err:   fmt.Errorf("fingerprint.key cannot be empty"),
+		},
+		{
+			store: makeSecretStore(vaultOCID, region),
+			err:   nil,
+		},
+	}
+	p := VaultManagementService{}
+	for _, tc := range testCases {
+		err := p.ValidateStore(tc.store)
+		if tc.err != nil && err != nil && err.Error() != tc.err.Error() {
+			t.Errorf("test failed! want %v, got %v", tc.err, err)
+		} else if tc.err == nil && err != nil {
+			t.Errorf("want nil got err %v", err)
+		} else if tc.err != nil && err == nil {
+			t.Errorf("want err %v got nil", tc.err)
+		}
+	}
+}