Browse Source

Merge pull request #707 from rodrmartinez/feature/kubernetes-provider

Implements Kubernetes Providers
paul-the-alien[bot] 4 years ago
parent
commit
f12c773f98

+ 87 - 0
apis/externalsecrets/v1alpha1/secretstore_kubernetes_types.go

@@ -0,0 +1,87 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+type KubernetesServer struct {
+
+	// configures the Kubernetes server Address.
+	// +kubebuilder:default=kubernetes.default
+	// +optional
+	URL string `json:"url,omitempty"`
+
+	// CABundle is a base64-encoded CA certificate
+	// +optional
+	CABundle []byte `json:"caBundle,omitempty"`
+
+	// see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider
+	// +optional
+	CAProvider *CAProvider `json:"caProvider,omitempty"`
+
+	// there's still room for impersonation or proxy settings:
+	// Impersonate-User
+	// Impersonate-Group
+	// Impersonate-Extra-( extra name )
+	// Impersonate-Uid
+	// Proxy Settings
+}
+
+// Configures a store to sync secrets with a Kubernetes instance.
+type KubernetesProvider struct {
+	// configures the Kubernetes server Address.
+	Server KubernetesServer `json:"server,omitempty"`
+
+	// Auth configures how secret-manager authenticates with a Kubernetes instance.
+	Auth KubernetesAuth `json:"auth"`
+
+	// Remote namespace to fetch the secrets from
+	// +kubebuilder:default= default
+	// +optional
+	RemoteNamespace string `json:"remoteNamespace"`
+}
+
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
+type KubernetesAuth struct {
+	// has both clientCert and clientKey as secretKeySelector
+	// +optional
+	Cert *CertAuth `json:"cert,omitempty"`
+
+	// use static token to authenticate with
+	// +optional
+	Token *TokenAuth `json:"token,omitempty"`
+
+	// points to a service account that should be used for authentication
+	// +optional
+	ServiceAccount *ServiceAccountAuth `json:"serviceAccount,omitempty"`
+
+	// possibly exec or webhook
+}
+
+type CertAuth struct {
+	ClientCert esmeta.SecretKeySelector `json:"clientCert,omitempty"`
+	ClientKey  esmeta.SecretKeySelector `json:"clientKey,omitempty"`
+}
+
+type TokenAuth struct {
+	BearerToken esmeta.SecretKeySelector `json:"bearerToken,omitempty"`
+}
+
+type ServiceAccountAuth struct {
+	ServiceAccountRef esmeta.ServiceAccountSelector `json:"serviceAccount,omitempty"`
+}

+ 3 - 0
apis/externalsecrets/v1alpha1/secretstore_types.go

