Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3570 fix tls irule when all the pool members are disabled #3639

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/RELEASE-NOTES.rst
Original file line number Diff line number Diff line change
@@ -7,13 +7,14 @@ Next Release
Added Functionality
```````````````````
**What's new:**
* Multi Cluster
* CRD


Bug Fixes
````````````
* `Issue 3561 <https://github.com/F5Networks/k8s-bigip-ctlr/issues/3561>`_: Controller stops posting changes at runtime when some ingress path has the + character

* `Issue 3570 <https://github.com/F5Networks/k8s-bigip-ctlr/issues/3570>`_: tls irule fails if pool has no active members

2.18.1
-------------
2 changes: 1 addition & 1 deletion pkg/controller/resourceConfig.go
Original file line number Diff line number Diff line change
@@ -2224,7 +2224,7 @@ func (ctlr *Controller) HandlePathBasedABIRuleTS(rsCfg *ResourceConfig) {
ruleName := getRSCfgResName(rsCfg.Virtual.Name, ABPathIRuleName)
rsCfg.addIRule(
ruleName, rsCfg.Virtual.Partition,
ctlr.getABDeployIruleForTS(rsCfg.Virtual.Name, rsCfg.Virtual.Partition, rsCfg.Virtual.IpProtocol))
ctlr.getABDeployIruleForTS(rsCfg.Virtual.Name, rsCfg.Virtual.Partition))
rsCfg.Virtual.AddIRule(ruleName)
}

6 changes: 5 additions & 1 deletion pkg/controller/resourceConfig_test.go
Original file line number Diff line number Diff line change
@@ -1296,7 +1296,7 @@ var _ = Describe("Resource Config Tests", func() {
Expect(ok).To(BeFalse(), "Validation Failed")
})

