Browse Source

Feat/generic webhook ntlm auth (#4316)

* Add support for ntlm authentication for webhook provider

Signed-off-by: Yi Fong Au <yi-fong.au@stater.nl>

refactored executeRequest method

* rm switch case + use esv1

regenerated docs

Signed-off-by: Yi Fong Au <yi-fong.au@stater.nl>

---------

Signed-off-by: Yi Fong Au <yi-fong.au@stater.nl>
yifongau 1 year ago
parent
commit
ec12919d04

+ 21 - 1
apis/externalsecrets/v1/secretstore_webhook_types.go

@@ -20,7 +20,7 @@ import (
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
 )
 
-// AkeylessProvider Configures an store to sync secrets using Akeyless KV.
+// WebHookProvider Configures an store to sync secrets from simple web apis.
 type WebhookProvider struct {
 	// Webhook Method
 	// +optional, default GET
@@ -33,6 +33,10 @@ type WebhookProvider struct {
 	// +optional
 	Headers map[string]string `json:"headers,omitempty"`
 
+	// Auth specifies a authorization protocol. Only one protocol may be set.
+	// +optional
+	Auth *AuthorizationProtocol `json:"auth,omitempty"`
+
 	// Body
 	// +optional
 	Body string `json:"body,omitempty"`
@@ -61,6 +65,22 @@ type WebhookProvider struct {
 	CAProvider *WebhookCAProvider `json:"caProvider,omitempty"`
 }
 
+// AuthorizationProtocol contains the protocol-specific configuration
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
+type AuthorizationProtocol struct {
+	// NTLMProtocol configures the store to use NTLM for auth
+	// +optional
+	NTLM *NTLMProtocol `json:"ntlm"`
+
+	// Define other protocols here
+}
+
+// NTLMProtocol contains the NTLM-specific configuration.
+type NTLMProtocol struct {
+	UserName esmeta.SecretKeySelector `json:"usernameSecret"`
+	Password esmeta.SecretKeySelector `json:"passwordSecret"`
+}
 type WebhookCAProviderType string
 
 const (

+ 42 - 0
apis/externalsecrets/v1/zz_generated.deepcopy.go

@@ -312,6 +312,26 @@ func (in *AlibabaRRSAAuth) DeepCopy() *AlibabaRRSAAuth {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthorizationProtocol) DeepCopyInto(out *AuthorizationProtocol) {
+	*out = *in
+	if in.NTLM != nil {
+		in, out := &in.NTLM, &out.NTLM
+		*out = new(NTLMProtocol)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProtocol.
+func (in *AuthorizationProtocol) DeepCopy() *AuthorizationProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthorizationProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AzureKVAuth) DeepCopyInto(out *AzureKVAuth) {
 	*out = *in
 	if in.ClientID != nil {
@@ -2097,6 +2117,23 @@ func (in *MachineIdentityScopeInWorkspace) DeepCopy() *MachineIdentityScopeInWor
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NTLMProtocol) DeepCopyInto(out *NTLMProtocol) {
+	*out = *in
+	in.UserName.DeepCopyInto(&out.UserName)
+	in.Password.DeepCopyInto(&out.Password)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NTLMProtocol.
+func (in *NTLMProtocol) DeepCopy() *NTLMProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(NTLMProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NoSecretError) DeepCopyInto(out *NoSecretError) {
 	*out = *in
 }
@@ -3529,6 +3566,11 @@ func (in *WebhookProvider) DeepCopyInto(out *WebhookProvider) {
 			(*out)[key] = val
 		}
 	}
+	if in.Auth != nil {
+		in, out := &in.Auth, &out.Auth
+		*out = new(AuthorizationProtocol)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Timeout != nil {
 		in, out := &in.Timeout, &out.Timeout
 		*out = new(metav1.Duration)

+ 22 - 1
apis/externalsecrets/v1beta1/secretstore_webhook_types.go

@@ -20,7 +20,7 @@ import (
 	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
 )
 
-// AkeylessProvider Configures an store to sync secrets using Akeyless KV.
+// WebHookProvider Configures an store to sync secrets from simple web apis.
 type WebhookProvider struct {
 	// Webhook Method
 	// +optional, default GET
@@ -33,6 +33,10 @@ type WebhookProvider struct {
 	// +optional
 	Headers map[string]string `json:"headers,omitempty"`
 
+	// Auth specifies a authorization protocol. Only one protocol may be set.
+	// +optional
+	Auth *AuthorizationProtocol `json:"auth,omitempty"`
+
 	// Body
 	// +optional
 	Body string `json:"body,omitempty"`
@@ -61,6 +65,23 @@ type WebhookProvider struct {
 	CAProvider *WebhookCAProvider `json:"caProvider,omitempty"`
 }
 
+// AuthorizationProtocol contains the protocol-specific configuration
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
+type AuthorizationProtocol struct {
+	// NTLMProtocol configures the store to use NTLM for auth
+	// +optional
+	NTLM *NTLMProtocol `json:"ntlm"`
+
+	// Define other protocols here
+}
+
+// NTLMProtocol contains the NTLM-specific configuration.
+type NTLMProtocol struct {
+	UserName esmeta.SecretKeySelector `json:"usernameSecret"`
+	Password esmeta.SecretKeySelector `json:"passwordSecret"`
+}
+
 type WebhookCAProviderType string
 
 const (

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

@@ -312,6 +312,26 @@ func (in *AlibabaRRSAAuth) DeepCopy() *AlibabaRRSAAuth {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthorizationProtocol) DeepCopyInto(out *AuthorizationProtocol) {
+	*out = *in
+	if in.NTLM != nil {
+		in, out := &in.NTLM, &out.NTLM
+		*out = new(NTLMProtocol)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProtocol.
+func (in *AuthorizationProtocol) DeepCopy() *AuthorizationProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthorizationProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AzureKVAuth) DeepCopyInto(out *AzureKVAuth) {
 	*out = *in
 	if in.ClientID != nil {
@@ -2097,6 +2117,23 @@ func (in *MachineIdentityScopeInWorkspace) DeepCopy() *MachineIdentityScopeInWor
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NTLMProtocol) DeepCopyInto(out *NTLMProtocol) {
+	*out = *in
+	in.UserName.DeepCopyInto(&out.UserName)
+	in.Password.DeepCopyInto(&out.Password)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NTLMProtocol.
+func (in *NTLMProtocol) DeepCopy() *NTLMProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(NTLMProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *NoSecretError) DeepCopyInto(out *NoSecretError) {
 	*out = *in
 }
@@ -3529,6 +3566,11 @@ func (in *WebhookProvider) DeepCopyInto(out *WebhookProvider) {
 			(*out)[key] = val
 		}
 	}
+	if in.Auth != nil {
+		in, out := &in.Auth, &out.Auth
+		*out = new(AuthorizationProtocol)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Timeout != nil {
 		in, out := &in.Timeout, &out.Timeout
 		*out = new(v1.Duration)

+ 23 - 0
apis/generators/v1alpha1/types_webhook.go

@@ -16,6 +16,8 @@ package v1alpha1
 
 import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
 )
 
 // WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field.
@@ -31,6 +33,10 @@ type WebhookSpec struct {
 	// +optional
 	Headers map[string]string `json:"headers,omitempty"`
 
+	// Auth specifies a authorization protocol. Only one protocol may be set.
+	// +optional
+	Auth *AuthorizationProtocol `json:"auth,omitempty"`
+
 	// Body
 	// +optional
 	Body string `json:"body,omitempty"`
@@ -59,6 +65,23 @@ type WebhookSpec struct {
 	CAProvider *WebhookCAProvider `json:"caProvider,omitempty"`
 }
 
+// AuthorizationProtocol contains the protocol-specific configuration
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
+type AuthorizationProtocol struct {
+	// NTLMProtocol configures the store to use NTLM for auth
+	// +optional
+	NTLM *NTLMProtocol `json:"ntlm,omitempty"`
+
+	// Define other protocols here
+}
+
+// NTLMProtocol contains the NTLM-specific configuration.
+type NTLMProtocol struct {
+	UserName esmeta.SecretKeySelector `json:"usernameSecret"`
+	Password esmeta.SecretKeySelector `json:"passwordSecret"`
+}
+
 type WebhookCAProviderType string
 
 const (

+ 42 - 0
apis/generators/v1alpha1/zz_generated.deepcopy.go

@@ -198,6 +198,26 @@ func (in *AWSJWTAuth) DeepCopy() *AWSJWTAuth {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *AuthorizationProtocol) DeepCopyInto(out *AuthorizationProtocol) {
+	*out = *in
+	if in.NTLM != nil {
+		in, out := &in.NTLM, &out.NTLM
+		*out = new(NTLMProtocol)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProtocol.
+func (in *AuthorizationProtocol) DeepCopy() *AuthorizationProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(AuthorizationProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AzureACRManagedIdentityAuth) DeepCopyInto(out *AzureACRManagedIdentityAuth) {
 	*out = *in
 }
@@ -1137,6 +1157,23 @@ func (in *GrafanaStateServiceAccount) DeepCopy() *GrafanaStateServiceAccount {
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *NTLMProtocol) DeepCopyInto(out *NTLMProtocol) {
+	*out = *in
+	in.UserName.DeepCopyInto(&out.UserName)
+	in.Password.DeepCopyInto(&out.Password)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NTLMProtocol.
+func (in *NTLMProtocol) DeepCopy() *NTLMProtocol {
+	if in == nil {
+		return nil
+	}
+	out := new(NTLMProtocol)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Password) DeepCopyInto(out *Password) {
 	*out = *in
 	out.TypeMeta = in.TypeMeta
@@ -1702,6 +1739,11 @@ func (in *WebhookSpec) DeepCopyInto(out *WebhookSpec) {
 			(*out)[key] = val
 		}
 	}
+	if in.Auth != nil {
+		in, out := &in.Auth, &out.Auth
+		*out = new(AuthorizationProtocol)
+		(*in).DeepCopyInto(*out)
+	}
 	if in.Timeout != nil {
 		in, out := &in.Timeout, &out.Timeout
 		*out = new(apismetav1.Duration)

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

@@ -4069,6 +4069,79 @@ spec:
                     description: Webhook configures this store to sync secrets using
                       a generic templated webhook
                     properties:
+                      auth:
+                        description: Auth specifies a authorization protocol. Only
+                          one protocol may be set.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          ntlm:
+                            description: NTLMProtocol configures the store to use
+                              NTLM for auth
+                            properties:
+                              passwordSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                              usernameSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                            required:
+                            - passwordSecret
+                            - usernameSecret
+                            type: object
+                        type: object
                       body:
                         description: Body
                         type: string
@@ -8432,6 +8505,79 @@ spec:
                     description: Webhook configures this store to sync secrets using
                       a generic templated webhook
                     properties:
+                      auth:
+                        description: Auth specifies a authorization protocol. Only
+                          one protocol may be set.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          ntlm:
+                            description: NTLMProtocol configures the store to use
+                              NTLM for auth
+                            properties:
+                              passwordSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                              usernameSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                            required:
+                            - passwordSecret
+                            - usernameSecret
+                            type: object
+                        type: object
                       body:
                         description: Body
                         type: string

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

@@ -4069,6 +4069,79 @@ spec:
                     description: Webhook configures this store to sync secrets using
                       a generic templated webhook
                     properties:
+                      auth:
+                        description: Auth specifies a authorization protocol. Only
+                          one protocol may be set.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          ntlm:
+                            description: NTLMProtocol configures the store to use
+                              NTLM for auth
+                            properties:
+                              passwordSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                              usernameSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                            required:
+                            - passwordSecret
+                            - usernameSecret
+                            type: object
+                        type: object
                       body:
                         description: Body
                         type: string
@@ -8432,6 +8505,79 @@ spec:
                     description: Webhook configures this store to sync secrets using
                       a generic templated webhook
                     properties:
+                      auth:
+                        description: Auth specifies a authorization protocol. Only
+                          one protocol may be set.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          ntlm:
+                            description: NTLMProtocol configures the store to use
+                              NTLM for auth
+                            properties:
+                              passwordSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                              usernameSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                            required:
+                            - passwordSecret
+                            - usernameSecret
+                            type: object
+                        type: object
                       body:
                         description: Body
                         type: string

+ 73 - 0
config/crds/bases/generators.external-secrets.io_clustergenerators.yaml

@@ -1720,6 +1720,79 @@ spec:
                       generator. Any body parameters should be passed to the server
                       through the parameters field.
                     properties:
+                      auth:
+                        description: Auth specifies a authorization protocol. Only
+                          one protocol may be set.
+                        maxProperties: 1
+                        minProperties: 1
+                        properties:
+                          ntlm:
+                            description: NTLMProtocol configures the store to use
+                              NTLM for auth
+                            properties:
+                              passwordSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                              usernameSecret:
+                                description: |-
+                                  A reference to a specific 'key' within a Secret resource.
+                                  In some instances, `key` is a required field.
+                                properties:
+                                  key:
+                                    description: |-
+                                      A key in the referenced Secret.
+                                      Some instances of this field may be defaulted, in others it may be required.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[-._a-zA-Z0-9]+$
+                                    type: string
+                                  name:
+                                    description: The name of the Secret resource being
+                                      referred to.
+                                    maxLength: 253
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                    type: string
+                                  namespace:
+                                    description: |-
+                                      The namespace of the Secret resource being referred to.
+                                      Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                    maxLength: 63
+                                    minLength: 1
+                                    pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                    type: string
+                                type: object
+                            required:
+                            - passwordSecret
+                            - usernameSecret
+                            type: object
+                        type: object
                       body:
                         description: Body
                         type: string

+ 73 - 0
config/crds/bases/generators.external-secrets.io_webhooks.yaml

@@ -49,6 +49,79 @@ spec:
               Any body parameters should be passed to the server through the parameters
               field.
             properties:
+              auth:
+                description: Auth specifies a authorization protocol. Only one protocol
+                  may be set.
+                maxProperties: 1
+                minProperties: 1
+                properties:
+                  ntlm:
+                    description: NTLMProtocol configures the store to use NTLM for
+                      auth
+                    properties:
+                      passwordSecret:
+                        description: |-
+                          A reference to a specific 'key' within a Secret resource.
+                          In some instances, `key` is a required field.
+                        properties:
+                          key:
+                            description: |-
+                              A key in the referenced Secret.
+                              Some instances of this field may be defaulted, in others it may be required.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[-._a-zA-Z0-9]+$
+                            type: string
+                          name:
+                            description: The name of the Secret resource being referred
+                              to.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                            type: string
+                          namespace:
+                            description: |-
+                              The namespace of the Secret resource being referred to.
+                              Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                            maxLength: 63
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                            type: string
+                        type: object
+                      usernameSecret:
+                        description: |-
+                          A reference to a specific 'key' within a Secret resource.
+                          In some instances, `key` is a required field.
+                        properties:
+                          key:
+                            description: |-
+                              A key in the referenced Secret.
+                              Some instances of this field may be defaulted, in others it may be required.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[-._a-zA-Z0-9]+$
+                            type: string
+                          name:
+                            description: The name of the Secret resource being referred
+                              to.
+                            maxLength: 253
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                            type: string
+                          namespace:
+                            description: |-
+                              The namespace of the Secret resource being referred to.
+                              Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                            maxLength: 63
+                            minLength: 1
+                            pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                            type: string
+                        type: object
+                    required:
+                    - passwordSecret
+                    - usernameSecret
+                    type: object
+                type: object
               body:
                 description: Body
                 type: string

+ 414 - 0
deploy/crds/bundle.yaml

@@ -5767,6 +5767,75 @@ spec:
                     webhook:
                       description: Webhook configures this store to sync secrets using a generic templated webhook
                       properties:
+                        auth:
+                          description: Auth specifies a authorization protocol. Only one protocol may be set.
+                          maxProperties: 1
+                          minProperties: 1
+                          properties:
+                            ntlm:
+                              description: NTLMProtocol configures the store to use NTLM for auth
+                              properties:
+                                passwordSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                                usernameSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - passwordSecret
+                                - usernameSecret
+                              type: object
+                          type: object
                         body:
                           description: Body
                           type: string
@@ -9839,6 +9908,75 @@ spec:
                     webhook:
                       description: Webhook configures this store to sync secrets using a generic templated webhook
                       properties:
+                        auth:
+                          description: Auth specifies a authorization protocol. Only one protocol may be set.
+                          maxProperties: 1
+                          minProperties: 1
+                          properties:
+                            ntlm:
+                              description: NTLMProtocol configures the store to use NTLM for auth
+                              properties:
+                                passwordSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                                usernameSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - passwordSecret
+                                - usernameSecret
+                              type: object
+                          type: object
                         body:
                           description: Body
                           type: string
@@ -15615,6 +15753,75 @@ spec:
                     webhook:
                       description: Webhook configures this store to sync secrets using a generic templated webhook
                       properties:
+                        auth:
+                          description: Auth specifies a authorization protocol. Only one protocol may be set.
+                          maxProperties: 1
+                          minProperties: 1
+                          properties:
+                            ntlm:
+                              description: NTLMProtocol configures the store to use NTLM for auth
+                              properties:
+                                passwordSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                                usernameSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - passwordSecret
+                                - usernameSecret
+                              type: object
+                          type: object
                         body:
                           description: Body
                           type: string
@@ -19687,6 +19894,75 @@ spec:
                     webhook:
                       description: Webhook configures this store to sync secrets using a generic templated webhook
                       properties:
+                        auth:
+                          description: Auth specifies a authorization protocol. Only one protocol may be set.
+                          maxProperties: 1
+                          minProperties: 1
+                          properties:
+                            ntlm:
+                              description: NTLMProtocol configures the store to use NTLM for auth
+                              properties:
+                                passwordSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                                usernameSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - passwordSecret
+                                - usernameSecret
+                              type: object
+                          type: object
                         body:
                           description: Body
                           type: string
@@ -21828,6 +22104,75 @@ spec:
                     webhookSpec:
                       description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field.
                       properties:
+                        auth:
+                          description: Auth specifies a authorization protocol. Only one protocol may be set.
+                          maxProperties: 1
+                          minProperties: 1
+                          properties:
+                            ntlm:
+                              description: NTLMProtocol configures the store to use NTLM for auth
+                              properties:
+                                passwordSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                                usernameSecret:
+                                  description: |-
+                                    A reference to a specific 'key' within a Secret resource.
+                                    In some instances, `key` is a required field.
+                                  properties:
+                                    key:
+                                      description: |-
+                                        A key in the referenced Secret.
+                                        Some instances of this field may be defaulted, in others it may be required.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[-._a-zA-Z0-9]+$
+                                      type: string
+                                    name:
+                                      description: The name of the Secret resource being referred to.
+                                      maxLength: 253
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                                      type: string
+                                    namespace:
+                                      description: |-
+                                        The namespace of the Secret resource being referred to.
+                                        Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                                      maxLength: 63
+                                      minLength: 1
+                                      pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                                      type: string
+                                  type: object
+                              required:
+                                - passwordSecret
+                                - usernameSecret
+                              type: object
+                          type: object
                         body:
                           description: Body
                           type: string
@@ -24033,6 +24378,75 @@ spec:
             spec:
               description: WebhookSpec controls the behavior of the external generator. Any body parameters should be passed to the server through the parameters field.
               properties:
+                auth:
+                  description: Auth specifies a authorization protocol. Only one protocol may be set.
+                  maxProperties: 1
+                  minProperties: 1
+                  properties:
+                    ntlm:
+                      description: NTLMProtocol configures the store to use NTLM for auth
+                      properties:
+                        passwordSecret:
+                          description: |-
+                            A reference to a specific 'key' within a Secret resource.
+                            In some instances, `key` is a required field.
+                          properties:
+                            key:
+                              description: |-
+                                A key in the referenced Secret.
+                                Some instances of this field may be defaulted, in others it may be required.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[-._a-zA-Z0-9]+$
+                              type: string
+                            name:
+                              description: The name of the Secret resource being referred to.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                              type: string
+                            namespace:
+                              description: |-
+                                The namespace of the Secret resource being referred to.
+                                Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                              maxLength: 63
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                              type: string
+                          type: object
+                        usernameSecret:
+                          description: |-
+                            A reference to a specific 'key' within a Secret resource.
+                            In some instances, `key` is a required field.
+                          properties:
+                            key:
+                              description: |-
+                                A key in the referenced Secret.
+                                Some instances of this field may be defaulted, in others it may be required.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[-._a-zA-Z0-9]+$
+                              type: string
+                            name:
+                              description: The name of the Secret resource being referred to.
+                              maxLength: 253
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
+                              type: string
+                            namespace:
+                              description: |-
+                                The namespace of the Secret resource being referred to.
+                                Ignored if referent is not cluster-scoped, otherwise defaults to the namespace of the referent.
+                              maxLength: 63
+                              minLength: 1
+                              pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
+                              type: string
+                          type: object
+                      required:
+                        - passwordSecret
+                        - usernameSecret
+                      type: object
+                  type: object
                 body:
                   description: Body
                   type: string

+ 91 - 1
docs/api/spec.md

@@ -763,6 +763,39 @@ string
 </tr>
 </tbody>
 </table>
+<h3 id="external-secrets.io/v1.AuthorizationProtocol">AuthorizationProtocol
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.WebhookProvider">WebhookProvider</a>)
+</p>
+<p>
+<p>AuthorizationProtocol contains the protocol-specific configuration</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>ntlm</code></br>
+<em>
+<a href="#external-secrets.io/v1.NTLMProtocol">
+NTLMProtocol
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>NTLMProtocol configures the store to use NTLM for auth</p>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1.AzureAuthType">AzureAuthType
 (<code>string</code> alias)</p></h3>
 <p>
@@ -5681,6 +5714,49 @@ bool
 <td></td>
 </tr></tbody>
 </table>
+<h3 id="external-secrets.io/v1.NTLMProtocol">NTLMProtocol
+</h3>
+<p>
+(<em>Appears on:</em>
+<a href="#external-secrets.io/v1.AuthorizationProtocol">AuthorizationProtocol</a>)
+</p>
+<p>
+<p>NTLMProtocol contains the NTLM-specific configuration.</p>
+</p>
+<table>
+<thead>
+<tr>
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+<code>usernameSecret</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>
+</td>
+</tr>
+<tr>
+<td>
+<code>passwordSecret</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>
+</td>
+</tr>
+</tbody>
+</table>
 <h3 id="external-secrets.io/v1.NoSecretError">NoSecretError
 </h3>
 <p>
@@ -9653,7 +9729,7 @@ string
 <a href="#external-secrets.io/v1.SecretStoreProvider">SecretStoreProvider</a>)
 </p>
 <p>
-<p>AkeylessProvider Configures an store to sync secrets using Akeyless KV.</p>
+<p>WebHookProvider Configures an store to sync secrets from simple web apis.</p>
 </p>
 <table>
 <thead>
@@ -9699,6 +9775,20 @@ map[string]string
 </tr>
 <tr>
 <td>
+<code>auth</code></br>
+<em>
+<a href="#external-secrets.io/v1.AuthorizationProtocol">
+AuthorizationProtocol
+</a>
+</em>
+</td>
+<td>
+<em>(Optional)</em>
+<p>Auth specifies a authorization protocol. Only one protocol may be set.</p>
+</td>
+</tr>
+<tr>
+<td>
 <code>body</code></br>
 <em>
 string

+ 40 - 2
docs/provider/webhook.md

@@ -68,6 +68,7 @@ metadata:
 data:
   foobar: c2VjcmV0
 ```
+#### Push secret
 
 To push a secret, create the following store:
 
@@ -118,9 +119,46 @@ If `secretKey` is not provided, the whole secret is provided JSON encoded.
 
 The secret will be added to the `remoteRef` object so that it is retrievable in the templating engine. The secret will be sent in the body when the body field of the provider is empty. In the rare case that the body should be empty, the provider can be configured to use `{% raw %}'{{ "" }}'{% endraw %}` for the body value.
 
-#### Limitations
+#### Authentication
+
+Webhook also supports using NTLM for authorization:
+
+```yaml
+{% raw %}
+apiVersion: external-secrets.io/v1beta1
+kind: SecretStore
+metadata:
+  name: webhook-backend
+spec:
+  provider:
+    webhook:
+      url: "http://httpbin.org/get?parameter={{ .remoteRef.key }}"
+      result:
+        jsonPath: "$.args.parameter"
+      auth:
+        ntlm:
+            usernameSecret:
+              name: webhook-credentials
+              key: username
+              namespace: externalsecrets
+            passwordSecret:
+              name: webhook-credentials
+              key: password
+              namespace: externalsecrets
+{%- endraw %}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+  name: webhook-credentials
+  namespace: externalsecrets
+data:
+  username: dGVzdA== # "test"
+  password: dGVzdA== # "test"
+```
+
+
 
-Webhook does not support authorization, other than what can be sent by generating http headers
 
 !!! note
       If a webhook endpoint for a given `ExternalSecret` returns a 404 status code, the secret is considered to have been deleted.  This will trigger the `deletionPolicy` set on the `ExternalSecret`.

+ 1 - 0
go.mod

@@ -65,6 +65,7 @@ require (
 	dario.cat/mergo v1.0.1
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
 	github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0
+	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
 	github.com/BeyondTrust/go-client-library-passwordsafe v0.20.0
 	github.com/DelineaXPM/dsv-sdk-go/v2 v2.2.0
 	github.com/DelineaXPM/tss-sdk-go/v2 v2.0.3

+ 2 - 0
go.sum

@@ -101,6 +101,8 @@ github.com/Azure/go-autorest/logger v0.2.2/go.mod h1:I5fg9K52o+iuydlWfa9T5K6WFos
 github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
 github.com/Azure/go-autorest/tracing v0.6.1 h1:YUMSrC/CeD1ZnnXcNYU4a/fzsO35u2Fsful9L/2nyR0=
 github.com/Azure/go-autorest/tracing v0.6.1/go.mod h1:/3EgjbsjraOqiicERAeu3m7/z0x1TzjQGAwDrJrXGkc=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
+github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
 github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
 github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.1.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=

+ 23 - 10
pkg/common/webhook/models.go

@@ -18,6 +18,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
 )
 
 type Spec struct {
@@ -32,6 +33,10 @@ type Spec struct {
 	// +optional
 	Headers map[string]string `json:"headers,omitempty"`
 
+	// Auth specifies a authorization protocol. Only one protocol may be set.
+	// +optional
+	Auth *AuthorizationProtocol `json:"auth,omitempty"`
+
 	// Body
 	// +optional
 	Body string `json:"body,omitempty"`
@@ -60,6 +65,23 @@ type Spec struct {
 	CAProvider *esv1.CAProvider `json:"caProvider,omitempty"`
 }
 
+// AuthorizationProtocol contains the protocol-specific configuration
+// +kubebuilder:validation:MinProperties=1
+// +kubebuilder:validation:MaxProperties=1
+type AuthorizationProtocol struct {
+	// NTLMProtocol configures the store to use NTLM for auth
+	// +optional
+	NTLM *NTLMProtocol `json:"ntlm,omitempty"`
+
+	// Define other protocols here
+}
+
+// NTLMProtocol contains the NTLM-specific configuration.
+type NTLMProtocol struct {
+	UserName esmeta.SecretKeySelector `json:"usernameSecret"`
+	Password esmeta.SecretKeySelector `json:"passwordSecret"`
+}
+
 type Result struct {
 	// Json path of return value
 	// +optional
@@ -71,14 +93,5 @@ type Secret struct {
 	Name string `json:"name"`
 
 	// Secret ref to fill in credentials
-	SecretRef SecretKeySelector `json:"secretRef"`
-}
-
-type SecretKeySelector struct {
-	// The name of the Secret resource being referred to.
-	Name string `json:"name,omitempty"`
-	// The key where the token is found.
-	Key string `json:"key,omitempty"`
-
-	Namespace *string `json:"namespace,omitempty"`
+	SecretRef esmeta.SecretKeySelector `json:"secretRef"`
 }

+ 91 - 17
pkg/common/webhook/webhook.go

@@ -27,11 +27,13 @@ import (
 	"net/url"
 	tpl "text/template"
 
+	"github.com/Azure/go-ntlmssp"
 	"github.com/PaesslerAG/jsonpath"
 	corev1 "k8s.io/api/core/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
 	"github.com/external-secrets/external-secrets/pkg/constants"
 	"github.com/external-secrets/external-secrets/pkg/metrics"
 	"github.com/external-secrets/external-secrets/pkg/template/v2"
@@ -47,7 +49,7 @@ type Webhook struct {
 	ClusterScoped bool
 }
 
-func (w *Webhook) getStoreSecret(ctx context.Context, ref SecretKeySelector) (*corev1.Secret, error) {
+func (w *Webhook) getStoreSecret(ctx context.Context, ref esmeta.SecretKeySelector) (*corev1.Secret, error) {
 	ke := client.ObjectKey{
 		Name:      ref.Name,
 		Namespace: w.Namespace,
@@ -189,6 +191,7 @@ func (w *Webhook) GetWebhookData(ctx context.Context, provider *Spec, ref *esv1.
 		return nil, errors.New("http client not initialized")
 	}
 
+	// Parse store secrets
 	escapedData, err := w.GetTemplateData(ctx, ref, provider.Secrets, true)
 	if err != nil {
 		return nil, err
@@ -198,14 +201,19 @@ func (w *Webhook) GetWebhookData(ctx context.Context, provider *Spec, ref *esv1.
 		return nil, err
 	}
 
+	// set method
 	method := provider.Method
 	if method == "" {
 		method = http.MethodGet
 	}
+
+	// set url
 	url, err := ExecuteTemplateString(provider.URL, escapedData)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse url: %w", err)
 	}
+
+	// set body
 	body, err := ExecuteTemplate(provider.Body, rawData)
 	if err != nil {
 		return nil, fmt.Errorf("failed to parse body: %w", err)
@@ -263,12 +271,18 @@ func (w *Webhook) executeRequest(ctx context.Context, provider *Spec, data []byt
 		return nil, fmt.Errorf("failed to create request: %w", err)
 	}
 
-	for hKey, hValueTpl := range provider.Headers {
-		hValue, err := ExecuteTemplateString(hValueTpl, rawData)
+	if provider.Headers != nil {
+		req, err = w.ReqAddHeaders(req, provider, rawData)
 		if err != nil {
-			return nil, fmt.Errorf("failed to parse header %s: %w", hKey, err)
+			return nil, err
+		}
+	}
+
+	if provider.Auth != nil {
+		req, err = w.ReqAddAuth(req, provider, ctx)
+		if err != nil {
+			return nil, err
 		}
-		req.Header.Add(hKey, hValue)
 	}
 
 	resp, err := w.HTTP.Do(req)
@@ -290,29 +304,89 @@ func (w *Webhook) executeRequest(ctx context.Context, provider *Spec, data []byt
 	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
 		return nil, fmt.Errorf("endpoint gave error %s", resp.Status)
 	}
+
+	// return response body
 	return io.ReadAll(resp.Body)
 }
 
+func (w *Webhook) ReqAddHeaders(r *http.Request, provider *Spec, rawData map[string]map[string]string) (*http.Request, error) {
+	reqWithHeaders := r
+
+	for hKey, hValueTpl := range provider.Headers {
+		hValue, err := ExecuteTemplateString(hValueTpl, rawData)
+		if err != nil {
+			return nil, fmt.Errorf("failed to parse header %s: %w", hKey, err)
+		}
+		reqWithHeaders.Header.Add(hKey, hValue)
+	}
+
+	return reqWithHeaders, nil
+}
+
+func (w *Webhook) ReqAddAuth(r *http.Request, provider *Spec, ctx context.Context) (*http.Request, error) {
+	reqWithAuth := r
+
+	//nolint:gocritic // singleCaseSwitch: we prefer to keep it as a switch for clarity
+	switch {
+	case provider.Auth.NTLM != nil:
+		userSecretRef := provider.Auth.NTLM.UserName
+		userSecret, err := w.getStoreSecret(ctx, userSecretRef)
+		if err != nil {
+			return nil, err
+		}
+		username := string(userSecret.Data[userSecretRef.Key])
+
+		PasswordSecretRef := provider.Auth.NTLM.Password
+		PasswordSecret, err := w.getStoreSecret(ctx, PasswordSecretRef)
+		if err != nil {
+			return nil, err
+		}
+		password := string(PasswordSecret.Data[PasswordSecretRef.Key])
+
+		// This overwrites auth headers set by providers.headers
+		reqWithAuth.SetBasicAuth(username, password)
+	}
+	return reqWithAuth, nil
+}
+
 func (w *Webhook) GetHTTPClient(ctx context.Context, provider *Spec) (*http.Client, error) {
 	client := &http.Client{}
+
+	// add timeout to client if it is there
 	if provider.Timeout != nil {
 		client.Timeout = provider.Timeout.Duration
 	}
-	if len(provider.CABundle) == 0 && provider.CAProvider == nil {
-		// No need to process ca stuff if it is not there
-		return client, nil
-	}
-	caCertPool, err := w.GetCACertPool(ctx, provider)
-	if err != nil {
-		return nil, err
+
+	// add CA to client if it is there
+	if len(provider.CABundle) > 0 || provider.CAProvider != nil {
+		caCertPool, err := w.GetCACertPool(ctx, provider)
+		if err != nil {
+			return nil, err
+		}
+
+		tlsConf := &tls.Config{
+			RootCAs:       caCertPool,
+			MinVersion:    tls.VersionTLS12,
+			Renegotiation: tls.RenegotiateOnceAsClient,
+		}
+
+		client.Transport = &http.Transport{TLSClientConfig: tlsConf}
 	}
+	// add authentication method if it s there
+	if provider.Auth != nil {
+		if provider.Auth.NTLM != nil {
+			client.Transport =
+				&ntlmssp.Negotiator{
+					RoundTripper: &http.Transport{
+						TLSNextProto: map[string]func(authority string, c *tls.Conn) http.RoundTripper{}, // Needed to disable HTTP/2
 
-	tlsConf := &tls.Config{
-		RootCAs:       caCertPool,
-		MinVersion:    tls.VersionTLS12,
-		Renegotiation: tls.RenegotiateOnceAsClient,
+					},
+				}
+		}
+		// add additional auth methods here
 	}
-	client.Transport = &http.Transport{TLSClientConfig: tlsConf}
+
+	// return client with all add-ons
 	return client, nil
 }
 

+ 218 - 0
pkg/provider/webhook/webhook_auth_test.go

@@ -0,0 +1,218 @@
+// /*
+// 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 webhook
+
+import (
+	"context"
+	b64 "encoding/base64"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+	"sigs.k8s.io/controller-runtime/pkg/client/fake"
+
+	esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
+	esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
+)
+
+type mockAuthTestPackage struct {
+	Creds      mockCreds
+	MockServer mockAuthTestServer
+	Request    mockAuthRequest
+	Expect     string
+}
+
+type mockCreds struct {
+	UserName string
+	Password string
+}
+
+type mockAuthTestServer func(
+	serverCreds mockCreds,
+	t *testing.T) *httptest.Server
+
+type mockAuthRequest func(
+	url string,
+	creds mockCreds,
+	t *testing.T) string
+
+func TestWebhookAuth(t *testing.T) {
+	// define test cases
+	creds := mockCreds{"correctuser123", "correctpassword123"}
+	basicAuthExpect := "Basic " + b64.StdEncoding.EncodeToString([]byte(creds.UserName+":"+creds.Password))
+	ntlmExpect := "NTLM TlRMTVNTUAABAAAAAQCIoAAAAAAoAAAAAAAAACgAAAAGAbEdAAAADw=="
+	negotiateExpect := "Negotiate TlRMTVNTUAABAAAAAQCIoAAAAAAoAAAAAAAAACgAAAAGAbEdAAAADw=="
+
+	// due to integrated nature of GetSecret(), we use a mock server
+	// to return relevant parts of a request, in this case, the auth header.
+	testAuthHeaders := map[string]mockAuthTestPackage{
+		"BasicAuth": {creds, basicAuthRequestEcho, basicAuthRequest, basicAuthExpect},
+		"NTLM":      {creds, ntlmRequestEcho, ntlmRequest, ntlmExpect},
+		"Negotiate": {creds, negotiateRequestEcho, ntlmRequest, negotiateExpect},
+	}
+
+	// execute test cases
+	for _, p := range testAuthHeaders {
+		server := p.MockServer(p.Creds, t)
+		result := p.Request(server.URL, creds, t)
+		server.Close()
+		expect := p.Expect
+		if result != expect {
+			t.Errorf("Test failed. Result: '%s' / Expected:  '%s'", result, expect)
+		}
+	}
+}
+
+func ntlmRequestEcho(creds mockCreds, t *testing.T) *httptest.Server {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		reqAuthString := r.Header.Get("Authorization")
+		if reqAuthString == "" {
+			// go-ntlmssp first sends anonymous request, respond with 401
+			w.Header().Add("WWW-Authenticate", "NTLM")
+			w.WriteHeader(401)
+		} else {
+			w.Write([]byte(reqAuthString))
+		}
+	}))
+	return server
+}
+
+func negotiateRequestEcho(creds mockCreds, t *testing.T) *httptest.Server {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		reqAuthString := r.Header.Get("Authorization")
+		if reqAuthString == "" {
+			// go-ntlmssp first sends anonymous request, respond with 401
+			w.Header().Add("WWW-Authenticate", "Negotiate")
+			w.WriteHeader(401)
+		} else {
+			w.Write([]byte(reqAuthString))
+		}
+	}))
+	return server
+}
+
+func ntlmRequest(url string, creds mockCreds, t *testing.T) string {
+	secretName := "ntlmTestAuthSecret"
+	secretNamespace := "default"
+
+	// ntlm clustersecretstore takes credentials from a secret,
+	// so we need to mock k8s-client retrieval of secret.
+	mockClient := fake.NewClientBuilder().WithObjects(&corev1.Secret{
+		ObjectMeta: metav1.ObjectMeta{
+			Namespace: secretNamespace,
+			Name:      secretName,
+			Labels: map[string]string{
+				"external-secrets.io/type": "webhook",
+			},
+		},
+		Data: map[string][]byte{
+			"userName": []byte(creds.UserName),
+			"password": []byte(creds.Password),
+		},
+	}).Build()
+
+	// create clusteSecretStore
+	ntlmAuthStore := &esv1.ClusterSecretStore{
+		TypeMeta: metav1.TypeMeta{
+			Kind: "ClusterSecretStore",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "webhook-store",
+			Namespace: secretNamespace,
+		},
+		Spec: esv1.SecretStoreSpec{
+			Provider: &esv1.SecretStoreProvider{
+				Webhook: &esv1.WebhookProvider{
+					URL: url,
+					Auth: &esv1.AuthorizationProtocol{
+						NTLM: &esv1.NTLMProtocol{
+							UserName: esmeta.SecretKeySelector{
+								Name:      secretName,
+								Namespace: &secretNamespace,
+								Key:       "userName",
+							},
+							Password: esmeta.SecretKeySelector{
+								Name:      secretName,
+								Namespace: &secretNamespace,
+								Key:       "password",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+
+	result := exerciseGetSecret(ntlmAuthStore, mockClient, t)
+	return result
+}
+
+func basicAuthRequestEcho(creds mockCreds, t *testing.T) *httptest.Server {
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		reqAuthString := r.Header.Get("Authorization")
+		if reqAuthString == "" {
+			w.Write([]byte("Empty Authorization header"))
+		} else {
+			w.Write([]byte(reqAuthString))
+		}
+	}))
+
+	return server
+}
+
+func basicAuthRequest(url string, creds mockCreds, t *testing.T) string {
+	reqAuthString := "Basic " + b64.StdEncoding.EncodeToString([]byte(creds.UserName+":"+creds.Password))
+
+	// create ClusterSecretStore
+	basicAuthStore := &esv1.ClusterSecretStore{
+		TypeMeta: metav1.TypeMeta{
+			Kind: "ClusterSecretStore",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      "webhook-store",
+			Namespace: "default",
+		},
+		Spec: esv1.SecretStoreSpec{
+			Provider: &esv1.SecretStoreProvider{
+				Webhook: &esv1.WebhookProvider{
+					URL: url,
+					Headers: map[string]string{
+						"Authorization": reqAuthString,
+					},
+				},
+			},
+		},
+	}
+	result := exerciseGetSecret(basicAuthStore, nil, t)
+	return result
+}
+
+func exerciseGetSecret(mockStore esv1.GenericStore, mockKubeClient client.Client, t *testing.T) string {
+	mockProvider := &Provider{}
+	client, err := mockProvider.NewClient(context.Background(), mockStore, mockKubeClient, "default")
+	if err != nil {
+		t.Errorf("Error creating client: %q", err)
+		return "error"
+	}
+
+	// perform request, exercising GetSecret
+	resp, err := client.GetSecret(context.Background(), esv1.ExternalSecretDataRemoteRef{Key: "dummy"})
+	if err != nil {
+		t.Errorf("Error retrieving secret:%s", err)
+	}
+	return string(resp)
+}