@@ -82,6 +82,9 @@ type SecretStoreProvider struct {
 	// +optional
 	Webhook *WebhookProvider `json:"webhook,omitempty"`
 
+	// Kubernetes configures this store to sync secrets using a Kubernetes cluster provider
+	// +optional
+	Kubernetes *KubernetesProvider `json:"kubernetes,omitempty"`
 	// Fake configures a store with static key/value pairs
 	// +optional
 	Fake *FakeProvider `json:"fake,omitempty"`

+ 126 - 0
apis/externalsecrets/v1alpha1/zz_generated.deepcopy.go

@@ -301,6 +301,23 @@ func (in *CAProvider) DeepCopy() *CAProvider {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *CertAuth) DeepCopyInto(out *CertAuth) {
+	*out = *in
+	in.ClientCert.DeepCopyInto(&out.ClientCert)
+	in.ClientKey.DeepCopyInto(&out.ClientKey)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertAuth.
+func (in *CertAuth) DeepCopy() *CertAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(CertAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *ClusterSecretStore) DeepCopyInto(out *ClusterSecretStore) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
@@ -818,6 +835,78 @@ func (in *IBMProvider) DeepCopy() *IBMProvider {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KubernetesAuth) DeepCopyInto(out *KubernetesAuth) {
+	*out = *in
+	if in.Cert != nil {
+		in, out := &in.Cert, &out.Cert
+		*out = new(CertAuth)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Token != nil {
+		in, out := &in.Token, &out.Token
+		*out = new(TokenAuth)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.ServiceAccount != nil {
+		in, out := &in.ServiceAccount, &out.ServiceAccount
+		*out = new(ServiceAccountAuth)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesAuth.
+func (in *KubernetesAuth) DeepCopy() *KubernetesAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(KubernetesAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KubernetesProvider) DeepCopyInto(out *KubernetesProvider) {
+	*out = *in
+	in.Server.DeepCopyInto(&out.Server)
+	in.Auth.DeepCopyInto(&out.Auth)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesProvider.
+func (in *KubernetesProvider) DeepCopy() *KubernetesProvider {
+	if in == nil {
+		return nil
+	}
+	out := new(KubernetesProvider)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KubernetesServer) DeepCopyInto(out *KubernetesServer) {
+	*out = *in
+	if in.CABundle != nil {
+		in, out := &in.CABundle, &out.CABundle
+		*out = make([]byte, len(*in))
+		copy(*out, *in)
+	}
+	if in.CAProvider != nil {
+		in, out := &in.CAProvider, &out.CAProvider
+		*out = new(CAProvider)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesServer.
+func (in *KubernetesServer) DeepCopy() *KubernetesServer {
+	if in == nil {
+		return nil
+	}
+	out := new(KubernetesServer)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *OracleAuth) DeepCopyInto(out *OracleAuth) {
 	*out = *in
 	in.SecretRef.DeepCopyInto(&out.SecretRef)
@@ -987,6 +1076,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
 		*out = new(WebhookProvider)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.Kubernetes != nil {
+		in, out := &in.Kubernetes, &out.Kubernetes
+		*out = new(KubernetesProvider)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Fake != nil {
 		in, out := &in.Fake, &out.Fake
 		*out = new(FakeProvider)
@@ -1108,6 +1202,22 @@ func (in *SecretStoreStatusCondition) DeepCopy() *SecretStoreStatusCondition {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ServiceAccountAuth) DeepCopyInto(out *ServiceAccountAuth) {
+	*out = *in
+	in.ServiceAccountRef.DeepCopyInto(&out.ServiceAccountRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAccountAuth.
+func (in *ServiceAccountAuth) DeepCopy() *ServiceAccountAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(ServiceAccountAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *TemplateFrom) DeepCopyInto(out *TemplateFrom) {
 	*out = *in
 	if in.ConfigMap != nil {
@@ -1168,6 +1278,22 @@ func (in *TemplateRefItem) DeepCopy() *TemplateRefItem {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TokenAuth) DeepCopyInto(out *TokenAuth) {
+	*out = *in
+	in.BearerToken.DeepCopyInto(&out.BearerToken)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TokenAuth.
+func (in *TokenAuth) DeepCopy() *TokenAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(TokenAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *VaultAppRole) DeepCopyInto(out *VaultAppRole) {
 	*out = *in
 	in.SecretRef.DeepCopyInto(&out.SecretRef)

+ 150 - 0
deploy/crds/external-secrets.io_clustersecretstores.yaml

@@ -555,6 +555,156 @@ spec:
                     required:
                     - auth
                     type: object
+                  kubernetes:
+                    description: Kubernetes configures this store to sync secrets
+                      using a Kubernetes cluster provider
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Kubernetes instance.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          cert:
+                            description: has both clientCert and clientKey as secretKeySelector
+                            properties:
+                              clientCert:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                              clientKey:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                            type: object
+                          serviceAccount:
+                            description: points to a service account that should be
+                              used for authentication
+                            properties:
+                              serviceAccount:
+                                description: A reference to a ServiceAccount resource.
+                                properties:
+                                  name:
+                                    description: The name of the ServiceAccount resource
+                                      being referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                required:
+                                - name
+                                type: object
+                            type: object
+                          token:
+                            description: use static token to authenticate with
+                            properties:
+                              bearerToken:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                            type: object
+                        type: object
+                      remoteNamespace:
+                        default: default
+                        description: Remote namespace to fetch the secrets from
+                        type: string
+                      server:
+                        description: configures the Kubernetes server Address.
+                        properties:
+                          caBundle:
+                            description: CABundle is a base64-encoded CA certificate
+                            format: byte
+                            type: string
+                          caProvider:
+                            description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
+                            properties:
+                              key:
+                                description: The key the value inside of the provider
+                                  type to use, only used with "Secret" type
+                                type: string
+                              name:
+                                description: The name of the object located at the
+                                  provider type.
+                                type: string
+                              namespace:
+                                description: The namespace the Provider type is in.
+                                type: string
+                              type:
+                                description: The type of provider to use such as "Secret",
+                                  or "ConfigMap".
+                                enum:
+                                - Secret
+                                - ConfigMap
+                                type: string
+                            required:
+                            - name
+                            - type
+                            type: object
+                          url:
+                            default: kubernetes.default
+                            description: configures the Kubernetes server Address.
+                            type: string
+                        type: object
+                    required:
+                    - auth
+                    type: object
                   oracle:
                     description: Oracle configures this store to sync secrets using
                       Oracle Vault provider

+ 150 - 0
deploy/crds/external-secrets.io_secretstores.yaml

@@ -555,6 +555,156 @@ spec:
                     required:
                     - auth
                     type: object
+                  kubernetes:
+                    description: Kubernetes configures this store to sync secrets
+                      using a Kubernetes cluster provider
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Kubernetes instance.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          cert:
+                            description: has both clientCert and clientKey as secretKeySelector
+                            properties:
+                              clientCert:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                              clientKey:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                            type: object
+                          serviceAccount:
+                            description: points to a service account that should be
+                              used for authentication
+                            properties:
+                              serviceAccount:
+                                description: A reference to a ServiceAccount resource.
+                                properties:
+                                  name:
+                                    description: The name of the ServiceAccount resource
+                                      being referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                required:
+                                - name
+                                type: object
+                            type: object
+                          token:
+                            description: use static token to authenticate with
+                            properties:
+                              bearerToken:
+                                description: A reference to a specific 'key' within
+                                  a Secret resource, In some instances, `key` is a
+                                  required field.
+                                properties:
+                                  key:
+                                    description: The key of the entry in the Secret
+                                      resource's `data` field to be used. Some instances
+                                      of this field may be defaulted, in others it
+                                      may be required.
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    type: string
+                                  namespace:
+                                    description: Namespace of the resource being referred
+                                      to. Ignored if referent is not cluster-scoped.
+                                      cluster-scoped defaults to the namespace of
+                                      the referent.
+                                    type: string
+                                type: object
+                            type: object
+                        type: object
+                      remoteNamespace:
+                        default: default
+                        description: Remote namespace to fetch the secrets from
+                        type: string
+                      server:
+                        description: configures the Kubernetes server Address.
+                        properties:
+                          caBundle:
+                            description: CABundle is a base64-encoded CA certificate
+                            format: byte
+                            type: string
+                          caProvider:
+                            description: 'see: https://external-secrets.io/v0.4.1/spec/#external-secrets.io/v1alpha1.CAProvider'
+                            properties:
+                              key:
+                                description: The key the value inside of the provider
+                                  type to use, only used with "Secret" type
+                                type: string
+                              name:
+                                description: The name of the object located at the
+                                  provider type.
+                                type: string
+                              namespace:
+                                description: The namespace the Provider type is in.
+                                type: string
+                              type:
+                                description: The type of provider to use such as "Secret",
+                                  or "ConfigMap".
+                                enum:
+                                - Secret
+                                - ConfigMap
+                                type: string
+                            required:
+                            - name
+                            - type
+                            type: object
+                          url:
+                            default: kubernetes.default
+                            description: configures the Kubernetes server Address.
+                            type: string
+                        type: object
+                    required:
+                    - auth
+                    type: object
                   oracle:
                     description: Oracle configures this store to sync secrets using
                       Oracle Vault provider

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

@@ -0,0 +1,231 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package kubernetes
+
+import (
+	"context"
+	"fmt"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/client-go/kubernetes"
+	"k8s.io/client-go/rest"
+	kclient "sigs.k8s.io/controller-runtime/pkg/client"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+	"github.com/external-secrets/external-secrets/pkg/provider"
+	"github.com/external-secrets/external-secrets/pkg/provider/schema"
+	"github.com/external-secrets/external-secrets/pkg/utils"
+)
+
+const (
+	errPropertyNotFound                    = "property field not found on extrenal secrets"
+	errKubernetesCredSecretName            = "kubernetes credentials are empty"
+	errInvalidClusterStoreMissingNamespace = "invalid clusterStore missing Cert namespace"
+	errFetchCredentialsSecret              = "could not fetch Credentials secret: %w"
+	errMissingCredentials                  = "missing Credentials: %v"
+	errUninitalizedKubernetesProvider      = "provider kubernetes is not initialized"
+	errEmptyKey                            = "key %s found but empty"
+)
+
+type KClient interface {
+	Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error)
+}
+
+// ProviderKubernetes is a provider for Kubernetes.
+type ProviderKubernetes struct {
+	Client KClient
+}
+
+var _ provider.SecretsClient = &ProviderKubernetes{}
+
+type BaseClient struct {
+	kube        kclient.Client
+	store       *esv1alpha1.KubernetesProvider
+	namespace   string
+	storeKind   string
+	Certificate []byte
+	Key         []byte
+	CA          []byte
+	BearerToken []byte
+}
+
+func init() {
+	schema.Register(&ProviderKubernetes{}, &esv1alpha1.SecretStoreProvider{
+		Kubernetes: &esv1alpha1.KubernetesProvider{},
+	})
+}
+
+// NewClient constructs a Kubernetes Provider.
+func (k *ProviderKubernetes) NewClient(ctx context.Context, store esv1alpha1.GenericStore, kube kclient.Client, namespace string) (provider.SecretsClient, error) {
+	storeSpec := store.GetSpec()
+	if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Kubernetes == nil {
+		return nil, fmt.Errorf("no store type or wrong store type")
+	}
+	storeSpecKubernetes := storeSpec.Provider.Kubernetes
+
+	bStore := BaseClient{
+		kube:      kube,
+		store:     storeSpecKubernetes,
+		namespace: namespace,
+		storeKind: store.GetObjectKind().GroupVersionKind().Kind,
+	}
+
+	if err := bStore.setAuth(ctx); err != nil {
+		return nil, err
+	}
+
+	config := &rest.Config{
+		Host:        bStore.store.Server.URL,
+		BearerToken: string(bStore.BearerToken),
+		TLSClientConfig: rest.TLSClientConfig{
+			Insecure: false,
+			CertData: bStore.Certificate,
+			KeyData:  bStore.Key,
+			CAData:   bStore.CA,
+		},
+	}
+
+	kubeClientSet, err := kubernetes.NewForConfig(config)
+	if err != nil {
+		return nil, fmt.Errorf("error configuring clientset: %w", err)
+	}
+
+	k.Client = kubeClientSet.CoreV1().Secrets(bStore.store.RemoteNamespace)
+
+	return k, nil
+}
+
+func (k *ProviderKubernetes) Close(ctx context.Context) error {
+	return nil
+}
+
+func (k *ProviderKubernetes) GetSecret(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) ([]byte, error) {
+	if ref.Property == "" {
+		return nil, fmt.Errorf(errPropertyNotFound)
+	}
+
+	payload, err := k.GetSecretMap(ctx, ref)
+
+	if err != nil {
+		return nil, err
+	}
+
+	val, ok := payload[ref.Property]
+	if !ok {
+		return nil, fmt.Errorf("property %s does not exist in key %s", ref.Property, ref.Key)
+	}
+	return val, nil
+}
+
+func (k *ProviderKubernetes) GetSecretMap(ctx context.Context, ref esv1alpha1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
+	if utils.IsNil(k.Client) {
+		return nil, fmt.Errorf(errUninitalizedKubernetesProvider)
+	}
+	opts := metav1.GetOptions{}
+	secretOut, err := k.Client.Get(ctx, ref.Key, opts)
+
+	if err != nil {
+		return nil, err
+	}
+
+	var payload map[string][]byte
+	if len(secretOut.Data) != 0 {
+		payload = secretOut.Data
+	}
+
+	return payload, nil
+}
+
+func (k *BaseClient) setAuth(ctx context.Context) error {
+	var err error
+	if len(k.store.Server.CABundle) > 0 {
+		k.CA = k.store.Server.CABundle
+	} else if k.store.Server.CAProvider != nil {
+		keySelector := esmeta.SecretKeySelector{
+			Name:      k.store.Server.CAProvider.Name,
+			Namespace: k.store.Server.CAProvider.Namespace,
+			Key:       k.store.Server.CAProvider.Key,
+		}
+		k.CA, err = k.fetchSecretKey(ctx, keySelector, "CA")
+		if err != nil {
+			return err
+		}
+	} else {
+		return fmt.Errorf("no Certificate Authority provided")
+	}
+
+	if k.store.Auth.Token != nil {
+		k.BearerToken, err = k.fetchSecretKey(ctx, k.store.Auth.Token.BearerToken, "bearerToken")
+		if err != nil {
+			return err
+		}
+	} else if k.store.Auth.ServiceAccount != nil {
+		return fmt.Errorf("not implemented yet")
+	} else if k.store.Auth.Cert != nil {
+		k.Certificate, err = k.fetchSecretKey(ctx, k.store.Auth.Cert.ClientCert, "cert")
+		if err != nil {
+			return err
+		}
+		k.Key, err = k.fetchSecretKey(ctx, k.store.Auth.Cert.ClientKey, "key")
+		if err != nil {
+			return err
+		}
+	} else {
+		return fmt.Errorf("no credentials provided")
+	}
+
+	return nil
+}
+
+func (k *BaseClient) fetchSecretKey(ctx context.Context, key esmeta.SecretKeySelector, component string) ([]byte, error) {
+	keySecret := &corev1.Secret{}
+	keySecretName := key.Name
+	if keySecretName == "" {
+		return nil, fmt.Errorf(errKubernetesCredSecretName)
+	}
+	objectKey := types.NamespacedName{
+		Name:      keySecretName,
+		Namespace: k.namespace,
+	}
+	// only ClusterStore is allowed to set namespace (and then it's required)
+	if k.storeKind == esv1alpha1.ClusterSecretStoreKind {
+		if key.Namespace == nil {
+			return nil, fmt.Errorf(errInvalidClusterStoreMissingNamespace)
+		}
+		objectKey.Namespace = *key.Namespace
+	}
+
+	err := k.kube.Get(ctx, objectKey, keySecret)
+	if err != nil {
+		return nil, fmt.Errorf(errFetchCredentialsSecret, err)
+	}
+
+	val, ok := keySecret.Data[key.Key]
+	if !ok {
+		return nil, fmt.Errorf(errMissingCredentials, component)
+	}
+
+	if len(val) == 0 {
+		return nil, fmt.Errorf(errEmptyKey, component)
+	}
+	return val, nil
+}
+
+func (k *ProviderKubernetes) Validate() error {
+	return nil
+}

+ 260 - 0
pkg/provider/kubernetes/kubernetes_test.go

@@ -0,0 +1,260 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+package kubernetes
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	fclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
+
+	esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
+	v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+const (
+	errTestFetchCredentialsSecret = "test could not fetch Credentials secret failed"
+	errTestAuthValue              = "test failed key didn't match expected value"
+)
+
+type fakeClient struct {
+	secretMap map[string]corev1.Secret
+}
+
+func (fk fakeClient) Get(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Secret, error) {
+	secret, ok := fk.secretMap[name]
+
+	if !ok {
+		return nil, errors.New("Something went wrong")
+	}
+	return &secret, nil
+}
+
+func TestKubernetesSecretManagerGetSecret(t *testing.T) {
+	expected := make(map[string][]byte)
+	value := "bar"
+	expected["foo"] = []byte(value)
+	mysecret := corev1.Secret{Data: expected}
+	mysecretmap := make(map[string]corev1.Secret)
+	mysecretmap["Key"] = mysecret
+
+	fk := fakeClient{secretMap: mysecretmap}
+	kp := ProviderKubernetes{Client: fk}
+
+	ref := esv1alpha1.ExternalSecretDataRemoteRef{Key: "Key", Property: "foo"}
+	ctx := context.Background()
+
+	output, _ := kp.GetSecret(ctx, ref)
+
+	if string(output) != value {
+		t.Error("missing match value of the secret")
+	}
+
+	ref = esv1alpha1.ExternalSecretDataRemoteRef{Key: "Key2", Property: "foo"}
+	_, err := kp.GetSecret(ctx, ref)
+
+	if err.Error() != "Something went wrong" {
+		t.Error("test failed")
+	}
+
+	ref = esv1alpha1.ExternalSecretDataRemoteRef{Key: "Key", Property: "foo2"}
+	_, err = kp.GetSecret(ctx, ref)
+	expectedError := fmt.Sprintf("property %s does not exist in key %s", ref.Property, ref.Key)
+	if err.Error() != expectedError {
+		t.Error("test not existing property failed")
+	}
+
+	kp = ProviderKubernetes{Client: nil}
+	_, err = kp.GetSecret(ctx, ref)
+
+	if err.Error() != errUninitalizedKubernetesProvider {
+		t.Error("test nil Client failed")
+	}
+
+	ref = esv1alpha1.ExternalSecretDataRemoteRef{Key: "Key", Property: ""}
+	_, err = kp.GetSecret(ctx, ref)
+
+	if err.Error() != "property field not found on extrenal secrets" {
+		t.Error("test nil Property failed")
+	}
+}
+
+func TestKubernetesSecretManagerGetSecretMap(t *testing.T) {
+	expected := make(map[string][]byte)
+	value := "bar"
+	expected["foo"] = []byte(value)
+	expected["foo2"] = []byte(value)
+	mysecret := corev1.Secret{Data: expected}
+	mysecretmap := make(map[string]corev1.Secret)
+	mysecretmap["Key"] = mysecret
+
+	fk := fakeClient{secretMap: mysecretmap}
+	kp := ProviderKubernetes{Client: fk}
+
+	ref := esv1alpha1.ExternalSecretDataRemoteRef{Key: "Key", Property: ""}
+	ctx := context.Background()
+
+	output, err := kp.GetSecretMap(ctx, ref)
+
+	if err != nil {
+		t.Error("test failed")
+	}
+	if !reflect.DeepEqual(output, expected) {
+		t.Error("Objects are not equal")
+	}
+}
+
+func TestKubernetesSecretManagerSetAuth(t *testing.T) {
+	secretName := "good-name"
+	CABundle := "CABundle"
+	kp := esv1alpha1.KubernetesProvider{Server: esv1alpha1.KubernetesServer{}}
+
+	fs := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{Name: secretName},
+		Data:       make(map[string][]byte),
+	}
+	fs.Data["cert"] = []byte("secret-cert")
+	fs.Data["ca"] = []byte("secret-ca")
+	fs.Data["bearerToken"] = []byte("bearerToken")
+
+	fs2 := &corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{Name: "secret-for-the-key"},
+		Data:       make(map[string][]byte),
+	}
+	fs2.Data["key"] = []byte("secret-key")
+
+	fk := fclient.NewClientBuilder().WithObjects(fs, fs2).Build()
+	bc := BaseClient{fk, &kp, "", "", nil, nil, nil, nil}
+
+	ctx := context.Background()
+
+	err := bc.setAuth(ctx)
+
+	if err.Error() != "no Certificate Authority provided" {
+		fmt.Println(err.Error())
+		t.Error("test no Certificate Authority provided failed")
+	}
+
+	kp.Server.CAProvider = &esv1alpha1.CAProvider{
+		Type:      esv1alpha1.CAProviderTypeConfigMap,
+		Name:      fs.ObjectMeta.Name,
+		Namespace: &fs.ObjectMeta.Namespace,
+		Key:       "ca",
+	}
+
+	bc.setAuth(ctx)
+
+	if string(bc.CA) != "secret-ca" {
+		t.Error("failed to set CA provider")
+	}
+
+	kp.Server.CABundle = []byte(CABundle)
+
+	err = bc.setAuth(ctx)
+
+	if err.Error() != "no credentials provided" {
+		fmt.Println(err.Error())
+		t.Error("test kubernetes credentials not empty failed")
+	}
+
+	if string(bc.CA) != CABundle {
+		t.Error("failed to set CA provider")
+	}
+
+	kp = esv1alpha1.KubernetesProvider{
+		Auth: esv1alpha1.KubernetesAuth{
+			Cert: &esv1alpha1.CertAuth{
+				ClientCert: v1.SecretKeySelector{
+					Name: "fake-name",
+				},
+			},
+		},
+	}
+	kp.Server.CABundle = []byte(CABundle)
+
+	err = bc.setAuth(ctx)
+
+	if err.Error() != "could not fetch Credentials secret: secrets \"fake-name\" not found" {
+		fmt.Println(err.Error())
+		t.Error(errTestFetchCredentialsSecret)
+	}
+
+	kp.Auth.Cert.ClientCert.Name = fs.ObjectMeta.Name
+
+	err = bc.setAuth(ctx)
+
+	if err.Error() != fmt.Errorf(errMissingCredentials, "cert").Error() {
+		fmt.Println(err.Error())
+		t.Error(errTestFetchCredentialsSecret)
+	}
+
+	kp.Auth.Cert.ClientCert.Key = "cert"
+	kp.Auth.Cert.ClientKey.Name = "secret-for-the-key"
+
+	err = bc.setAuth(ctx)
+
+	if err.Error() != fmt.Errorf(errMissingCredentials, "key").Error() {
+		fmt.Println(err.Error())
+		t.Error(errTestFetchCredentialsSecret)
+	}
+	kp.Auth.Cert.ClientKey.Key = "key"
+
+	bc.setAuth(ctx)
+
+	kp.Auth.Token = &esv1alpha1.TokenAuth{BearerToken: v1.SecretKeySelector{Name: secretName}}
+
+	err = bc.setAuth(ctx)
+
+	if err.Error() != fmt.Errorf(errMissingCredentials, "bearerToken").Error() {
+		fmt.Println(err.Error())
+		t.Error(errTestFetchCredentialsSecret)
+	}
+
+	kp.Auth.Token = &esv1alpha1.TokenAuth{BearerToken: v1.SecretKeySelector{Name: secretName, Key: "bearerToken"}}
+
+	err = bc.setAuth(ctx)
+
+	if err != nil {
+		fmt.Println(err.Error())
+		t.Error(errTestFetchCredentialsSecret)
+	}
+	if string(bc.CA) != CABundle {
+		t.Error(errTestAuthValue)
+	}
+	if string(bc.Certificate) != "secret-cert" {
+		t.Error(errTestAuthValue)
+	}
+	if string(bc.Key) != "secret-key" {
+		t.Errorf(errTestAuthValue)
+	}
+	if string(bc.BearerToken) != "bearerToken" {
+		t.Error(errTestAuthValue)
+	}
+}
+
+func ErrorContains(out error, want string) bool {
+	if out == nil {
+		return want == ""
+	}
+	if want == "" {
+		return false
+	}
+	return strings.Contains(out.Error(), want)
+}

+ 1 - 0
pkg/provider/register/register.go

@@ -25,6 +25,7 @@ import (
 	_ "github.com/external-secrets/external-secrets/pkg/provider/gcp/secretmanager"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/gitlab"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/ibm"
+	_ "github.com/external-secrets/external-secrets/pkg/provider/kubernetes"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/oracle"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/vault"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/webhook"