It("Invalide TLS Reference", func() {
It("Invalid TLS Reference", func() {
vs.Spec.TLSProfileName = "SampleTLS"
ok := mockCtlr.handleVirtualServerTLS(rsCfg, vs, tlsProf, ip, false)
Expect(ok).To(BeFalse(), "Failed to Validate TLS Reference")
@@ -1324,6 +1324,10 @@ var _ = Describe("Resource Config Tests", func() {
}

ok := mockCtlr.handleVirtualServerTLS(rsCfg, vs, tlsProf, ip, false)
Expect(rsCfg.IRulesMap[NameRef{
Name: "My_VS_80_tls_irule",
Partition: "",
}].Code).To(Equal("when CLIENT_ACCEPTED { TCP::collect }\n\n\n\t\tproc select_ab_pool {path default_pool domainpath} {\n\t\t\tset last_slash [string length $path]\n\t\t\tset ab_class \"//Shared/My_VS_80_ab_deployment_dg\"\n\t\t\twhile {$last_slash >= 0} {\n\t\t\t\tif {[class match $path equals $ab_class]} then {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tset last_slash [string last \"/\" $path $last_slash]\n\t\t\t\tincr last_slash -1\n\t\t\t\tset path [string range $path 0 $last_slash]\n\t\t\t}\n\t\t\tif {$last_slash >= 0} {\n\t\t\t\tset ab_rule [class match -value $path equals $ab_class]\n\t\t\t\tif {$ab_rule != \"\"} then {\n\t\t\t\t\tset weight_selection [expr {rand()}]\n\t\t\t\t\tset service_rules [split $ab_rule \";\"]\n set active_pool \"\"\n\t\t\t\t\tforeach service_rule $service_rules {\n\t\t\t\t\t\tset fields [split $service_rule \",\"]\n\t\t\t\t\t\tset pool_name [lindex $fields 0]\n if { [active_members $pool_name] >= 1 } {\n\t\t\t\t\t\t set active_pool $pool_name\n\t\t\t\t\t\t}\n\t\t\t\t\t\tset weight [expr {double([lindex $fields 1])}]\n\t\t\t\t\t\tif {$weight_selection <= $weight} then {\n #check if active pool members are available\n\t\t\t\t\t\t if { [active_members $pool_name] >= 1 } {\n\t\t\t\t\t\t\t return $pool_name\n\t\t\t\t\t\t } else {\n\t\t\t\t\t\t # select the any of pool with active members \n\t\t\t\t\t\t if {$active_pool!= \"\"} then {\n\t\t\t\t\t\t return $active_pool\n\t\t\t\t\t\t } \n\t\t\t\t\t\t }\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t# If we had a match, but all weights were 0 then\n\t\t\t\t# retrun a 503 (Service Unavailable)\n\t\t\t\tset ::http_status_503 1\n\t\t\t}\n\t\t\treturn $default_pool\n\t\t}\n\n\n\t\twhen CLIENT_DATA {\n\t\t\t# Byte 0 is the content type.\n\t\t\t# Bytes 1-2 are the TLS version.\n\t\t\t# Bytes 3-4 are the TLS payload length.\n\t\t\t# Bytes 5-$tls_payload_len are the TLS payload.\n\t\t\tset payload [TCP::payload]\n set payloadlen [TCP::payload length]\n\n if {![info exists payloadscan]} {\n set payloadscan [binary scan $payload cSS tls_content_type tls_version tls_payload_len ]\n }\n\t\t \n\t if {($payloadscan == 3)} {\n if {($tls_payload_len < 0 || $tls_payload_len > 16389)} { \n log local0.warn \"[IP::remote_addr] : parsed SSL/TLS record length ${tls_payload_len} outside of handled length (0..16389)\"\n reject\n return\n } elseif {($payloadlen < $tls_payload_len+5)} {\n TCP::collect [expr {$tls_payload_len +5 - $payloadlen}]\n return\n }\n\t\t\t\tif { ! [ expr { [info exists tls_content_type] && [string is integer -strict $tls_content_type] } ] } { reject ; event disable all; return; }\n\t\t\t\tif { ! [ expr { [info exists tls_version] && [string is integer -strict $tls_version] } ] } { reject ; event disable all; return; }\n\t\t\t\tswitch -exact $tls_version {\n\t\t\t\t\t\"769\" -\n\t\t\t\t\t\"770\" -\n\t\t\t\t\t\"771\" {\n\t\t\t\t\t\t# Content type of 22 indicates the TLS payload contains a handshake.\n\t\t\t\t\t\tif { $tls_content_type == 22 } {\n\t\t\t\t\t\t\t# Byte 5 (the first byte of the handshake) indicates the handshake\n\t\t\t\t\t\t\t# record type, and a value of 1 signifies that the handshake record is\n\t\t\t\t\t\t\t# a ClientHello.\n\t\t\t\t\t\t\tbinary scan [TCP::payload] @5c tls_handshake_record_type\n\t\t\t\t\t\t\tif { ! [ expr { [info exists tls_handshake_record_type] && [string is integer -strict $tls_handshake_record_type] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\tif { $tls_handshake_record_type == 1 } {\n\t\t\t\t\t\t\t\t# Bytes 6-8 are the handshake length (which we ignore).\n\t\t\t\t\t\t\t\t# Bytes 9-10 are the TLS version (which we ignore).\n\t\t\t\t\t\t\t\t# Bytes 11-42 are random data (which we ignore).\n\t\n\t\t\t\t\t\t\t\t# Byte 43 is the session ID length. Following this are three\n\t\t\t\t\t\t\t\t# variable-length fields which we shall skip over.\n\t\t\t\t\t\t\t\tset record_offset 43\n\t\n\t\t\t\t\t\t\t\t# Skip the session ID.\n\t\t\t\t\t\t\t\tbinary scan [TCP::payload] @${record_offset}c tls_session_id_len\n\t\t\t\t\t\t\t\tif { ! [ expr { [info exists tls_session_id_len] && [string is integer -strict $tls_session_id_len] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\tincr record_offset [expr {1 + $tls_session_id_len}]\n\t\n\t\t\t\t\t\t\t\t# Skip the cipher_suites field.\n\t\t\t\t\t\t\t\tbinary scan [TCP::payload] @${record_offset}S tls_cipher_suites_len\n\t\t\t\t\t\t\t\tif { ! [ expr { [info exists tls_cipher_suites_len] && [string is integer -strict $tls_cipher_suites_len] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\tincr record_offset [expr {2 + $tls_cipher_suites_len}]\n\t\n\t\t\t\t\t\t\t\t# Skip the compression_methods field.\n\t\t\t\t\t\t\t\tbinary scan [TCP::payload] @${record_offset}c tls_compression_methods_len\n\t\t\t\t\t\t\t\tif { ! [ expr { [info exists tls_compression_methods_len] && [string is integer -strict $tls_compression_methods_len] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\tincr record_offset [expr {1 + $tls_compression_methods_len}]\n\t\n\t\t\t\t\t\t\t\t# Get the number of extensions, and store the extensions.\n\t\t\t\t\t\t\t\tbinary scan [TCP::payload] @${record_offset}S tls_extensions_len\n\t\t\t\t\t\t\t\tif { ! [ expr { [info exists tls_extensions_len] && [string is integer -strict $tls_extensions_len] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\tincr record_offset 2\n\t\t\t\t\t\t\t\tbinary scan [TCP::payload] @${record_offset}a* tls_extensions\n\t\t\t\t\t\t\t\tif { ! [info exists tls_extensions] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\tfor { set extension_start 0 }\n\t\t\t\t\t\t\t\t\t\t{ $tls_extensions_len - $extension_start == abs($tls_extensions_len - $extension_start) }\n\t\t\t\t\t\t\t\t\t\t{ incr extension_start 4 } {\n\t\t\t\t\t\t\t\t\t# Bytes 0-1 of the extension are the extension type.\n\t\t\t\t\t\t\t\t\t# Bytes 2-3 of the extension are the extension length.\n\t\t\t\t\t\t\t\t\tbinary scan $tls_extensions @${extension_start}SS extension_type extension_len\n\t\t\t\t\t\t\t\t\tif { ! [ expr { [info exists extension_type] && [string is integer -strict $extension_type] } ] } { reject ; event disable all; return; }\n\t\t\t\t\t\t\t\t\tif { ! [ expr { [info exists extension_len] && [string is integer -strict $extension_len] } ] } { reject ; event disable all; return; }\n\t\n\t\t\t\t\t\t\t\t\t# Extension type 00 is the ServerName extension.\n\t\t\t\t\t\t\t\t\tif { $extension_type == \"00\" } {\n\t\t\t\t\t\t\t\t\t\t# Bytes 4-5 of the extension are the SNI length (we ignore this).\n\t\n\t\t\t\t\t\t\t\t\t\t# Byte 6 of the extension is the SNI type.\n\t\t\t\t\t\t\t\t\t\tset sni_type_offset [expr {$extension_start + 6}]\n\t\t\t\t\t\t\t\t\t\tbinary scan $tls_extensions @${sni_type_offset}S sni_type\n\t\t\t\t\t\t\t\t\t\tif { ! [ expr { [info exists sni_type] && [string is integer -strict $sni_type] } ] } { reject ; event disable all; return; }\n\t\n\t\t\t\t\t\t\t\t\t\t# Type 0 is host_name.\n\t\t\t\t\t\t\t\t\t\tif { $sni_type == \"0\" } {\n\t\t\t\t\t\t\t\t\t\t\t# Bytes 7-8 of the extension are the SNI data (host_name)\n\t\t\t\t\t\t\t\t\t\t\t# length.\n\t\t\t\t\t\t\t\t\t\t\tset sni_len_offset [expr {$extension_start + 7}]\n\t\t\t\t\t\t\t\t\t\t\tbinary scan $tls_extensions @${sni_len_offset}S sni_len\n\t\t\t\t\t\t\t\t\t\t\tif { ! [ expr { [info exists sni_len] && [string is integer -strict $sni_len] } ] } { reject ; event disable all; return; } \n\t\n\t\t\t\t\t\t\t\t\t\t\t# Bytes 9-$sni_len are the SNI data (host_name).\n\t\t\t\t\t\t\t\t\t\t\tset sni_start [expr {$extension_start + 9}]\n\t\t\t\t\t\t\t\t\t\t\tbinary scan $tls_extensions @${sni_start}A${sni_len} tls_servername\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\n\t\t\t\t\t\t\t\t\tincr extension_start $extension_len\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif { [info exists tls_servername] } {\n\t\t\t\t\t\t\t\t\tset servername_lower [string tolower $tls_servername]\n\t\t\t\t\t\t\t\t\tset domain_length [llength [split $servername_lower \".\"]]\n\t\t\t\t\t\t\t\t\tset domain_wc [domain $servername_lower [expr {$domain_length - 1}] ]\n\t\t\t\t\t\t\t\t\t# Set wc_host with the wildcard domain\n\t\t\t\t\t\t\t\t\tset wc_host \".$domain_wc\"\n\t\t\t\t\t\t\t\t\tset passthru_class \"//Shared/My_VS_80_ssl_passthrough_servername_dg\"\n\t\t\t\t\t\t\t\t\tif { [class exists $passthru_class] } {\n\t\t\t\t\t\t\t\t\t\t# check if the passthrough data group has a record with the servername\n\t\t\t\t\t\t\t\t\t\tset passthru_dg_key [class match $servername_lower equals $passthru_class]\n\t\t\t\t\t\t\t\t\t\tset passthru_dg_wc_key [class match $wc_host equals $passthru_class]\n\t\t\t\t\t\t\t\t\t\tif { $passthru_dg_key != 0 || $passthru_dg_wc_key != 0 } {\n\t\t\t\t\t\t\t\t\t\t\tSSL::disable serverside\n\t\t\t\t\t\t\t\t\t\t\tset dflt_pool_passthrough \"\"\n\t\t\n\t\t\t\t\t\t\t\t\t\t\t# Disable Serverside SSL for Passthrough Class\n\t\t\t\t\t\t\t\t\t\t\tset dflt_pool_passthrough [class match -value $servername_lower equals $passthru_class]\n\t\t\t\t\t\t\t\t\t\t\t# If no match, try wildcard domain\n\t\t\t\t\t\t\t\t\t\t\tif { $dflt_pool_passthrough == \"\" } {\n\t\t\t\t\t\t\t\t\t\t\t\tif { [class match $wc_host equals $passthru_class] } {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tset dflt_pool_passthrough [class match -value $wc_host equals $passthru_class]\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif { not ($dflt_pool_passthrough equals \"\") } {\n\t\t\t\t\t\t\t\t\t\t\t\tSSL::disable\n\t\t\t\t\t\t\t\t\t\t\t\tHTTP::disable\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\n\t\t\t\t\t\t\t\t\t\t\tset ab_class \"//Shared/My_VS_80_ab_deployment_dg\"\n\t\t\t\t\t\t\t\t\t\t\tif { not [class exists $ab_class] } {\n\t\t\t\t\t\t\t\t\t\t\t\tif { $dflt_pool_passthrough == \"\" } then {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlog local0.debug \"Failed to find pool for $servername_lower $\"\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tpool $dflt_pool_passthrough\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tset selected_pool [call select_ab_pool $servername_lower $dflt_pool_passthrough \"\"]\n\t\t\t\t\t\t\t\t\t\t\t\tif { $selected_pool == \"\" } then {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlog local0.debug \"Failed to find pool for $servername_lower\"\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\tpool $selected_pool\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tTCP::release\n\t\t}\n\n\t\t\n\n\t\t when CLIENTSSL_HANDSHAKE {\n\t\t\t\t\tSSL::collect\n\t\t\t\t}\n\n\t\t when CLIENTSSL_DATA {\n\t\t\tif { [llength [split [SSL::payload]]] < 1 }{\n\t\t\t\treject ; event disable all; return;\n\t\t\t\t}\n\t\t\tset sslpath [lindex [split [SSL::payload]] 1]\n\t\t\t# for http2 protocol we receive the sslpath as '*', hence replacing it with root path,\n\t\t\t# however it will not handle the http2 path based routing for now.\n\t\t\t# for http2 currently only host based routing is supported.\n\t\t\tif { $sslpath equals \"*\" } { \n\t\t\t\tset sslpath \"/\"\n\t\t\t}\n\t\t\tset domainpath $sslpath\n\t\t\tset routepath \"\"\n\t\t\tset wc_routepath \"\"\n\t\t\t\n\t\t\tif { [info exists tls_servername] } {\n\t\t\t\tset servername_lower [string tolower $tls_servername]\n\t\t\t\tset domain_length [llength [split $servername_lower \".\"]]\n\t\t\t\tset domain_wc [domain $servername_lower [expr {$domain_length - 1}] ]\n\t\t\t\tset wc_host \".$domain_wc\"\n\t\t\t\t# Set routepath as combination of servername and url path\n\t\t\t\tappend routepath $servername_lower $sslpath\n\t\t\t\tappend wc_routepath $wc_host $sslpath\n\t\t\t\tset routepath [string tolower $routepath]\n\t\t\t\tset wc_routepath [string tolower $wc_routepath]\n\t\t\t\tset sslpath $routepath\n\t\t\t\t# Find the number of \"/\" in the routepath\n\t\t\t\tset rc 0\n\t\t\t\tforeach x [split $routepath {}] {\n\t\t\t\t if {$x eq \"/\"} {\n\t\t\t\t\t incr rc\n\t\t\t\t }\n\t\t\t\t}\n\n\t\t\t\tset reencrypt_class \"//Shared/My_VS_80_ssl_reencrypt_servername_dg\"\n\t\t\t\tset edge_class \"//Shared/My_VS_80_ssl_edge_servername_dg\"\n\t\t\t\tif { [class exists $reencrypt_class] || [class exists $edge_class] } {\n\t\t\t\t\t# Compares the routepath with the entries in ssl_reencrypt_servername_dg and\n\t\t\t\t\t# ssl_edge_servername_dg.\n\t\t\t\t\tfor {set i $rc} {$i >= 0} {incr i -1} {\n\t\t\t\t\t\tif { [class exists $reencrypt_class] } {\n\t\t\t\t\t\t\tset reen_pool [class match -value $routepath equals $reencrypt_class]\n\t\t\t\t\t\t\t# Check for wildcard domain\n\t\t\t\t\t\t\tif { $reen_pool equals \"\" } {\n\t\t\t\t\t\t\t\tif { [class match $wc_routepath equals $reencrypt_class] } {\n\t\t\t\t\t\t\t\t\tset reen_pool [class match -value $wc_routepath equals $reencrypt_class]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t# Disable serverside ssl and enable only for reencrypt routes with valid pool\n\t\t\t\t\t\t\tif { not ($reen_pool equals \"\") } {\n\t\t\t\t\t\t\t\tset dflt_pool $reen_pool\n\t\t\t\t\t\t\t\tSSL::enable serverside\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif { [class exists $edge_class] } {\n\t\t\t\t\t\t\tset edge_pool [class match -value $routepath equals $edge_class]\n\t\t\t\t\t\t\t# Check for wildcard domain\n\t\t\t\t\t\t\tif { $edge_pool equals \"\" } {\n\t\t\t\t\t\t\t\tif { [class match $wc_routepath equals $edge_class] } {\n\t\t\t\t\t\t\t\t\tset edge_pool [class match -value $wc_routepath equals $edge_class]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif { not ($edge_pool equals \"\") } {\n\t\t\t\t\t\t\t\t# Disable serverside ssl for edge routes\n\t\t\t\t\t\t\t\tSSL::disable serverside\n\t\t\t\t\t\t\t\tset dflt_pool $edge_pool\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif { not [info exists dflt_pool] } {\n\t\t\t\t\t\t\tset routepath [\n\t\t\t\t\t\t\t\tstring range $routepath 0 [\n\t\t\t\t\t\t\t\t\texpr {[string last \"/\" $routepath]-1}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\tset wc_routepath [\n\t\t\t\t\t\t\t\tstring range $wc_routepath 0 [\n\t\t\t\t\t\t\t\t\texpr {[string last \"/\" $wc_routepath]-1}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t# Disable serverside ssl for passthrough routes as well\n\t\t\t\t\tSSL::disable serverside\n\t\t\t\t}\n\t\t\t\t# handle the default pool for virtual server\n\t\t\t\tset default_class \"//Shared/My_VS_80_default_pool_servername_dg\"\n\t\t\t\t if { [class exists $default_class] } { \n\t\t\t\t\tset dflt_pool [class match -value \"defaultPool\" equals $default_class]\n\t\t\t\t }\n\t\t\t\t\n\t\t\t\t# Handle requests sent to unknown hosts.\n\t\t\t\t# For valid hosts, Send the request to respective pool.\n\t\t\t\tif { not [info exists dflt_pool] } then {\n\t\t\t\t\t # Allowing HTTP2 traffic to be handled by policies and closing the connection for HTTP/1.1 unknown hosts.\n\t\t\t\t\t if { not ([SSL::payload] starts_with \"PRI * HTTP/2.0\") } {\n\t\t\t\t\t\treject ; event disable all;\n\t\t\t\t\t\tlog local0.debug \"Failed to find pool for $servername_lower\"\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tpool $dflt_pool\n\t\t\t\t}\n\t\t\t\tset ab_class \"//Shared/My_VS_80_ab_deployment_dg\"\n\t\t\t\tif { [class exists $ab_class] } {\n\t\t\t\t\tset selected_pool [call select_ab_pool $servername_lower $dflt_pool $domainpath]\n\t\t\t\t\tif { $selected_pool == \"\" } then {\n\t\t\t\t\t\tlog local0.debug \"Unable to find pool for $servername_lower\"\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpool $selected_pool\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tSSL::release\n\t\t}\n\n\t\n\t\t\n\t\twhen SERVER_CONNECTED {\n\t\t\tset reencryptssl_class \"//Shared/My_VS_80_ssl_reencrypt_serverssl_dg\"\n\t\t\tset edgessl_class \"//Shared/My_VS_80_ssl_edge_serverssl_dg\"\n\t\t\tif { [info exists sslpath] and [class exists $reencryptssl_class] } {\n\t\t\t\t# Find the nearest child path which matches the reencrypt_class\n\t\t\t\tfor {set i $rc} {$i >= 0} {incr i -1} {\n\t\t\t\t\tif { [class exists $reencryptssl_class] } {\n\t\t\t\t\t\tset reen [class match -value $sslpath equals $reencryptssl_class]\n # check for wildcard domain match\n if { $reen equals \"\" } {\n\t\t\t\t\t\t if { [class match $wc_routepath equals $reencryptssl_class] } {\n\t\t\t\t\t\t set reen [class match -value $wc_routepath equals $reencryptssl_class]\n\t\t\t\t\t\t }\n }\n\t\t\t\t\t\tif { not ($reen equals \"\") } {\n\t\t\t\t\t\t\t set sslprofile $reen\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif { [class exists $edgessl_class] } {\n\t\t\t\t\t\tset edge [class match -value $sslpath equals $edgessl_class]\n # check for wildcard domain match\n if { $edge equals \"\" } {\n\t\t\t\t\t\t if { [class match $wc_routepath equals $edgessl_class] } {\n\t\t\t\t\t\t set edge [class match -value $wc_routepath equals $edgessl_class]\n\t\t\t\t\t\t }\n }\n\t\t\t\t\t\tif { not ($edge equals \"\") } {\n\t\t\t\t\t\t\t set sslprofile $edge\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\tif { not [info exists sslprofile] } {\n\t\t\t\t\t\tset sslpath [\n\t\t\t\t\t\t\tstring range $sslpath 0 [\n\t\t\t\t\t\t\t\texpr {[string last \"/\" $sslpath]-1}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t]\n set wc_routepaath [\n\t\t\t\t\t\t\tstring range $wc_routepath 0 [\n\t\t\t\t\t\t\t\texpr {[string last \"/\" $wc_routepath]-1}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t# Assign respective SSL profile based on ssl_reencrypt_serverssl_dg\n\t\t\t\tif { not ($sslprofile equals \"false\") } {\n\t\t\t\t\t\tSSL::profile $reen\n\t\t\t\t}\n\t\t\t}\n }\n\t\t\t\n\t\t\n\n\t\twhen HTTP_REQUEST {\n\t\t\tif { [info exists ::http_status_503] && $::http_status_503 == 1 } {\n \t\t# Respond with 503\n \t\t\tHTTP::respond 503\n\n \t\t# Unset the variable\n \t\tunset ::http_status_503\n \t\t}\n\t\t}\n\t"), "IRule isn't correct")
Expect(ok).To(BeTrue(), "Failed to Process TLS Termination: Edge")

Expect(len(rsCfg.Virtual.Profiles)).To(Equal(1), "Failed to Process TLS Termination: Edge")
36 changes: 30 additions & 6 deletions pkg/controller/routing.go
Original file line number Diff line number Diff line change
@@ -697,7 +697,7 @@ func httpRedirectIRule(port int32, rsVSName string, partition string) string {
return iRuleCode
}

func (ctlr *Controller) getABDeployIruleForTS(rsVSName string, partition string, tsType string) string {
func (ctlr *Controller) getABDeployIruleForTS(rsVSName string, partition string) string {
dgPath := strings.Join([]string{partition, Shared}, "/")

return fmt.Sprintf(`when CLIENT_ACCEPTED {
@@ -731,9 +731,19 @@ func (ctlr *Controller) getABDeployIruleForTS(rsVSName string, partition string,
}
# If we had a match, but all weights were 0 then
# retrun a 503 (Service Unavailable)
%[3]s::respond 503
set ::http_status_503 1
return
}`, dgPath, rsVSName, strings.ToUpper(tsType))
}
when HTTP_REQUEST {
if { [info exists ::http_status_503] && $::http_status_503 == 1 } {
# Respond with 503
HTTP::respond 503
# Unset the variable
unset ::http_status_503
}
})`, dgPath, rsVSName)
}

func (ctlr *Controller) getPathBasedABDeployIRule(rsVSName string, partition string, multiPoolPersistence MultiPoolPersistence) string {
@@ -969,6 +979,18 @@ func (ctlr *Controller) getTLSIRule(rsVSName string, partition string, allowSour

sslDisable := "SSL::disable"

httpRequest := "\n" + fmt.Sprintf(`
when HTTP_REQUEST {
if { [info exists ::http_status_503] && $::http_status_503 == 1 } {
# Respond with 503
HTTP::respond 503
# Unset the variable
unset ::http_status_503
}
}
`)

if ctlr.Agent.bigIPAS3Version >= 3.52 && passthroughVSGrp {
clientSSL = ""
sslDisable = ""
@@ -1181,7 +1203,9 @@ func (ctlr *Controller) getTLSIRule(rsVSName string, partition string, allowSour
SSL::profile $reen
}
}
}`, dgPath, rsVSName, clientSSL, sslDisable)
}
%[5]s`, dgPath, rsVSName, clientSSL, sslDisable, httpRequest)

iRuleCode := fmt.Sprintf("%s\n\n%s\n\n%s", ctlr.selectClientAcceptediRule(rsVSName, dgPath, allowSourceRange), ctlr.selectPoolIRuleFunc(rsVSName, dgPath, multiPoolPersistence), iRule)

@@ -1243,7 +1267,7 @@ func (ctlr *Controller) selectPoolIRuleFunc(rsVSName string, dgPath string, mult
}
# If we had a match, but all weights were 0 then
# retrun a 503 (Service Unavailable)
HTTP::respond 503
set ::http_status_503 1
}
return $default_pool
}`)
@@ -1291,7 +1315,7 @@ func (ctlr *Controller) selectPoolIRuleFunc(rsVSName string, dgPath string, mult
}
# If we had a match, but all weights were 0 then
# retrun a 503 (Service Unavailable)
HTTP::respond 503
set ::http_status_503 1
}
return $default_pool
}`, persistenceType, persistenceType, multiPoolPersistence.TimeOut, persistenceType, multiPoolPersistence.TimeOut)