From 3ccf1cb76dc5e9d0cb80f0894de61eb9174acb17 Mon Sep 17 00:00:00 2001 From: akhil nittala Date: Wed, 15 Jul 2026 19:50:34 +0530 Subject: [PATCH 1/3] [GITOPS-10474]: Configure TLS MinVersion,MaxVersion,CipherSuites Signed-off-by: akhil nittala --- deploy/deployment.yaml | 6 ++ pkg/cmd/root.go | 179 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 179 insertions(+), 6 deletions(-) diff --git a/deploy/deployment.yaml b/deploy/deployment.yaml index 9373553..84c9deb 100644 --- a/deploy/deployment.yaml +++ b/deploy/deployment.yaml @@ -22,6 +22,12 @@ spec: env: - name: INSECURE value: "true" + - name: TLSMINVERSION + value: "1.3" + - name: TLSMAXVERSION + value: "1.3" + - name: TLSCIPHERSUITES + value: "" volumeMounts: - mountPath: "/etc/gitops/ssl" name: backend-ssl diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index d488e7a..88e7394 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "strings" argoV1aplha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -22,14 +23,155 @@ import ( ) const ( - portFlag = "port" - insecureFlag = "insecure" - tlsCertFlag = "tls-cert" - tlsKeyFlag = "tls-key" - noTLSFlag = "no-tls" - enableHTTP2 = "enable-http2" + portFlag = "port" + insecureFlag = "insecure" + tlsCertFlag = "tls-cert" + tlsKeyFlag = "tls-key" + noTLSFlag = "no-tls" + enableHTTP2 = "enable-http2" + tlsMinVersionFlag = "tlsminversion" + tlsMaxVersionFlag = "tlsmaxversion" + tlsCipherSuitesFlag = "tlsciphersuites" ) +type TLSConfig struct { + MinVersion string + MaxVersion string + Ciphers string +} + +// tlsVersionMap maps version strings to tls version constants. +// TLS 1.0 is not supported as it is considered insecure. +var tlsVersionMap = map[string]uint16{ + "1.1": tls.VersionTLS11, + "tls1.1": tls.VersionTLS11, + "1.2": tls.VersionTLS12, + "tls1.2": tls.VersionTLS12, + "1.3": tls.VersionTLS13, + "tls1.3": tls.VersionTLS13, +} + +// TLSVersionName returns a human-readable name for a TLS version constant. +func TLSVersionName(version uint16) string { + for name, v := range tlsVersionMap { + if v == version { + return name + } + } + return fmt.Sprintf("unknown (%d)", version) +} + +// ParseTLSVersion parses a TLS version string (e.g. "1.2", "1.3", "TLS1.2") into a tls version constant. +// Returns 0 if the string is empty (meaning "use default"). +func ParseTLSVersion(version string) (uint16, error) { + if version == "" { + return 0, nil + } + v, ok := tlsVersionMap[strings.ToLower(strings.TrimSpace(version))] + if !ok { + return 0, fmt.Errorf("unsupported TLS version: %q (supported: 1.1, 1.2, 1.3)", version) + } + return v, nil +} + +// ParseTLSCiphers parses a colon-separated list of cipher suite names into cipher suite IDs. +// Only secure cipher suites (from tls.CipherSuites()) are allowed. +// Returns nil if the input is empty. +func ParseTLSCiphers(ciphers string) ([]uint16, error) { + if ciphers == "" { + return nil, nil + } + // Build lookup map from Go's secure cipher suites only + cipherMap := make(map[string]uint16) + for _, cs := range tls.CipherSuites() { + cipherMap[cs.Name] = cs.ID + } + var result []uint16 + for _, name := range strings.Split(ciphers, ":") { + name = strings.TrimSpace(name) + if name == "" { + continue + } + id, ok := cipherMap[name] + if !ok { + return nil, fmt.Errorf("unsupported TLS cipher suite: %q", name) + } + result = append(result, id) + } + return result, nil +} + +// ValidateTLSConfig validates the TLS configuration parameters. +// It checks that: +// - The minimum TLS version is not greater than the maximum TLS version +// - All configured cipher suites are compatible with the minimum TLS version +func ValidateTLSConfig(minVersion, maxVersion uint16, cipherSuites []uint16) error { + if minVersion != 0 && maxVersion != 0 && minVersion > maxVersion { + return fmt.Errorf("minimum TLS version (%s) cannot be higher than maximum TLS version (%s)", + TLSVersionName(minVersion), TLSVersionName(maxVersion)) + } + if len(cipherSuites) > 0 && minVersion != 0 { + availableCiphers := tls.CipherSuites() + for _, cipherID := range cipherSuites { + for _, cs := range availableCiphers { + if cs.ID == cipherID { + supported := false + for _, v := range cs.SupportedVersions { + if v == minVersion { + supported = true + break + } + } + if !supported { + return fmt.Errorf("cipher suite %s is not supported by minimum TLS version %s", + cs.Name, TLSVersionName(minVersion)) + } + break + } + } + } + } + + return nil +} + +func buildTLSConfig() (*tls.Config, error) { + cfg := TLSConfig{ + MinVersion: viper.GetString(tlsMinVersionFlag), + MaxVersion: viper.GetString(tlsMaxVersionFlag), + Ciphers: viper.GetString(tlsCipherSuitesFlag), + } + + tlsCfg := &tls.Config{} //nolint:gosec + minVer, err := ParseTLSVersion(cfg.MinVersion) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsMinVersionFlag, err) + } + tlsCfg.MinVersion = minVer + maxVer, err := ParseTLSVersion(cfg.MaxVersion) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsMaxVersionFlag, err) + } + tlsCfg.MaxVersion = maxVer + ciphers, err := ParseTLSCiphers(cfg.Ciphers) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsCipherSuitesFlag, err) + } + if len(ciphers) > 0 && minVer == tls.VersionTLS13 { + log.Printf( + "%s has no effect when minimum TLS version is 1.3 because TLS 1.3 cipher suites are not configurable; ignoring", + tlsCipherSuitesFlag, + ) + ciphers = nil + } + if err := ValidateTLSConfig(minVer, maxVer, ciphers); err != nil { + return nil, err + } + tlsCfg.CipherSuites = ciphers + + return tlsCfg, nil +} + func init() { cobra.OnInitialize(initConfig) if err := argoV1aplha1.AddToScheme(scheme.Scheme); err != nil { @@ -79,6 +221,11 @@ func makeHTTPCmd() *cobra.Command { log.Println("TLS connections disabled") return server.ListenAndServe() } + tlsConfig, err := buildTLSConfig() + if err != nil { + return err + } + server.TLSConfig = tlsConfig log.Printf("Using TLS from %q and %q", viper.GetString(tlsCertFlag), viper.GetString(tlsKeyFlag)) return server.ListenAndServeTLS(viper.GetString(tlsCertFlag), viper.GetString(tlsKeyFlag)) }, @@ -125,6 +272,26 @@ func makeHTTPCmd() *cobra.Command { "enable HTTP/2 for the server", ) logIfError(viper.BindPFlag(enableHTTP2, cmd.Flags().Lookup(enableHTTP2))) + cmd.Flags().String( + tlsMinVersionFlag, + "", + "minimum supported TLS version (1.2, 1.3)", + ) + logIfError(viper.BindPFlag(tlsMinVersionFlag, cmd.Flags().Lookup(tlsMinVersionFlag))) + + cmd.Flags().String( + tlsMaxVersionFlag, + "", + "maximum supported TLS version (1.2, 1.3)", + ) + logIfError(viper.BindPFlag(tlsMaxVersionFlag, cmd.Flags().Lookup(tlsMaxVersionFlag))) + + cmd.Flags().String( + tlsCipherSuitesFlag, + "", + "comma-separated list of TLS cipher suites", + ) + logIfError(viper.BindPFlag(tlsCipherSuitesFlag, cmd.Flags().Lookup(tlsCipherSuitesFlag))) return cmd } From 25745f911ee39525d3c633211ffc4fc690c8684b Mon Sep 17 00:00:00 2001 From: akhil nittala Date: Fri, 17 Jul 2026 11:00:24 +0530 Subject: [PATCH 2/3] [GITOPS-10474]: Configure TLS MinVersion,MaxVersion,CipherSuites Signed-off-by: akhil nittala --- deploy/deployment.yaml | 6 +- pkg/cmd/root.go | 154 +--------------------- pkg/cmd/tls.go | 154 ++++++++++++++++++++++ pkg/cmd/tls_test.go | 288 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 451 insertions(+), 151 deletions(-) create mode 100644 pkg/cmd/tls.go create mode 100644 pkg/cmd/tls_test.go diff --git a/deploy/deployment.yaml b/deploy/deployment.yaml index 84c9deb..6d8ba1c 100644 --- a/deploy/deployment.yaml +++ b/deploy/deployment.yaml @@ -22,11 +22,11 @@ spec: env: - name: INSECURE value: "true" - - name: TLSMINVERSION + - name: TLS_MIN_VERSION value: "1.3" - - name: TLSMAXVERSION + - name: TLS_MAX_VERSION value: "1.3" - - name: TLSCIPHERSUITES + - name: TLS_CIPHER_SUITES value: "" volumeMounts: - mountPath: "/etc/gitops/ssl" diff --git a/pkg/cmd/root.go b/pkg/cmd/root.go index 88e7394..8129fb0 100644 --- a/pkg/cmd/root.go +++ b/pkg/cmd/root.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "net/http" - "strings" argoV1aplha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -23,155 +22,14 @@ import ( ) const ( - portFlag = "port" - insecureFlag = "insecure" - tlsCertFlag = "tls-cert" - tlsKeyFlag = "tls-key" - noTLSFlag = "no-tls" - enableHTTP2 = "enable-http2" - tlsMinVersionFlag = "tlsminversion" - tlsMaxVersionFlag = "tlsmaxversion" - tlsCipherSuitesFlag = "tlsciphersuites" + portFlag = "port" + insecureFlag = "insecure" + tlsCertFlag = "tls-cert" + tlsKeyFlag = "tls-key" + noTLSFlag = "no-tls" + enableHTTP2 = "enable-http2" ) -type TLSConfig struct { - MinVersion string - MaxVersion string - Ciphers string -} - -// tlsVersionMap maps version strings to tls version constants. -// TLS 1.0 is not supported as it is considered insecure. -var tlsVersionMap = map[string]uint16{ - "1.1": tls.VersionTLS11, - "tls1.1": tls.VersionTLS11, - "1.2": tls.VersionTLS12, - "tls1.2": tls.VersionTLS12, - "1.3": tls.VersionTLS13, - "tls1.3": tls.VersionTLS13, -} - -// TLSVersionName returns a human-readable name for a TLS version constant. -func TLSVersionName(version uint16) string { - for name, v := range tlsVersionMap { - if v == version { - return name - } - } - return fmt.Sprintf("unknown (%d)", version) -} - -// ParseTLSVersion parses a TLS version string (e.g. "1.2", "1.3", "TLS1.2") into a tls version constant. -// Returns 0 if the string is empty (meaning "use default"). -func ParseTLSVersion(version string) (uint16, error) { - if version == "" { - return 0, nil - } - v, ok := tlsVersionMap[strings.ToLower(strings.TrimSpace(version))] - if !ok { - return 0, fmt.Errorf("unsupported TLS version: %q (supported: 1.1, 1.2, 1.3)", version) - } - return v, nil -} - -// ParseTLSCiphers parses a colon-separated list of cipher suite names into cipher suite IDs. -// Only secure cipher suites (from tls.CipherSuites()) are allowed. -// Returns nil if the input is empty. -func ParseTLSCiphers(ciphers string) ([]uint16, error) { - if ciphers == "" { - return nil, nil - } - // Build lookup map from Go's secure cipher suites only - cipherMap := make(map[string]uint16) - for _, cs := range tls.CipherSuites() { - cipherMap[cs.Name] = cs.ID - } - var result []uint16 - for _, name := range strings.Split(ciphers, ":") { - name = strings.TrimSpace(name) - if name == "" { - continue - } - id, ok := cipherMap[name] - if !ok { - return nil, fmt.Errorf("unsupported TLS cipher suite: %q", name) - } - result = append(result, id) - } - return result, nil -} - -// ValidateTLSConfig validates the TLS configuration parameters. -// It checks that: -// - The minimum TLS version is not greater than the maximum TLS version -// - All configured cipher suites are compatible with the minimum TLS version -func ValidateTLSConfig(minVersion, maxVersion uint16, cipherSuites []uint16) error { - if minVersion != 0 && maxVersion != 0 && minVersion > maxVersion { - return fmt.Errorf("minimum TLS version (%s) cannot be higher than maximum TLS version (%s)", - TLSVersionName(minVersion), TLSVersionName(maxVersion)) - } - if len(cipherSuites) > 0 && minVersion != 0 { - availableCiphers := tls.CipherSuites() - for _, cipherID := range cipherSuites { - for _, cs := range availableCiphers { - if cs.ID == cipherID { - supported := false - for _, v := range cs.SupportedVersions { - if v == minVersion { - supported = true - break - } - } - if !supported { - return fmt.Errorf("cipher suite %s is not supported by minimum TLS version %s", - cs.Name, TLSVersionName(minVersion)) - } - break - } - } - } - } - - return nil -} - -func buildTLSConfig() (*tls.Config, error) { - cfg := TLSConfig{ - MinVersion: viper.GetString(tlsMinVersionFlag), - MaxVersion: viper.GetString(tlsMaxVersionFlag), - Ciphers: viper.GetString(tlsCipherSuitesFlag), - } - - tlsCfg := &tls.Config{} //nolint:gosec - minVer, err := ParseTLSVersion(cfg.MinVersion) - if err != nil { - return nil, fmt.Errorf("invalid --%s: %w", tlsMinVersionFlag, err) - } - tlsCfg.MinVersion = minVer - maxVer, err := ParseTLSVersion(cfg.MaxVersion) - if err != nil { - return nil, fmt.Errorf("invalid --%s: %w", tlsMaxVersionFlag, err) - } - tlsCfg.MaxVersion = maxVer - ciphers, err := ParseTLSCiphers(cfg.Ciphers) - if err != nil { - return nil, fmt.Errorf("invalid --%s: %w", tlsCipherSuitesFlag, err) - } - if len(ciphers) > 0 && minVer == tls.VersionTLS13 { - log.Printf( - "%s has no effect when minimum TLS version is 1.3 because TLS 1.3 cipher suites are not configurable; ignoring", - tlsCipherSuitesFlag, - ) - ciphers = nil - } - if err := ValidateTLSConfig(minVer, maxVer, ciphers); err != nil { - return nil, err - } - tlsCfg.CipherSuites = ciphers - - return tlsCfg, nil -} - func init() { cobra.OnInitialize(initConfig) if err := argoV1aplha1.AddToScheme(scheme.Scheme); err != nil { diff --git a/pkg/cmd/tls.go b/pkg/cmd/tls.go new file mode 100644 index 0000000..7fd18e5 --- /dev/null +++ b/pkg/cmd/tls.go @@ -0,0 +1,154 @@ +package cmd + +import ( + "crypto/tls" + "fmt" + "log" + "strings" + + "github.com/spf13/viper" +) + +const ( + tlsMinVersionFlag = "tls-min-version" + tlsMaxVersionFlag = "tls-max-version" + tlsCipherSuitesFlag = "tls-cipher-suites" +) + +type TLSConfig struct { + MinVersion string + MaxVersion string + Ciphers string +} + +// tlsVersionMap maps version strings to tls version constants. +// TLS 1.0 is not supported as it is considered insecure. +var tlsVersionMap = map[string]uint16{ + "1.1": tls.VersionTLS11, + "tls1.1": tls.VersionTLS11, + "1.2": tls.VersionTLS12, + "tls1.2": tls.VersionTLS12, + "1.3": tls.VersionTLS13, + "tls1.3": tls.VersionTLS13, +} + +// TLSVersionName returns a human-readable name for a TLS version constant. +func TLSVersionName(version uint16) string { + for name, v := range tlsVersionMap { + if v == version { + return name + } + } + return fmt.Sprintf("unknown (%d)", version) +} + +// ParseTLSVersion parses a TLS version string (e.g. "1.2", "1.3", "TLS1.2") into a tls version constant. +// Returns 0 if the string is empty (meaning "use default"). +func ParseTLSVersion(version string) (uint16, error) { + if version == "" { + return 0, nil + } + v, ok := tlsVersionMap[strings.ToLower(strings.TrimSpace(version))] + if !ok { + return 0, fmt.Errorf("unsupported TLS version: %q (supported: 1.1, 1.2, 1.3)", version) + } + return v, nil +} + +// ParseTLSCiphers parses a colon-separated list of cipher suite names into cipher suite IDs. +// Only secure cipher suites (from tls.CipherSuites()) are allowed. +// Returns nil if the input is empty. +func ParseTLSCiphers(ciphers string) ([]uint16, error) { + if ciphers == "" { + return nil, nil + } + // Build lookup map from Go's secure cipher suites only + cipherMap := make(map[string]uint16) + for _, cs := range tls.CipherSuites() { + cipherMap[cs.Name] = cs.ID + } + var result []uint16 + for _, name := range strings.Split(ciphers, ":") { + name = strings.TrimSpace(name) + if name == "" { + continue + } + id, ok := cipherMap[name] + if !ok { + return nil, fmt.Errorf("unsupported TLS cipher suite: %q", name) + } + result = append(result, id) + } + return result, nil +} + +// ValidateTLSConfig validates the TLS configuration parameters. +// It checks that: +// - The minimum TLS version is not greater than the maximum TLS version +// - All configured cipher suites are compatible with the minimum TLS version +func ValidateTLSConfig(minVersion, maxVersion uint16, cipherSuites []uint16) error { + if minVersion != 0 && maxVersion != 0 && minVersion > maxVersion { + return fmt.Errorf("minimum TLS version (%s) cannot be higher than maximum TLS version (%s)", + TLSVersionName(minVersion), TLSVersionName(maxVersion)) + } + if len(cipherSuites) > 0 && minVersion != 0 { + availableCiphers := tls.CipherSuites() + for _, cipherID := range cipherSuites { + for _, cs := range availableCiphers { + if cs.ID == cipherID { + supported := false + for _, v := range cs.SupportedVersions { + if v == minVersion { + supported = true + break + } + } + if !supported { + return fmt.Errorf("cipher suite %s is not supported by minimum TLS version %s", + cs.Name, TLSVersionName(minVersion)) + } + break + } + } + } + } + + return nil +} + +func buildTLSConfig() (*tls.Config, error) { + cfg := TLSConfig{ + MinVersion: viper.GetString(tlsMinVersionFlag), + MaxVersion: viper.GetString(tlsMaxVersionFlag), + Ciphers: viper.GetString(tlsCipherSuitesFlag), + } + + tlsCfg := &tls.Config{} //nolint:gosec + minVer, err := ParseTLSVersion(cfg.MinVersion) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsMinVersionFlag, err) + } + tlsCfg.MinVersion = minVer + maxVer, err := ParseTLSVersion(cfg.MaxVersion) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsMaxVersionFlag, err) + } + tlsCfg.MaxVersion = maxVer + ciphers, err := ParseTLSCiphers(cfg.Ciphers) + if err != nil { + return nil, fmt.Errorf("invalid --%s: %w", tlsCipherSuitesFlag, err) + } + if len(ciphers) > 0 && minVer == tls.VersionTLS13 { + log.Printf( + "%s has no effect when minimum TLS version is 1.3 because TLS 1.3 cipher suites are not configurable; ignoring", + tlsCipherSuitesFlag, + ) + ciphers = nil + } + if err := ValidateTLSConfig(minVer, maxVer, ciphers); err != nil { + return nil, err + } + tlsCfg.CipherSuites = ciphers + + return tlsCfg, nil +} diff --git a/pkg/cmd/tls_test.go b/pkg/cmd/tls_test.go new file mode 100644 index 0000000..f4a94b0 --- /dev/null +++ b/pkg/cmd/tls_test.go @@ -0,0 +1,288 @@ +package cmd + +import ( + "crypto/tls" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTLSVersionName(t *testing.T) { + tests := []struct { + name string + version uint16 + expected string + }{ + { + name: "TLS1.1", + version: tls.VersionTLS11, + expected: "1.1", + }, + { + name: "TLS1.2", + version: tls.VersionTLS12, + expected: "1.2", + }, + { + name: "TLS1.3", + version: tls.VersionTLS13, + expected: "1.3", + }, + { + name: "unknown", + version: 999, + expected: "unknown (999)", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equal(t, tt.expected, TLSVersionName(tt.version)) + }) + } +} + +func TestParseTLSVersion(t *testing.T) { + tests := []struct { + name string + input string + expected uint16 + expectErr bool + }{ + { + name: "empty", + input: "", + expected: 0, + }, + { + name: "1.2", + input: "1.2", + expected: tls.VersionTLS12, + }, + { + name: "TLS1.2", + input: "TLS1.2", + expected: tls.VersionTLS12, + }, + { + name: "trim spaces", + input: " 1.3 ", + expected: tls.VersionTLS13, + }, + { + name: "unsupported", + input: "1.0", + expectErr: true, + }, + { + name: "garbage", + input: "abc", + expectErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + version, err := ParseTLSVersion(tt.input) + + if tt.expectErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + assert.Equal(t, tt.expected, version) + }) + } +} + +func TestParseTLSCiphers(t *testing.T) { + validCipher := tls.CipherSuites()[0] + + tests := []struct { + name string + input string + expected []uint16 + expectErr bool + }{ + { + name: "empty", + input: "", + expected: nil, + }, + { + name: "single cipher", + input: validCipher.Name, + expected: []uint16{validCipher.ID}, + }, + { + name: "multiple ciphers", + input: validCipher.Name + ":" + + tls.CipherSuites()[1].Name, + expected: []uint16{ + validCipher.ID, + tls.CipherSuites()[1].ID, + }, + }, + { + name: "invalid cipher", + input: "INVALID_CIPHER", + expectErr: true, + }, + { + name: "ignore empty entries", + input: ":" + validCipher.Name + "::", + expected: []uint16{validCipher.ID}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ciphers, err := ParseTLSCiphers(tt.input) + + if tt.expectErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + assert.Equal(t, tt.expected, ciphers) + }) + } +} + +func TestValidateTLSConfig(t *testing.T) { + tls12cipher := tls.CipherSuites()[3] + + tests := []struct { + name string + minVersion uint16 + maxVersion uint16 + ciphers []uint16 + expectErr bool + }{ + { + name: "valid versions", + minVersion: tls.VersionTLS12, + maxVersion: tls.VersionTLS13, + }, + { + name: "min greater than max", + minVersion: tls.VersionTLS13, + maxVersion: tls.VersionTLS12, + expectErr: true, + }, + { + name: "no versions", + minVersion: 0, + maxVersion: 0, + }, + { + name: "valid cipher", + minVersion: tls.VersionTLS12, + maxVersion: tls.VersionTLS13, + ciphers: []uint16{tls12cipher.ID}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := ValidateTLSConfig( + tt.minVersion, + tt.maxVersion, + tt.ciphers, + ) + + if tt.expectErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + }) + } +} + +func TestBuildTLSConfig(t *testing.T) { + validCipher := tls.CipherSuites()[3] + + tests := []struct { + name string + minVersion string + maxVersion string + ciphers string + expectedMin uint16 + expectedMax uint16 + expectedSuite []uint16 + expectErr bool + }{ + { + name: "defaults", + expectedMin: 0, + expectedMax: 0, + }, + { + name: "valid config", + minVersion: "1.2", + maxVersion: "1.3", + ciphers: validCipher.Name, + expectedMin: tls.VersionTLS12, + expectedMax: tls.VersionTLS13, + expectedSuite: []uint16{ + validCipher.ID, + }, + }, + { + name: "invalid min version", + minVersion: "1.0", + expectErr: true, + }, + { + name: "invalid max version", + maxVersion: "abc", + expectErr: true, + }, + { + name: "invalid cipher", + ciphers: "BAD_CIPHER", + expectErr: true, + }, + { + name: "min greater than max", + minVersion: "1.3", + maxVersion: "1.2", + expectErr: true, + }, + { + name: "tls13 ignores ciphers", + minVersion: "1.3", + ciphers: validCipher.Name, + expectedMin: tls.VersionTLS13, + expectedMax: 0, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + viper.Reset() + + viper.Set(tlsMinVersionFlag, tt.minVersion) + viper.Set(tlsMaxVersionFlag, tt.maxVersion) + viper.Set(tlsCipherSuitesFlag, tt.ciphers) + + cfg, err := buildTLSConfig() + + if tt.expectErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + assert.Equal(t, tt.expectedMin, cfg.MinVersion) + assert.Equal(t, tt.expectedMax, cfg.MaxVersion) + assert.Equal(t, tt.expectedSuite, cfg.CipherSuites) + }) + } +} From 3683ed8ad0ee69e3f2ed089fdd1cc5a9b7e3f047 Mon Sep 17 00:00:00 2001 From: akhil nittala Date: Fri, 17 Jul 2026 11:48:31 +0530 Subject: [PATCH 3/3] [GITOPS-10474]: Configure TLS MinVersion,MaxVersion,CipherSuites Signed-off-by: akhil nittala --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e8017e5..e336033 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.9.1 github.com/spf13/viper v1.7.0 + github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.27.0 k8s.io/api v0.33.1 k8s.io/apimachinery v0.33.1 @@ -135,7 +136,6 @@ require ( github.com/spf13/cast v1.7.1 // indirect github.com/spf13/jwalterweatherman v1.0.0 // indirect github.com/spf13/pflag v1.0.6 // indirect - github.com/stretchr/testify v1.11.1 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/vmihailenco/go-tinylfu v0.2.2 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect