Browse Source

Merge branch 'external-secrets:main' into feature/validate-gitlab-provider

Pedro Carmezim 4 years ago
parent
commit
8dd947f9ba

+ 10 - 10
pkg/controllers/externalsecret/externalsecret_controller.go

@@ -46,10 +46,8 @@ import (
 )
 )
 
 
 const (
 const (
-	requeueAfter = time.Second * 30
-
-	fieldOwner = "external-secrets"
-
+	requeueAfter             = time.Second * 30
+	fieldOwnerTemplate       = "externalsecrets.external-secrets.io/%v"
 	errGetES                 = "could not get ExternalSecret"
 	errGetES                 = "could not get ExternalSecret"
 	errConvert               = "could not apply conversion strategy to keys: %v"
 	errConvert               = "could not apply conversion strategy to keys: %v"
 	errUpdateSecret          = "could not update Secret"
 	errUpdateSecret          = "could not update Secret"
@@ -281,7 +279,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 
 
 		// diff existing keys
 		// diff existing keys
 		if externalSecret.Spec.Target.DeletionPolicy == esv1beta1.DeletionPolicyMerge {
 		if externalSecret.Spec.Target.DeletionPolicy == esv1beta1.DeletionPolicyMerge {
-			keys, err := getManagedKeys(&existingSecret)
+			keys, err := getManagedKeys(&existingSecret, externalSecret.Name)
 			if err != nil {
 			if err != nil {
 				return err
 				return err
 			}
 			}
@@ -297,7 +295,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	// nolint
 	// nolint
 	switch externalSecret.Spec.Target.CreationPolicy {
 	switch externalSecret.Spec.Target.CreationPolicy {
 	case esv1beta1.CreatePolicyMerge:
 	case esv1beta1.CreatePolicyMerge:
-		err = patchSecret(ctx, r.Client, r.Scheme, secret, mutationFunc)
+		err = patchSecret(ctx, r.Client, r.Scheme, secret, mutationFunc, externalSecret.Name)
 	case esv1beta1.CreatePolicyNone:
 	case esv1beta1.CreatePolicyNone:
 		log.V(1).Info("secret creation skipped due to creationPolicy=None")
 		log.V(1).Info("secret creation skipped due to creationPolicy=None")
 		err = nil
 		err = nil
@@ -332,7 +330,8 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu
 	}, nil
 	}, nil
 }
 }
 
 
-func patchSecret(ctx context.Context, c client.Client, scheme *runtime.Scheme, secret *v1.Secret, mutationFunc func() error) error {
+func patchSecret(ctx context.Context, c client.Client, scheme *runtime.Scheme, secret *v1.Secret, mutationFunc func() error, fieldOwner string) error {
+	fqdn := fmt.Sprintf(fieldOwnerTemplate, fieldOwner)
 	err := c.Get(ctx, client.ObjectKeyFromObject(secret), secret.DeepCopy())
 	err := c.Get(ctx, client.ObjectKeyFromObject(secret), secret.DeepCopy())
 	if apierrors.IsNotFound(err) {
 	if apierrors.IsNotFound(err) {
 		return fmt.Errorf(errPolicyMergeNotFound, secret.Name)
 		return fmt.Errorf(errPolicyMergeNotFound, secret.Name)
@@ -366,17 +365,18 @@ func patchSecret(ctx context.Context, c client.Client, scheme *runtime.Scheme, s
 
 
 	// we're not able to resolve conflicts so we force ownership
 	// we're not able to resolve conflicts so we force ownership
 	// see: https://kubernetes.io/docs/reference/using-api/server-side-apply/#using-server-side-apply-in-a-controller
 	// see: https://kubernetes.io/docs/reference/using-api/server-side-apply/#using-server-side-apply-in-a-controller
-	err = c.Patch(ctx, secret, client.Apply, client.FieldOwner(fieldOwner), client.ForceOwnership)
+	err = c.Patch(ctx, secret, client.Apply, client.FieldOwner(fqdn), client.ForceOwnership)
 	if err != nil {
 	if err != nil {
 		return fmt.Errorf(errPolicyMergePatch, secret.Name, err)
 		return fmt.Errorf(errPolicyMergePatch, secret.Name, err)
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
-func getManagedKeys(secret *v1.Secret) ([]string, error) {
+func getManagedKeys(secret *v1.Secret, fieldOwner string) ([]string, error) {
+	fqdn := fmt.Sprintf(fieldOwnerTemplate, fieldOwner)
 	var keys []string
 	var keys []string
 	for _, v := range secret.ObjectMeta.ManagedFields {
 	for _, v := range secret.ObjectMeta.ManagedFields {
-		if v.Manager != fieldOwner {
+		if v.Manager != fqdn {
 			continue
 			continue
 		}
 		}
 		fields := make(map[string]interface{})
 		fields := make(map[string]interface{})

+ 5 - 4
pkg/controllers/externalsecret/externalsecret_controller_test.go

@@ -131,6 +131,7 @@ var _ = Describe("Kind=secret existence logic", func() {
 var _ = Describe("ExternalSecret controller", func() {
 var _ = Describe("ExternalSecret controller", func() {
 	const (
 	const (
 		ExternalSecretName             = "test-es"
 		ExternalSecretName             = "test-es"
+		ExternalSecretFQDN             = "externalsecrets.external-secrets.io/test-es"
 		ExternalSecretStore            = "test-store"
 		ExternalSecretStore            = "test-store"
 		ExternalSecretTargetSecretName = "test-secret"
 		ExternalSecretTargetSecretName = "test-secret"
 		FakeManager                    = "fake.manager"
 		FakeManager                    = "fake.manager"
@@ -308,11 +309,11 @@ var _ = Describe("ExternalSecret controller", func() {
 			for k, v := range es.ObjectMeta.Annotations {
 			for k, v := range es.ObjectMeta.Annotations {
 				Expect(secret.ObjectMeta.Annotations).To(HaveKeyWithValue(k, v))
 				Expect(secret.ObjectMeta.Annotations).To(HaveKeyWithValue(k, v))
 			}
 			}
-			Expect(ctest.HasOwnerRef(secret.ObjectMeta, "ExternalSecret", ExternalSecretName)).To(BeFalse())
+			Expect(ctest.HasOwnerRef(secret.ObjectMeta, "ExternalSecret", ExternalSecretFQDN)).To(BeFalse())
 			Expect(secret.ObjectMeta.ManagedFields).To(HaveLen(2))
 			Expect(secret.ObjectMeta.ManagedFields).To(HaveLen(2))
 			Expect(ctest.HasFieldOwnership(
 			Expect(ctest.HasFieldOwnership(
 				secret.ObjectMeta,
 				secret.ObjectMeta,
-				"external-secrets",
+				ExternalSecretFQDN,
 				fmt.Sprintf("{\"f:data\":{\"f:targetProperty\":{}},\"f:immutable\":{},\"f:metadata\":{\"f:annotations\":{\"f:%s\":{}}}}", esv1beta1.AnnotationDataHash)),
 				fmt.Sprintf("{\"f:data\":{\"f:targetProperty\":{}},\"f:immutable\":{},\"f:metadata\":{\"f:annotations\":{\"f:%s\":{}}}}", esv1beta1.AnnotationDataHash)),
 			).To(BeTrue())
 			).To(BeTrue())
 			Expect(ctest.HasFieldOwnership(secret.ObjectMeta, FakeManager, "{\"f:data\":{\".\":{},\"f:pre-existing-key\":{}},\"f:type\":{}}")).To(BeTrue())
 			Expect(ctest.HasFieldOwnership(secret.ObjectMeta, FakeManager, "{\"f:data\":{\".\":{},\"f:pre-existing-key\":{}},\"f:type\":{}}")).To(BeTrue())
@@ -408,9 +409,9 @@ var _ = Describe("ExternalSecret controller", func() {
 			Expect(string(secret.Data[existingKey])).To(Equal(secretVal))
 			Expect(string(secret.Data[existingKey])).To(Equal(secretVal))
 
 
 			// check owner/managedFields
 			// check owner/managedFields
-			Expect(ctest.HasOwnerRef(secret.ObjectMeta, "ExternalSecret", ExternalSecretName)).To(BeFalse())
+			Expect(ctest.HasOwnerRef(secret.ObjectMeta, "ExternalSecret", ExternalSecretFQDN)).To(BeFalse())
 			Expect(secret.ObjectMeta.ManagedFields).To(HaveLen(2))
 			Expect(secret.ObjectMeta.ManagedFields).To(HaveLen(2))
-			Expect(ctest.HasFieldOwnership(secret.ObjectMeta, "external-secrets", "{\"f:data\":{\"f:targetProperty\":{}},\"f:immutable\":{},\"f:metadata\":{\"f:annotations\":{\"f:reconcile.external-secrets.io/data-hash\":{}}}}")).To(BeTrue())
+			Expect(ctest.HasFieldOwnership(secret.ObjectMeta, ExternalSecretFQDN, "{\"f:data\":{\"f:targetProperty\":{}},\"f:immutable\":{},\"f:metadata\":{\"f:annotations\":{\"f:reconcile.external-secrets.io/data-hash\":{}}}}")).To(BeTrue())
 		}
 		}
 	}
 	}
 
 

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

@@ -32,6 +32,10 @@ const (
 	defaultAPIUrl = "https://api.akeyless.io"
 	defaultAPIUrl = "https://api.akeyless.io"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &Akeyless{}
+var _ esv1beta1.Provider = &Provider{}
+
 // Provider satisfies the provider interface.
 // Provider satisfies the provider interface.
 type Provider struct{}
 type Provider struct{}
 
 

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

@@ -52,6 +52,10 @@ type Client struct {
 	accessKey []byte
 	accessKey []byte
 }
 }
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &KeyManagementService{}
+var _ esv1beta1.Provider = &KeyManagementService{}
+
 type KeyManagementService struct {
 type KeyManagementService struct {
 	Client SMInterface
 	Client SMInterface
 	url    string
 	url    string

+ 12 - 0
pkg/provider/aws/parameterstore/parameterstore.go

@@ -18,6 +18,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
+	"strings"
 
 
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws"
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/aws/session"
@@ -31,6 +32,9 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/utils"
 	"github.com/external-secrets/external-secrets/pkg/utils"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &ParameterStore{}
+
 // ParameterStore is a provider for AWS ParameterStore.
 // ParameterStore is a provider for AWS ParameterStore.
 type ParameterStore struct {
 type ParameterStore struct {
 	sess   *session.Session
 	sess   *session.Session
@@ -184,6 +188,14 @@ func (pm *ParameterStore) GetSecret(ctx context.Context, ref esv1beta1.ExternalS
 		}
 		}
 		return nil, fmt.Errorf("invalid secret received. parameter value is nil for key: %s", ref.Key)
 		return nil, fmt.Errorf("invalid secret received. parameter value is nil for key: %s", ref.Key)
 	}
 	}
+	idx := strings.Index(ref.Property, ".")
+	if idx > 0 {
+		refProperty := strings.ReplaceAll(ref.Property, ".", "\\.")
+		val := gjson.Get(*out.Parameter.Value, refProperty)
+		if val.Exists() {
+			return []byte(val.String()), nil
+		}
+	}
 	val := gjson.Get(*out.Parameter.Value, ref.Property)
 	val := gjson.Get(*out.Parameter.Value, ref.Property)
 	if !val.Exists() {
 	if !val.Exists() {
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)

+ 7 - 0
pkg/provider/aws/parameterstore/parameterstore_test.go

@@ -96,6 +96,12 @@ func TestGetSecret(t *testing.T) {
 		pstc.expectedSecret = "bang"
 		pstc.expectedSecret = "bang"
 		pstc.remoteRef.Property = "/shmoo"
 		pstc.remoteRef.Property = "/shmoo"
 	}
 	}
+	// good case: extract property with `.`
+	setExtractPropertyWithDot := func(pstc *parameterstoreTestCase) {
+		pstc.apiOutput.Parameter.Value = aws.String(`{"/shmoo.boom": "bang"}`)
+		pstc.expectedSecret = "bang"
+		pstc.remoteRef.Property = "/shmoo.boom"
+	}
 
 
 	// bad case: missing property
 	// bad case: missing property
 	setMissingProperty := func(pstc *parameterstoreTestCase) {
 	setMissingProperty := func(pstc *parameterstoreTestCase) {
@@ -131,6 +137,7 @@ func TestGetSecret(t *testing.T) {
 		makeValidParameterStoreTestCaseCustom(setPropertyFail),
 		makeValidParameterStoreTestCaseCustom(setPropertyFail),
 		makeValidParameterStoreTestCaseCustom(setParameterValueNil),
 		makeValidParameterStoreTestCaseCustom(setParameterValueNil),
 		makeValidParameterStoreTestCaseCustom(setAPIError),
 		makeValidParameterStoreTestCaseCustom(setAPIError),
+		makeValidParameterStoreTestCaseCustom(setExtractPropertyWithDot),
 	}
 	}
 
 
 	ps := ParameterStore{}
 	ps := ParameterStore{}

+ 3 - 0
pkg/provider/aws/provider.go

@@ -29,6 +29,9 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/utils"
 	"github.com/external-secrets/external-secrets/pkg/utils"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.Provider = &Provider{}
+
 // Provider satisfies the provider interface.
 // Provider satisfies the provider interface.
 type Provider struct{}
 type Provider struct{}
 
 

+ 13 - 1
pkg/provider/aws/secretsmanager/secretsmanager.go

@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"errors"
 	"errors"
 	"fmt"
 	"fmt"
+	"strings"
 
 
 	"github.com/aws/aws-sdk-go/aws/session"
 	"github.com/aws/aws-sdk-go/aws/session"
 	awssm "github.com/aws/aws-sdk-go/service/secretsmanager"
 	awssm "github.com/aws/aws-sdk-go/service/secretsmanager"
@@ -32,6 +33,9 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/utils"
 	"github.com/external-secrets/external-secrets/pkg/utils"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &SecretsManager{}
+
 // SecretsManager is a provider for AWS SecretsManager.
 // SecretsManager is a provider for AWS SecretsManager.
 type SecretsManager struct {
 type SecretsManager struct {
 	sess   *session.Session
 	sess   *session.Session
@@ -238,7 +242,15 @@ func (sm *SecretsManager) GetSecret(ctx context.Context, ref esv1beta1.ExternalS
 	if secretOut.SecretBinary != nil {
 	if secretOut.SecretBinary != nil {
 		payload = string(secretOut.SecretBinary)
 		payload = string(secretOut.SecretBinary)
 	}
 	}
-
+	// We need to search if a given key with a . exists before using gjson operations.
+	idx := strings.Index(ref.Property, ".")
+	if idx > 0 {
+		refProperty := strings.ReplaceAll(ref.Property, ".", "\\.")
+		val := gjson.Get(payload, refProperty)
+		if val.Exists() {
+			return []byte(val.String()), nil
+		}
+	}
 	val := gjson.Get(payload, ref.Property)
 	val := gjson.Get(payload, ref.Property)
 	if !val.Exists() {
 	if !val.Exists() {
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
 		return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)

+ 8 - 0
pkg/provider/aws/secretsmanager/secretsmanager_test.go

@@ -147,6 +147,13 @@ func TestSecretsManagerGetSecret(t *testing.T) {
 		smtc.remoteRef.Property = "foobar.baz"
 		smtc.remoteRef.Property = "foobar.baz"
 		smtc.expectedSecret = "nestedval"
 		smtc.expectedSecret = "nestedval"
 	}
 	}
+	// good case: secretOut.SecretBinary no JSON parsing if name on key
+	setSecretValueWithDot := func(smtc *secretsManagerTestCase) {
+		smtc.apiOutput.SecretString = nil
+		smtc.apiOutput.SecretBinary = []byte(`{"foobar.baz":"nestedval"}`)
+		smtc.remoteRef.Property = "foobar.baz"
+		smtc.expectedSecret = "nestedval"
+	}
 
 
 	// good case: custom version set
 	// good case: custom version set
 	setCustomVersion := func(smtc *secretsManagerTestCase) {
 	setCustomVersion := func(smtc *secretsManagerTestCase) {
@@ -165,6 +172,7 @@ func TestSecretsManagerGetSecret(t *testing.T) {
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryNotSecretString),
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryNotSecretString),
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryAndSecretStringToNil),
 		makeValidSecretsManagerTestCaseCustom(setSecretBinaryAndSecretStringToNil),
 		makeValidSecretsManagerTestCaseCustom(setNestedSecretValueJSONParsing),
 		makeValidSecretsManagerTestCaseCustom(setNestedSecretValueJSONParsing),
+		makeValidSecretsManagerTestCaseCustom(setSecretValueWithDot),
 		makeValidSecretsManagerTestCaseCustom(setCustomVersion),
 		makeValidSecretsManagerTestCaseCustom(setCustomVersion),
 		makeValidSecretsManagerTestCaseCustom(setAPIErr),
 		makeValidSecretsManagerTestCaseCustom(setAPIErr),
 	}
 	}

+ 4 - 0
pkg/provider/azure/keyvault/keyvault.go

@@ -79,6 +79,10 @@ const (
 	errMissingSAAnnotation    = "missing service account annotation: %s"
 	errMissingSAAnnotation    = "missing service account annotation: %s"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &Azure{}
+var _ esv1beta1.Provider = &Azure{}
+
 // interface to keyvault.BaseClient.
 // interface to keyvault.BaseClient.
 type SecretClient interface {
 type SecretClient interface {
 	GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error)
 	GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error)

+ 6 - 3
pkg/provider/gcp/secretmanager/secretsmanager.go

@@ -41,9 +41,8 @@ import (
 )
 )
 
 
 const (
 const (
-	CloudPlatformRole = "https://www.googleapis.com/auth/cloud-platform"
-	defaultVersion    = "latest"
-
+	CloudPlatformRole                         = "https://www.googleapis.com/auth/cloud-platform"
+	defaultVersion                            = "latest"
 	errGCPSMStore                             = "received invalid GCPSM SecretStore resource"
 	errGCPSMStore                             = "received invalid GCPSM SecretStore resource"
 	errUnableGetCredentials                   = "unable to get credentials: %w"
 	errUnableGetCredentials                   = "unable to get credentials: %w"
 	errClientClose                            = "unable to close SecretManager client: %w"
 	errClientClose                            = "unable to close SecretManager client: %w"
@@ -84,6 +83,10 @@ type GoogleSecretManagerClient interface {
 */
 */
 var useMu = sync.Mutex{}
 var useMu = sync.Mutex{}
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &ProviderGCP{}
+var _ esv1beta1.Provider = &ProviderGCP{}
+
 // ProviderGCP is a provider for GCP Secret Manager.
 // ProviderGCP is a provider for GCP Secret Manager.
 type ProviderGCP struct {
 type ProviderGCP struct {
 	projectID           string
 	projectID           string

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

@@ -42,6 +42,10 @@ const (
 	errJSONSecretUnmarshal                    = "unable to unmarshal secret: %w"
 	errJSONSecretUnmarshal                    = "unable to unmarshal secret: %w"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &Gitlab{}
+var _ esv1beta1.Provider = &Gitlab{}
+
 type Client interface {
 type Client interface {
 	GetVariable(pid interface{}, key string, opt *gitlab.GetProjectVariableOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectVariable, *gitlab.Response, error)
 	GetVariable(pid interface{}, key string, opt *gitlab.GetProjectVariableOptions, options ...gitlab.RequestOptionFunc) (*gitlab.ProjectVariable, *gitlab.Response, error)
 }
 }

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

@@ -47,6 +47,10 @@ const (
 	errJSONSecretUnmarshal                   = "unable to unmarshal secret: %w"
 	errJSONSecretUnmarshal                   = "unable to unmarshal secret: %w"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &providerIBM{}
+var _ esv1beta1.Provider = &providerIBM{}
+
 type SecretManagerClient interface {
 type SecretManagerClient interface {
 	GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error)
 	GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error)
 }
 }

+ 4 - 0
pkg/provider/kubernetes/kubernetes.go

@@ -41,6 +41,10 @@ const (
 	errEmptyKey                            = "key %s found but empty"
 	errEmptyKey                            = "key %s found but empty"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &ProviderKubernetes{}
+var _ esv1beta1.Provider = &ProviderKubernetes{}
+
 type KClient interface {
 type KClient interface {
 	Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error)
 	Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error)
 }
 }

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

@@ -52,6 +52,10 @@ const (
 	errUnexpectedContent                     = "unexpected secret bundle content"
 	errUnexpectedContent                     = "unexpected secret bundle content"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &VaultManagementService{}
+var _ esv1beta1.Provider = &VaultManagementService{}
+
 type VaultManagementService struct {
 type VaultManagementService struct {
 	Client VMInterface
 	Client VMInterface
 	vault  string
 	vault  string

+ 4 - 0
pkg/provider/vault/vault.go

@@ -103,6 +103,10 @@ const (
 	errInvalidTokenRef   = "invalid Auth.TokenSecretRef: %w"
 	errInvalidTokenRef   = "invalid Auth.TokenSecretRef: %w"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &client{}
+var _ esv1beta1.Provider = &connector{}
+
 type Client interface {
 type Client interface {
 	NewRequest(method, requestPath string) *vault.Request
 	NewRequest(method, requestPath string) *vault.Request
 	RawRequestWithContext(ctx context.Context, r *vault.Request) (*vault.Response, error)
 	RawRequestWithContext(ctx context.Context, r *vault.Request) (*vault.Response, error)

+ 4 - 0
pkg/provider/webhook/webhook.go

@@ -39,6 +39,10 @@ import (
 	"github.com/external-secrets/external-secrets/pkg/utils"
 	"github.com/external-secrets/external-secrets/pkg/utils"
 )
 )
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &WebHook{}
+var _ esv1beta1.Provider = &Provider{}
+
 // Provider satisfies the provider interface.
 // Provider satisfies the provider interface.
 type Provider struct{}
 type Provider struct{}
 
 

+ 4 - 0
pkg/provider/yandex/lockbox/lockbox.go

@@ -45,6 +45,10 @@ type iamTokenKey struct {
 	privateKeyHash   string
 	privateKeyHash   string
 }
 }
 
 
+// https://github.com/external-secrets/external-secrets/issues/644
+var _ esv1beta1.SecretsClient = &lockboxSecretsClient{}
+var _ esv1beta1.Provider = &lockboxProvider{}
+
 // lockboxProvider is a provider for Yandex Lockbox.
 // lockboxProvider is a provider for Yandex Lockbox.
 type lockboxProvider struct {
 type lockboxProvider struct {
 	yandexCloudCreator client.YandexCloudCreator
 	yandexCloudCreator client.YandexCloudCreator