Преглед на файлове

feat: expose admission warnings to ValidateStore interface (#3058)

This allows providers to issue warnings, e.g. during a
migration/deprecation period

Signed-off-by: Moritz Johner <beller.moritz@googlemail.com>
Moritz Johner преди 2 години
родител
ревизия
ee35aa0f9f
променени са 39 файла, в които са добавени 219 реда и са изтрити 191 реда
  1. 6 1
      apis/externalsecrets/v1beta1/provider.go
  2. 3 2
      apis/externalsecrets/v1beta1/provider_schema_test.go
  3. 1 1
      apis/externalsecrets/v1beta1/secretstore_validator.go
  4. 3 2
      pkg/controllers/secretstore/client_manager_test.go
  5. 15 14
      pkg/provider/akeyless/akeyless.go
  6. 4 4
      pkg/provider/akeyless/akeyless_test.go
  7. 4 3
      pkg/provider/alibaba/kms.go
  8. 2 2
      pkg/provider/alibaba/kms_test.go
  9. 10 9
      pkg/provider/aws/provider.go
  10. 1 1
      pkg/provider/aws/provider_test.go
  11. 10 9
      pkg/provider/azure/keyvault/keyvault.go
  12. 2 2
      pkg/provider/azure/keyvault/keyvault_test.go
  13. 16 15
      pkg/provider/conjur/provider.go
  14. 1 1
      pkg/provider/conjur/provider_test.go
  15. 3 2
      pkg/provider/delinea/provider.go
  16. 2 2
      pkg/provider/delinea/provider_test.go
  17. 1 1
      pkg/provider/doppler/doppler_test.go
  18. 5 4
      pkg/provider/doppler/provider.go
  19. 6 5
      pkg/provider/fake/fake.go
  20. 4 4
      pkg/provider/fake/fake_test.go
  21. 1 1
      pkg/provider/gcp/secretmanager/client_test.go
  22. 9 8
      pkg/provider/gcp/secretmanager/provider.go
  23. 1 1
      pkg/provider/gitlab/gitlab_test.go
  24. 8 7
      pkg/provider/gitlab/provider.go
  25. 12 11
      pkg/provider/ibm/provider.go
  26. 4 4
      pkg/provider/ibm/provider_test.go
  27. 9 8
      pkg/provider/keepersecurity/provider.go
  28. 12 11
      pkg/provider/kubernetes/validate.go
  29. 1 1
      pkg/provider/kubernetes/validate_test.go
  30. 3 2
      pkg/provider/onepassword/onepassword.go
  31. 15 14
      pkg/provider/oracle/oracle.go
  32. 1 1
      pkg/provider/oracle/oracle_test.go
  33. 3 2
      pkg/provider/scaleway/provider.go
  34. 3 2
      pkg/provider/senhasegura/provider.go
  35. 3 2
      pkg/provider/testing/fake/fake.go
  36. 27 26
      pkg/provider/vault/vault.go
  37. 1 1
      pkg/provider/vault/vault_test.go
  38. 3 2
      pkg/provider/webhook/webhook.go
  39. 4 3
      pkg/provider/yandex/common/provider.go

+ 6 - 1
apis/externalsecrets/v1beta1/provider.go

@@ -19,6 +19,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 )
 
 const (
@@ -51,7 +52,11 @@ type Provider interface {
 	NewClient(ctx context.Context, store GenericStore, kube client.Client, namespace string) (SecretsClient, error)
 
 	// ValidateStore checks if the provided store is valid
-	ValidateStore(store GenericStore) error
+	// The provider may return a warning and an error.
+	// The intended use of the warning to indicate a deprecation of behavior
+	// or other type of message that is NOT a validation failure but should be noticed by the user.
+	ValidateStore(store GenericStore) (admission.Warnings, error)
+
 	// Capabilities returns the provider Capabilities (Read, Write, ReadWrite)
 	Capabilities() SecretStoreCapabilities
 }

+ 3 - 2
apis/externalsecrets/v1beta1/provider_schema_test.go

@@ -20,6 +20,7 @@ import (
 	"github.com/stretchr/testify/assert"
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 )
 
 type PP struct{}
@@ -69,8 +70,8 @@ func (p *PP) Validate() (ValidationResult, error) {
 	return ValidationResultReady, nil
 }
 
-func (p *PP) ValidateStore(_ GenericStore) error {
-	return nil
+func (p *PP) ValidateStore(_ GenericStore) (admission.Warnings, error) {
+	return nil, nil
 }
 
 // TestRegister tests if the Register function

+ 1 - 1
apis/externalsecrets/v1beta1/secretstore_validator.go

@@ -58,5 +58,5 @@ func validateStore(store GenericStore) (admission.Warnings, error) {
 	if err != nil {
 		return nil, err
 	}
-	return nil, provider.ValidateStore(store)
+	return provider.ValidateStore(store)
 }

+ 3 - 2
pkg/controllers/secretstore/client_manager_test.go

@@ -28,6 +28,7 @@ import (
 	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 )
@@ -331,8 +332,8 @@ func (f *WrapProvider) Capabilities() esv1beta1.SecretStoreCapabilities {
 }
 
 // ValidateStore checks if the provided store is valid.
-func (f *WrapProvider) ValidateStore(_ esv1beta1.GenericStore) error {
-	return nil
+func (f *WrapProvider) ValidateStore(_ esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, nil
 }
 
 type MockFakeClient struct {

+ 15 - 14
pkg/provider/akeyless/akeyless.go

@@ -34,6 +34,7 @@ import (
 	typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -110,7 +111,7 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 	return newClient(ctx, store, kube, clientset.CoreV1(), namespace)
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	akeylessSpec := storeSpec.Provider.Akeyless
 
@@ -119,63 +120,63 @@ func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
 	if akeylessGWApiURL != nil && *akeylessGWApiURL != "" {
 		url, err := url.Parse(*akeylessGWApiURL)
 		if err != nil {
-			return fmt.Errorf(errInvalidAkeylessURL)
+			return nil, fmt.Errorf(errInvalidAkeylessURL)
 		}
 
 		if url.Host == "" {
-			return fmt.Errorf(errInvalidAkeylessURL)
+			return nil, fmt.Errorf(errInvalidAkeylessURL)
 		}
 	}
 	if akeylessSpec.Auth.KubernetesAuth != nil {
 		if akeylessSpec.Auth.KubernetesAuth.ServiceAccountRef != nil {
 			if err := utils.ValidateReferentServiceAccountSelector(store, *akeylessSpec.Auth.KubernetesAuth.ServiceAccountRef); err != nil {
-				return fmt.Errorf(errInvalidKubeSA, err)
+				return nil, fmt.Errorf(errInvalidKubeSA, err)
 			}
 		}
 		if akeylessSpec.Auth.KubernetesAuth.SecretRef != nil {
 			err := utils.ValidateSecretSelector(store, *akeylessSpec.Auth.KubernetesAuth.SecretRef)
 			if err != nil {
-				return err
+				return nil, err
 			}
 		}
 
 		if akeylessSpec.Auth.KubernetesAuth.AccessID == "" {
-			return fmt.Errorf("missing kubernetes auth-method access-id")
+			return nil, fmt.Errorf("missing kubernetes auth-method access-id")
 		}
 
 		if akeylessSpec.Auth.KubernetesAuth.K8sConfName == "" {
-			return fmt.Errorf("missing kubernetes config name")
+			return nil, fmt.Errorf("missing kubernetes config name")
 		}
-		return nil
+		return nil, nil
 	}
 
 	accessID := akeylessSpec.Auth.SecretRef.AccessID
 	err := utils.ValidateSecretSelector(store, accessID)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	if accessID.Name == "" {
-		return fmt.Errorf(errInvalidAkeylessAccessIDName)
+		return nil, fmt.Errorf(errInvalidAkeylessAccessIDName)
 	}
 
 	if accessID.Key == "" {
-		return fmt.Errorf(errInvalidAkeylessAccessIDKey)
+		return nil, fmt.Errorf(errInvalidAkeylessAccessIDKey)
 	}
 
 	accessType := akeylessSpec.Auth.SecretRef.AccessType
 	err = utils.ValidateSecretSelector(store, accessType)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	accessTypeParam := akeylessSpec.Auth.SecretRef.AccessTypeParam
 	err = utils.ValidateSecretSelector(store, accessTypeParam)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
-	return nil
+	return nil, nil
 }
 
 func newClient(_ context.Context, store esv1beta1.GenericStore, kube client.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) {

+ 4 - 4
pkg/provider/akeyless/akeyless_test.go

@@ -157,7 +157,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		}
 
-		err := provider.ValidateStore(store)
+		_, err := provider.ValidateStore(store)
 		if err != nil {
 			t.Errorf(err.Error())
 		}
@@ -183,7 +183,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		}
 
-		err := provider.ValidateStore(store)
+		_, err := provider.ValidateStore(store)
 		if err != nil {
 			t.Errorf(err.Error())
 		}
@@ -201,7 +201,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		}
 
-		err := provider.ValidateStore(store)
+		_, err := provider.ValidateStore(store)
 		if err == nil {
 			t.Errorf("expected an error")
 		}
@@ -226,7 +226,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		}
 
-		err := provider.ValidateStore(store)
+		_, err := provider.ValidateStore(store)
 		if err == nil {
 			t.Errorf("expected an error")
 		}

+ 4 - 3
pkg/provider/alibaba/kms.go

@@ -27,6 +27,7 @@ import (
 	"github.com/tidwall/gjson"
 	corev1 "k8s.io/api/core/v1"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -260,17 +261,17 @@ func (kms *KeyManagementService) Validate() (esv1beta1.ValidationResult, error)
 	return esv1beta1.ValidationResultReady, nil
 }
 
-func (kms *KeyManagementService) ValidateStore(store esv1beta1.GenericStore) error {
+func (kms *KeyManagementService) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	alibabaSpec := storeSpec.Provider.Alibaba
 
 	regionID := alibabaSpec.RegionID
 
 	if regionID == "" {
-		return fmt.Errorf("missing alibaba region")
+		return nil, fmt.Errorf("missing alibaba region")
 	}
 
-	return kms.validateStoreAuth(store)
+	return nil, kms.validateStoreAuth(store)
 }
 
 func (kms *KeyManagementService) validateStoreAuth(store esv1beta1.GenericStore) error {

+ 2 - 2
pkg/provider/alibaba/kms_test.go

@@ -201,7 +201,7 @@ func TestValidateAccessKeyStore(t *testing.T) {
 		},
 	}
 
-	err := kms.ValidateStore(store)
+	_, err := kms.ValidateStore(store)
 	if err != nil {
 		t.Errorf(err.Error())
 	}
@@ -228,7 +228,7 @@ func TestValidateRRSAStore(t *testing.T) {
 		},
 	}
 
