From a04ab0f8d1851420176dbc41a37c6c46d73d25a9 Mon Sep 17 00:00:00 2001 From: yunmaoQu <2643354262@qq.com> Date: Fri, 13 Dec 2024 10:51:16 +0000 Subject: [PATCH] feat: add TLS version annotation support for per-rule configuration --- pkg/ingress/config/ingress_config.go | 2 + pkg/ingress/kube/annotations/annotations.go | 6 ++ .../kube/annotations/annotations_test.go | 40 +++++++++ pkg/ingress/kube/annotations/tls.go | 81 +++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 pkg/ingress/kube/annotations/tls.go diff --git a/pkg/ingress/config/ingress_config.go b/pkg/ingress/config/ingress_config.go index bb4b261ac1..fbf28d2eb5 100644 --- a/pkg/ingress/config/ingress_config.go +++ b/pkg/ingress/config/ingress_config.go @@ -151,6 +151,8 @@ type IngressConfig struct { clusterId cluster.ID httpsConfigMgr *cert.ConfigMgr + + UpstreamTLS *TLSConfig } func NewIngressConfig(localKubeClient kube.Client, xdsUpdater istiomodel.XDSUpdater, namespace string, clusterId cluster.ID) *IngressConfig { diff --git a/pkg/ingress/kube/annotations/annotations.go b/pkg/ingress/kube/annotations/annotations.go index 36e4a6dea0..4d48231654 100644 --- a/pkg/ingress/kube/annotations/annotations.go +++ b/pkg/ingress/kube/annotations/annotations.go @@ -138,6 +138,10 @@ type AnnotationHandler interface { RouteHandler TrafficPolicyHandler } +type TLSConfig struct { + MinVersion string + MaxVersion string +} type AnnotationHandlerManager struct { parsers []Parser @@ -169,6 +173,7 @@ func NewAnnotationHandlerManager() AnnotationHandler { match{}, headerControl{}, http2rpc{}, + tls{}, }, gatewayHandlers: []GatewayHandler{ downstreamTLS{}, @@ -193,6 +198,7 @@ func NewAnnotationHandlerManager() AnnotationHandler { trafficPolicyHandlers: []TrafficPolicyHandler{ upstreamTLS{}, loadBalance{}, + tls{}, }, } } diff --git a/pkg/ingress/kube/annotations/annotations_test.go b/pkg/ingress/kube/annotations/annotations_test.go index bfad684d20..c8ed7f703c 100644 --- a/pkg/ingress/kube/annotations/annotations_test.go +++ b/pkg/ingress/kube/annotations/annotations_test.go @@ -219,3 +219,43 @@ func TestNeedTrafficPolicy(t *testing.T) { t.Fatal("should be true") } } + +func TestTLSConfig(t *testing.T) { + testCases := []struct { + annotations map[string]string + expectTLS *TLSConfig + }{ + { + annotations: map[string]string{ + "tls-min-version": "TLSv1_2", + "tls-max-version": "TLSv1_3", + }, + expectTLS: &TLSConfig{ + MinVersion: "TLSv1_2", + MaxVersion: "TLSv1_3", + }, + }, + { + annotations: map[string]string{ + "tls-min-version": "TLSv1_1", + }, + expectTLS: &TLSConfig{ + MinVersion: "TLSv1_1", + }, + }, + } + + for _, testCase := range testCases { + ingress := &Ingress{} + annotations := Annotations(testCase.annotations) + handler := tls{} + err := handler.Parse(annotations, ingress, nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if ingress.UpstreamTLS.MinVersion != testCase.expectTLS.MinVersion || ingress.UpstreamTLS.MaxVersion != testCase.expectTLS.MaxVersion { + t.Fatalf("expected %+v, got %+v", testCase.expectTLS, ingress.UpstreamTLS) + } + } +} \ No newline at end of file diff --git a/pkg/ingress/kube/annotations/tls.go b/pkg/ingress/kube/annotations/tls.go new file mode 100644 index 0000000000..ddfe227e76 --- /dev/null +++ b/pkg/ingress/kube/annotations/tls.go @@ -0,0 +1,81 @@ +package annotations + +import ( + networking "istio.io/api/networking/v1alpha3" +) + +const ( + tlsMinVersion = "tls-min-version" + tlsMaxVersion = "tls-max-version" +) + +var ( + _ Parser = tls{} + _ TrafficPolicyHandler = tls{} +) + +type tls struct{} + +func (t tls) Parse(annotations Annotations, config *Ingress, _ *GlobalContext) error { + if !needTLSConfig(annotations) { + return nil + } + + tlsConfig := &TLSConfig{} + defer func() { + config.UpstreamTLS = tlsConfig + }() + + // Parse minimum TLS version + if minVersion, err := annotations.ParseStringASAP(tlsMinVersion); err == nil { + tlsConfig.MinVersion = minVersion + } + + // Parse maximum TLS version + if maxVersion, err := annotations.ParseStringASAP(tlsMaxVersion); err == nil { + tlsConfig.MaxVersion = maxVersion + } + + return nil +} + +func (t tls) ApplyTrafficPolicy(trafficPolicy *networking.TrafficPolicy, _ *networking.TrafficPolicy_PortTrafficPolicy, config *Ingress) { + tlsConfig := config.UpstreamTLS + if tlsConfig == nil { + return + } + + if trafficPolicy.Tls == nil { + trafficPolicy.Tls = &networking.ClientTLSSettings{} + } + + // Apply min version + if tlsConfig.MinVersion != "" { + trafficPolicy.Tls.MinProtocolVersion = convertTLSVersion(tlsConfig.MinVersion) + } + + // Apply max version + if tlsConfig.MaxVersion != "" { + trafficPolicy.Tls.MaxProtocolVersion = convertTLSVersion(tlsConfig.MaxVersion) + } +} + +func needTLSConfig(annotations Annotations) bool { + return annotations.HasASAP(tlsMinVersion) || annotations.HasASAP(tlsMaxVersion) +} + +// Helper to convert TLS version string to istio enum +func convertTLSVersion(version string) networking.ClientTLSSettings_TLSProtocol { + switch version { + case "TLSv1_0": + return networking.ClientTLSSettings_TLSV1_0 + case "TLSv1_1": + return networking.ClientTLSSettings_TLSV1_1 + case "TLSv1_2": + return networking.ClientTLSSettings_TLSV1_2 + case "TLSv1_3": + return networking.ClientTLSSettings_TLSV1_3 + default: + return networking.ClientTLSSettings_TLS_AUTO + } +}