Skip to content

Commit

Permalink
#3637 support for TLS in Transport Server (#3652)
Browse files Browse the repository at this point in the history
* rebasing from the source

* update resource config

* fix uts
  • Loading branch information
vidyasagar-m authored Nov 19, 2024
1 parent 3d9ed5b commit 4fd9827
Show file tree
Hide file tree
Showing 11 changed files with 378 additions and 21 deletions.
17 changes: 9 additions & 8 deletions config/apis/cis/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions docs/RELEASE-NOTES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Added Functionality
* Multi Cluster
* CRD
* `Issue 3523 <https://github.com/F5Networks/k8s-bigip-ctlr/issues/3523>`_: Support for HTTP Compression profile in VS CR. See `Example <https://github.com/F5Networks/k8s-bigip-ctlr/blob/2.x-master/docs/config_examples/customResource/VirtualServer/httpCompressionProfile/>`_
* `Issue 3637 <https://github.com/F5Networks/k8s-bigip-ctlr/issues/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
Expand Down
10 changes: 10 additions & 0 deletions docs/config_examples/customResource/CustomResource.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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_.:]+\/?)+$'
Expand Down
29 changes: 19 additions & 10 deletions pkg/controller/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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",
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1663,6 +1670,7 @@ func createUpdateCABundle(prof CustomProfile, caBundleName string, sharedApp as3
}

func createTLSClient(
resourceType string,
prof CustomProfile,
svcName, caBundleName string,
sharedApp as3Application,
Expand Down Expand Up @@ -1704,8 +1712,9 @@ func createTLSClient(
}
sharedApp[tlsClientName] = tlsClient
svc.ClientTLS = tlsClientName
updateVirtualToHTTPS(svc)

if resourceType == VirtualServer {
updateVirtualToHTTPS(svc)
}
return tlsClient
}
return nil
Expand Down
91 changes: 88 additions & 3 deletions pkg/controller/resourceConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down Expand Up @@ -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,
Expand Down
Loading

0 comments on commit 4fd9827

Please sign in to comment.