diff --git a/go.mod b/go.mod index 9809c941..1f236b15 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-logr/logr v1.4.3 github.com/onsi/ginkgo/v2 v2.28.1 github.com/onsi/gomega v1.39.1 - github.com/openshift/api v0.0.0-20260715165912-72066cc9718b + github.com/openshift/api v0.0.0-20260728120005-8ba0b25b0f29 github.com/openshift/library-go v0.0.0-20260720185249-0595e37fe20f k8s.io/apimachinery v0.36.2 k8s.io/client-go v0.36.2 @@ -81,3 +81,6 @@ require ( sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) + +// TODO: Remove this replace directive and revendor once https://github.com/openshift/library-go/pull/2347 merges. +replace github.com/openshift/library-go => github.com/damdo/library-go v0.0.0-20260804155721-fceccb2c136d diff --git a/go.sum b/go.sum index 8e595807..b40788d9 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/damdo/library-go v0.0.0-20260804155721-fceccb2c136d h1:k3uIWroA3znestq3AdxKpkQ7cl7ObLfmhcW77gc80Po= +github.com/damdo/library-go v0.0.0-20260804155721-fceccb2c136d/go.mod h1:iahMN6YoNSRG1xyRj03YYU5iboJzv+UZFu9S0grJmQc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -113,10 +115,8 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= -github.com/openshift/api v0.0.0-20260715165912-72066cc9718b h1:gN3SihCYEwoIksD+f24wHhwiEgvaV0RxNjgmkDvBBeg= -github.com/openshift/api v0.0.0-20260715165912-72066cc9718b/go.mod h1:k6qH5QOVa5GDln2VVm8Jz4NV3Z7R2SATHFLwGS6Wh3M= -github.com/openshift/library-go v0.0.0-20260720185249-0595e37fe20f h1:NdSEtKB+vvHlGELA+jX/c+TALNwe8iSsJAQYvMabgHQ= -github.com/openshift/library-go v0.0.0-20260720185249-0595e37fe20f/go.mod h1:iWcB6wgeOhsByZAZGhmzBtEnrLQzABL0s3aeou8AmSI= +github.com/openshift/api v0.0.0-20260728120005-8ba0b25b0f29 h1:WrS2vkQtwJyo5xHJnJfjmHPDasdyKLKwojhMDV3tPto= +github.com/openshift/api v0.0.0-20260728120005-8ba0b25b0f29/go.mod h1:k6qH5QOVa5GDln2VVm8Jz4NV3Z7R2SATHFLwGS6Wh3M= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go index 53c159c7..29275c69 100644 --- a/pkg/tls/tls.go +++ b/pkg/tls/tls.go @@ -123,14 +123,18 @@ func GetTLSProfileSpec(profile *configv1.TLSSecurityProfile) (configv1.TLSProfil // Note: CipherSuites are only set when MinVersion is below TLS 1.3, as Go's TLS 1.3 implementation // does not allow configuring cipher suites - all TLS 1.3 ciphers are always enabled. // See: https://github.com/golang/go/issues/29349 -func NewTLSConfigFromProfile(profile configv1.TLSProfileSpec) (tlsConfig func(*tls.Config), unsupportedCiphers []string) { +func NewTLSConfigFromProfile(profile configv1.TLSProfileSpec) (tlsConfig func(*tls.Config), unsupported []string) { minVersion := libgocrypto.TLSVersionOrDie(string(profile.MinTLSVersion)) cipherSuites, unsupportedCiphers := cipherCodes(profile.Ciphers) + curvePrefs, unsupportedGroups := libgocrypto.CurveIDsForTLSGroups(profile.Groups) + + unsupported = append(unsupportedCiphers, unsupportedGroups...) return func(tlsConf *tls.Config) { tlsConf.MinVersion = minVersion - // TODO: add curve preferences from profile once https://github.com/openshift/api/pull/2583 merges. - // tlsConf.CurvePreferences <<<<<< profile.Curves + if len(curvePrefs) > 0 { + tlsConf.CurvePreferences = curvePrefs + } // TLS 1.3 cipher suites are not configurable in Go (https://github.com/golang/go/issues/29349), so only set CipherSuites accordingly. // TODO: revisit this once we get an answer on the best way to handle this here: @@ -138,7 +142,7 @@ func NewTLSConfigFromProfile(profile configv1.TLSProfileSpec) (tlsConfig func(*t if minVersion != tls.VersionTLS13 { tlsConf.CipherSuites = cipherSuites } - }, unsupportedCiphers + }, unsupported } // SetNextProtos returns a TLS configuration function that sets the ALPN diff --git a/pkg/tls/tls_test.go b/pkg/tls/tls_test.go index 5e63375b..391c2b1b 100644 --- a/pkg/tls/tls_test.go +++ b/pkg/tls/tls_test.go @@ -22,6 +22,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" configv1 "github.com/openshift/api/config/v1" + libgocrypto "github.com/openshift/library-go/pkg/crypto" ) var _ = Describe("GetTLSProfileSpec", func() { @@ -379,4 +380,80 @@ var _ = Describe("NewTLSConfigFromProfile", func() { Expect(tlsConf.CipherSuites).To(BeNil()) }) }) + + Context("when profile contains Groups", func() { + It("should set CurvePreferences for supported groups", func() { + profile := configv1.TLSProfileSpec{ + MinTLSVersion: configv1.VersionTLS12, + Groups: []configv1.TLSGroup{ + configv1.TLSGroupX25519, + configv1.TLSGroupSecP256r1, + }, + } + + tlsConfigFn, unsupported := NewTLSConfigFromProfile(profile) + Expect(unsupported).To(BeEmpty()) + + tlsConf := &tls.Config{} + tlsConfigFn(tlsConf) + + Expect(tlsConf.CurvePreferences).To(Equal([]tls.CurveID{tls.X25519, tls.CurveP256})) + }) + }) + + Context("when profile contains unsupported Groups", func() { + It("should return unsupported groups and set only supported curves", func() { + profile := configv1.TLSProfileSpec{ + MinTLSVersion: configv1.VersionTLS12, + Groups: []configv1.TLSGroup{ + configv1.TLSGroupX25519, + configv1.TLSGroup("unsupported_group"), + }, + } + + tlsConfigFn, unsupported := NewTLSConfigFromProfile(profile) + Expect(unsupported).To(ConsistOf("unsupported_group")) + + tlsConf := &tls.Config{} + tlsConfigFn(tlsConf) + + Expect(tlsConf.CurvePreferences).To(HaveLen(1)) + Expect(tlsConf.CurvePreferences).To(ContainElement(tls.X25519)) + }) + }) + + Context("when profile has empty Groups", func() { + It("should not set CurvePreferences", func() { + profile := configv1.TLSProfileSpec{ + MinTLSVersion: configv1.VersionTLS12, + Groups: []configv1.TLSGroup{}, + } + + tlsConfigFn, unsupported := NewTLSConfigFromProfile(profile) + Expect(unsupported).To(BeEmpty()) + + tlsConf := &tls.Config{} + tlsConfigFn(tlsConf) + + Expect(tlsConf.CurvePreferences).To(BeNil()) + }) + }) + + Context("when using Intermediate profile with Groups", func() { + It("should set CurvePreferences from the profile", func() { + profile := *configv1.TLSProfiles[configv1.TLSProfileIntermediateType] + + tlsConfigFn, _ := NewTLSConfigFromProfile(profile) + + tlsConf := &tls.Config{} + tlsConfigFn(tlsConf) + + expectedCurves, _ := libgocrypto.CurveIDsForTLSGroups(profile.Groups) + if len(expectedCurves) > 0 { + Expect(tlsConf.CurvePreferences).To(Equal(expectedCurves)) + } else { + Expect(tlsConf.CurvePreferences).To(BeNil()) + } + }) + }) })