Repository: kedacore/http-add-on (go)

Issue:
Allow skipping TLS verification for upstreams in interceptor
### Proposal

In-cluster upstreams using TLS are often using self signed certificates or certificates that are not trusted by the interceptor. Adding all certificates to the trusted certificates for the interceptor might not always be possible.

### Use-Case

_No response_

### Is this a feature you are interested in implementing yourself?

Yes

### Anything else?

_No response_

Pull request description:
feat(interceptor): Add possibility to skip tls verification for upstreams
Closes #1306

<!-- Thank you for contributing!

     Read more about how you can contribute in our contribution guide:
     https://github.com/kedacore/http-add-on/blob/main/CONTRIBUTING.md
-->

_Provide a description of what has been changed_

### Checklist

- [x] Commits are signed with Developer Certificate of Origin (DCO)
- [x] Changelog has been updated and is aligned with our [changelog requirements](https://github.com/kedacore/keda/blob/main/CONTRIBUTING.md#Changelog)
- [x] Any necessary documentation is added, such as:
  - [`README.md`](/README.md)
  - [The `docs/` directory](./docs)
  - [The docs repo](https://github.com/kedacore/keda-docs)

Fixes #


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a2ee74c..4ac247d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,7 +28,7 @@ This changelog keeps track of work items that have been completed and are ready
 - **General**: Add configurable tracing support to the interceptor proxy ([#1021](https://github.com/kedacore/http-add-on/pull/1021))
 - **General**: Allow using HSO and SO with different names ([#1293](https://github.com/kedacore/http-add-on/issues/1293))
 - **General**: Support profiling for KEDA components ([#4789](https://github.com/kedacore/keda/issues/4789))
-
+- **General**: Add possibility to skip TLS verification for upstreams in interceptor ([#1307](https://github.com/kedacore/http-add-on/pull/1307))
 ### Improvements
 
 - **General**: TODO ([#TODO](https://github.com/kedacore/http-add-on/issues/TODO))
diff --git a/docs/operate.md b/docs/operate.md
index 7f63c8b..aff11ef 100644
--- a/docs/operate.md
+++ b/docs/operate.md
@@ -28,6 +28,8 @@ For setting multiple TLS certs, set `KEDA_HTTP_PROXY_TLS_CERT_STORE_PATHS` with
 * `XYZ.crt` + `XYZ.key` - this is a convention when using Kubernetes Secrets of type tls
 * `XYZ.pem` + `XYZ-key.pem`
 
+To disable certificate chain verification, set `KEDA_HTTP_PROXY_TLS_SKIP_VERIFY` to `false`
+
 The matching between certs and requests is performed during the TLS ClientHelo message, where the SNI service name is compared to SANs provided in each cert and the first matching cert will be used for the rest of the TLS handshake.
 # Configuring tracing for the KEDA HTTP Add-on interceptor proxy
 
diff --git a/interceptor/config/serving.go b/interceptor/config/serving.go
index 6d33cb1..3dfb0c5 100644
--- a/interceptor/config/serving.go
+++ b/interceptor/config/serving.go
@@ -43,6 +43,8 @@ type Serving struct {
 	TLSKeyPath string `envconfig:"KEDA_HTTP_PROXY_TLS_KEY_PATH" default:"/certs/tls.key"`
 	// TLSCertStorePaths is a comma separated list of paths to read the certificate/key pairs for the TLS server
 	TLSCertStorePaths string `envconfig:"KEDA_HTTP_PROXY_TLS_CERT_STORE_PATHS" default:""`
+	// TLSSkipVerify is a boolean flag to specify whether the interceptor should skip TLS verification for upstreams
+	TLSSkipVerify bool `envconfig:"KEDA_HTTP_PROXY_TLS_SKIP_VERIFY" default:"false"`
 	// TLSPort is the port that the server should serve on if TLS is enabled
 	TLSPort int `envconfig:"KEDA_HTTP_PROXY_TLS_PORT" default:"8443"`
 	// ProfilingAddr if not empty, pprof will be available on this address, assuming host:port here
diff --git a/interceptor/main.go b/interceptor/main.go
index c01970c..5b5645b 100644
--- a/interceptor/main.go
+++ b/interceptor/main.go
@@ -192,7 +192,7 @@ func main() {
 	// start a proxy server with TLS
 	if proxyTLSEnabled {
 		eg.Go(func() error {
-			proxyTLSConfig := map[string]string{"certificatePath": servingCfg.TLSCertPath, "keyPath": servingCfg.TLSKeyPath, "certstorePaths": servingCfg.TLSCertStorePaths}
+			proxyTLSConfig := map[string]interface{}{"certificatePath": servingCfg.TLSCertPath, "keyPath": servingCfg.TLSKeyPath, "certstorePaths": servingCfg.TLSCertStorePaths, "skipVerify": servingCfg.TLSSkipVerify}
 			proxyTLSPort := servingCfg.TLSPort
 			k8sSharedInformerFactory.WaitForCacheSync(ctx.Done())
 
@@ -308,12 +308,15 @@ func defaultCertPool(logger logr.Logger) *x509.CertPool {
 
 // getTLSConfig creates a TLS config from KEDA_HTTP_PROXY_TLS_CERT_PATH, KEDA_HTTP_PROXY_TLS_KEY_PATH and KEDA_HTTP_PROXY_TLS_CERTSTORE_PATHS
 // The matching between request and certificate is performed by comparing TLS/SNI server name with x509 SANs
-func getTLSConfig(tlsConfig map[string]string, logger logr.Logger) (*tls.Config, error) {
-	certPath := tlsConfig["certificatePath"]
-	keyPath := tlsConfig["keyPath"]
-	certStorePaths := tlsConfig["certstorePaths"]
+func getTLSConfig(tlsConfig map[string]interface{}, logger logr.Logger) (*tls.Config, error) {
+	certPath, _ := tlsConfig["certificatePath"].(string)
+	keyPath, _ := tlsConfig["keyPath"].(string)
+	certStorePaths, _ := tlsConfig["certstorePaths"].(string)
+	insecureSkipVerify, _ := tlsConfig["skipVerify"].(bool)
+
 	servingTLS := &tls.Config{
-		RootCAs: defaultCertPool(logger),
+		RootCAs:            defaultCertPool(logger),
+		InsecureSkipVerify: insecureSkipVerify,
 	}
 	var defaultCert *tls.Certificate
 
@@ -404,7 +407,7 @@ func runProxyServer(
 	timeouts *config.Timeouts,
 	port int,
 	tlsEnabled bool,
-	tlsConfig map[string]string,
+	tlsConfig map[string]interface{},
 	tracingConfig *config.Tracing,
 ) error {
 	dialer := kedanet.NewNetDialer(timeouts.Connect, timeouts.KeepAlive)
@@ -430,6 +433,7 @@ func runProxyServer(
 	if tlsCfg != nil {
 		forwardingTLSCfg.RootCAs = tlsCfg.RootCAs
 		forwardingTLSCfg.Certificates = tlsCfg.Certificates
+		forwardingTLSCfg.InsecureSkipVerify = tlsCfg.InsecureSkipVerify
 	}
 
 	upstreamHandler = newForwardingHandler(


Test patch:
diff --git a/interceptor/main_test.go b/interceptor/main_test.go
index 95934b5..adefff2 100644
--- a/interceptor/main_test.go
+++ b/interceptor/main_test.go
@@ -92,7 +92,7 @@ func TestRunProxyServerCountMiddleware(t *testing.T) {
 			timeouts,
 			port,
 			false,
-			map[string]string{},
+			map[string]interface{}{},
 			&tracingCfg,
 		)
 	})
@@ -232,7 +232,7 @@ func TestRunProxyServerWithTLSCountMiddleware(t *testing.T) {
 			timeouts,
 			port,
 			true,
-			map[string]string{"certificatePath": "../certs/tls.crt", "keyPath": "../certs/tls.key"},
+			map[string]interface{}{"certificatePath": "../certs/tls.crt", "keyPath": "../certs/tls.key", "skipVerify": true},
 			&tracingCfg,
 		)
 	})
@@ -382,7 +382,7 @@ func TestRunProxyServerWithMultipleCertsTLSCountMiddleware(t *testing.T) {
 			timeouts,
 			port,
 			true,
-			map[string]string{"certstorePaths": "../certs"},
+			map[string]interface{}{"certstorePaths": "../certs"},
 			&tracingCfg,
 		)
 	})