Browse Source

added userPass authentication to the hashicorp vault provider (#2539)

Signed-off-by: Martin Schuessler <1407812+c0ffee@users.noreply.github.com>
Co-authored-by: Moritz Johner <moolen@users.noreply.github.com>
Martin Schuessler 2 years ago
parent
commit
f777a85156

+ 23 - 1
apis/externalsecrets/v1beta1/secretstore_vault_types.go

@@ -81,7 +81,7 @@ type VaultProvider struct {
 }
 
 // VaultAuth is the configuration used to authenticate with a Vault server.
-// Only one of `tokenSecretRef`, `appRole`,  `kubernetes`, `ldap`, `jwt` or `cert`
+// Only one of `tokenSecretRef`, `appRole`,  `kubernetes`, `ldap`, `userPass`, `jwt` or `cert`
 // can be specified.
 type VaultAuth struct {
 	// TokenSecretRef authenticates with Vault by presenting a token.
@@ -117,6 +117,10 @@ type VaultAuth struct {
 	// AWS IAM authentication method
 	// +optional
 	Iam *VaultIamAuth `json:"iam,omitempty"`
+
+	// UserPass authenticates with Vault by passing username/password pair
+	// +optional
+	UserPass *VaultUserPassAuth `json:"userPass,omitempty"`
 }
 
 // VaultAppRole authenticates with Vault using the App Role auth mechanism,
@@ -304,3 +308,21 @@ type VaultIamAuth struct {
 	// +optional
 	JWTAuth *VaultAwsJWTAuth `json:"jwt,omitempty"`
 }
+
+// VaultUserPassAuth authenticates with Vault using UserPass authentication method,
+// with the username and password stored in a Kubernetes Secret resource.
+type VaultUserPassAuth struct {
+	// Path where the UserPassword authentication backend is mounted
+	// in Vault, e.g: "user"
+	// +kubebuilder:default=user
+	Path string `json:"path"`
+
+	// Username is a user name used to authenticate using the UserPass Vault
+	// authentication method
+	Username string `json:"username"`
+
+	// SecretRef to a key in a Secret resource containing password for the
+	// user used to authenticate with Vault using the UserPass authentication
+	// method
+	SecretRef esmeta.SecretKeySelector `json:"secretRef,omitempty"`
+}

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

@@ -2245,6 +2245,11 @@ func (in *VaultAuth) DeepCopyInto(out *VaultAuth) {
 		*out = new(VaultIamAuth)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.UserPass != nil {
+		in, out := &in.UserPass, &out.UserPass
+		*out = new(VaultUserPassAuth)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultAuth.
@@ -2499,6 +2504,22 @@ func (in *VaultProvider) DeepCopy() *VaultProvider {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *VaultUserPassAuth) DeepCopyInto(out *VaultUserPassAuth) {
+	*out = *in
+	in.SecretRef.DeepCopyInto(&out.SecretRef)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VaultUserPassAuth.
+func (in *VaultUserPassAuth) DeepCopy() *VaultUserPassAuth {
+	if in == nil {
+		return nil
+	}
+	out := new(VaultUserPassAuth)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *WebhookCAProvider) DeepCopyInto(out *WebhookCAProvider) {
 	*out = *in
 	if in.Namespace != nil {

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

@@ -3540,6 +3540,45 @@ spec:
                                   defaults to the namespace of the referent.
                                 type: string
                             type: object
+                          userPass:
+                            description: UserPass authenticates with Vault by passing
+                              username/password pair
+                            properties:
+                              path:
+                                default: user
+                                description: 'Path where the UserPassword authentication
+                                  backend is mounted in Vault, e.g: "user"'
+                                type: string
+                              secretRef:
+                                description: SecretRef to a key in a Secret resource
+                                  containing password for the user used to authenticate
+                                  with Vault using the UserPass authentication method
+                                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
+                              username:
+                                description: Username is a user name used to authenticate
+                                  using the UserPass Vault authentication method
+                                type: string
+                            required:
+                            - path
+                            - username
+                            type: object
                         type: object
                       caBundle:
                         description: PEM encoded CA bundle used to validate Vault

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

@@ -3540,6 +3540,45 @@ spec:
                                   defaults to the namespace of the referent.
                                 type: string
                             type: object
+                          userPass:
+                            description: UserPass authenticates with Vault by passing
+                              username/password pair
+                            properties:
+                              path:
+                                default: user
+                                description: 'Path where the UserPassword authentication
+                                  backend is mounted in Vault, e.g: "user"'
+                                type: string
+                              secretRef:
+                                description: SecretRef to a key in a Secret resource
+                                  containing password for the user used to authenticate
+                                  with Vault using the UserPass authentication method
+                                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
+                              username:
+                                description: Username is a user name used to authenticate
+                                  using the UserPass Vault authentication method
+                                type: string
+                            required:
+                            - path
+                            - username
+                            type: object
                         type: object
                       caBundle:
                         description: PEM encoded CA bundle used to validate Vault

+ 37 - 0
config/crds/bases/generators.external-secrets.io_vaultdynamicsecrets.yaml

@@ -504,6 +504,43 @@ spec:
                               defaults to the namespace of the referent.
                             type: string
                         type: object
+                      userPass:
+                        description: UserPass authenticates with Vault by passing
+                          username/password pair
+                        properties:
+                          path:
+                            default: user
+                            description: 'Path where the UserPassword authentication
+                              backend is mounted in Vault, e.g: "user"'
+                            type: string
+                          secretRef:
+                            description: SecretRef to a key in a Secret resource containing
+                              password for the user used to authenticate with Vault
+                              using the UserPass authentication method
+                            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
+                          username:
+                            description: Username is a user name used to authenticate
+                              using the UserPass Vault authentication method
+                            type: string
+                        required:
+                        - path
+                        - username
+                        type: object
                     type: object
                   caBundle:
                     description: PEM encoded CA bundle used to validate Vault server

+ 81 - 0
deploy/crds/bundle.yaml

@@ -3032,6 +3032,33 @@ spec:
                                   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
+                            userPass:
+                              description: UserPass authenticates with Vault by passing username/password pair
+                              properties:
+                                path:
+                                  default: user
+                                  description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"'
+                                  type: string
+                                secretRef:
+                                  description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method
+                                  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
+                                username:
+                                  description: Username is a user name used to authenticate using the UserPass Vault authentication method
+                                  type: string
+                              required:
+                                - path
+                                - username
+                              type: object
                           type: object
                         caBundle:
                           description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.
@@ -6735,6 +6762,33 @@ spec:
                                   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
+                            userPass:
+                              description: UserPass authenticates with Vault by passing username/password pair
+                              properties:
+                                path:
+                                  default: user
+                                  description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"'
+                                  type: string
+                                secretRef:
+                                  description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method
+                                  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
+                                username:
+                                  description: Username is a user name used to authenticate using the UserPass Vault authentication method
+                                  type: string
+                              required:
+                                - path
+                                - username
+                              type: object
                           type: object
                         caBundle:
                           description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.
@@ -7876,6 +7930,33 @@ spec:
                               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
+                        userPass:
+                          description: UserPass authenticates with Vault by passing username/password pair
+                          properties:
+                            path:
+                              default: user
+                              description: 'Path where the UserPassword authentication backend is mounted in Vault, e.g: "user"'
+                              type: string
+                            secretRef:
+                              description: SecretRef to a key in a Secret resource containing password for the user used to authenticate with Vault using the UserPass authentication method
+                              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
+                            username:
+                              description: Username is a user name used to authenticate using the UserPass Vault authentication method
+                              type: string
+                          required:
+                            - path
+                            - username
+                          type: object
                       type: object
                     caBundle:
                       description: PEM encoded CA bundle used to validate Vault server certificate. Only used if the Server URL is using HTTPS protocol. This parameter is ignored for plain HTTP protocol connection. If not set the system root certificates are used to validate the TLS connection.

+ 74 - 1
docs/api/spec.md

@@ -5890,7 +5890,7 @@ resource is used as the app role secret.</p>
 </p>
 <p>
 <p>VaultAuth is the configuration used to authenticate with a Vault server.
-Only one of <code>tokenSecretRef</code>, <code>appRole</code>,  <code>kubernetes</code>, <code>ldap</code>, <code>jwt</code> or <code>cert</code>
+Only one of <code>tokenSecretRef</code>, <code>appRole</code>,  <code>kubernetes</code>, <code>ldap</code>, <code>userPass</code>, <code>jwt</code> or <code>cert</code>
 can be specified.</p>
 </p>
 <table>
@@ -6005,6 +6005,20 @@ VaultIamAuth
 AWS IAM authentication method</p>
 </td>
 </tr>
+<tr>
+<td>
+<code>userPass</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.VaultUserPassAuth">
+VaultUserPassAuth
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>UserPass authenticates with Vault by passing username/password pair</p>
+</td>
+</tr>
 </tbody>
 </table>
 <h3 id="external-secrets.io/v1beta1.VaultAwsAuth">VaultAwsAuth
@@ -6750,6 +6764,65 @@ the option is enabled serverside.
 </tr>
 </tbody>
 </table>
+<h3 id="external-secrets.io/v1beta1.VaultUserPassAuth">VaultUserPassAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.VaultAuth">VaultAuth</a>)
+</p>
+<p>
+<p>VaultUserPassAuth authenticates with Vault using UserPass authentication method,
+with the username and password stored in a Kubernetes Secret resource.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>path</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Path where the UserPassword authentication backend is mounted
+in Vault, e.g: &ldquo;user&rdquo;</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>username</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Username is a user name used to authenticate using the UserPass Vault
+authentication method</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>secretRef</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>
+<p>SecretRef to a key in a Secret resource containing password for the
+user used to authenticate with Vault using the UserPass authentication
+method</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.WebhookCAProvider">WebhookCAProvider
 </h3>
 <p>

+ 13 - 0
docs/provider/hashicorp-vault.md

@@ -272,6 +272,7 @@ We support five different modes for authentication:
 [appRole](https://www.vaultproject.io/docs/auth/approle),
 [kubernetes-native](https://www.vaultproject.io/docs/auth/kubernetes),
 [ldap](https://www.vaultproject.io/docs/auth/ldap),
+[userPass](https://www.vaultproject.io/docs/auth/userpass),
 [jwt/oidc](https://www.vaultproject.io/docs/auth/jwt) and
 [awsAuth](https://developer.hashicorp.com/vault/docs/auth/aws), each one comes with it's own
 trade-offs. Depending on the authentication method you need to adapt your environment.
@@ -322,6 +323,18 @@ in a `Kind=Secret` referenced by the `secretRef`.
 ```
 **NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` in `secretRef` with the namespace where the secret resides.
 
+#### UserPass authentication
+
+[UserPass authentication](https://www.vaultproject.io/docs/auth/userpass) uses
+username/password pair to get an access token. Username is stored directly in
+a `Kind=SecretStore` or `Kind=ClusterSecretStore` resource, password is stored
+in a `Kind=Secret` referenced by the `secretRef`.
+
+```yaml
+{% include 'vault-userpass-store.yaml' %}
+```
+**NOTE:** In case of a `ClusterSecretStore`, Be sure to provide `namespace` in `secretRef` with the namespace where the secret resides.
+
 #### JWT/OIDC authentication
 
 [JWT/OIDC](https://www.vaultproject.io/docs/auth/jwt) uses either a

+ 21 - 0
docs/snippets/vault-userpass-store.yaml

@@ -0,0 +1,21 @@
+apiVersion: external-secrets.io/v1beta1
+kind: SecretStore
+metadata:
+  name: vault-backend
+  namespace: example
+spec:
+  provider:
+    vault:
+      server: "https://vault.acme.org"
+      path: "secret"
+      version: "v2"
+      auth:
+        # VaultUserPass authenticates with Vault using the UserPass auth mechanism
+        # https://www.vaultproject.io/docs/auth/userpass
+        userPass:
+          # Path where the UserPass authentication backend is mounted
+          path: "userpass"
+          username: "username"
+          secretRef:
+            name: "my-secret"
+            key: "password"

+ 73 - 1
docs/spec.md

@@ -5010,7 +5010,7 @@ resource is used as the app role secret.</p>
 </p>
 <p>
 <p>VaultAuth is the configuration used to authenticate with a Vault server.
-Only one of <code>tokenSecretRef</code>, <code>appRole</code>,  <code>kubernetes</code>, <code>ldap</code>, <code>jwt</code> or <code>cert</code>
+Only one of <code>tokenSecretRef</code>, <code>appRole</code>,  <code>kubernetes</code>, <code>ldap</code>, <code>userPass</code>, <code>jwt</code> or <code>cert</code>
 can be specified.</p>
 </p>
 <table>
@@ -5080,6 +5080,21 @@ the LDAP authentication method</p>
 </tr>
 <tr>
 <td>
+<code>userPass</code></br>
+<em>
+<a href="#external-secrets.io/v1beta1.VaultUserPassAuth">
+VaultUserPassAuth
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>UserPass authenticates with Vault by passing username/password pair using
+the userPass authentication method</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>jwt</code></br>
 <em>
 <a href="#external-secrets.io/v1beta1.VaultJwtAuth">
@@ -5443,6 +5458,63 @@ method</p>
 </tr>
 </tbody>
 </table>
+<h3 id="external-secrets.io/v1beta1.VaultUserPassAuth">VaultUserPassAuth
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1beta1.VaultAuth">VaultAuth</a>)
+</p>
+<p>
+<p>VaultUserPassAuth authenticates with Vault using the UserPass authentication method,
+with the username and password stored in a Kubernetes Secret resource.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>path</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Path where the UserPass authentication backend is mounted
+in Vault, e.g: &ldquo;userpass&rdquo;</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>username</code></br>
+<em>
+string
+</em>
+</td>
+<td>
+<p>Username is a user name used to authenticate using the UserPass Vault
+authentication method</p>
+</td>
+</tr>
+<tr>
+<td>
+<code>secretRef</code></br>
+<em>
+github.com/external-secrets/external-secrets/apis/meta/v1.SecretKeySelector
+</em>
+</td>
+<td>
+<p>SecretRef to a key in a Secret resource containing password for the
+user used to authenticate with Vault using the UserPass authentication
+method</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1beta1.VaultProvider">VaultProvider
 </h3>
 <p>

+ 1 - 0
go.mod

@@ -77,6 +77,7 @@ require (
 	github.com/golang-jwt/jwt/v5 v5.0.0
 	github.com/hashicorp/golang-lru v0.5.4
 	github.com/hashicorp/vault/api/auth/aws v0.4.1
+	github.com/hashicorp/vault/api/auth/userpass v0.4.1
 	github.com/keeper-security/secrets-manager-go/core v1.5.2
 	github.com/maxbrunsfeld/counterfeiter/v6 v6.6.2
 	github.com/scaleway/scaleway-sdk-go v1.0.0-beta.17

+ 2 - 0
go.sum

@@ -429,6 +429,8 @@ github.com/hashicorp/vault/api/auth/kubernetes v0.4.1 h1:amFWL1ZhwMWdmqvT51J9phX
 github.com/hashicorp/vault/api/auth/kubernetes v0.4.1/go.mod h1:ikWDT8Adnfvm+8DzKez50vvLD9GWD/unZfJxeqP09sU=
 github.com/hashicorp/vault/api/auth/ldap v0.4.1 h1:5I9K7Tn/b4Sdv/7/ZU5Dvqxce7SnFeMH099bGuipkR8=
 github.com/hashicorp/vault/api/auth/ldap v0.4.1/go.mod h1:BrrVM2IXUII33MKKzdMLJQA4da9TFQoXIO73MVaHM5Y=
+github.com/hashicorp/vault/api/auth/userpass v0.4.1 h1:k/OJOeFqPWdp3H4buyjRF2nPMdgk2qLnEqAAUkDQikU=
+github.com/hashicorp/vault/api/auth/userpass v0.4.1/go.mod h1:PJJd/rurbT65M1nNu9LesRyCb9HI3ywfE10hVeO7gEA=
 github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
 github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=

+ 62 - 15
pkg/provider/vault/vault.go

@@ -38,6 +38,7 @@ import (
 	authaws "github.com/hashicorp/vault/api/auth/aws"
 	authkubernetes "github.com/hashicorp/vault/api/auth/kubernetes"
 	authldap "github.com/hashicorp/vault/api/auth/ldap"
+	authuserpass "github.com/hashicorp/vault/api/auth/userpass"
 	"github.com/spf13/pflag"
 	"github.com/tidwall/gjson"
 	authenticationv1 "k8s.io/api/authentication/v1"
@@ -118,21 +119,22 @@ const (
 	errUnknownCAProvider = "unknown caProvider type given"
 	errCANamespace       = "cannot read secret for CAProvider due to missing namespace on kind ClusterSecretStore"
 
-	errInvalidStore      = "invalid store"
-	errInvalidStoreSpec  = "invalid store spec"
-	errInvalidStoreProv  = "invalid store provider"
-	errInvalidVaultProv  = "invalid vault provider"
-	errInvalidAppRoleID  = "invalid Auth.AppRole: neither `roleId` nor `roleRef` was supplied"
-	errInvalidAppRoleRef = "invalid Auth.AppRole.RoleRef: %w"
-	errInvalidAppRoleSec = "invalid Auth.AppRole.SecretRef: %w"
-	errInvalidClientCert = "invalid Auth.Cert.ClientCert: %w"
-	errInvalidCertSec    = "invalid Auth.Cert.SecretRef: %w"
-	errInvalidJwtSec     = "invalid Auth.Jwt.SecretRef: %w"
-	errInvalidJwtK8sSA   = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
-	errInvalidKubeSA     = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
-	errInvalidKubeSec    = "invalid Auth.Kubernetes.SecretRef: %w"
-	errInvalidLdapSec    = "invalid Auth.Ldap.SecretRef: %w"
-	errInvalidTokenRef   = "invalid Auth.TokenSecretRef: %w"
+	errInvalidStore       = "invalid store"
+	errInvalidStoreSpec   = "invalid store spec"
+	errInvalidStoreProv   = "invalid store provider"
+	errInvalidVaultProv   = "invalid vault provider"
+	errInvalidAppRoleID   = "invalid Auth.AppRole: neither `roleId` nor `roleRef` was supplied"
+	errInvalidAppRoleRef  = "invalid Auth.AppRole.RoleRef: %w"
+	errInvalidAppRoleSec  = "invalid Auth.AppRole.SecretRef: %w"
+	errInvalidClientCert  = "invalid Auth.Cert.ClientCert: %w"
+	errInvalidCertSec     = "invalid Auth.Cert.SecretRef: %w"
+	errInvalidJwtSec      = "invalid Auth.Jwt.SecretRef: %w"
+	errInvalidJwtK8sSA    = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
+	errInvalidKubeSA      = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
+	errInvalidKubeSec     = "invalid Auth.Kubernetes.SecretRef: %w"
+	errInvalidLdapSec     = "invalid Auth.Ldap.SecretRef: %w"
+	errInvalidTokenRef    = "invalid Auth.TokenSecretRef: %w"
+	errInvalidUserPassSec = "invalid Auth.UserPass.SecretRef: %w"
 )
 
 // https://github.com/external-secrets/external-secrets/issues/644
@@ -375,6 +377,11 @@ func (c *Connector) ValidateStore(store esv1beta1.GenericStore) error {
 			return fmt.Errorf(errInvalidLdapSec, err)
 		}
 	}
+	if p.Auth.UserPass != nil {
+		if err := utils.ValidateReferentSecretSelector(store, p.Auth.UserPass.SecretRef); err != nil {
+			return fmt.Errorf(errInvalidUserPassSec, err)
+		}
+	}
 	if p.Auth.TokenSecretRef != nil {
 		if err := utils.ValidateReferentSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
 			return fmt.Errorf(errInvalidTokenRef, err)
@@ -823,6 +830,9 @@ func isReferentSpec(prov *esv1beta1.VaultProvider) bool {
 	if prov.Auth.Ldap != nil && prov.Auth.Ldap.SecretRef.Namespace == nil {
 		return true
 	}
+	if prov.Auth.UserPass != nil && prov.Auth.UserPass.SecretRef.Namespace == nil {
+		return true
+	}
 	if prov.Auth.Jwt != nil && prov.Auth.Jwt.SecretRef != nil && prov.Auth.Jwt.SecretRef.Namespace == nil {
 		return true
 	}
@@ -1123,6 +1133,11 @@ func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
 		return err
 	}
 
+	tokenExists, err = setUserPassAuthToken(ctx, v)
+	if tokenExists {
+		v.log.V(1).Info("Retrieved new token using userPass auth")
+		return err
+	}
 	tokenExists, err = setJwtAuthToken(ctx, v)
 	if tokenExists {
 		v.log.V(1).Info("Retrieved new token using JWT auth")
@@ -1193,6 +1208,18 @@ func setLdapAuthToken(ctx context.Context, v *client) (bool, error) {
 	return false, nil
 }
 
+func setUserPassAuthToken(ctx context.Context, v *client) (bool, error) {
+	userPassAuth := v.store.Auth.UserPass
+	if userPassAuth != nil {
+		err := v.requestTokenWithUserPassAuth(ctx, userPassAuth)
+		if err != nil {
+			return true, err
+		}
+		return true, nil
+	}
+	return false, nil
+}
+
 func setJwtAuthToken(ctx context.Context, v *client) (bool, error) {
 	jwtAuth := v.store.Auth.Jwt
 	if jwtAuth != nil {
@@ -1463,6 +1490,26 @@ func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1bet
 	return nil
 }
 
+func (v *client) requestTokenWithUserPassAuth(ctx context.Context, userPassAuth *esv1beta1.VaultUserPassAuth) error {
+	username := strings.TrimSpace(userPassAuth.Username)
+
+	password, err := v.secretKeyRef(ctx, &userPassAuth.SecretRef)
+	if err != nil {
+		return err
+	}
+	pass := authuserpass.Password{FromString: password}
+	l, err := authuserpass.NewUserpassAuth(username, &pass, authuserpass.WithMountPath(userPassAuth.Path))
+	if err != nil {
+		return err
+	}
+	_, err = v.auth.Login(ctx, l)
+	metrics.ObserveAPICall(constants.ProviderHCVault, constants.CallHCVaultLogin, err)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1.VaultJwtAuth) error {
 	role := strings.TrimSpace(jwtAuth.Role)
 	var jwt string

+ 13 - 0
pkg/provider/vault/vault_test.go

@@ -1591,6 +1591,19 @@ func TestValidateStore(t *testing.T) {
 			wantErr: true,
 		},
 		{
+			name: "invalid userpass secret",
+			args: args{
+				auth: esv1beta1.VaultAuth{
+					UserPass: &esv1beta1.VaultUserPassAuth{
+						SecretRef: esmeta.SecretKeySelector{
+							Namespace: pointer.String("invalid"),
+						},
+					},
+				},
+			},
+			wantErr: true,
+		},
+		{
 			name: "invalid token secret",
 			args: args{
 				auth: esv1beta1.VaultAuth{