-	err := kms.ValidateStore(store)
+	_, err := kms.ValidateStore(store)
 	if err != nil {
 		t.Errorf(err.Error())
 	}

+ 10 - 9
pkg/provider/aws/provider.go

@@ -26,6 +26,7 @@ import (
 	"github.com/aws/aws-sdk-go/aws/session"
 	awssm "github.com/aws/aws-sdk-go/service/secretsmanager"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	awsauth "github.com/external-secrets/external-secrets/pkg/provider/aws/auth"
@@ -59,31 +60,31 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 	return newClient(ctx, store, kube, namespace, awsauth.DefaultSTSProvider)
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	prov, err := util.GetAWSProvider(store)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	err = validateRegion(prov)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	err = validateSecretsManagerConfig(prov)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	// case: static credentials
 	if prov.Auth.SecretRef != nil {
 		if err := utils.ValidateReferentSecretSelector(store, prov.Auth.SecretRef.AccessKeyID); err != nil {
-			return fmt.Errorf("invalid Auth.SecretRef.AccessKeyID: %w", err)
+			return nil, fmt.Errorf("invalid Auth.SecretRef.AccessKeyID: %w", err)
 		}
 		if err := utils.ValidateReferentSecretSelector(store, prov.Auth.SecretRef.SecretAccessKey); err != nil {
-			return fmt.Errorf("invalid Auth.SecretRef.SecretAccessKey: %w", err)
+			return nil, fmt.Errorf("invalid Auth.SecretRef.SecretAccessKey: %w", err)
 		}
 		if prov.Auth.SecretRef.SessionToken != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.SecretRef.SessionToken); err != nil {
-				return fmt.Errorf("invalid Auth.SecretRef.SessionToken: %w", err)
+				return nil, fmt.Errorf("invalid Auth.SecretRef.SessionToken: %w", err)
 			}
 		}
 	}
@@ -91,11 +92,11 @@ func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
 	// case: jwt credentials
 	if prov.Auth.JWTAuth != nil && prov.Auth.JWTAuth.ServiceAccountRef != nil {
 		if err := utils.ValidateReferentServiceAccountSelector(store, *prov.Auth.JWTAuth.ServiceAccountRef); err != nil {
-			return fmt.Errorf("invalid Auth.JWT.ServiceAccountRef: %w", err)
+			return nil, fmt.Errorf("invalid Auth.JWT.ServiceAccountRef: %w", err)
 		}
 	}
 
-	return nil
+	return nil, nil
 }
 
 func validateRegion(prov *esv1beta1.AWSProvider) error {

+ 1 - 1
pkg/provider/aws/provider_test.go

@@ -474,7 +474,7 @@ func TestValidateStore(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			p := &Provider{}
-			if err := p.ValidateStore(tt.args.store); (err != nil) != tt.wantErr {
+			if _, err := p.ValidateStore(tt.args.store); (err != nil) != tt.wantErr {
 				t.Errorf("Provider.ValidateStore() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})

+ 10 - 9
pkg/provider/azure/keyvault/keyvault.go

@@ -46,6 +46,7 @@ import (
 	pointer "k8s.io/utils/ptr"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/constants"
@@ -190,39 +191,39 @@ func getProvider(store esv1beta1.GenericStore) (*esv1beta1.AzureKVProvider, erro
 	return spc.Provider.AzureKV, nil
 }
 
-func (a *Azure) ValidateStore(store esv1beta1.GenericStore) error {
+func (a *Azure) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	if store == nil {
-		return fmt.Errorf(errInvalidStore)
+		return nil, fmt.Errorf(errInvalidStore)
 	}
 	spc := store.GetSpec()
 	if spc == nil {
-		return fmt.Errorf(errInvalidStoreSpec)
+		return nil, fmt.Errorf(errInvalidStoreSpec)
 	}
 	if spc.Provider == nil {
-		return fmt.Errorf(errInvalidStoreProv)
+		return nil, fmt.Errorf(errInvalidStoreProv)
 	}
 	p := spc.Provider.AzureKV
 	if p == nil {
-		return fmt.Errorf(errInvalidAzureProv)
+		return nil, fmt.Errorf(errInvalidAzureProv)
 	}
 	if p.AuthSecretRef != nil {
 		if p.AuthSecretRef.ClientID != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *p.AuthSecretRef.ClientID); err != nil {
-				return fmt.Errorf(errInvalidSecRefClientID, err)
+				return nil, fmt.Errorf(errInvalidSecRefClientID, err)
 			}
 		}
 		if p.AuthSecretRef.ClientSecret != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *p.AuthSecretRef.ClientSecret); err != nil {
-				return fmt.Errorf(errInvalidSecRefClientSecret, err)
+				return nil, fmt.Errorf(errInvalidSecRefClientSecret, err)
 			}
 		}
 	}
 	if p.ServiceAccountRef != nil {
 		if err := utils.ValidateReferentServiceAccountSelector(store, *p.ServiceAccountRef); err != nil {
-			return fmt.Errorf(errInvalidSARef, err)
+			return nil, fmt.Errorf(errInvalidSARef, err)
 		}
 	}
-	return nil
+	return nil, nil
 }
 
 func canDelete(tags map[string]*string, err error) (bool, error) {

+ 2 - 2
pkg/provider/azure/keyvault/keyvault_test.go

@@ -1611,10 +1611,10 @@ func TestValidateStore(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			a := &Azure{}
 			if tt.name == "storeIsNil" {
-				if err := a.ValidateStore(nil); (err != nil) != tt.wantErr {
+				if _, err := a.ValidateStore(nil); (err != nil) != tt.wantErr {
 					t.Errorf(errStore, err, tt.wantErr)
 				}
-			} else if err := a.ValidateStore(tt.args.store); (err != nil) != tt.wantErr {
+			} else if _, err := a.ValidateStore(tt.args.store); (err != nil) != tt.wantErr {
 				t.Errorf(errStore, err, tt.wantErr)
 			}
 		})

+ 16 - 15
pkg/provider/conjur/provider.go

@@ -27,6 +27,7 @@ import (
 	typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -225,61 +226,61 @@ func (p *Client) Validate() (esv1beta1.ValidationResult, error) {
 }
 
 // ValidateStore validates the store.
-func (c *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (c *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	prov, err := util.GetConjurProvider(store)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	if prov.URL == "" {
-		return fmt.Errorf("conjur URL cannot be empty")
+		return nil, fmt.Errorf("conjur URL cannot be empty")
 	}
 	if prov.Auth.APIKey != nil {
 		if prov.Auth.APIKey.Account == "" {
-			return fmt.Errorf("missing Auth.ApiKey.Account")
+			return nil, fmt.Errorf("missing Auth.ApiKey.Account")
 		}
 		if prov.Auth.APIKey.UserRef == nil {
-			return fmt.Errorf("missing Auth.Apikey.UserRef")
+			return nil, fmt.Errorf("missing Auth.Apikey.UserRef")
 		}
 		if prov.Auth.APIKey.APIKeyRef == nil {
-			return fmt.Errorf("missing Auth.Apikey.ApiKeyRef")
+			return nil, fmt.Errorf("missing Auth.Apikey.ApiKeyRef")
 		}
 		if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.APIKey.UserRef); err != nil {
-			return fmt.Errorf("invalid Auth.Apikey.UserRef: %w", err)
+			return nil, fmt.Errorf("invalid Auth.Apikey.UserRef: %w", err)
 		}
 		if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.APIKey.APIKeyRef); err != nil {
-			return fmt.Errorf("invalid Auth.Apikey.ApiKeyRef: %w", err)
+			return nil, fmt.Errorf("invalid Auth.Apikey.ApiKeyRef: %w", err)
 		}
 	}
 
 	if prov.Auth.Jwt != nil {
 		if prov.Auth.Jwt.Account == "" {
-			return fmt.Errorf("missing Auth.Jwt.Account")
+			return nil, fmt.Errorf("missing Auth.Jwt.Account")
 		}
 		if prov.Auth.Jwt.ServiceID == "" {
-			return fmt.Errorf("missing Auth.Jwt.ServiceID")
+			return nil, fmt.Errorf("missing Auth.Jwt.ServiceID")
 		}
 		if prov.Auth.Jwt.ServiceAccountRef == nil && prov.Auth.Jwt.SecretRef == nil {
-			return fmt.Errorf("must specify Auth.Jwt.SecretRef or Auth.Jwt.ServiceAccountRef")
+			return nil, fmt.Errorf("must specify Auth.Jwt.SecretRef or Auth.Jwt.ServiceAccountRef")
 		}
 		if prov.Auth.Jwt.SecretRef != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *prov.Auth.Jwt.SecretRef); err != nil {
-				return fmt.Errorf("invalid Auth.Jwt.SecretRef: %w", err)
+				return nil, fmt.Errorf("invalid Auth.Jwt.SecretRef: %w", err)
 			}
 		}
 		if prov.Auth.Jwt.ServiceAccountRef != nil {
 			if err := utils.ValidateReferentServiceAccountSelector(store, *prov.Auth.Jwt.ServiceAccountRef); err != nil {
-				return fmt.Errorf("invalid Auth.Jwt.ServiceAccountRef: %w", err)
+				return nil, fmt.Errorf("invalid Auth.Jwt.ServiceAccountRef: %w", err)
 			}
 		}
 	}
 
 	// At least one auth must be configured
 	if prov.Auth.APIKey == nil && prov.Auth.Jwt == nil {
-		return fmt.Errorf("missing Auth.* configuration")
+		return nil, fmt.Errorf("missing Auth.* configuration")
 	}
 
-	return nil
+	return nil, nil
 }
 
 // Capabilities returns the provider Capabilities (Read, Write, ReadWrite).

+ 1 - 1
pkg/provider/conjur/provider_test.go

@@ -112,7 +112,7 @@ func TestValidateStore(t *testing.T) {
 	}
 	c := Provider{}
 	for _, tc := range testCases {
-		err := c.ValidateStore(tc.store)
+		_, err := c.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 {

+ 3 - 2
pkg/provider/delinea/provider.go

@@ -20,6 +20,7 @@ import (
 
 	"github.com/DelineaXPM/dsv-sdk-go/v2/vault"
 	kubeClient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -178,9 +179,9 @@ func getConfig(store esv1beta1.GenericStore) (*esv1beta1.DelineaProvider, error)
 	return cfg, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	_, err := getConfig(store)
-	return err
+	return nil, err
 }
 
 func init() {

+ 2 - 2
pkg/provider/delinea/provider_test.go

@@ -153,7 +153,7 @@ func TestValidateStore(t *testing.T) {
 				},
 			}
 			p := &Provider{}
-			got := p.ValidateStore(&s)
+			_, got := p.ValidateStore(&s)
 			assert.Equal(t, tc.want, got)
 		})
 	}
