From 4fd9827cd1c778323e6230a2d8092ed3269c68cd Mon Sep 17 00:00:00 2001 From: Vidya Sagar <42372699+vidyasagar-m@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:47:31 +0530 Subject: [PATCH] #3637 support for TLS in Transport Server (#3652) * rebasing from the source * update resource config * fix uts --- config/apis/cis/v1/types.go | 17 +-- docs/RELEASE-NOTES.rst | 1 + .../customResource/CustomResource.md | 10 ++ .../transport-server-with-tls/README.md | 20 +++ .../ts-with-tls-bigip-ref.yaml | 30 ++++ .../ts-with-tls-secret-ref.yaml | 30 ++++ .../incubator/customresourcedefinitions.yml | 16 +++ pkg/controller/backend.go | 29 ++-- pkg/controller/resourceConfig.go | 91 +++++++++++- pkg/controller/resourceConfig_test.go | 129 ++++++++++++++++++ pkg/controller/worker.go | 26 ++++ 11 files changed, 378 insertions(+), 21 deletions(-) create mode 100644 docs/config_examples/customResource/TransportServer/transport-server-with-tls/README.md create mode 100644 docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-bigip-ref.yaml create mode 100644 docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-secret-ref.yaml diff --git a/config/apis/cis/v1/types.go b/config/apis/cis/v1/types.go index 013d638e3..faaad8be9 100644 --- a/config/apis/cis/v1/types.go +++ b/config/apis/cis/v1/types.go @@ -214,14 +214,14 @@ type TLSProfileCipher struct { // TLS contains required fields for TLS termination type TLS struct { - Termination string `json:"termination"` - ClientSSL string `json:"clientSSL"` - ClientSSLs []string `json:"clientSSLs"` - ServerSSL string `json:"serverSSL"` - ServerSSLs []string `json:"serverSSLs"` - Reference string `json:"reference"` - ClientSSLParams ClientSSLParams `json:"clientSSLParams"` - ServerSSLParams ServerSSLParams `json:"serverSSLParams"` + Termination string `json:"termination,omitempty"` + ClientSSL string `json:"clientSSL,omitempty"` + ClientSSLs []string `json:"clientSSLs,omitempty"` + ServerSSL string `json:"serverSSL,omitempty"` + ServerSSLs []string `json:"serverSSLs,omitempty"` + Reference string `json:"reference,omitempty"` + ClientSSLParams ClientSSLParams `json:"clientSSLParams,omitempty"` + ServerSSLParams ServerSSLParams `json:"serverSSLParams,omitempty"` } // ClientSSLParams contains required fields for Client SSL @@ -333,6 +333,7 @@ type TransportServerSpec struct { BotDefense string `json:"botDefense,omitempty"` Profiles ProfileTSSpec `json:"profiles,omitempty"` Partition string `json:"partition,omitempty"` + TLS TLS `json:"tls,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/docs/RELEASE-NOTES.rst b/docs/RELEASE-NOTES.rst index 533c5cda3..ebf7dac89 100644 --- a/docs/RELEASE-NOTES.rst +++ b/docs/RELEASE-NOTES.rst @@ -10,6 +10,7 @@ Added Functionality * Multi Cluster * CRD * `Issue 3523 `_: Support for HTTP Compression profile in VS CR. See `Example `_ + * `Issue 3637 `_: Support for TLS in transport server. See `Example <./config_examples/customResource/TransportServer/transport-server-with-tls>`_ * Support for empty node label selector Bug Fixes diff --git a/docs/config_examples/customResource/CustomResource.md b/docs/config_examples/customResource/CustomResource.md index 27e51cc63..fcf51f31f 100644 --- a/docs/config_examples/customResource/CustomResource.md +++ b/docs/config_examples/customResource/CustomResource.md @@ -312,7 +312,9 @@ different terminations(for same domain), one with edge and another with re-encry | partition | String | Optional | NA | bigip partition | | bigipRouteDomain | Integer | Optional | 0 | Appends route domain to the virtual addresses of the BigIP and is not supported in cluster mode | +| tls | object | Optional | NA | Describes the TLS configuration for BIG-IP Virtual Server. +| **Pool Components** | PARAMETER | TYPE | REQUIRED | DEFAULT | DESCRIPTION | @@ -358,6 +360,14 @@ different terminations(for same domain), one with edge and another with re-encry | name | String | Required | NA | Refrence to health monitor name existing on bigip| | reference | String | Required | NA | Value should be bigip for referencing custom monitor on bigip| +**TLS Components** + +| PARAMETER | TYPE | REQUIRED | DEFAULT | DESCRIPTION | +|-----------------|----------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| clientSSLs | List of string | Required | NA | Multiple ClientSSL Profiles on the BIG-IP OR list of kubernetes secrets. | +| serverSSLs | List of string | Optional | NA | Multiple ServerSSL Profiles on the BIG-IP OR list of kubernetes secrets. | +| reference | String | Required | NA | Describes the location of profile, BIG-IP or k8s Secrets. Allowed values: [bigip,secret] | + **Note**: * monitor can be a reference to existing helathmonitor on bigip in which case, name and reference are required parameters. * For creating health monitor object on bigip with UserInput type, send, interval are required parameters. diff --git a/docs/config_examples/customResource/TransportServer/transport-server-with-tls/README.md b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/README.md new file mode 100644 index 000000000..1618b76e5 --- /dev/null +++ b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/README.md @@ -0,0 +1,20 @@ +# Transport server with TLS +This section demonstrates the option to configure TLS in transport server. + +Option which can be used is: +``` +tls: + clientSSLs: + - + serverSSLs: + - + reference: +``` + +## ts-with-tls-bigip-ref.yaml + +By deploying this yaml file in your cluster, CIS will create a transport server with BIGIP TLS Configuration. + +## ts-with-tls-secret-ref.yaml + +By deploying this yaml file in your cluster, CIS will create a transport server with k8s Secret TLS Configuration. diff --git a/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-bigip-ref.yaml b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-bigip-ref.yaml new file mode 100644 index 000000000..761e90bac --- /dev/null +++ b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-bigip-ref.yaml @@ -0,0 +1,30 @@ +apiVersion: cis.f5.com/v1 +kind: TransportServer +metadata: + labels: + f5cr: "true" + name: cr-transport-server + namespace: default +spec: + allowVlans: [] + iRules: + - /Common/test_rule2 + mode: standard + partition: dev + pool: + monitor: + interval: 20 + timeout: 10 + type: udp + service: pytest-svc-1 + servicePort: 1344 + snat: auto + type: udp + virtualServerAddress: 10.8.3.11 + virtualServerPort: 1344 + tls: + clientSSLs: + - /Common/clientssl + serverSSLs: + - /Common/serverssl + reference: bigip \ No newline at end of file diff --git a/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-secret-ref.yaml b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-secret-ref.yaml new file mode 100644 index 000000000..6f66bdcc2 --- /dev/null +++ b/docs/config_examples/customResource/TransportServer/transport-server-with-tls/ts-with-tls-secret-ref.yaml @@ -0,0 +1,30 @@ +apiVersion: cis.f5.com/v1 +kind: TransportServer +metadata: + labels: + f5cr: "true" + name: cr-transport-server + namespace: default +spec: + allowVlans: [] + iRules: + - /Common/test_rule2 + mode: standard + partition: dev + pool: + monitor: + interval: 20 + timeout: 10 + type: udp + service: pytest-svc-1 + servicePort: 1344 + snat: auto + type: tcp + virtualServerAddress: 10.8.3.11 + virtualServerPort: 1344 + tls: + clientSSLs: + - foo-secret + serverSSLs: + - foo-back-secret + reference: secret \ No newline at end of file diff --git a/docs/config_examples/customResourceDefinitions/incubator/customresourcedefinitions.yml b/docs/config_examples/customResourceDefinitions/incubator/customresourcedefinitions.yml index f471eb7ec..e07dca679 100644 --- a/docs/config_examples/customResourceDefinitions/incubator/customresourcedefinitions.yml +++ b/docs/config_examples/customResourceDefinitions/incubator/customresourcedefinitions.yml @@ -613,6 +613,22 @@ spec: type: type: string enum: [tcp, udp, sctp] + tls: + type: object + properties: + clientSSLs: + type: array + items: + type: string + pattern: '^\/?[a-zA-Z]+([-A-z0-9_+]+\/)*([-A-z0-9_.:]+\/?)*$' + serverSSLs: + type: array + items: + type: string + pattern: '^\/?[a-zA-Z]+([-A-z0-9_+]+\/)*([-A-z0-9_.:]+\/?)*$' + reference: + type: string + enum: [bigip, secret] snat: type: string pattern: '^$|^\/?[a-zA-Z]+([-A-z0-9_+]+\/)*([-A-z0-9_.:]+\/?)+$' diff --git a/pkg/controller/backend.go b/pkg/controller/backend.go index 253c2bd13..2fb505a52 100644 --- a/pkg/controller/backend.go +++ b/pkg/controller/backend.go @@ -1470,13 +1470,14 @@ func DeepEqualJSON(decl1, decl2 as3Declaration) bool { func processProfilesForAS3(rsMap ResourceMap, sharedApp as3Application) { for _, cfg := range rsMap { if svc, ok := sharedApp[cfg.Virtual.Name].(*as3Service); ok { - processTLSProfilesForAS3(&cfg.Virtual, svc, cfg.Virtual.Name) + processTLSProfilesForAS3(cfg, svc, cfg.Virtual.Name) } } } -func processTLSProfilesForAS3(virtual *Virtual, svc *as3Service, profileName string) { +func processTLSProfilesForAS3(cfg *ResourceConfig, svc *as3Service, profileName string) { // lets discard BIGIP profile creation when there exists a custom profile. + virtual := cfg.Virtual as3ClientSuffix := "_tls_client" as3ServerSuffix := "_tls_server" var clientProfiles []as3MultiTypeParam @@ -1497,7 +1498,9 @@ func processTLSProfilesForAS3(virtual *Virtual, svc *as3Service, profileName str BigIP: fmt.Sprintf("/%v/%v", profile.Partition, profile.Name), }) } - updateVirtualToHTTPS(svc) + if cfg.MetaData.ResourceType == VirtualServer { + updateVirtualToHTTPS(svc) + } case CustomProfileServer: // Profile is stored in a k8s secret if !profile.BigIPProfile { @@ -1511,7 +1514,9 @@ func processTLSProfilesForAS3(virtual *Virtual, svc *as3Service, profileName str BigIP: fmt.Sprintf("/%v/%v", profile.Partition, profile.Name), }) } - updateVirtualToHTTPS(svc) + if cfg.MetaData.ResourceType == VirtualServer { + updateVirtualToHTTPS(svc) + } } } if len(clientProfiles) > 0 { @@ -1538,13 +1543,13 @@ func processCustomProfilesForAS3(rsMap ResourceMap, sharedApp as3Application, as if svcName == "" { continue } - if ok := createUpdateTLSServer(prof, svcName, sharedApp); ok { + if ok := createUpdateTLSServer(rsCfg.MetaData.ResourceType, prof, svcName, sharedApp); ok { // Create Certificate only if the corresponding TLSServer is created createCertificateDecl(prof, sharedApp) svcNameMap[svcName] = struct{}{} } else { createUpdateCABundle(prof, caBundleName, sharedApp) - tlsClient = createTLSClient(prof, svcName, caBundleName, sharedApp) + tlsClient = createTLSClient(rsCfg.MetaData.ResourceType, prof, svcName, caBundleName, sharedApp) skey := SecretKey{ Name: prof.Name + "-ca", @@ -1576,7 +1581,7 @@ func processCustomProfilesForAS3(rsMap ResourceMap, sharedApp as3Application, as } // createUpdateTLSServer creates a new TLSServer instance or updates if one exists already -func createUpdateTLSServer(prof CustomProfile, svcName string, sharedApp as3Application) bool { +func createUpdateTLSServer(resourceType string, prof CustomProfile, svcName string, sharedApp as3Application) bool { if len(prof.Certificates) > 0 { if sharedApp[svcName] == nil { return false @@ -1609,7 +1614,9 @@ func createUpdateTLSServer(prof CustomProfile, svcName string, sharedApp as3Appl } sharedApp[tlsServerName] = tlsServer svc.ServerTLS = tlsServerName - updateVirtualToHTTPS(svc) + if resourceType == VirtualServer { + updateVirtualToHTTPS(svc) + } } for index, certificate := range prof.Certificates { certName := fmt.Sprintf("%s_%d", prof.Name, index) @@ -1663,6 +1670,7 @@ func createUpdateCABundle(prof CustomProfile, caBundleName string, sharedApp as3 } func createTLSClient( + resourceType string, prof CustomProfile, svcName, caBundleName string, sharedApp as3Application, @@ -1704,8 +1712,9 @@ func createTLSClient( } sharedApp[tlsClientName] = tlsClient svc.ClientTLS = tlsClientName - updateVirtualToHTTPS(svc) - + if resourceType == VirtualServer { + updateVirtualToHTTPS(svc) + } return tlsClient } return nil diff --git a/pkg/controller/resourceConfig.go b/pkg/controller/resourceConfig.go index 04cab2db9..8b511e47b 100644 --- a/pkg/controller/resourceConfig.go +++ b/pkg/controller/resourceConfig.go @@ -298,9 +298,6 @@ func formatVirtualServerName(ip string, port int32) string { // format the virtual server name for an VirtualServer func formatCustomVirtualServerName(name string, port int32) string { - // Replace special characters ". : /" - // with "-" and "%" with ".", for naming purposes - name = AS3NameFormatter(name) return fmt.Sprintf("%s_%d", name, port) } @@ -1128,6 +1125,94 @@ func (rsCfg *ResourceConfig) AddRuleToPolicy(policyName, partition string, rules } } +func (ctlr *Controller) handleTransportServerTLS(rsCfg *ResourceConfig, tlsContext TLSContext) bool { + infStore := ctlr.multiClusterHandler.getInformerStore(ctlr.multiClusterHandler.LocalClusterName) + clientSSL := tlsContext.bigIPSSLProfiles.clientSSLs + serverSSL := tlsContext.bigIPSSLProfiles.serverSSLs + // Process Profile + switch tlsContext.referenceType { + case BIGIP: + log.Debugf("Processing BIGIP referenced profiles for '%s' '%s'/'%s'", + tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + // Process referenced BIG-IP clientSSL + if len(clientSSL) > 0 { + for _, profile := range clientSSL { + clientProfRef := ConvertStringToProfileRef( + profile, CustomProfileClient, tlsContext.namespace) + rsCfg.Virtual.AddOrUpdateProfile(clientProfRef) + } + } + // Process referenced BIG-IP serverSSL + if len(serverSSL) > 0 { + for _, profile := range serverSSL { + serverProfRef := ConvertStringToProfileRef( + profile, CustomProfileServer, tlsContext.namespace) + rsCfg.Virtual.AddOrUpdateProfile(serverProfRef) + } + } + log.Debugf("Updated BIGIP referenced profiles for '%s' '%s'/'%s'", + tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + case Secret: + // Process ClientSSL stored as kubernetes secret + var namespace string + if ctlr.watchingAllNamespaces(ctlr.multiClusterHandler.LocalClusterName) { + namespace = "" + } else { + namespace = tlsContext.namespace + } + if len(clientSSL) > 0 { + var secrets []*v1.Secret + for _, secretName := range clientSSL { + secretKey := tlsContext.namespace + "/" + secretName + if _, ok := infStore.comInformers[namespace]; !ok { + return false + } + obj, found, err := infStore.comInformers[namespace].secretsInformer.GetIndexer().GetByKey(secretKey) + if err != nil || !found { + log.Errorf("secret %s not found for '%s' '%s'/'%s'", + clientSSL, tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + return false + } + secrets = append(secrets, obj.(*v1.Secret)) + } + err, _ := ctlr.createSecretClientSSLProfile(rsCfg, secrets, tlsContext.tlsCipher, CustomProfileClient, tlsContext.bigIPSSLProfiles.clientSSlParams.RenegotiationEnabled) + if err != nil { + log.Errorf("error %v encountered while creating clientssl profile for '%s' '%s'/'%s'", + err, tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + return false + } + } + // Process ServerSSL stored as kubernetes secret + if len(serverSSL) > 0 { + var secrets []*v1.Secret + for _, secret := range serverSSL { + secretKey := tlsContext.namespace + "/" + secret + if _, ok := infStore.comInformers[namespace]; !ok { + return false + } + obj, found, err := infStore.comInformers[namespace].secretsInformer.GetIndexer().GetByKey(secretKey) + if err != nil || !found { + log.Errorf("secret %s not found for '%s' '%s'/'%s'", + serverSSL, tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + return false + } + secrets = append(secrets, obj.(*v1.Secret)) + err, _ = ctlr.createSecretServerSSLProfile(rsCfg, secrets, tlsContext.tlsCipher, CustomProfileServer, tlsContext.bigIPSSLProfiles.serverSSlParams.RenegotiationEnabled) + if err != nil { + log.Errorf("error %v encountered while creating serverssl profile for '%s' '%s'/'%s'", + err, tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + return false + } + } + } + default: + log.Errorf("Invalid reference type provided for '%s' '%s'/'%s'", + tlsContext.resourceType, tlsContext.namespace, tlsContext.name) + return false + } + return true +} + // function updates the rscfg as per the passed parameter for routes as well as for virtual server func (ctlr *Controller) handleTLS( rsCfg *ResourceConfig, diff --git a/pkg/controller/resourceConfig_test.go b/pkg/controller/resourceConfig_test.go index 331e16413..7750faf63 100644 --- a/pkg/controller/resourceConfig_test.go +++ b/pkg/controller/resourceConfig_test.go @@ -1217,6 +1217,135 @@ var _ = Describe("Resource Config Tests", func() { }) }) + Describe("Handle Transport Server TLS", func() { + var mockCtlr *mockController + var rsCfg *ResourceConfig + var ip string + + BeforeEach(func() { + ip = "10.8.0.22" + mockCtlr = newMockController() + mockCtlr.multiClusterHandler = NewClusterHandler("") + mockCtlr.resources = NewResourceStore() + mockCtlr.multiClusterResources = newMultiClusterResourceStore() + }) + + It("Validate TLS", func() { + rsCfg = &ResourceConfig{} + rsCfg.MetaData.ResourceType = TransportServer + rsCfg.Virtual.Name = formatCustomVirtualServerName("My_TS", 80) + rsCfg.Virtual.SetVirtualAddress( + ip, + 80, + ) + rsCfg.IntDgMap = make(InternalDataGroupMap) + rsCfg.IRulesMap = make(IRulesMap) + rsCfg.customProfiles = make(map[SecretKey]CustomProfile) + ok := mockCtlr.handleTransportServerTLS(rsCfg, TLSContext{ + name: "SampleTS", + namespace: "default", + resourceType: TransportServer, + referenceType: Hybrid, + ipAddress: ip, + bigIPSSLProfiles: BigIPSSLProfiles{ + clientSSLs: []string{"/Common/clientssl"}, + serverSSLs: []string{"/Common/serverssl"}, + }, + tlsCipher: TLSCipher{}, + poolPathRefs: []poolPathRef{}, + }) + Expect(ok).To(BeFalse(), "Failed to Validate TLS Reference") + }) + + It("TLS with BIGIP Reference", func() { + rsCfg = &ResourceConfig{} + rsCfg.MetaData.ResourceType = TransportServer + rsCfg.Virtual.Name = formatCustomVirtualServerName("My_TS", 80) + rsCfg.Virtual.SetVirtualAddress( + ip, + 80, + ) + rsCfg.IntDgMap = make(InternalDataGroupMap) + rsCfg.IRulesMap = make(IRulesMap) + rsCfg.customProfiles = make(map[SecretKey]CustomProfile) + ok := mockCtlr.handleTransportServerTLS(rsCfg, TLSContext{ + name: "SampleTS", + namespace: "default", + resourceType: TransportServer, + referenceType: BIGIP, + ipAddress: ip, + bigIPSSLProfiles: BigIPSSLProfiles{ + clientSSLs: []string{"/Common/clientssl"}, + serverSSLs: []string{"/Common/serverssl"}, + }, + tlsCipher: TLSCipher{}, + poolPathRefs: []poolPathRef{}, + }) + Expect(len(rsCfg.Virtual.Profiles)).To(Equal(2), "Expected profiles are not created") + Expect(rsCfg.Virtual.Profiles[0].Name).To(Equal("clientssl"), "Profile name not matched") + Expect(rsCfg.Virtual.Profiles[0].Context).To(Equal(CustomProfileClient), "Expected clientside profile") + Expect(rsCfg.Virtual.Profiles[0].BigIPProfile).To(BeTrue(), "Big IP Profile should be true") + Expect(rsCfg.Virtual.Profiles[1].Name).To(Equal("serverssl"), "Profile name not matched") + Expect(rsCfg.Virtual.Profiles[1].Context).To(Equal(CustomProfileServer), "Expected serverside profile") + Expect(rsCfg.Virtual.Profiles[1].BigIPProfile).To(BeTrue(), "Big IP Profile should be true") + Expect(ok).To(BeTrue(), "Failed to Validate TLS Reference") + }) + + It("TLS with Secret Reference", func() { + rsCfg = &ResourceConfig{} + rsCfg.MetaData.ResourceType = TransportServer + rsCfg.Virtual.Name = formatCustomVirtualServerName("My_TS", 80) + rsCfg.Virtual.SetVirtualAddress( + ip, + 80, + ) + rsCfg.IntDgMap = make(InternalDataGroupMap) + rsCfg.IRulesMap = make(IRulesMap) + rsCfg.customProfiles = make(map[SecretKey]CustomProfile) + clientSecret := test.NewSecret( + "foo-secret", + "default", + "### cert ###", + "#### key ####", + ) + + serverSecret := test.NewSecret( + "foo-back-secret", + "default", + "### cert ###", + "#### key ####", + ) + + mockCtlr.multiClusterHandler.ClusterConfigs[""] = &ClusterConfig{kubeClient: k8sfake.NewSimpleClientset(), + InformerStore: initInformerStore()} + mockCtlr.multiClusterHandler.ClusterConfigs[""].comInformers["default"] = mockCtlr.newNamespacedCommonResourceInformer("default", "") + mockCtlr.multiClusterHandler.ClusterConfigs[""].comInformers["default"].secretsInformer.GetStore().Add(clientSecret) + mockCtlr.multiClusterHandler.ClusterConfigs[""].comInformers["default"].secretsInformer.GetStore().Add(serverSecret) + + ok := mockCtlr.handleTransportServerTLS(rsCfg, TLSContext{ + name: "SampleTS", + namespace: "default", + resourceType: TransportServer, + referenceType: Secret, + ipAddress: ip, + bigIPSSLProfiles: BigIPSSLProfiles{ + clientSSLs: []string{"foo-secret"}, + serverSSLs: []string{"foo-back-secret"}, + }, + tlsCipher: TLSCipher{}, + poolPathRefs: []poolPathRef{}, + }) + Expect(len(rsCfg.Virtual.Profiles)).To(Equal(2), "Expected profiles are not created") + Expect(rsCfg.Virtual.Profiles[0].Name).To(Equal("foo-back-secret"), "Profile name not matched") + Expect(rsCfg.Virtual.Profiles[0].Context).To(Equal(CustomProfileServer), "Expected serverside profile") + Expect(rsCfg.Virtual.Profiles[0].BigIPProfile).To(BeFalse(), "Big IP Profile should be false") + Expect(rsCfg.Virtual.Profiles[1].Name).To(Equal("foo-secret"), "Profile name not matched") + Expect(rsCfg.Virtual.Profiles[1].Context).To(Equal(CustomProfileClient), "Expected clientside profile") + Expect(rsCfg.Virtual.Profiles[1].BigIPProfile).To(BeFalse(), "Big IP Profile should be false") + Expect(ok).To(BeTrue(), "Failed to Validate TLS Reference") + }) + }) + Describe("Handle Virtual Server TLS", func() { var mockCtlr *mockController var vs *cisapiv1.VirtualServer diff --git a/pkg/controller/worker.go b/pkg/controller/worker.go index 1d68d2716..4d5927700 100644 --- a/pkg/controller/worker.go +++ b/pkg/controller/worker.go @@ -3063,6 +3063,7 @@ func (ctlr *Controller) processTransportServers( rsCfg.MetaData.baseResources = make(map[string]string) rsCfg.IntDgMap = make(InternalDataGroupMap) rsCfg.IRulesMap = make(IRulesMap) + rsCfg.customProfiles = make(map[SecretKey]CustomProfile) if virtual.Spec.BigIPRouteDomain > 0 { if ctlr.PoolMemberType == Cluster { log.Warning("bigipRouteDomain is not supported in cluster mode") @@ -3094,6 +3095,31 @@ func (ctlr *Controller) processTransportServers( return nil } + if !reflect.DeepEqual(virtual.Spec.TLS, cisapiv1.TLS{}) { + bigIPSSLProfiles := BigIPSSLProfiles{} + if len(virtual.Spec.TLS.ClientSSLs) > 0 { + bigIPSSLProfiles.clientSSLs = virtual.Spec.TLS.ClientSSLs + } + if len(virtual.Spec.TLS.ServerSSLs) > 0 { + bigIPSSLProfiles.serverSSLs = virtual.Spec.TLS.ServerSSLs + } + processed := ctlr.handleTransportServerTLS(rsCfg, TLSContext{ + name: virtual.ObjectMeta.Name, + namespace: virtual.ObjectMeta.Namespace, + resourceType: TransportServer, + referenceType: virtual.Spec.TLS.Reference, + ipAddress: ip, + bigIPSSLProfiles: bigIPSSLProfiles, + tlsCipher: TLSCipher{}, + poolPathRefs: []poolPathRef{}, + }) + if !processed { + // Processing failed + ctlr.updateResourceStatus(TransportServer, virtual, "", StatusError, errors.New("error while handling TLS Transport Server")) + return nil + } + } + log.Debugf("Processing Transport Server %s for port %v", virtual.ObjectMeta.Name, virtual.Spec.VirtualServerPort) rsCfg.MetaData.baseResources[virtual.ObjectMeta.Namespace+"/"+virtual.ObjectMeta.Name] = TransportServer