Skip to content

Commit

Permalink
feat: allow configuring min tls for grpc
Browse files Browse the repository at this point in the history
Signed-off-by: Or Shachar <[email protected]>
  • Loading branch information
or-shachar committed Nov 11, 2024
1 parent aae3192 commit 3e2e6fa
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ Here is an overview of all new **experimental** features:

### Improvements

- **General**: Allow configuring minimum TLS version for GRPC client via `KEDA_GRPC_MIN_TLS_VERSION` ([#6320](https://github.com/kedacore/keda/pull/6320))
- TODO ([#XXX](https://github.com/kedacore/keda/issues/XXX))

### Fixes
Expand Down
54 changes: 54 additions & 0 deletions pkg/common/tls/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package tls

import (
ctls "crypto/tls"
"fmt"
"os"
)

type tlsVersion string

const (
TLS10 tlsVersion = "TLS10"
TLS11 tlsVersion = "TLS11"
TLS12 tlsVersion = "TLS12"
TLS13 tlsVersion = "TLS13"
)

type tlsEnvVariableName string

const (
minHTTPTLSVersionEnv tlsEnvVariableName = "KEDA_HTTP_MIN_TLS_VERSION"
minGrpcTLSVersionEnv tlsEnvVariableName = "KEDA_GRPC_MIN_TLS_VERSION"
)

const (
defaultMinHTTPTLSVersion = TLS12
defaultMinGrpcTLSVersion = TLS13
)

func getMinTLSVersion(envKey tlsEnvVariableName, defaultVal tlsVersion) (uint16, error) {
version := string(defaultVal)
if val, ok := os.LookupEnv(string(envKey)); ok {
version = val
}
mapping := map[string]uint16{
string(TLS10): ctls.VersionTLS10,
string(TLS11): ctls.VersionTLS11,
string(TLS12): ctls.VersionTLS12,
string(TLS13): ctls.VersionTLS13,
}
if v, ok := mapping[version]; ok {
return v, nil
}
fallback := mapping[string(defaultVal)]
return fallback, fmt.Errorf("invalid TLS version: %s, using %s", version, defaultVal)
}

func GetMinHTTPTLSVersion() (uint16, error) {
return getMinTLSVersion(minHTTPTLSVersionEnv, defaultMinHTTPTLSVersion)
}

func GetMinGrpcTLSVersion() (uint16, error) {
return getMinTLSVersion(minGrpcTLSVersionEnv, defaultMinGrpcTLSVersion)
}
81 changes: 81 additions & 0 deletions pkg/common/tls/tls_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package tls

import (
"crypto/tls"
"fmt"
"os"
"testing"
)

type minTLSVersionTestData struct {
name string
envSet bool
envValue string
expectedVersion uint16
shouldError bool
}

var minTLSVersionTestDatas = []minTLSVersionTestData{
{
name: "Set to TLS10",
envSet: true,
envValue: "TLS10",
expectedVersion: tls.VersionTLS10,
},
{
name: "Set to TLS11",
envSet: true,
envValue: "TLS11",
expectedVersion: tls.VersionTLS11,
},
{
name: "Set to TLS12",
envSet: true,
envValue: "TLS12",
expectedVersion: tls.VersionTLS12,
},
{
name: "Set to TLS13",
envSet: true,
envValue: "TLS13",
expectedVersion: tls.VersionTLS13,
},
{
name: "No setting",
envSet: false,
},
{
name: "Invalid settings",
envSet: true,
envValue: "TLS9",
shouldError: true,
},
}

func testResolveMinTLSVersion(t *testing.T, minVersionFunc func() (uint16, error), envName string, defaultVersion uint16) {
defer os.Unsetenv(envName)
for _, testData := range minTLSVersionTestDatas {
name := fmt.Sprintf("%s: %s", envName, testData.name)
t.Run(name, func(t *testing.T) {
os.Unsetenv(envName)
expectedVersion := defaultVersion
if testData.expectedVersion != 0 {
expectedVersion = testData.expectedVersion
}
if testData.envSet {
os.Setenv(envName, testData.envValue)
}
minVersion, err := minVersionFunc()
if testData.shouldError && err == nil {
t.Error("Expected error but got none")
}
if expectedVersion != minVersion {
t.Error("Failed to resolve minTLSVersion correctly", "wants", testData.expectedVersion, "got", minVersion)
}
})
}
}
func TestResolveMinTLSVersion(t *testing.T) {
testResolveMinTLSVersion(t, GetMinHTTPTLSVersion, "KEDA_HTTP_MIN_TLS_VERSION", tls.VersionTLS12)
testResolveMinTLSVersion(t, GetMinGrpcTLSVersion, "KEDA_GRPC_MIN_TLS_VERSION", tls.VersionTLS13)
}
9 changes: 8 additions & 1 deletion pkg/metricsservice/utils/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import (
"path"

"google.golang.org/grpc/credentials"
ctrl "sigs.k8s.io/controller-runtime"

kedatls "github.com/kedacore/keda/v2/pkg/common/tls"
)

// LoadGrpcTLSCredentials reads the certificate from the given path and returns TLS transport credentials
Expand All @@ -50,8 +53,12 @@ func LoadGrpcTLSCredentials(certDir string, server bool) (credentials.TransportC
}

// Create the credentials and return it
minTLSVersion, err := kedatls.GetMinGrpcTLSVersion()
if err != nil {
ctrl.Log.WithName("grpc_tls_setup").Info(err.Error())
}
config := &tls.Config{
MinVersion: tls.VersionTLS13,
MinVersion: minTLSVersion,
Certificates: []tls.Certificate{cert},
}
if server {
Expand Down
22 changes: 3 additions & 19 deletions pkg/util/tls_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"os"

"github.com/youmark/pkcs8"
ctrl "sigs.k8s.io/controller-runtime"

kedatls "github.com/kedacore/keda/v2/pkg/common/tls"
)

var minTLSVersion uint16
Expand Down Expand Up @@ -89,24 +90,7 @@ func GetMinTLSVersion() uint16 {
}

func initMinTLSVersion() (uint16, error) {
version, _ := os.LookupEnv("KEDA_HTTP_MIN_TLS_VERSION")

switch version {
case "":
minTLSVersion = tls.VersionTLS12
case "TLS10":
minTLSVersion = tls.VersionTLS10
case "TLS11":
minTLSVersion = tls.VersionTLS11
case "TLS12":
minTLSVersion = tls.VersionTLS12
case "TLS13":
minTLSVersion = tls.VersionTLS13
default:
return tls.VersionTLS12, fmt.Errorf("%s is not a valid value, using `TLS12`. Allowed values are: `TLS13`,`TLS12`,`TLS11`,`TLS10`", version)
}

return minTLSVersion, nil
return kedatls.GetMinHTTPTLSVersion()
}

func decryptClientKey(clientKey, clientKeyPassword string) ([]byte, error) {
Expand Down
50 changes: 0 additions & 50 deletions pkg/util/tls_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ limitations under the License.
package util

import (
"crypto/tls"
"crypto/x509"
"os"
"strings"
"testing"
)
Expand Down Expand Up @@ -252,51 +250,3 @@ func TestNewTLSConfig_WithPassword(t *testing.T) {
})
}
}

type minTLSVersionTestData struct {
envSet bool
envValue string
expectedVersion uint16
}

var minTLSVersionTestDatas = []minTLSVersionTestData{
{
envSet: true,
envValue: "TLS10",
expectedVersion: tls.VersionTLS10,
},
{
envSet: true,
envValue: "TLS11",
expectedVersion: tls.VersionTLS11,
},
{
envSet: true,
envValue: "TLS12",
expectedVersion: tls.VersionTLS12,
},
{
envSet: true,
envValue: "TLS13",
expectedVersion: tls.VersionTLS13,
},
{
envSet: false,
expectedVersion: tls.VersionTLS12,
},
}

func TestResolveMinTLSVersion(t *testing.T) {
defer os.Unsetenv("KEDA_HTTP_MIN_TLS_VERSION")
for _, testData := range minTLSVersionTestDatas {
os.Unsetenv("KEDA_HTTP_MIN_TLS_VERSION")
if testData.envSet {
os.Setenv("KEDA_HTTP_MIN_TLS_VERSION", testData.envValue)
}
minVersion, _ := initMinTLSVersion()

if testData.expectedVersion != minVersion {
t.Error("Failed to resolve minTLSVersion correctly", "wants", testData.expectedVersion, "got", minVersion)
}
}
}

0 comments on commit 3e2e6fa

Please sign in to comment.