Browse Source

Integrate Passworddepot (#2799)

* PLAT-1179 | updated to beta1

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Updating External Secrets fixes

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Fix to Passworddepots-crds-generation

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | apiextensionsv1 removal

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* Update apis/externalsecrets/v1beta1/secretstore_passworddeport_types.go

Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Signed-off-by: Sulfixx <135371229+Sulfixx@users.noreply.github.com>

* Update apis/externalsecrets/v1beta1/secretstore_passworddeport_types.go

Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Signed-off-by: Sulfixx <135371229+Sulfixx@users.noreply.github.com>

* Update apis/externalsecrets/v1beta1/secretstore_types.go

Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Signed-off-by: Sulfixx <135371229+Sulfixx@users.noreply.github.com>

* PLAT-1179 | Removed insecureverify and other fixes

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Fixed Linter and Sonar Issues

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Fixed Typo in Passworddepot_api.go

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Resolved go.mod Conflict

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Resolved go.mod conflict typo

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | admission.Warnings error fix

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Added nolint:bodyclose // linters bug

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Removed <= Head arrow from mkdocs.yml

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Added Make Check-Diff Changes

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Changed Error Package, Added Context, API Refactor

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Added const DoRequestError to reduce Codesmell

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Moved defer body close func into ReadAndUnmarshal

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Moved Status Check into ReadAndUnmarshal

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Removed Response.body from ReadAndUnmarshal

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* Update apis/externalsecrets/v1alpha1/secretstore_passworddepot_types.go

Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Signed-off-by: Sulfixx <135371229+Sulfixx@users.noreply.github.com>

* PLAT-1179 | Go mod tidy and Make generate

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Added empty SecretExists Method

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

* PLAT-1179 | Renamed unsed ctx to _

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>

---------

Signed-off-by: Simon Becker <simon.becker@fastleansmart.com>
Signed-off-by: Sulfixx <135371229+Sulfixx@users.noreply.github.com>
Co-authored-by: Sören Rohweder <soeren.rohweder@fastleansmart.com>
Co-authored-by: Simon Becker <simon.becker@fastleansmart.com>
Co-authored-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Sulfixx 2 years ago
parent
commit
e57e4b72ca

+ 40 - 0
apis/externalsecrets/v1alpha1/secretstore_passworddepot_types.go

@@ -0,0 +1,40 @@
+/*
+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"
+)
+
+// Configures a store to sync secrets with a Password Depot instance.
+type PasswordDepotProvider struct {
+	// URL configures the Password Depot instance URL.
+	Host string `json:"host"`
+
+	// Database to use as source
+	Database string `json:"database"`
+
+	// Auth configures how secret-manager authenticates with a Password Depot instance.
+	Auth PasswordDepotAuth `json:"auth"`
+}
+
+type PasswordDepotAuth struct {
+	SecretRef PasswordDepotSecretRef `json:"secretRef"`
+}
+
+type PasswordDepotSecretRef struct {
+	// Username / Password is used for authentication.
+	Credentials esmeta.SecretKeySelector `json:"credentials,omitempty"`
+}

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

@@ -86,6 +86,8 @@ type SecretStoreProvider struct {
 	// +optional
 	Kubernetes *KubernetesProvider `json:"kubernetes,omitempty"`
 
+	PasswordDepot *PasswordDepotProvider `json:"passworddepot,omitempty"`
+
 	// Fake configures a store with static key/value pairs
 	// +optional
 	Fake *FakeProvider `json:"fake,omitempty"`

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

@@ -1032,6 +1032,54 @@ func (in *OracleSecretRef) DeepCopy() *OracleSecretRef {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotAuth) DeepCopyInto(out *PasswordDepotAuth) {
+	*out = *in
+	in.SecretRef.DeepCopyInto(&out.SecretRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotAuth.
+func (in *PasswordDepotAuth) DeepCopy() *PasswordDepotAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotProvider) DeepCopyInto(out *PasswordDepotProvider) {
+	*out = *in
+	in.Auth.DeepCopyInto(&out.Auth)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotProvider.
+func (in *PasswordDepotProvider) DeepCopy() *PasswordDepotProvider {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotProvider)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotSecretRef) DeepCopyInto(out *PasswordDepotSecretRef) {
+	*out = *in
+	in.Credentials.DeepCopyInto(&out.Credentials)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotSecretRef.
+func (in *PasswordDepotSecretRef) DeepCopy() *PasswordDepotSecretRef {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotSecretRef)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PushSecret) DeepCopyInto(out *PushSecret) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
@@ -1412,6 +1460,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
 		*out = new(KubernetesProvider)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.PasswordDepot != nil {
+		in, out := &in.PasswordDepot, &out.PasswordDepot
+		*out = new(PasswordDepotProvider)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Fake != nil {
 		in, out := &in.Fake, &out.Fake
 		*out = new(FakeProvider)

+ 41 - 0
apis/externalsecrets/v1beta1/secretstore_passworddeport_types.go

@@ -0,0 +1,41 @@
+/*
+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 v1beta1
+
+import (
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+// Configures a store to sync secrets with a Password Depot instance.
+type PasswordDepotProvider struct {
+	// URL configures the Password Depot instance URL.
+	Host string `json:"host"`
+
+	// Database to use as source
+	Database string `json:"database"`
+
+	// Auth configures how secret-manager authenticates with a Password Depot instance.
+	Auth PasswordDepotAuth `json:"auth"`
+}
+
+type PasswordDepotAuth struct {
+	SecretRef PasswordDepotSecretRef `json:"secretRef"`
+}
+
+type PasswordDepotSecretRef struct {
+	// Username / Password is used for authentication.
+	// +optional
+	Credentials esmeta.SecretKeySelector `json:"credentials,omitempty"`
+}

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

@@ -157,6 +157,9 @@ type SecretStoreProvider struct {
 	// Fortanix configures this store to sync secrets using the Fortanix provider
 	// +optional
 	Fortanix *FortanixProvider `json:"fortanix,omitempty"`
+
+	// +optional
+	PasswordDepot *PasswordDepotProvider `json:"passworddepot,omitempty"`
 }
 
 type CAProviderType string

+ 53 - 0
apis/externalsecrets/v1beta1/zz_generated.deepcopy.go

@@ -1910,6 +1910,54 @@ func (in *OracleSecretRef) DeepCopy() *OracleSecretRef {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotAuth) DeepCopyInto(out *PasswordDepotAuth) {
+	*out = *in
+	in.SecretRef.DeepCopyInto(&out.SecretRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotAuth.
+func (in *PasswordDepotAuth) DeepCopy() *PasswordDepotAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotProvider) DeepCopyInto(out *PasswordDepotProvider) {
+	*out = *in
+	in.Auth.DeepCopyInto(&out.Auth)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotProvider.
+func (in *PasswordDepotProvider) DeepCopy() *PasswordDepotProvider {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotProvider)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *PasswordDepotSecretRef) DeepCopyInto(out *PasswordDepotSecretRef) {
+	*out = *in
+	in.Credentials.DeepCopyInto(&out.Credentials)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PasswordDepotSecretRef.
+func (in *PasswordDepotSecretRef) DeepCopy() *PasswordDepotSecretRef {
+	if in == nil {
+		return nil
+	}
+	out := new(PasswordDepotSecretRef)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PulumiProvider) DeepCopyInto(out *PulumiProvider) {
 	*out = *in
 	if in.AccessToken != nil {
@@ -2181,6 +2229,11 @@ func (in *SecretStoreProvider) DeepCopyInto(out *SecretStoreProvider) {
 		*out = new(FortanixProvider)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.PasswordDepot != nil {
+		in, out := &in.PasswordDepot, &out.PasswordDepot
+		*out = new(PasswordDepotProvider)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreProvider.

+ 86 - 0
config/crds/bases/external-secrets.io_clustersecretstores.yaml

@@ -965,6 +965,49 @@ spec:
                     - region
                     - vault
                     type: object
+                  passworddepot:
+                    description: Configures a store to sync secrets with a Password
+                      Depot instance.
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Password Depot instance.
+                        properties:
+                          secretRef:
+                            properties:
+                              credentials:
+                                description: Username / Password is used for authentication.
+                                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
+                        required:
+                        - secretRef
+                        type: object
+                      database:
+                        description: Database to use as source
+                        type: string
+                      host:
+                        description: URL configures the Password Depot instance URL.
+                        type: string
+                    required:
+                    - auth
+                    - database
+                    - host
+                    type: object
                   vault:
                     description: Vault configures this store to sync secrets using
                       Hashi provider
@@ -3220,6 +3263,49 @@ spec:
                     - region
                     - vault
                     type: object
+                  passworddepot:
+                    description: Configures a store to sync secrets with a Password
+                      Depot instance.
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Password Depot instance.
+                        properties:
+                          secretRef:
+                            properties:
+                              credentials:
+                                description: Username / Password is used for authentication.
+                                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
+                        required:
+                        - secretRef
+                        type: object
+                      database:
+                        description: Database to use as source
+                        type: string
+                      host:
+                        description: URL configures the Password Depot instance URL.
+                        type: string
+                    required:
+                    - auth
+                    - database
+                    - host
+                    type: object
                   pulumi:
                     description: Pulumi configures this store to sync secrets using
                       the Pulumi provider

+ 86 - 0
config/crds/bases/external-secrets.io_secretstores.yaml

@@ -965,6 +965,49 @@ spec:
                     - region
                     - vault
                     type: object
+                  passworddepot:
+                    description: Configures a store to sync secrets with a Password
+                      Depot instance.
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Password Depot instance.
+                        properties:
+                          secretRef:
+                            properties:
+                              credentials:
+                                description: Username / Password is used for authentication.
+                                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
+                        required:
+                        - secretRef
+                        type: object
+                      database:
+                        description: Database to use as source
+                        type: string
+                      host:
+                        description: URL configures the Password Depot instance URL.
+                        type: string
+                    required:
+                    - auth
+                    - database
+                    - host
+                    type: object
                   vault:
                     description: Vault configures this store to sync secrets using
                       Hashi provider
@@ -3220,6 +3263,49 @@ spec:
                     - region
                     - vault
                     type: object
+                  passworddepot:
+                    description: Configures a store to sync secrets with a Password
+                      Depot instance.
+                    properties:
+                      auth:
+                        description: Auth configures how secret-manager authenticates
+                          with a Password Depot instance.
+                        properties:
+                          secretRef:
+                            properties:
+                              credentials:
+                                description: Username / Password is used for authentication.
+                                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
+                        required:
+                        - secretRef
+                        type: object
+                      database:
+                        description: Database to use as source
+                        type: string
+                      host:
+                        description: URL configures the Password Depot instance URL.
+                        type: string
+                    required:
+                    - auth
+                    - database
+                    - host
+                    type: object
                   pulumi:
                     description: Pulumi configures this store to sync secrets using
                       the Pulumi provider

+ 160 - 0
deploy/crds/bundle.yaml

@@ -1500,6 +1500,46 @@ spec:
                         - region
                         - vault
                       type: object
+                    passworddepot:
+                      description: Configures a store to sync secrets with a Password Depot instance.
+                      properties:
+                        auth:
+                          description: Auth configures how secret-manager authenticates with a Password Depot instance.
+                          properties:
+                            secretRef:
+                              properties:
+                                credentials:
+                                  description: Username / Password is used for authentication.
+                                  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
+                          required:
+                            - secretRef
+                          type: object
+                        database:
+                          description: Database to use as source
+                          type: string
+                        host:
+                          description: URL configures the Password Depot instance URL.
+                          type: string
+                      required:
+                        - auth
+                        - database
+                        - host
+                      type: object
                     vault:
                       description: Vault configures this store to sync secrets using Hashi provider
                       properties:
@@ -3595,6 +3635,46 @@ spec:
                         - region
                         - vault
                       type: object
+                    passworddepot:
+                      description: Configures a store to sync secrets with a Password Depot instance.
+                      properties:
+                        auth:
+                          description: Auth configures how secret-manager authenticates with a Password Depot instance.
+                          properties:
+                            secretRef:
+                              properties:
+                                credentials:
+                                  description: Username / Password is used for authentication.
+                                  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
+                          required:
+                            - secretRef
+                          type: object
+                        database:
+                          description: Database to use as source
+                          type: string
+                        host:
+                          description: URL configures the Password Depot instance URL.
+                          type: string
+                      required:
+                        - auth
+                        - database
+                        - host
+                      type: object
                     pulumi:
                       description: Pulumi configures this store to sync secrets using the Pulumi provider
                       properties:
@@ -6668,6 +6748,46 @@ spec:
                         - region
                         - vault
                       type: object
+                    passworddepot:
+                      description: Configures a store to sync secrets with a Password Depot instance.
+                      properties:
+                        auth:
+                          description: Auth configures how secret-manager authenticates with a Password Depot instance.
+                          properties:
+                            secretRef:
+                              properties:
+                                credentials:
+                                  description: Username / Password is used for authentication.
+                                  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
+                          required:
+                            - secretRef
+                          type: object
+                        database:
+                          description: Database to use as source
+                          type: string
+                        host:
+                          description: URL configures the Password Depot instance URL.
+                          type: string
+                      required:
+                        - auth
+                        - database
+                        - host
+                      type: object
                     vault:
                       description: Vault configures this store to sync secrets using Hashi provider
                       properties:
@@ -8763,6 +8883,46 @@ spec:
                         - region
                         - vault
                       type: object
+                    passworddepot:
+                      description: Configures a store to sync secrets with a Password Depot instance.
+                      properties:
+                        auth:
+                          description: Auth configures how secret-manager authenticates with a Password Depot instance.
+                          properties:
+                            secretRef:
+                              properties:
+                                credentials:
+                                  description: Username / Password is used for authentication.
+                                  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
+                          required:
+                            - secretRef
+                          type: object
+                        database:
+                          description: Database to use as source
+                          type: string
+                        host:
+                          description: URL configures the Password Depot instance URL.
+                          type: string
+                      required:
+                        - auth
+                        - database
+                        - host
+                      type: object
                     pulumi:
                       description: Pulumi configures this store to sync secrets using the Pulumi provider
                       properties:

+ 129 - 0
docs/api/spec.md

@@ -4989,6 +4989,122 @@ External Secrets meta/v1.SecretKeySelector
 </tr>
 </tbody>
 </table>
+<h3 id="external-secrets.io/v1beta1.PasswordDepotAuth">PasswordDepotAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.PasswordDepotProvider">PasswordDepotProvider</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>secretRef</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.PasswordDepotSecretRef">
+PasswordDepotSecretRef
+</a>
+</em>
+</td>
+<td>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1beta1.PasswordDepotProvider">PasswordDepotProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.SecretStoreProvider">SecretStoreProvider</a>)
+</p>
+<p>
+<p>Configures a store to sync secrets with a Password Depot instance.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>host</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>URL configures the Password Depot instance URL.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>database</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Database to use as source</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.PasswordDepotAuth">
+PasswordDepotAuth
+</a>
+</em>
+</td>
+<td>
+<p>Auth configures how secret-manager authenticates with a Password Depot instance.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1beta1.PasswordDepotSecretRef">PasswordDepotSecretRef
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.PasswordDepotAuth">PasswordDepotAuth</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>credentials</code></br>
+<em>
+<a href="https://pkg.go.dev/github.com/external-secrets/external-secrets/apis/meta/v1#SecretKeySelector">
+External Secrets meta/v1.SecretKeySelector
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Username / Password is used for authentication.</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.Provider">Provider
 </h3>
 <p>
@@ -5759,6 +5875,19 @@ FortanixProvider
 <p>Fortanix configures this store to sync secrets using the Fortanix provider</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>passworddepot</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.PasswordDepotProvider">
+PasswordDepotProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1beta1.SecretStoreRef">SecretStoreRef

+ 40 - 0
docs/provider-passworddepot.md

@@ -0,0 +1,40 @@
+External Secrets Operator integrates with [Password Depot API](https://www.password-depot.de/) to sync Password Depot to secrets held on the Kubernetes cluster.
+
+### Authentication
+
+The API requires a username and password. 
+
+
+```yaml
+{% include 'password-depot-credentials-secret.yaml' %}
+```
+
+### Update secret store
+Be sure the `passworddepot` provider is listed in the `Kind=SecretStore` and host and database are set.
+
+```yaml
+{% include 'passworddepot-secret-store.yaml' %}
+```
+
+
+### Creating external secret
+
+To sync a Password Depot variable to a secret on the Kubernetes cluster, a `Kind=ExternalSecret` is needed.
+
+```yaml
+{% include 'passworddepot-external-secret.yaml' %}
+```
+
+#### Using DataFrom
+
+DataFrom can be used to get a variable as a JSON string and attempt to parse it.
+
+```yaml
+{% include 'passworddepot-external-secret-json.yaml' %}
+```
+
+### Getting the Kubernetes secret
+The operator will fetch the project variable and inject it as a `Kind=Secret`.
+```
+kubectl get secret passworddepot-secret-to-create -o jsonpath='{.data.secretKey}' | base64 -d
+```

+ 10 - 0
docs/snippets/password-depot-credentials-secret.yaml

@@ -0,0 +1,10 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: password-depot-secret
+  labels: 
+    type: password-depot
+type: Opaque 
+stringData:
+  username: the-username-for-password-depot
+  password: the secret password

+ 18 - 0
docs/snippets/passworddepot-external-secret-json.yaml

@@ -0,0 +1,18 @@
+apiVersion: external-secrets.io/v1alpha1
+kind: ExternalSecret
+metadata:
+  name: passworddepot-external-secret-example
+spec:
+  refreshInterval: 1h
+
+  secretStoreRef:
+    kind: SecretStore
+    name: passworddepot-secret-store # Must match SecretStore on the cluster
+
+  target:
+    name: passworddepot-secret-to-create # Name for the secret to be created on the cluster
+    creationPolicy: Owner
+
+  # each property in the secret will be used as the secret key in the SECRET k8s target object
+  dataFrom:
+  - key: "Production.mySecret" # Key of the secret

+ 20 - 0
docs/snippets/passworddepot-external-secret.yaml

@@ -0,0 +1,20 @@
+apiVersion: external-secrets.io/v1alpha1
+kind: ExternalSecret
+metadata:
+  name: passworddepot-external-secret-example
+spec:
+  refreshInterval: 1h
+
+  secretStoreRef:
+    kind: SecretStore
+    name: passworddepot-secret-store # Must match SecretStore on the cluster
+
+  target:
+    name: passworddepot-secret-to-create # Name for the secret to be created on the cluster
+    creationPolicy: Owner
+
+  data:
+    - secretKey: username # Key given to the secret to be created on the cluster
+      remoteRef: 
+        key: Production.mySecret
+        property: login # field named in passworddepot

+ 18 - 0
docs/snippets/passworddepot-secret-store.yaml

@@ -0,0 +1,18 @@
+apiVersion: external-secrets.io/v1alpha1
+kind: ClusterSecretStore
+metadata:
+  name: external-secrets-store
+spec:
+
+  # provider field contains the configuration to access the provider
+  # which contains the secret exactly one provider must be configured.
+  provider:
+
+    passworddepot:
+      host: host-of-password-depot # port is 8714 by default
+      database: "password depot database name"
+      auth:
+        SecretRef:
+          credentials:
+            name: password-depot-secret
+            namespace: external-secrets

+ 533 - 4
docs/spec.md

@@ -238,7 +238,132 @@ see: <a href="https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.
 </td>
 </tr></tbody>
 </table>
-<h3 id="external-secrets.io/v1beta1.AkeylessAuth">AkeylessAuth
+<h3 id="external-secrets.io/v1alpha1.AlibabaAuth">AlibabaAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.AlibabaProvider">AlibabaProvider</a>)
+</p>
+<p>
+<p>AlibabaAuth contains a secretRef for credentials.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>secretRef</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.AlibabaAuthSecretRef">
+AlibabaAuthSecretRef
+</a>
+</em>
+</td>
+<td>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.AlibabaAuthSecretRef">AlibabaAuthSecretRef
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.AlibabaAuth">AlibabaAuth</a>)
+</p>
+<p>
+<p>AlibabaAuthSecretRef holds secret references for Alibaba credentials.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>accessKeyIDSecretRef</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>The AccessKeyID is used for authentication</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>accessKeySecretSecretRef</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>The AccessKeySecret is used for authentication</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.AlibabaProvider">AlibabaProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.SecretStoreProvider">SecretStoreProvider</a>)
+</p>
+<p>
+<p>AlibabaProvider configures a store to sync secrets using the Alibaba Secret Manager provider.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.AlibabaAuth">
+AlibabaAuth
+</a>
+</em>
+</td>
+<td>
+</td>
+</tr>
+<tr>
+<td>
+<code>endpoint</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+</td>
+</tr>
+<tr>
+<td>
+<code>regionID</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Alibaba Region to be used for the provider</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.AzureKVAuth">AzureKVAuth
 </h3>
 <p>
 (<em>Appears on:</em>
@@ -337,7 +462,93 @@ github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
 </tr>
 </tbody>
 </table>
-<h3 id="external-secrets.io/v1beta1.AkeylessKubernetesAuth">AkeylessKubernetesAuth
+<h3 id="external-secrets.io/v1alpha1.CAProvider">CAProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.VaultProvider">VaultProvider</a>)
+</p>
+<p>
+<p>Defines a location to fetch the cert for the vault provider from.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>type</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.CAProviderType">
+CAProviderType
+</a>
+</em>
+</td>
+<td>
+<p>The type of provider to use such as &ldquo;Secret&rdquo;, or &ldquo;ConfigMap&rdquo;.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>name</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>The name of the object located at the provider type.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>key</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>The key the value inside of the provider type to use, only used with &ldquo;Secret&rdquo; type</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>namespace</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>The namespace the Provider type is in.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.CAProviderType">CAProviderType
+(<code>string</code> alias)</p></h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.CAProvider">CAProvider</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Value</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody><tr><td><p>&#34;ConfigMap&#34;</p></td>
+<td></td>
+</tr><tr><td><p>&#34;Secret&#34;</p></td>
+<td></td>
+</tr></tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.ClusterSecretStore">ClusterSecretStore
 </h3>
 <p>
 (<em>Appears on:</em>
@@ -1092,6 +1303,18 @@ string
 <p>Reason is why the ExternalSecret failed to apply to the namespace</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>immutable</code></br>
+<em>
+bool
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Immutable defines if the final secret will be immutable</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1beta1.ClusterExternalSecretSpec">ClusterExternalSecretSpec
@@ -1585,7 +1808,257 @@ string
 </tr>
 </tbody>
 </table>
-<h3 id="external-secrets.io/v1beta1.ExternalSecret">ExternalSecret
+<h3 id="external-secrets.io/v1alpha1.OracleAuth">OracleAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.OracleProvider">OracleProvider</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>secretRef</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.OracleSecretRef">
+OracleSecretRef
+</a>
+</em>
+</td>
+<td>
+<p>SecretRef to pass through sensitive information.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.OracleProvider">OracleProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.SecretStoreProvider">SecretStoreProvider</a>)
+</p>
+<p>
+<p>Configures an store to sync secrets using a Oracle Vault
+backend.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.OracleAuth">
+OracleAuth
+</a>
+</em>
+</td>
+<td>
+<p>Auth configures how secret-manager authenticates with the Oracle Vault.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>user</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>User is an access OCID specific to the account.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>tenancy</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>projectID is an access token specific to the secret.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>region</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>projectID is an access token specific to the secret.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.OracleSecretRef">OracleSecretRef
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.OracleAuth">OracleAuth</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>privatekey</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>The Access Token is used for authentication</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>fingerprint</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>projectID is an access token specific to the secret.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.PasswordDepotAuth">PasswordDepotAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.PasswordDepotProvider">PasswordDepotProvider</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>SecretRef</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.PasswordDepotSecretRef">
+PasswordDepotSecretRef
+</a>
+</em>
+</td>
+<td>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.PasswordDepotProvider">PasswordDepotProvider
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.SecretStoreProvider">SecretStoreProvider</a>)
+</p>
+<p>
+<p>Configures a store to sync secrets with a Password Depot instance.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>host</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>URL configures the Password Depot instance URL.</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>database</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Database to use as source</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.PasswordDepotAuth">
+PasswordDepotAuth
+</a>
+</em>
+</td>
+<td>
+<p>Auth configures how secret-manager authenticates with a Password Depot instance.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.PasswordDepotSecretRef">PasswordDepotSecretRef
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1alpha1.PasswordDepotAuth">PasswordDepotAuth</a>)
+</p>
+<p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>credentials</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>Username / Password is used for authentication.</p>
+</td>
+</tr>
+</tbody>
+</table>
+<h3 id="external-secrets.io/v1alpha1.SecretStore">SecretStore
 </h3>
 <p>
 <p>ExternalSecret is the Schema for the external-secrets API.</p>
@@ -5359,7 +5832,21 @@ Kubernetes service account token retrieved by the <code>TokenRequest</code> API.
 <tbody>
 <tr>
 <td>
-<code>serviceAccountRef</code></br>
+<code>oracle</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.OracleProvider">
+OracleProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Oracle configures this store to sync secrets using Oracle Vault provider</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>ibm</code></br>
 <em>
 github.com/external-secrets/external-secrets/apis/meta/v1.ServiceAccountSelector
 </em>
@@ -5399,6 +5886,34 @@ Deprecated: this will be removed in the future.
 Defaults to 10 minutes.</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>alibaba</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.AlibabaProvider">
+AlibabaProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Alibaba configures this store to sync secrets using Alibaba Cloud provider</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>passworddepot</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.PasswordDepotProvider">
+PasswordDepotProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>PasswordDepot configures this store to sync secrets using PasswordDepot provider</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1beta1.VaultLdapAuth">VaultLdapAuth
@@ -6098,6 +6613,20 @@ github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
 <p>The authorized key used for authentication</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>caProvider</code></br>
+<em>
+<a href="#external-secrets.io/v1alpha1.CAProvider">
+CAProvider
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>The provider for the CA bundle to use to validate Vault server certificate.</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1beta1.YandexLockboxCAProvider">YandexLockboxCAProvider

+ 24 - 0
hack/api-docs/mkdocs.yml

@@ -131,3 +131,27 @@ nav:
       - Talks: eso-talks.md
       - Demos: eso-demos.md
       - Blogs: eso-blogs.md
+    - AWS:
+      - Secrets Manager: provider-aws-secrets-manager.md
+      - Parameter Store: provider-aws-parameter-store.md
+    - Azure:
+      - Key Vault: provider-azure-key-vault.md
+    - Google:
+      - Secrets Manager: provider-google-secrets-manager.md
+    - IBM:
+      - Secrets Manager: provider-ibm-secrets-manager.md
+    - HashiCorp Vault: provider-hashicorp-vault.md
+    - Yandex:
+        - Lockbox: provider-yandex-lockbox.md
+    - Password Depot: provider-passworddepot.md
+    - Gitlab:
+      - Gitlab Project Variables: provider-gitlab-project-variables.md
+    - Oracle:
+      - Oracle Vault: provider-oracle-vault.md
+  - References:
+    - API specification: spec.md
+  - Contributing:
+    - Developer guide: contributing-devguide.md
+    - Contributing Process: contributing-process.md
+    - Code of Conduct: contributing-coc.md
+  - Deprecation Policy: deprecation-policy.md

+ 30 - 0
pkg/provider/passworddepot/fake/httpclient_mock.go

@@ -0,0 +1,30 @@
+/*
+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 fake
+
+import "net/http"
+
+// MockClient is the mock client.
+type MockClient struct {
+	index     int
+	FuncStack []func(req *http.Request) (*http.Response, error)
+}
+
+// Do is the mock client's `Do` func.
+func (m *MockClient) Do(req *http.Request) (*http.Response, error) {
+	res, err := m.FuncStack[m.index](req)
+	m.index++
+
+	return res, err
+}

+ 192 - 0
pkg/provider/passworddepot/passworddepot.go

@@ -0,0 +1,192 @@
+/*
+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 passworddepot
+
+import (
+	"context"
+	"errors"
+	"fmt"
+
+	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/types"
+	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"
+)
+
+// Requires PASSWORDDEPOT_TOKEN and PASSWORDDEPOT_PROJECT_ID to be set in environment variables
+
+const (
+	errPasswordDepotCredSecretName            = "credentials are empty"
+	errInvalidClusterStoreMissingSAKNamespace = "invalid clusterStore missing SAK namespace"
+	errFetchSAKSecret                         = "couldn't find secret on cluster: %w"
+	errMissingSAK                             = "missing credentials while setting auth"
+	errUninitalizedPasswordDepotProvider      = "provider passworddepot is not initialized"
+	errJSONSecretUnmarshal                    = "unable to unmarshal secret: %w"
+)
+
+type Client interface {
+	GetSecret(database, key string) (SecretEntry, error)
+}
+
+// PasswordDepot Provider struct with reference to a PasswordDepot client and a projectID.
+type PasswordDepot struct {
+	client   Client
+	database string
+}
+
+func (p *PasswordDepot) ValidateStore(esv1beta1.GenericStore) (admission.Warnings, error) {
+	return nil, nil
+}
+
+func (p *PasswordDepot) Capabilities() esv1beta1.SecretStoreCapabilities {
+	return esv1beta1.SecretStoreReadOnly
+}
+
+// Client for interacting with kubernetes cluster...?
+type passwordDepotClient struct {
+	kube      kclient.Client
+	store     *esv1beta1.PasswordDepotProvider
+	namespace string
+	storeKind string
+}
+type Provider struct{}
+
+func (c *passwordDepotClient) getAuth(ctx context.Context) (string, string, error) {
+	credentialsSecret := &corev1.Secret{}
+	credentialsSecretName := c.store.Auth.SecretRef.Credentials.Name
+	if credentialsSecretName == "" {
+		return "", "", fmt.Errorf(errPasswordDepotCredSecretName)
+	}
+	objectKey := types.NamespacedName{
+		Name:      credentialsSecretName,
+		Namespace: c.namespace,
+	}
+	// only ClusterStore is allowed to set namespace (and then it's required)
+	if c.storeKind == esv1beta1.ClusterSecretStoreKind {
+		if c.store.Auth.SecretRef.Credentials.Namespace == nil {
+			return "", "", fmt.Errorf(errInvalidClusterStoreMissingSAKNamespace)
+		}
+		objectKey.Namespace = *c.store.Auth.SecretRef.Credentials.Namespace
+	}
+
+	err := c.kube.Get(ctx, objectKey, credentialsSecret)
+	if err != nil {
+		return "", "", fmt.Errorf(errFetchSAKSecret, err)
+	}
+
+	username := credentialsSecret.Data["username"]
+	password := credentialsSecret.Data["password"]
+	if (username == nil) || (len(username) == 0 || password == nil) || (len(password) == 0) {
+		return "", "", fmt.Errorf(errMissingSAK)
+	}
+
+	return string(username), string(password), nil
+}
+
+// Function newPasswordDepotProvider returns a reference to a new instance of a 'PasswordDepot' struct.
+func NewPasswordDepotProvider() *PasswordDepot {
+	return &PasswordDepot{}
+}
+
+// Method on PasswordDepot Provider to set up client with credentials and populate projectID.
+func (p *PasswordDepot) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
+	storeSpec := store.GetSpec()
+	if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.PasswordDepot == nil {
+		return nil, fmt.Errorf("no store type or wrong store type")
+	}
+	storeSpecPasswordDepot := storeSpec.Provider.PasswordDepot
+
+	cliStore := passwordDepotClient{
+		kube:      kube,
+		store:     storeSpecPasswordDepot,
+		namespace: namespace,
+		storeKind: store.GetObjectKind().GroupVersionKind().Kind,
+	}
+
+	username, password, err := cliStore.getAuth(ctx)
+	if err != nil {
+		return nil, err
+	}
+
+	// Create a new PasswordDepot client using credentials and options
+	passworddepotClient, err := NewAPI(ctx, storeSpecPasswordDepot.Host, username, password, "8714")
+	if err != nil {
+		return nil, err
+	}
+
+	p.client = passworddepotClient
+	p.database = storeSpecPasswordDepot.Database
+
+	return p, nil
+}
+
+func (p *PasswordDepot) SecretExists(_ context.Context, _ esv1beta1.PushSecretRemoteRef) (bool, error) {
+	return false, fmt.Errorf("not implemented")
+}
+
+func (p *PasswordDepot) Validate() (esv1beta1.ValidationResult, error) {
+	return 0, nil
+}
+
+func (p *PasswordDepot) PushSecret(_ context.Context, _ *corev1.Secret, _ esv1beta1.PushSecretData) error {
+	return fmt.Errorf("not implemented")
+}
+
+func (p *PasswordDepot) GetAllSecrets(_ context.Context, _ esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
+	return nil, fmt.Errorf("GetAllSecrets not implemented")
+}
+
+func (p *PasswordDepot) DeleteSecret(_ context.Context, _ esv1beta1.PushSecretRemoteRef) error {
+	return fmt.Errorf("not implemented")
+}
+
+func (p *PasswordDepot) GetSecret(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
+	if utils.IsNil(p.client) {
+		return nil, fmt.Errorf(errUninitalizedPasswordDepotProvider)
+	}
+
+	data, err := p.client.GetSecret(p.database, ref.Key)
+	if err != nil {
+		return nil, err
+	}
+	mappedData := data.ToMap()
+	value, ok := mappedData[ref.Property]
+	if !ok {
+		return nil, errors.New("key not found in secret data")
+	}
+
+	return value, nil
+}
+
+func (p *PasswordDepot) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
+	data, err := p.client.GetSecret(p.database, ref.Key)
+	if err != nil {
+		return nil, fmt.Errorf("error getting secret %s: %w", ref.Key, err)
+	}
+
+	return data.ToMap(), nil
+}
+
+func (p *PasswordDepot) Close(_ context.Context) error {
+	return nil
+}
+
+func init() {
+	esv1beta1.Register(&PasswordDepot{}, &esv1beta1.SecretStoreProvider{
+		PasswordDepot: &esv1beta1.PasswordDepotProvider{},
+	})
+}

+ 315 - 0
pkg/provider/passworddepot/passworddepot_api.go

@@ -0,0 +1,315 @@
+/*
+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 passworddepot
+
+import (
+	"bytes"
+	"context"
+	"crypto/tls"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+)
+
+const (
+	DoRequestError = "error: do request: %w"
+)
+
+type HTTPClient interface {
+	Do(*http.Request) (*http.Response, error)
+}
+
+type AccessData struct {
+	ClientID    string `json:"client_id"`
+	AccessToken string `json:"access_token"`
+}
+
+type Databases struct {
+	Databases []struct {
+		Name         string    `json:"name"`
+		Fingerprint  string    `json:"fingerprint"`
+		Date         time.Time `json:"date"`
+		Rights       string    `json:"rights"`
+		Reasondelete string    `json:"reasondelete"`
+	} `json:"databases"`
+	Infoclasses          string `json:"infoclasses"`
+	Policyforce          string `json:"policyforce"`
+	Policyminlength      string `json:"policyminlength"`
+	Policyincludeatleast string `json:"policyincludeatleast"`
+	Policymingroups      string `json:"policymingroups"`
+	Policyselectedgroups string `json:"policyselectedgroups"`
+}
+
+type DatabaseEntries struct {
+	Name         string  `json:"name"`
+	Parent       string  `json:"parent"`
+	Entries      []Entry `json:"entries"`
+	Infoclasses  string  `json:"infoclasses"`
+	Reasondelete string  `json:"reasondelete"`
+}
+
+type Entry struct {
+	Name        string    `json:"name"`
+	Login       string    `json:"login"`
+	Password    string    `json:"pass"`
+	URL         string    `json:"url"`
+	Importance  string    `json:"importance"`
+	Date        time.Time `json:"date"`
+	Icon        string    `json:"icon"`
+	Secondeye   string    `json:"secondeye"`
+	Fingerprint string    `json:"fingerprint"`
+	Rights      string    `json:"rights"`
+	Itemclass   string    `json:"itemclass"`
+}
+
+type API struct {
+	client   HTTPClient
+	baseURL  string
+	hostPort string
+	secret   *AccessData
+	password string
+	username string
+}
+
+type SecretEntry struct {
+	Name        string    `json:"name"`
+	Fingerprint string    `json:"fingerprint"`
+	Itemclass   string    `json:"itemclass"`
+	Login       string    `json:"login"`
+	Pass        string    `json:"pass"`
+	URL         string    `json:"url"`
+	Importance  string    `json:"importance"`
+	Date        time.Time `json:"date"`
+	Comment     string    `json:"comment"`
+	Expirydate  string    `json:"expirydate"`
+	Tags        string    `json:"tags"`
+	Author      string    `json:"author"`
+	Category    string    `json:"category"`
+	Icon        string    `json:"icon"`
+	Secondeye   string    `json:"secondeye"`
+	Secondpass  string    `json:"secondpass"`
+	Template    string    `json:"template"`
+	Acm         string    `json:"acm"`
+	Paramstr    string    `json:"paramstr"`
+	Loginid     string    `json:"loginid"`
+	Passid      string    `json:"passid"`
+	Donotaddon  string    `json:"donotaddon"`
+	Markassafe  string    `json:"markassafe"`
+	Safemode    string    `json:"safemode"`
+}
+
+var errDBNotFound = errors.New("database not found")
+var errSecretNotFound = errors.New("secret not found")
+
+// load tls certificates
+
+func NewAPI(ctx context.Context, baseURL, username, password, hostPort string) (*API, error) {
+	api := &API{
+		baseURL:  baseURL,
+		hostPort: hostPort,
+		username: username,
+		password: password,
+	}
+	tr := &http.Transport{
+		TLSClientConfig: &tls.Config{MinVersion: tls.VersionTLS12},
+	}
+
+	api.client = &http.Client{Transport: tr}
+	err := api.login(ctx)
+	if err != nil {
+		return nil, fmt.Errorf("failed to login: %w", err)
+	}
+	return api, nil
+}
+
+func (api *API) doAuthenticatedRequest(r *http.Request) (*http.Response, error) {
+	r.Header.Add("access_token", api.secret.AccessToken)
+	r.Header.Add("client_id", api.secret.ClientID)
+
+	return api.client.Do(r)
+}
+func (api *API) getDatabaseFingerprint(database string) (string, error) {
+	databases, err := api.ListDatabases()
+	if err != nil {
+		return "", fmt.Errorf("error: getting database list: %w", err)
+	}
+
+	for _, db := range databases.Databases {
+		if strings.Contains(db.Name, database) {
+			return db.Fingerprint, nil
+		}
+	}
+
+	return "", errDBNotFound
+}
+
+func (api *API) getSecretFingerprint(databaseFingerprint, secretName, folder string) (string, error) {
+	secrets, err := api.ListSecrets(databaseFingerprint, folder)
+	if err != nil {
+		return "", fmt.Errorf("error: getting secrets list: %w", err)
+	}
+
+	parts := strings.Split(secretName, ".")
+	searchName := parts[0]
+	var fingerprint string
+	for _, entry := range secrets.Entries {
+		if strings.Contains(entry.Name, searchName) {
+			fingerprint = entry.Fingerprint
+			if len(parts) > 1 {
+				return api.getSecretFingerprint(databaseFingerprint, strings.Join(parts[1:], "."), fingerprint)
+			}
+			return fingerprint, nil
+		}
+	}
+	return "", errSecretNotFound
+}
+
+func (api *API) getendpointURL(endpoint string) string {
+	return fmt.Sprintf("https://%s:%s/v1.0/%s", api.baseURL, api.hostPort, endpoint)
+}
+
+func (api *API) login(ctx context.Context) error {
+	loginRequest, err := http.NewRequestWithContext(ctx, "GET", api.getendpointURL("login"), http.NoBody)
+	if err != nil {
+		return fmt.Errorf("error creating request: %w", err)
+	}
+	loginRequest.Header.Add("user", api.username)
+	loginRequest.Header.Add("pass", api.password)
+
+	resp, err := api.client.Do(loginRequest) //nolint:bodyclose // linters bug
+	if err != nil {
+		return fmt.Errorf(DoRequestError, err)
+	}
+
+	accessData := AccessData{}
+	err = ReadAndUnmarshal(resp, &accessData)
+	if err != nil {
+		return fmt.Errorf("error: failed to unmarshal response body: %w", err)
+	}
+
+	api.secret = &accessData
+
+	return nil
+}
+
+func (api *API) ListSecrets(dbFingerprint, folder string) (DatabaseEntries, error) {
+	endpointURL := api.getendpointURL(fmt.Sprintf("list?db=%s", dbFingerprint))
+	if folder != "" {
+		endpointURL = fmt.Sprintf("%s&folder=%s", endpointURL, folder)
+	}
+	listSecrets, err := http.NewRequest("GET", endpointURL, http.NoBody)
+	if err != nil {
+		return DatabaseEntries{}, fmt.Errorf("error: creating secrets request: %w", err)
+	}
+
+	respSecretsList, err := api.doAuthenticatedRequest(listSecrets) //nolint:bodyclose // linters bug
+	if err != nil {
+		return DatabaseEntries{}, fmt.Errorf(DoRequestError, err)
+	}
+
+	dbEntries := DatabaseEntries{}
+	err = ReadAndUnmarshal(respSecretsList, &dbEntries)
+	return dbEntries, err
+}
+
+func ReadAndUnmarshal(resp *http.Response, target any) error {
+	var buf bytes.Buffer
+	defer func() {
+		if resp.Body != nil {
+			resp.Body.Close()
+		}
+	}()
+	if resp.StatusCode < 200 || resp.StatusCode > 299 {
+		return fmt.Errorf("failed to authenticate with the given credentials: %d %s", resp.StatusCode, buf.String())
+	}
+	_, err := buf.ReadFrom(resp.Body)
+	if err != nil {
+		return err
+	}
+	return json.Unmarshal(buf.Bytes(), target)
+}
+
+func (api *API) ListDatabases() (Databases, error) {
+	listDBRequest, err := http.NewRequest("GET", api.getendpointURL("list"), http.NoBody)
+	if err != nil {
+		return Databases{}, fmt.Errorf("error: creating db request: %w", err)
+	}
+
+	respDBList, err := api.doAuthenticatedRequest(listDBRequest) //nolint:bodyclose // linters bug
+	if err != nil {
+		return Databases{}, fmt.Errorf(DoRequestError, err)
+	}
+
+	databases := Databases{}
+	err = ReadAndUnmarshal(respDBList, &databases)
+	return databases, err
+}
+
+func (api *API) GetSecret(database, secretName string) (SecretEntry, error) {
+	dbFingerprint, err := api.getDatabaseFingerprint(database)
+	if err != nil {
+		return SecretEntry{}, fmt.Errorf("error: getting DB fingerprint: %w", err)
+	}
+
+	secretFingerprint, err := api.getSecretFingerprint(dbFingerprint, secretName, "")
+	if err != nil {
+		return SecretEntry{}, fmt.Errorf("error: getting Secret fingerprint: %w", err)
+	}
+	readSecretRequest, err := http.NewRequest("GET", api.getendpointURL(fmt.Sprintf("read?db=%s&entry=%s", dbFingerprint, secretFingerprint)), http.NoBody)
+	if err != nil {
+		return SecretEntry{}, fmt.Errorf("error: creating secrets request: %w", err)
+	}
+
+	respSecretRead, err := api.doAuthenticatedRequest(readSecretRequest) //nolint:bodyclose // linters bug
+	if err != nil {
+		return SecretEntry{}, fmt.Errorf(DoRequestError, err)
+	}
+
+	secretEntry := SecretEntry{}
+	err = ReadAndUnmarshal(respSecretRead, &secretEntry)
+	return secretEntry, err
+}
+
+func (s SecretEntry) ToMap() map[string][]byte {
+	m := make(map[string][]byte)
+
+	m["name"] = []byte(s.Name)
+	m["fingerprint"] = []byte(s.Fingerprint)
+	m["itemclass"] = []byte(s.Itemclass)
+	m["login"] = []byte(s.Login)
+	m["pass"] = []byte(s.Pass)
+	m["url"] = []byte(s.URL)
+	m["importance"] = []byte(s.Importance)
+	m["comment"] = []byte(s.Comment)
+	m["expirydate"] = []byte(s.Expirydate)
+	m["tags"] = []byte(s.Tags)
+	m["author"] = []byte(s.Author)
+	m["category"] = []byte(s.Category)
+	m["icon"] = []byte(s.Icon)
+	m["secondeye"] = []byte(s.Secondeye)
+	m["secondpass"] = []byte(s.Secondpass)
+	m["template"] = []byte(s.Template)
+	m["acm"] = []byte(s.Acm)
+	m["paramstr"] = []byte(s.Paramstr)
+	m["loginid"] = []byte(s.Loginid)
+	m["passid"] = []byte(s.Passid)
+	m["donotaddon"] = []byte(s.Donotaddon)
+	m["markassafe"] = []byte(s.Markassafe)
+	m["safemode"] = []byte(s.Safemode)
+
+	return m
+}

+ 289 - 0
pkg/provider/passworddepot/passworddepot_api_test.go

@@ -0,0 +1,289 @@
+/*
+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 passworddepot
+
+import (
+	"bytes"
+	"encoding/json"
+	"io"
+	"net/http"
+	"reflect"
+	"testing"
+	"time"
+
+	fakepassworddepot "github.com/external-secrets/external-secrets/pkg/provider/passworddepot/fake"
+)
+
+const fingerprint1 = "53fe39bd-0d5c-4b46-83b3-122fef14364e"
+const mySecret = "my-secret"
+const someDB = "some-db"
+
+var (
+	mockDatabaseList = Databases{
+		Databases: []struct {
+			Name         string    `json:"name"`
+			Fingerprint  string    `json:"fingerprint"`
+			Date         time.Time `json:"date"`
+			Rights       string    `json:"rights"`
+			Reasondelete string    `json:"reasondelete"`
+		}{
+			{
+				Name:        someDB,
+				Fingerprint: "434da246-c165-499b-8996-6ee2a9673429",
+			},
+		},
+	}
+
+	mockDatabaseEntries = DatabaseEntries{
+		Entries: []Entry{
+			{
+				Name:        mySecret,
+				Fingerprint: fingerprint1,
+			},
+		},
+	}
+)
+
+func TestPasswortDepotApiListDatabases(t *testing.T) {
+	type fields struct {
+		funcStack []func(req *http.Request) (*http.Response, error)
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		want    Databases
+		wantErr bool
+	}{
+		{
+			name: "list databases",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
+				},
+			},
+			want: Databases{
+				Databases: []struct {
+					Name         string    `json:"name"`
+					Fingerprint  string    `json:"fingerprint"`
+					Date         time.Time `json:"date"`
+					Rights       string    `json:"rights"`
+					Reasondelete string    `json:"reasondelete"`
+				}{
+					{
+						Name:        someDB,
+						Fingerprint: "434da246-c165-499b-8996-6ee2a9673429",
+					},
+				},
+			},
+			wantErr: false,
+		},
+		{
+			name: "bad response body",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder([]byte("bad response"), false), //nolint:bodyclose // linters bug
+				},
+			},
+			want:    Databases{},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			api := &API{
+				client: &fakepassworddepot.MockClient{
+					FuncStack: tt.fields.funcStack,
+				},
+				baseURL:  "localhost",
+				hostPort: "8714",
+				password: "test",
+				username: "test",
+				secret: &AccessData{
+					ClientID:    "12345",
+					AccessToken: "f02a1f7c-7629-422e-96f5-a98b29da1287",
+				},
+			}
+			got, err := api.ListDatabases()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("PasswortDepotApi.ListDatabases() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("PasswortDepotApi.ListDatabases() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestPasswortDepotApiGetSecret(t *testing.T) {
+	type fields struct {
+		funcStack []func(req *http.Request) (*http.Response, error)
+	}
+	type args struct {
+		database   string
+		secretName string
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		args    args
+		want    SecretEntry
+		wantErr bool
+	}{
+		{
+			name: "get secret",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true),    //nolint:bodyclose // linters bug
+					createResponder(mockDatabaseEntries, true), //nolint:bodyclose // linters bug
+					createResponder(SecretEntry{ //nolint:bodyclose // linters bug
+						Name:        mySecret,
+						Fingerprint: fingerprint1,
+						Pass:        "yery53cr3t",
+					}, true),
+				},
+			},
+			args: args{
+				database:   someDB,
+				secretName: mySecret,
+			},
+			want: SecretEntry{
+				Name:        mySecret,
+				Fingerprint: fingerprint1,
+				Pass:        "yery53cr3t",
+			},
+			wantErr: false,
+		},
+		{
+			name: "get nested secret",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true), //nolint:bodyclose // linters bug
+					createResponder(DatabaseEntries{ //nolint:bodyclose // linters bug
+						Entries: []Entry{
+							{
+								Name:        "Production",
+								Fingerprint: "33f918ae-ec60-41cb-8131-67d8f21eef4c",
+							},
+						},
+					}, true),
+					createResponder(mockDatabaseEntries, true), //nolint:bodyclose // linters bug
+					createResponder(SecretEntry{ //nolint:bodyclose // linters bug
+						Name:        mySecret,
+						Fingerprint: fingerprint1,
+						Pass:        "yery53cr3t",
+					}, true),
+				},
+			},
+			args: args{
+				database:   someDB,
+				secretName: "Production.my-secret",
+			},
+			want: SecretEntry{
+				Name:        mySecret,
+				Fingerprint: fingerprint1,
+				Pass:        "yery53cr3t",
+			},
+			wantErr: false,
+		},
+		{
+			name: "bad response body on database entries",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true),    //nolint:bodyclose // linters bug
+					createResponder([]byte("bad body"), false), //nolint:bodyclose // linters bug
+				},
+			},
+			args: args{
+				database:   someDB,
+				secretName: mySecret,
+			},
+			want:    SecretEntry{},
+			wantErr: true,
+		},
+		{
+			name: "bad response on secret entry",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true),             //nolint:bodyclose // linters bug
+					createResponder(mockDatabaseEntries, true),          //nolint:bodyclose // linters bug
+					createResponder([]byte("bad response body"), false), //nolint:bodyclose // linters bug
+				},
+			},
+			args: args{
+				database:   someDB,
+				secretName: mySecret,
+			},
+			want:    SecretEntry{},
+			wantErr: true,
+		},
+		{
+			name: "no secret with name",
+			fields: fields{
+				funcStack: []func(req *http.Request) (*http.Response, error){
+					createResponder(mockDatabaseList, true),                    //nolint:bodyclose // linters bug
+					createResponder(DatabaseEntries{Entries: []Entry{}}, true), //nolint:bodyclose // linters bug
+				},
+			},
+			args: args{
+				database:   someDB,
+				secretName: mySecret,
+			},
+			want:    SecretEntry{},
+			wantErr: true,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			api := &API{
+				client: &fakepassworddepot.MockClient{
+					FuncStack: tt.fields.funcStack,
+				},
+				baseURL:  "localhost",
+				hostPort: "8714",
+				password: "test",
+				username: "test",
+				secret: &AccessData{
+					ClientID:    "12345",
+					AccessToken: "f02a1f7c-7629-422e-96f5-a98b29da1287",
+				},
+			}
+			got, err := api.GetSecret(tt.args.database, tt.args.secretName)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("PasswortDepotApi.GetSecret() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("PasswortDepotApi.GetSecret() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func createResponder(payload interface{}, withMarshal bool) func(*http.Request) (*http.Response, error) {
+	return func(req *http.Request) (*http.Response, error) {
+		var payloadBytes []byte
+		if withMarshal {
+			payloadBytes, _ = json.Marshal(payload)
+		} else {
+			payloadBytes = payload.([]byte)
+		}
+		res := http.Response{
+			Status:     "OK",
+			StatusCode: http.StatusOK,
+			Body:       io.NopCloser(bytes.NewReader(payloadBytes)),
+		}
+		return &res, nil
+	}
+}

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

@@ -36,6 +36,7 @@ import (
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onboardbase"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/onepassword"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/oracle"
+	_ "github.com/external-secrets/external-secrets/pkg/provider/passworddepot"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/pulumi"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/scaleway"
 	_ "github.com/external-secrets/external-secrets/pkg/provider/senhasegura"