@@ -178,7 +178,7 @@ func TestValidateStoreBailsOnUnexpectedStore(t *testing.T) {
 	for name, tc := range tests {
 		t.Run(name, func(t *testing.T) {
 			p := &Provider{}
-			got := p.ValidateStore(tc.store)
+			_, got := p.ValidateStore(tc.store)
 			assert.Equal(t, tc.want, got)
 		})
 	}

+ 1 - 1
pkg/provider/doppler/doppler_test.go

@@ -268,7 +268,7 @@ func TestValidateStore(t *testing.T) {
 	p := Provider{}
 	for _, tc := range testCases {
 		t.Run(tc.label, func(t *testing.T) {
-			err := p.ValidateStore(tc.store)
+			_, 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 {

+ 5 - 4
pkg/provider/doppler/provider.go

@@ -21,6 +21,7 @@ import (
 	"strconv"
 
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	dClient "github.com/external-secrets/external-secrets/pkg/provider/doppler/client"
@@ -102,17 +103,17 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 	return client, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	dopplerStoreSpec := storeSpec.Provider.Doppler
 	dopplerTokenSecretRef := dopplerStoreSpec.Auth.SecretRef.DopplerToken
 	if err := utils.ValidateSecretSelector(store, dopplerTokenSecretRef); err != nil {
-		return fmt.Errorf(errInvalidStore, err)
+		return nil, fmt.Errorf(errInvalidStore, err)
 	}
 
 	if dopplerTokenSecretRef.Name == "" {
-		return fmt.Errorf(errInvalidStore, "dopplerToken.name cannot be empty")
+		return nil, fmt.Errorf(errInvalidStore, "dopplerToken.name cannot be empty")
 	}
 
-	return nil
+	return nil, nil
 }

+ 6 - 5
pkg/provider/fake/fake.go

@@ -23,6 +23,7 @@ import (
 	"github.com/tidwall/gjson"
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/find"
@@ -235,20 +236,20 @@ func (p *Provider) Validate() (esv1beta1.ValidationResult, error) {
 	return esv1beta1.ValidationResultReady, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	prov := store.GetSpec().Provider.Fake
 	if prov == nil {
-		return nil
+		return nil, nil
 	}
 	for pos, data := range prov.Data {
 		if data.Key == "" {
-			return fmt.Errorf(errMissingKeyField, pos)
+			return nil, fmt.Errorf(errMissingKeyField, pos)
 		}
 		if data.Value == "" && data.ValueMap == nil {
-			return fmt.Errorf(errMissingValueField, pos)
+			return nil, fmt.Errorf(errMissingValueField, pos)
 		}
 	}
-	return nil
+	return nil, nil
 }
 
 func mapKey(key, version string) string {

+ 4 - 4
pkg/provider/fake/fake_test.go

@@ -56,24 +56,24 @@ func TestValidateStore(t *testing.T) {
 		},
 	}
 	// empty data must not error
-	err := p.ValidateStore(store)
+	_, err := p.ValidateStore(store)
 	gomega.Expect(err).To(gomega.BeNil())
 	// missing key in data
 	data := esv1beta1.FakeProviderData{}
 	data.Version = "v1"
 	store.Spec.Provider.Fake.Data = []esv1beta1.FakeProviderData{data}
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	gomega.Expect(err).To(gomega.BeEquivalentTo(fmt.Errorf(errMissingKeyField, 0)))
 	// missing values in data
 	data.Key = "/foo"
 	store.Spec.Provider.Fake.Data = []esv1beta1.FakeProviderData{data}
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	gomega.Expect(err).To(gomega.BeEquivalentTo(fmt.Errorf(errMissingValueField, 0)))
 	// spec ok
 	data.Value = "bar"
 	data.ValueMap = map[string]string{"foo": "bar"}
 	store.Spec.Provider.Fake.Data = []esv1beta1.FakeProviderData{data}
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	gomega.Expect(err).To(gomega.BeNil())
 }
 func TestClose(t *testing.T) {

+ 1 - 1
pkg/provider/gcp/secretmanager/client_test.go

@@ -1084,7 +1084,7 @@ func TestValidateStore(t *testing.T) {
 					},
 				},
 			}
-			if err := sm.ValidateStore(store); (err != nil) != tt.wantErr {
+			if _, err := sm.ValidateStore(store); (err != nil) != tt.wantErr {
 				t.Errorf("ProviderGCP.ValidateStore() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})

+ 9 - 8
pkg/provider/gcp/secretmanager/provider.go

@@ -22,6 +22,7 @@ import (
 	"golang.org/x/oauth2"
 	"google.golang.org/api/option"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -109,32 +110,32 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 	return client, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	if store == nil {
-		return fmt.Errorf(errInvalidStore)
+		return nil, fmt.Errorf(errInvalidStore)
 	}
 	spc := store.GetSpec()
 	if spc == nil {
-		return fmt.Errorf(errInvalidStoreSpec)
+		return nil, fmt.Errorf(errInvalidStoreSpec)
 	}
 	if spc.Provider == nil {
-		return fmt.Errorf(errInvalidStoreProv)
+		return nil, fmt.Errorf(errInvalidStoreProv)
 	}
 	g := spc.Provider.GCPSM
 	if p == nil {
-		return fmt.Errorf(errInvalidGCPProv)
+		return nil, fmt.Errorf(errInvalidGCPProv)
 	}
 	if g.Auth.SecretRef != nil {
 		if err := utils.ValidateReferentSecretSelector(store, g.Auth.SecretRef.SecretAccessKey); err != nil {
-			return fmt.Errorf(errInvalidAuthSecretRef, err)
+			return nil, fmt.Errorf(errInvalidAuthSecretRef, err)
 		}
 	}
 	if g.Auth.WorkloadIdentity != nil {
 		if err := utils.ValidateReferentServiceAccountSelector(store, g.Auth.WorkloadIdentity.ServiceAccountRef); err != nil {
-			return fmt.Errorf(errInvalidWISARef, err)
+			return nil, fmt.Errorf(errInvalidWISARef, err)
 		}
 	}
-	return nil
+	return nil, nil
 }
 
 func clusterProjectID(spec *esv1beta1.SecretStoreSpec) (string, error) {

+ 1 - 1
pkg/provider/gitlab/gitlab_test.go

@@ -873,7 +873,7 @@ func TestValidateStore(t *testing.T) {
 	}
 	p := Provider{}
 	for _, tc := range testCases {
-		err := p.ValidateStore(tc.store)
+		_, 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 {

+ 8 - 7
pkg/provider/gitlab/provider.go

@@ -19,6 +19,7 @@ import (
 
 	"github.com/xanzy/go-gitlab"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -94,32 +95,32 @@ func (g *gitlabBase) getClient(ctx context.Context, provider *esv1beta1.GitlabPr
 	return client, nil
 }
 
-func (g *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (g *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	gitlabSpec := storeSpec.Provider.Gitlab
 	accessToken := gitlabSpec.Auth.SecretRef.AccessToken
 	err := utils.ValidateSecretSelector(store, accessToken)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	if gitlabSpec.ProjectID == "" && len(gitlabSpec.GroupIDs) == 0 {
-		return fmt.Errorf("projectID and groupIDs must not both be empty")
+		return nil, fmt.Errorf("projectID and groupIDs must not both be empty")
 	}
 
 	if gitlabSpec.InheritFromGroups && len(gitlabSpec.GroupIDs) > 0 {
-		return fmt.Errorf("defining groupIDs and inheritFromGroups = true is not allowed")
+		return nil, fmt.Errorf("defining groupIDs and inheritFromGroups = true is not allowed")
 	}
 
 	if accessToken.Key == "" {
-		return fmt.Errorf("accessToken.key cannot be empty")
+		return nil, fmt.Errorf("accessToken.key cannot be empty")
 	}
 
 	if accessToken.Name == "" {
-		return fmt.Errorf("accessToken.name cannot be empty")
+		return nil, fmt.Errorf("accessToken.name cannot be empty")
 	}
 
-	return nil
+	return nil, nil
 }
 
 func init() {

+ 12 - 11
pkg/provider/ibm/provider.go

@@ -27,6 +27,7 @@ import (
 	"github.com/tidwall/gjson"
 	corev1 "k8s.io/api/core/v1"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/constants"
@@ -587,11 +588,11 @@ func (ibm *providerIBM) Validate() (esv1beta1.ValidationResult, error) {
 	return esv1beta1.ValidationResultReady, nil
 }
 
-func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) error {
+func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	ibmSpec := storeSpec.Provider.IBM
 	if ibmSpec.ServiceURL == nil {
-		return fmt.Errorf("serviceURL is required")
+		return nil, fmt.Errorf("serviceURL is required")
 	}
 
 	containerRef := ibmSpec.Auth.ContainerAuth
@@ -603,15 +604,15 @@ func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) error {
 	if missingContainerRef == missingSecretRef {
 		// since both are equal, if one is missing assume both are missing
 		if missingContainerRef {
-			return fmt.Errorf("missing auth method")
+			return nil, fmt.Errorf("missing auth method")
 		}
-		return fmt.Errorf("too many auth methods defined")
+		return nil, fmt.Errorf("too many auth methods defined")
 	}
 
 	if !missingContainerRef {
 		// catch undefined container auth profile
 		if containerRef.Profile == "" {
-			return fmt.Errorf("container auth profile cannot be empty")
+			return nil, fmt.Errorf("container auth profile cannot be empty")
 		}
 
 		// proceed with container auth
@@ -619,25 +620,25 @@ func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) error {
 			containerRef.TokenLocation = "/var/run/secrets/tokens/vault-token"
 		}
 		if _, err := os.Open(containerRef.TokenLocation); err != nil {
-			return fmt.Errorf("cannot read container auth token %s. %w", containerRef.TokenLocation, err)
+			return nil, fmt.Errorf("cannot read container auth token %s. %w", containerRef.TokenLocation, err)
 		}
-		return nil
+		return nil, nil
 	}
 
 	// proceed with API Key Auth validation
 	secretKeyRef := secretRef.SecretAPIKey
 	err := utils.ValidateSecretSelector(store, secretKeyRef)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	if secretKeyRef.Name == "" {
-		return fmt.Errorf("secretAPIKey.name cannot be empty")
+		return nil, fmt.Errorf("secretAPIKey.name cannot be empty")
 	}
 	if secretKeyRef.Key == "" {
-		return fmt.Errorf("secretAPIKey.key cannot be empty")
+		return nil, fmt.Errorf("secretAPIKey.key cannot be empty")
 	}
 
-	return nil
+	return nil, nil
 }
 
 // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite).

+ 4 - 4
pkg/provider/ibm/provider_test.go

@@ -185,7 +185,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		},
 	}
-	err := p.ValidateStore(store)
+	_, err := p.ValidateStore(store)
 	if err == nil {
 		t.Errorf(errExpectedErr)
 	} else if err.Error() != "serviceURL is required" {
@@ -193,7 +193,7 @@ func TestValidateStore(t *testing.T) {
 	}
 	url := "my-url"
 	store.Spec.Provider.IBM.ServiceURL = &url
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	if err == nil {
 		t.Errorf(errExpectedErr)
 	} else if err.Error() != "missing auth method" {
@@ -207,7 +207,7 @@ func TestValidateStore(t *testing.T) {
 			Namespace: &ns,
 		},
 	}
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	if err == nil {
 		t.Errorf(errExpectedErr)
 	} else if err.Error() != "namespace not allowed with namespaced SecretStore" {
@@ -230,7 +230,7 @@ func TestValidateStore(t *testing.T) {
 			},
 		},
 	}
-	err = p.ValidateStore(store)
+	_, err = p.ValidateStore(store)
 	expected := "cannot read container auth token"
 	if !ErrorContains(err, expected) {
 		t.Errorf("ProfileSelector test failed: %s, expected: '%s'", err.Error(), expected)

+ 9 - 8
pkg/provider/keepersecurity/provider.go

@@ -20,6 +20,7 @@ import (
 	ksm "github.com/keeper-security/secrets-manager-go/core"
 	"github.com/keeper-security/secrets-manager-go/core/logger"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -82,32 +83,32 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 	return client, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	if store == nil {
-		return fmt.Errorf(errKeeperSecurityStore, store)
+		return nil, fmt.Errorf(errKeeperSecurityStore, store)
 	}
 	spc := store.GetSpec()
 	if spc == nil {
-		return fmt.Errorf(errKeeperSecurityNilSpec)
+		return nil, fmt.Errorf(errKeeperSecurityNilSpec)
 	}
 	if spc.Provider == nil {
-		return fmt.Errorf(errKeeperSecurityNilSpecProvider)
+		return nil, fmt.Errorf(errKeeperSecurityNilSpecProvider)
 	}
 	if spc.Provider.KeeperSecurity == nil {
-		return fmt.Errorf(errKeeperSecurityNilSpecProviderKeeperSecurity)
+		return nil, fmt.Errorf(errKeeperSecurityNilSpecProviderKeeperSecurity)
 	}
 
 	// check mandatory fields
 	config := spc.Provider.KeeperSecurity
 
 	if err := utils.ValidateSecretSelector(store, config.Auth); err != nil {
-		return fmt.Errorf(errKeeperSecurityStoreMissingAuth)
+		return nil, fmt.Errorf(errKeeperSecurityStoreMissingAuth)
 	}
 	if config.FolderID == "" {
-		return fmt.Errorf(errKeeperSecurityStoreMissingFolderID)
+		return nil, fmt.Errorf(errKeeperSecurityStoreMissingFolderID)
 	}
 
-	return nil
+	return nil, nil
 }
 
 func getKeeperSecurityAuth(ctx context.Context, store *esv1beta1.KeeperSecurityProvider, kube kclient.Client, storeKind, namespace string) (string, error) {

+ 12 - 11
pkg/provider/kubernetes/validate.go

@@ -19,6 +19,7 @@ import (
 
 	authv1 "k8s.io/api/authorization/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/constants"
@@ -26,45 +27,45 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/utils"
 )
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	k8sSpec := storeSpec.Provider.Kubernetes
 	if k8sSpec.Server.CABundle == nil && k8sSpec.Server.CAProvider == nil {
-		return fmt.Errorf("a CABundle or CAProvider is required")
+		return nil, fmt.Errorf("a CABundle or CAProvider is required")
 	}
 	if store.GetObjectKind().GroupVersionKind().Kind == esv1beta1.ClusterSecretStoreKind &&
 		k8sSpec.Server.CAProvider != nil &&
 		k8sSpec.Server.CAProvider.Namespace == nil {
-		return fmt.Errorf("CAProvider.namespace must not be empty with ClusterSecretStore")
+		return nil, fmt.Errorf("CAProvider.namespace must not be empty with ClusterSecretStore")
 	}
 	if k8sSpec.Auth.Cert != nil {
 		if k8sSpec.Auth.Cert.ClientCert.Name == "" {
-			return fmt.Errorf("ClientCert.Name cannot be empty")
+			return nil, fmt.Errorf("ClientCert.Name cannot be empty")
 		}
 		if k8sSpec.Auth.Cert.ClientCert.Key == "" {
-			return fmt.Errorf("ClientCert.Key cannot be empty")
+			return nil, fmt.Errorf("ClientCert.Key cannot be empty")
 		}
 		if err := utils.ValidateSecretSelector(store, k8sSpec.Auth.Cert.ClientCert); err != nil {
-			return err
+			return nil, err
 		}
 	}
 	if k8sSpec.Auth.Token != nil {
 		if k8sSpec.Auth.Token.BearerToken.Name == "" {
-			return fmt.Errorf("BearerToken.Name cannot be empty")
+			return nil, fmt.Errorf("BearerToken.Name cannot be empty")
 		}
 		if k8sSpec.Auth.Token.BearerToken.Key == "" {
-			return fmt.Errorf("BearerToken.Key cannot be empty")
+			return nil, fmt.Errorf("BearerToken.Key cannot be empty")
 		}
 		if err := utils.ValidateSecretSelector(store, k8sSpec.Auth.Token.BearerToken); err != nil {
-			return err
+			return nil, err
 		}
 	}
 	if k8sSpec.Auth.ServiceAccount != nil {
 		if err := utils.ValidateReferentServiceAccountSelector(store, *k8sSpec.Auth.ServiceAccount); err != nil {
-			return err
+			return nil, err
 		}
 	}
-	return nil
+	return nil, nil
 }
 
 func (c *Client) Validate() (esv1beta1.ValidationResult, error) {

+ 1 - 1
pkg/provider/kubernetes/validate_test.go

@@ -245,7 +245,7 @@ func TestValidateStore(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			k := &Provider{}
-			if err := k.ValidateStore(tt.store); (err != nil) != tt.wantErr {
+			if _, err := k.ValidateStore(tt.store); (err != nil) != tt.wantErr {
 				t.Errorf("ProviderKubernetes.ValidateStore() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})

+ 3 - 2
pkg/provider/onepassword/onepassword.go

@@ -24,6 +24,7 @@ import (
 	"github.com/1Password/connect-sdk-go/onepassword"
 	corev1 "k8s.io/api/core/v1"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/find"
@@ -111,8 +112,8 @@ func (provider *ProviderOnePassword) NewClient(ctx context.Context, store esv1be
 }
 
 // ValidateStore checks if the provided store is valid.
-func (provider *ProviderOnePassword) ValidateStore(store esv1beta1.GenericStore) error {
-	return validateStore(store)
+func (provider *ProviderOnePassword) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, validateStore(store)
 }
 
 func validateStore(store esv1beta1.GenericStore) error {

+ 15 - 14
pkg/provider/oracle/oracle.go

@@ -35,6 +35,7 @@ import (
 	"k8s.io/client-go/kubernetes"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -477,71 +478,71 @@ func (vms *VaultManagementService) Validate() (esv1beta1.ValidationResult, error
 	return esv1beta1.ValidationResultReady, nil
 }
 
-func (vms *VaultManagementService) ValidateStore(store esv1beta1.GenericStore) error {
+func (vms *VaultManagementService) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	storeSpec := store.GetSpec()
 	oracleSpec := storeSpec.Provider.Oracle
 
 	vault := oracleSpec.Vault
 	if vault == "" {
-		return fmt.Errorf("vault cannot be empty")
+		return nil, fmt.Errorf("vault cannot be empty")
 	}
 
 	region := oracleSpec.Region
 	if region == "" {
-		return fmt.Errorf("region cannot be empty")
+		return nil, fmt.Errorf("region cannot be empty")
 	}
 
 	auth := oracleSpec.Auth
 	if auth == nil {
-		return nil
+		return nil, nil
 	}
 
 	user := oracleSpec.Auth.User
 	if user == "" {
-		return fmt.Errorf("user cannot be empty")
+		return nil, fmt.Errorf("user cannot be empty")
 	}
 
 	tenant := oracleSpec.Auth.Tenancy
 	if tenant == "" {
-		return fmt.Errorf("tenant cannot be empty")
+		return nil, fmt.Errorf("tenant cannot be empty")
 	}
 	privateKey := oracleSpec.Auth.SecretRef.PrivateKey
 
 	if privateKey.Name == "" {
-		return fmt.Errorf("privateKey.name cannot be empty")
+		return nil, fmt.Errorf("privateKey.name cannot be empty")
 	}
 
 	if privateKey.Key == "" {
-		return fmt.Errorf("privateKey.key cannot be empty")
+		return nil, fmt.Errorf("privateKey.key cannot be empty")
 	}
 
 	err := utils.ValidateSecretSelector(store, privateKey)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	fingerprint := oracleSpec.Auth.SecretRef.Fingerprint
 
 	if fingerprint.Name == "" {
-		return fmt.Errorf("fingerprint.name cannot be empty")
+		return nil, fmt.Errorf("fingerprint.name cannot be empty")
 	}
 
 	if fingerprint.Key == "" {
-		return fmt.Errorf("fingerprint.key cannot be empty")
+		return nil, fmt.Errorf("fingerprint.key cannot be empty")
 	}
 
 	err = utils.ValidateSecretSelector(store, fingerprint)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	if oracleSpec.ServiceAccountRef != nil {
 		if err := utils.ValidateReferentServiceAccountSelector(store, *oracleSpec.ServiceAccountRef); err != nil {
-			return fmt.Errorf("invalid ServiceAccountRef: %w", err)
+			return nil, fmt.Errorf("invalid ServiceAccountRef: %w", err)
 		}
 	}
 
-	return nil
+	return nil, nil
 }
 
 func (vms *VaultManagementService) getWorkloadIdentityProvider(store esv1beta1.GenericStore, serviceAcccountRef *esmeta.ServiceAccountSelector, region, namespace string) (configurationProvider common.ConfigurationProvider, err error) {

+ 1 - 1
pkg/provider/oracle/oracle_test.go

@@ -308,7 +308,7 @@ func TestValidateStore(t *testing.T) {
 	}
 	p := VaultManagementService{}
 	for _, tc := range testCases {
-		err := p.ValidateStore(tc.store)
+		_, 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 {

+ 3 - 2
pkg/provider/scaleway/provider.go

@@ -23,6 +23,7 @@ import (
 	"github.com/scaleway/scaleway-sdk-go/validation"
 	ctrl "sigs.k8s.io/controller-runtime"
 	kubeClient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	"github.com/external-secrets/external-secrets/pkg/utils"
@@ -159,9 +160,9 @@ func getConfig(store esv1beta1.GenericStore) (*esv1beta1.ScalewayProvider, error
 	return cfg, nil
 }
 
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	_, err := getConfig(store)
-	return err
+	return nil, err
 }
 
 func init() {

+ 3 - 2
pkg/provider/senhasegura/provider.go

@@ -20,6 +20,7 @@ import (
 	"net/url"
 
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	senhaseguraAuth "github.com/external-secrets/external-secrets/pkg/provider/senhasegura/auth"
@@ -70,8 +71,8 @@ func (p *Provider) NewClient(ctx context.Context, store esv1beta1.GenericStore,
 // Validate store using Validating webhook during secret store creating
 // Checks here are usually the best experience for the user, as the SecretStore will not be created until it is a 'valid' one.
 // https://github.com/external-secrets/external-secrets/pull/830#discussion_r833278518
-func (p *Provider) ValidateStore(store esv1beta1.GenericStore) error {
-	return validateStore(store)
+func (p *Provider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, validateStore(store)
 }
 
 func validateStore(store esv1beta1.GenericStore) error {

+ 3 - 2
pkg/provider/testing/fake/fake.go

@@ -19,6 +19,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 )
@@ -118,8 +119,8 @@ func (v *Client) Validate() (esv1beta1.ValidationResult, error) {
 	return esv1beta1.ValidationResultReady, nil
 }
 
-func (v *Client) ValidateStore(_ esv1beta1.GenericStore) error {
-	return nil
+func (v *Client) ValidateStore(_ esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, nil
 }
 
 // WithGetSecretMap wraps the secret data map returned by this fake provider.

+ 27 - 26
pkg/provider/vault/vault.go

@@ -49,6 +49,7 @@ import (
 	ctrl "sigs.k8s.io/controller-runtime"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
 	ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -330,120 +331,120 @@ func (c *Connector) initClient(ctx context.Context, vStore *client, client util.
 	return vStore, nil
 }
 
-func (c *Connector) ValidateStore(store esv1beta1.GenericStore) error {
+func (c *Connector) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	if store == nil {
-		return fmt.Errorf(errInvalidStore)
+		return nil, fmt.Errorf(errInvalidStore)
 	}
 	spc := store.GetSpec()
 	if spc == nil {
-		return fmt.Errorf(errInvalidStoreSpec)
+		return nil, fmt.Errorf(errInvalidStoreSpec)
 	}
 	if spc.Provider == nil {
-		return fmt.Errorf(errInvalidStoreProv)
+		return nil, fmt.Errorf(errInvalidStoreProv)
 	}
 	p := spc.Provider.Vault
 	if p == nil {
-		return fmt.Errorf(errInvalidVaultProv)
+		return nil, fmt.Errorf(errInvalidVaultProv)
 	}
 	if p.Auth.AppRole != nil {
 		// check SecretRef for valid configuration
 		if err := utils.ValidateReferentSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
-			return fmt.Errorf(errInvalidAppRoleSec, err)
+			return nil, fmt.Errorf(errInvalidAppRoleSec, err)
 		}
 
 		// prefer .auth.appRole.roleId, fallback to .auth.appRole.roleRef, give up after that.
 		if p.Auth.AppRole.RoleID == "" { // prevents further RoleID tests if .auth.appRole.roleId is given
 			if p.Auth.AppRole.RoleRef != nil { // check RoleRef for valid configuration
 				if err := utils.ValidateReferentSecretSelector(store, *p.Auth.AppRole.RoleRef); err != nil {
-					return fmt.Errorf(errInvalidAppRoleRef, err)
+					return nil, fmt.Errorf(errInvalidAppRoleRef, err)
 				}
 			} else { // we ran out of ways to get RoleID. return an appropriate error
-				return fmt.Errorf(errInvalidAppRoleID)
+				return nil, fmt.Errorf(errInvalidAppRoleID)
 			}
 		}
 	}
 	if p.Auth.Cert != nil {
 		if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
-			return fmt.Errorf(errInvalidClientCert, err)
+			return nil, fmt.Errorf(errInvalidClientCert, err)
 		}
 		if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
-			return fmt.Errorf(errInvalidCertSec, err)
+			return nil, fmt.Errorf(errInvalidCertSec, err)
 		}
 	}
 	if p.Auth.Jwt != nil {
 		if p.Auth.Jwt.SecretRef != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
-				return fmt.Errorf(errInvalidJwtSec, err)
+				return nil, fmt.Errorf(errInvalidJwtSec, err)
 			}
 		} else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
 			if err := utils.ValidateReferentServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
-				return fmt.Errorf(errInvalidJwtK8sSA, err)
+				return nil, fmt.Errorf(errInvalidJwtK8sSA, err)
 			}
 		} else {
-			return fmt.Errorf(errJwtNoTokenSource)
+			return nil, fmt.Errorf(errJwtNoTokenSource)
 		}
 	}
 	if p.Auth.Kubernetes != nil {
 		if p.Auth.Kubernetes.ServiceAccountRef != nil {
 			if err := utils.ValidateReferentServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
-				return fmt.Errorf(errInvalidKubeSA, err)
+				return nil, fmt.Errorf(errInvalidKubeSA, err)
 			}
 		}
 		if p.Auth.Kubernetes.SecretRef != nil {
 			if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
-				return fmt.Errorf(errInvalidKubeSec, err)
+				return nil, fmt.Errorf(errInvalidKubeSec, err)
 			}
 		}
 	}
 	if p.Auth.Ldap != nil {
 		if err := utils.ValidateReferentSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
-			return fmt.Errorf(errInvalidLdapSec, err)
+			return nil, fmt.Errorf(errInvalidLdapSec, err)
 		}
 	}
 	if p.Auth.UserPass != nil {
 		if err := utils.ValidateReferentSecretSelector(store, p.Auth.UserPass.SecretRef); err != nil {
-			return fmt.Errorf(errInvalidUserPassSec, err)
+			return nil, fmt.Errorf(errInvalidUserPassSec, err)
 		}
 	}
 	if p.Auth.TokenSecretRef != nil {
 		if err := utils.ValidateReferentSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
-			return fmt.Errorf(errInvalidTokenRef, err)
+			return nil, fmt.Errorf(errInvalidTokenRef, err)
 		}
 	}
 	if p.Auth.Iam != nil {
 		if p.Auth.Iam.JWTAuth != nil {
 			if p.Auth.Iam.JWTAuth.ServiceAccountRef != nil {
 				if err := utils.ValidateReferentServiceAccountSelector(store, *p.Auth.Iam.JWTAuth.ServiceAccountRef); err != nil {
-					return fmt.Errorf(errInvalidTokenRef, err)
+					return nil, fmt.Errorf(errInvalidTokenRef, err)
 				}
 			}
 		}
 
 		if p.Auth.Iam.SecretRef != nil {
 			if err := utils.ValidateReferentSecretSelector(store, p.Auth.Iam.SecretRef.AccessKeyID); err != nil {
-				return fmt.Errorf(errInvalidTokenRef, err)
+				return nil, fmt.Errorf(errInvalidTokenRef, err)
 			}
 			if err := utils.ValidateReferentSecretSelector(store, p.Auth.Iam.SecretRef.SecretAccessKey); err != nil {
-				return fmt.Errorf(errInvalidTokenRef, err)
+				return nil, fmt.Errorf(errInvalidTokenRef, err)
 			}
 			if p.Auth.Iam.SecretRef.SessionToken != nil {
 				if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Iam.SecretRef.SessionToken); err != nil {
-					return fmt.Errorf(errInvalidTokenRef, err)
+					return nil, fmt.Errorf(errInvalidTokenRef, err)
 				}
 			}
 		}
 	}
 	if p.ClientTLS.CertSecretRef != nil && p.ClientTLS.KeySecretRef != nil {
 		if err := utils.ValidateReferentSecretSelector(store, *p.ClientTLS.CertSecretRef); err != nil {
-			return fmt.Errorf(errInvalidClientTLSCert, err)
+			return nil, fmt.Errorf(errInvalidClientTLSCert, err)
 		}
 		if err := utils.ValidateReferentSecretSelector(store, *p.ClientTLS.KeySecretRef); err != nil {
-			return fmt.Errorf(errInvalidClientTLSSecret, err)
+			return nil, fmt.Errorf(errInvalidClientTLSSecret, err)
 		}
 	} else if p.ClientTLS.CertSecretRef != nil || p.ClientTLS.KeySecretRef != nil {
-		return errors.New(errInvalidClientTLS)
+		return nil, errors.New(errInvalidClientTLS)
 	}
-	return nil
+	return nil, nil
 }
 
 func (v *client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushSecretRemoteRef) error {

+ 1 - 1
pkg/provider/vault/vault_test.go

@@ -1785,7 +1785,7 @@ func TestValidateStore(t *testing.T) {
 					},
 				},
 			}
-			if err := c.ValidateStore(store); (err != nil) != tt.wantErr {
+			if _, err := c.ValidateStore(store); (err != nil) != tt.wantErr {
 				t.Errorf("connector.ValidateStore() error = %v, wantErr %v", err, tt.wantErr)
 			}
 		})

+ 3 - 2
pkg/provider/webhook/webhook.go

@@ -31,6 +31,7 @@ import (
 	"github.com/PaesslerAG/jsonpath"
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -88,8 +89,8 @@ func (p *Provider) NewClient(_ context.Context, store esv1beta1.GenericStore, ku
 	return whClient, nil
 }
 
-func (p *Provider) ValidateStore(_ esv1beta1.GenericStore) error {
-	return nil
+func (p *Provider) ValidateStore(_ esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, nil
 }
 
 func getProvider(store esv1beta1.GenericStore) (*esv1beta1.WebhookProvider, error) {

+ 4 - 3
pkg/provider/yandex/common/provider.go

@@ -25,6 +25,7 @@ import (
 	"github.com/go-logr/logr"
 	"github.com/yandex-cloud/go-sdk/iamkey"
 	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
 	esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
@@ -230,10 +231,10 @@ func (p *YandexCloudProvider) CleanUpIamTokenMap() {
 	}
 }
 
-func (p *YandexCloudProvider) ValidateStore(store esv1beta1.GenericStore) error {
+func (p *YandexCloudProvider) ValidateStore(store esv1beta1.GenericStore) (admission.Warnings, error) {
 	_, err := p.adaptInputFunc(store) // adaptInputFunc validates the input store
 	if err != nil {
-		return err
+		return nil, err
 	}
-	return nil
+	return nil, nil
 }