From 1a52a30246247d3ceba3075085580e3be87dd6c1 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 2 Feb 2021 15:38:02 +0100 Subject: [PATCH 01/17] net/haproxy: bump version --- net/haproxy/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile index c37496e58..9ae44f3d7 100644 --- a/net/haproxy/Makefile +++ b/net/haproxy/Makefile @@ -1,5 +1,5 @@ PLUGIN_NAME= haproxy -PLUGIN_VERSION= 2.26 +PLUGIN_VERSION= 3.0 PLUGIN_REVISION= 1 PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer PLUGIN_DEPENDS= haproxy From 666554593748340d165c0de70dff69ffa5046bc7 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 2 Feb 2021 15:39:19 +0100 Subject: [PATCH 02/17] net/haproxy: update changelog --- net/haproxy/pkg-descr | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index af22b3790..8fd3de23c 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -6,6 +6,11 @@ very high loads while needing persistence or Layer7 processing. Plugin Changelog ================ +3.0 + +Added: +* new feature to change server state and weight on-the-fly (#2213) + 2.26 Fixed: From 43f984def679c4416124b4ce3ed061b22d9289b1 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Thu, 4 Feb 2021 21:09:56 +0100 Subject: [PATCH 03/17] net/haproxy: translate tooltips, refs #2213 --- net/haproxy/Makefile | 1 - .../app/views/OPNsense/HAProxy/maintenance.volt | 16 ++++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/net/haproxy/Makefile b/net/haproxy/Makefile index 9ae44f3d7..fa8508ba7 100644 --- a/net/haproxy/Makefile +++ b/net/haproxy/Makefile @@ -1,6 +1,5 @@ PLUGIN_NAME= haproxy PLUGIN_VERSION= 3.0 -PLUGIN_REVISION= 1 PLUGIN_COMMENT= Reliable, high performance TCP/HTTP load balancer PLUGIN_DEPENDS= haproxy PLUGIN_MAINTAINER= opnsense@moov.de diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/maintenance.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/maintenance.volt index 33332c27b..63c870e6d 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/maintenance.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/maintenance.volt @@ -45,10 +45,10 @@ POSSIBILITY OF SUCH DAMAGE. formatters: { "commands": function (column, row) { buttons = "" - buttons += "" - buttons += " " - buttons += " " - buttons += " " + buttons += "" + buttons += " " + buttons += " " + buttons += " " return buttons; }, }, @@ -272,10 +272,10 @@ POSSIBILITY OF SUCH DAMAGE. - - - - + + + + From 436f5801f415d200426a842f1dbd32474e213e28 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Thu, 4 Feb 2021 22:29:14 +0100 Subject: [PATCH 04/17] net/haproxy: update default SSL settings --- net/haproxy/pkg-descr | 7 +++++++ .../OPNsense/HAProxy/forms/dialogFrontend.xml | 18 +++++++++--------- .../OPNsense/HAProxy/forms/generalTuning.xml | 18 +++++++++--------- .../app/models/OPNsense/HAProxy/HAProxy.xml | 18 +++++++++++------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 8fd3de23c..60f1c4d12 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -10,6 +10,13 @@ Plugin Changelog Added: * new feature to change server state and weight on-the-fly (#2213) +* add new SSL bind option: prefer-client-ciphers + +Changed: +* change default SSL version to TLSv1.2 (ssl-min-ver) +* remove weak ciphers from (default) SSL settings +* remove default SSL bind options that would conflict with ssl-min-ver +* move SSL bind options below other SSL settings, they are rarely used nowadays 2.26 diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml index 754bd8b03..4a12988a5 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml @@ -89,15 +89,6 @@ header - - frontend.ssl_bindOptions - - select_multiple - - true - true - - frontend.ssl_minVersion @@ -146,6 +137,15 @@ text + + frontend.ssl_bindOptions + + select_multiple + + true + true + + header diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml index add58fc53..f34ae4ee9 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml @@ -85,15 +85,6 @@ checkbox - - haproxy.general.tuning.ssl_bindOptions - - select_multiple - - true - true - - haproxy.general.tuning.ssl_minVersion @@ -118,4 +109,13 @@ text + + haproxy.general.tuning.ssl_bindOptions + + select_multiple + + true + true + + diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 3c7763fc7..a855cf632 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -1,6 +1,6 @@ //OPNsense/HAProxy - 2.10.0 + 3.0.0 the HAProxy load balancer @@ -129,7 +129,7 @@ N - no-sslv3,no-tlsv10,no-tls-tickets + prefer-client-ciphers Y Y @@ -144,11 +144,13 @@ force-tlsv11 force-tlsv12 force-tlsv13 + prefer-client-ciphers strict-sni N + TLSv1.2 SSLv3 TLSv1.0 @@ -168,11 +170,11 @@ - ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 N - TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 + TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 N @@ -461,7 +463,7 @@ N - no-sslv3,no-tlsv10,no-tls-tickets + prefer-client-ciphers Y Y @@ -476,11 +478,13 @@ force-tlsv11 force-tlsv12 force-tlsv13 + prefer-client-ciphers strict-sni N + TLSv1.2 SSLv3 TLSv1.0 @@ -500,11 +504,11 @@ - ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256 N - TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 + TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 N From e1d1a8c7823a8db5a1d13d6091e5800de75dea3e Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Fri, 5 Feb 2021 00:25:37 +0100 Subject: [PATCH 05/17] net/haproxy: switch to HAProxy 2.2 release series, closes #2092 --- net/haproxy/pkg-descr | 8 ++++++++ .../OPNsense/HAProxy/forms/generalTuning.xml | 6 ++++++ .../app/models/OPNsense/HAProxy/HAProxy.xml | 9 +++++++-- .../scripts/OPNsense/HAProxy/socketCommand.py | 2 +- .../templates/OPNsense/HAProxy/haproxy.conf | 18 +++++++++++++----- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 60f1c4d12..c739a0215 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -11,12 +11,20 @@ Plugin Changelog Added: * new feature to change server state and weight on-the-fly (#2213) * add new SSL bind option: prefer-client-ciphers +* add global option to enable old buggy behaviour for PROXY v2 connections +* add support for HTTP/2 in health checks + +Fixed: +* fix maintenance page (python error: 'list' object has no attribute 'strip') Changed: * change default SSL version to TLSv1.2 (ssl-min-ver) * remove weak ciphers from (default) SSL settings * remove default SSL bind options that would conflict with ssl-min-ver * move SSL bind options below other SSL settings, they are rarely used nowadays +* change default for tune.ssl.default-dh-param from 1024 to 2048 +* use new "http-check send" command for HTTP health checks +* change default for spreadChecks from 0 to 2 2.26 diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml index f34ae4ee9..0fd011d4d 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalTuning.xml @@ -68,6 +68,12 @@ text + + haproxy.general.tuning.bogusProxyEnabled + + checkbox + + haproxy.general.tuning.customOptions diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index a855cf632..3cb8e5b2e 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -86,7 +86,7 @@ - 1024 + 2048 1024 16384 Please specify a value between 1024 and 16384. @@ -107,12 +107,16 @@ N - 0 + 2 0 50 Please specify a value between 0 and 50. Y + + 0 + Y + 0 0 @@ -1322,6 +1326,7 @@ HTTP/1.0 [default] HTTP/1.1 + HTTP/2 diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/socketCommand.py b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/socketCommand.py index fd9b438c0..554db684a 100755 --- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/socketCommand.py +++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/socketCommand.py @@ -148,7 +148,7 @@ try: if con: result = con.sendCmd(command_class(**command_args), objectify=False) if result: - print(result.strip()) + print(result) else: print(f"Could not open socket {SOCKET}") diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index 1796018a4..8f3ce54f1 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -838,6 +838,9 @@ global {% if OPNsense.HAProxy.general.tuning.spreadChecks|default("") != "" %} spread-checks {{OPNsense.HAProxy.general.tuning.spreadChecks}} {% endif %} +{% if OPNsense.HAProxy.general.tuning.bogusProxyEnabled|default("") == '1' %} + pp2-never-send-local +{% endif %} {% if OPNsense.HAProxy.general.tuning.checkBufferSize|default("") != "" %} tune.chksize {{OPNsense.HAProxy.general.tuning.checkBufferSize}} {% endif %} @@ -1285,15 +1288,20 @@ backend {{backend.name}} {% endif %} {% endif %} {% elif healthcheck_data.type == 'http' %} -{% do healthcheck_options.append('httpchk') %} + option httpchk {# # HTTP method must be uppercase #} +{% do healthcheck_options.append('send meth') %} {% do healthcheck_options.append(healthcheck_data.http_method|upper) %} +{% do healthcheck_options.append('uri') %} {% do healthcheck_options.append(healthcheck_data.http_uri) %} -{% do healthcheck_options.append('HTTP/1.0') if healthcheck_data.http_version == 'http10' %} {# # HTTP Host header requires HTTP 1.1 #} -{% do healthcheck_options.append('HTTP/1.1') if healthcheck_data.http_version == 'http11' and healthcheck_data.http_host|default("") == "" %} -{% do healthcheck_options.append('HTTP/1.1\\r\\nHost:\ ' ~ healthcheck_data.http_host) if healthcheck_data.http_version == 'http11' and healthcheck_data.http_host|default("") != "" %} - option {{healthcheck_options|join(' ')}} +{% if (healthcheck_data.http_version == 'http11' or healthcheck_data.http_version == 'http2') and healthcheck_data.http_host|default('') != '' %} +{% do healthcheck_options.append('ver HTTP/1.1 hdr Host ' ~ healthcheck_data.http_host) if healthcheck_data.http_version == 'http11' %} +{% do healthcheck_options.append('ver HTTP/2 hdr Host ' ~ healthcheck_data.http_host) if healthcheck_data.http_version == 'http2' %} +{% elif healthcheck_data.http_version == 'http10' %} +{% do healthcheck_options.append('ver HTTP/1.0') %} +{% endif %} + http-check {{healthcheck_options|join(' ')}} {# # custom HTTP health check option #} {% if healthcheck_data.http_expressionEnabled|default("") == '1' %} {# # validate options #} From d6ea9600e089a9528a31fad50b2c9416d1a0bc0c Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Fri, 5 Feb 2021 23:51:39 +0100 Subject: [PATCH 06/17] net/haproxy: add config export, closes #2035 --- net/haproxy/pkg-descr | 1 + .../OPNsense/HAProxy/Api/ExportController.php | 83 ++++++++++++++++++ .../OPNsense/HAProxy/ExportController.php | 45 ++++++++++ .../app/models/OPNsense/HAProxy/Menu/Menu.xml | 1 + .../app/views/OPNsense/HAProxy/export.volt | 86 +++++++++++++++++++ .../conf/actions.d/actions_haproxy.conf | 13 +++ 6 files changed, 229 insertions(+) create mode 100644 net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php create mode 100644 net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/ExportController.php create mode 100644 net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index c739a0215..122f67789 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -13,6 +13,7 @@ Added: * add new SSL bind option: prefer-client-ciphers * add global option to enable old buggy behaviour for PROXY v2 connections * add support for HTTP/2 in health checks +* add config export (#2035) Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php new file mode 100644 index 000000000..89f9df4ca --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php @@ -0,0 +1,83 @@ +configdRun("haproxy showconf"); + return array("response" => $response); + } + + /** + * download config file or config archive + * @return array|mixed + */ + public function downloadAction($type) + { + $backend = new Backend(); + + if ($type == 'config') { + $result = $backend->configdRun("haproxy showconf"); + $filename = 'haproxy.conf'; + $filetype = 'text/plain'; + $content = $result; + } else { + $result = $backend->configdRun("haproxy exportall"); + $filename = 'haproxy_config_export.zip'; + $filetype = 'application/zip'; + $content = file_get_contents('/tmp/haproxy_config_export.zip'); + } + + $response = array( + 'result' => $result, + 'filename' => $filename, + 'filetype' => $filetype, + 'content' => base64_encode($content), + ); + return $response; + } +} diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/ExportController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/ExportController.php new file mode 100644 index 000000000..390adaded --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/ExportController.php @@ -0,0 +1,45 @@ +view->pick('OPNsense/HAProxy/export'); + } +} diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml index 8d12e55ab..520fcc7c3 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml @@ -32,6 +32,7 @@ + diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt new file mode 100644 index 000000000..e9134da57 --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt @@ -0,0 +1,86 @@ +{# + +Copyright (C) 2021 Frank Wall +OPNsense® is Copyright © 2014 – 2016 by Deciso B.V. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +#} + + + + + +
+ +
+
+

+            
+
+ + +
+
+
+ +
+ +{{ partial("layout_partials/base_dialog_processing") }} diff --git a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf index 48bcc629d..e23f091f6 100644 --- a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf +++ b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf @@ -100,3 +100,16 @@ parameters: type:script_output message:Sync ssl certificates into HAProxy memory for all frontends description:Sync ssl certificates changes into HAProxy memory + +[showconf] +command:test -f /usr/local/etc/haproxy.conf && cat /usr/local/etc/haproxy.conf +parameters: +type:script_output +message:show haproxy config + +[exportall] +command:/usr/local/bin/zip -r /tmp/haproxy_config_export.zip /tmp/haproxy /usr/local/etc/haproxy.conf +parameters: +type:script_output +message:show haproxy config + From 3852c59f4bfba181f59ab03920d3cfe9e1c59ab8 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Sun, 7 Feb 2021 21:53:38 +0100 Subject: [PATCH 07/17] net/haproxy: update URLs to HAProxy 2.2 documentation, refs #2092 --- .../OPNsense/HAProxy/forms/dialogAction.xml | 10 +++++----- .../OPNsense/HAProxy/forms/dialogBackend.xml | 10 +++++----- .../OPNsense/HAProxy/forms/dialogFrontend.xml | 6 +++--- .../OPNsense/HAProxy/forms/dialogMapfile.xml | 2 +- .../opnsense/mvc/app/views/OPNsense/HAProxy/index.volt | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAction.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAction.xml index c10565e9f..1e8683637 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAction.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAction.xml @@ -89,7 +89,7 @@ action.http_request_redirect text - HAProxy's documentation for further details and examples.]]> + HAProxy's documentation for further details and examples.]]>
@@ -128,7 +128,7 @@ action.http_request_add_header_content text - HAProxy's documentation for further details and examples.]]> + HAProxy's documentation for further details and examples.]]> @@ -145,7 +145,7 @@ action.http_request_set_header_content text - HAProxy's documentation for further details and examples.]]> + HAProxy's documentation for further details and examples.]]> @@ -251,7 +251,7 @@ action.http_response_add_header_content text - HAProxy's documentation for further details and examples.]]> + HAProxy's documentation for further details and examples.]]> @@ -268,7 +268,7 @@ action.http_response_set_header_content text - HAProxy's documentation for further details and examples.]]> + HAProxy's documentation for further details and examples.]]> diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml index 8d4479ef5..4744fb03c 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml @@ -28,7 +28,7 @@ backend.algorithm dropdown - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> Choose a load balancing algorithm. @@ -42,7 +42,7 @@ backend.proxyProtocol dropdown - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> true @@ -164,7 +164,7 @@ backend.persistence_cookiemode dropdown - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> backend.persistence_cookiename @@ -186,14 +186,14 @@ backend.stickiness_pattern dropdown - HAProxy documentation for a full description.
NOTE: Consider not using this feature in multi-process mode, it can result in random behaviours.
]]>
+ HAProxy documentation for a full description.
NOTE: Consider not using this feature in multi-process mode, it can result in random behaviours.
]]>
Choose a persistence type.
backend.stickiness_dataTypes select_multiple - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> backend.stickiness_expire diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml index 4a12988a5..14e644849 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogFrontend.xml @@ -322,14 +322,14 @@ frontend.stickiness_pattern dropdown - HAProxy documentation for further information.]]> + HAProxy documentation for further information.]]> Choose a stick-table type. frontend.stickiness_dataTypes select_multiple - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> frontend.stickiness_expire @@ -356,7 +356,7 @@ frontend.stickiness_counter_key text - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> true diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMapfile.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMapfile.xml index 49888d4e9..f571ce69c 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMapfile.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMapfile.xml @@ -15,6 +15,6 @@ mapfile.content textbox - HAProxy documentation for a full description.]]> + HAProxy documentation for a full description.]]> diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index 59adaa892..45d6749ef 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -645,7 +645,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._('Lastly, enable HAProxy using the %sService%s settings page.') | format('', '') }}
  • {{ lang._('Please be aware that you need to %smanually%s add the required firewall rules for all configured services.') | format('', '') }}

    -

    {{ lang._('Further information is available in our %sHAProxy plugin documentation%s and of course in the %sofficial HAProxy documentation%s. Be sure to report bugs and request features on our %sGitHub issue page%s. Code contributions are also very welcome!') | format('', '', '', '', '', '') }}

    +

    {{ lang._('Further information is available in our %sHAProxy plugin documentation%s and of course in the %sofficial HAProxy documentation%s. Be sure to report bugs and request features on our %sGitHub issue page%s. Code contributions are also very welcome!') | format('', '', '', '', '', '') }}


    @@ -687,7 +687,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._('%sConditions:%s HAProxy is capable of extracting data from requests, responses and other connection data and match it against predefined patterns. Use these powerful patterns to compose a condition that may be used in multiple Rules.') | format('', '') }}
  • {{ lang._('%sRules:%s Perform a large set of actions if one or more %sConditions%s match. These Rules may be used in %sBackend Pools%s as well as %sPublic Services%s.') | format('', '', '', '', '', '', '', '') }}
  • -

    {{ lang._("For more information on HAProxy's %sACL feature%s see the %sofficial documentation%s.") | format('', '', '', '') }}

    +

    {{ lang._("For more information on HAProxy's %sACL feature%s see the %sofficial documentation%s.") | format('', '', '', '') }}

    {{ lang._('Note that it is possible to directly add options to the HAProxy configuration by using the "option pass-through", a setting that is available for several configuration items. It allows you to implement configurations that are currently not officially supported by this plugin. It is strongly discouraged to rely on this feature. Please report missing features on our GitHub page!') | format('', '') }}


    @@ -702,7 +702,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._('%sGroup:%s A optional list containing one or more users. Groups usually make it easier to manage permissions for a large number of users') | format('', '') }}
  • {{ lang._('Note that users and groups must be selected from the Backend Pool or Public Service configuration in order to be used for authentication. In addition to this users and groups may also be used in Rules/Conditions.') }}

    -

    {{ lang._("For more information on HAProxy's %suser/group management%s see the %sofficial documentation%s.") | format('', '', '', '') }}

    +

    {{ lang._("For more information on HAProxy's %suser/group management%s see the %sofficial documentation%s.") | format('', '', '', '') }}


    @@ -720,7 +720,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._("%sCache:%s HAProxy's cache which was designed to perform cache on small objects (favicon, css, etc.). This is a minimalist low-maintenance cache which runs in RAM.") | format('', '', '', '') }}
  • {{ lang._("%sPeers:%s Configure a communication channel between two HAProxy instances. This will propagate entries of any data-types in stick-tables between these HAProxy instances over TCP connections in a multi-master fashion. Useful when aiming for a seamless failover in a HA setup.") | format('', '', '', '') }}
  • -

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sStatistics%s, %sCache%s and %sPeers%s features.") | format('', '', '', '', '', '') }}

    +

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sStatistics%s, %sCache%s and %sPeers%s features.") | format('', '', '', '', '', '') }}


    @@ -736,7 +736,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._("%sCPU Affinity Rules:%s This feature makes it possible to bind HAProxy's processes/threads to a specific CPU (or a CPU set). Furthermore it is possible to select CPU Affinity Rules in %sPublic Services%s to restrict them to a certain set of processes/threads/CPUs.") | format('', '', '', '') }}
  • {{ lang._("%sResolvers:%s This feature allows in-depth configuration of how HAProxy handles name resolution and interacts with name resolvers (DNS). Each resolver configuration can be used in %sBackend Pools%s to apply individual name resolution configurations.") | format('', '', '', '') }}
  • -

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s. A detailed explanation of the resolvers feature can be found %shere%s.") | format('', '', '', '', '', '' ,'', '' ,'', '' ,'', '','', '') }}

    +

    {{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s. A detailed explanation of the resolvers feature can be found %shere%s.") | format('', '', '', '', '', '' ,'', '' ,'', '' ,'', '','', '') }}


    From 470a8d204aa970f38ba5ffd4c143334c26b8f290 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 9 Feb 2021 23:32:59 +0100 Subject: [PATCH 08/17] net/haproxy: guard service against broken configs, add config diff --- net/haproxy/pkg-descr | 4 +++ .../OPNsense/HAProxy/Api/ExportController.php | 11 ++++++ .../app/views/OPNsense/HAProxy/export.volt | 36 +++++++++++++++++++ .../mvc/app/views/OPNsense/HAProxy/index.volt | 30 +++------------- .../scripts/OPNsense/HAProxy/setup.sh | 10 ++++++ .../conf/actions.d/actions_haproxy.conf | 18 ++++++---- .../templates/OPNsense/HAProxy/+TARGETS | 2 +- 7 files changed, 79 insertions(+), 32 deletions(-) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 122f67789..902dc499e 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -14,9 +14,12 @@ Added: * add global option to enable old buggy behaviour for PROXY v2 connections * add support for HTTP/2 in health checks * add config export (#2035) +* add config diff +* guard against broken config by using a staging config file Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') +* prevent service outage by aborting "Apply" when configtest fails Changed: * change default SSL version to TLSv1.2 (ssl-min-ver) @@ -26,6 +29,7 @@ Changed: * change default for tune.ssl.default-dh-param from 1024 to 2048 * use new "http-check send" command for HTTP health checks * change default for spreadChecks from 0 to 2 +* no longer overwrite live config file when running a syntax check 2.26 diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php index 89f9df4ca..5a3cd58f9 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/ExportController.php @@ -52,6 +52,17 @@ class ExportController extends ApiControllerBase return array("response" => $response); } + /** + * get config diff + * @return string + */ + public function diffAction() + { + $backend = new Backend(); + $response = $backend->configdRun("haproxy configdiff"); + return array("response" => $response); + } + /** * download config file or config archive * @return array|mixed diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt index e9134da57..ccfbb5f95 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt @@ -39,6 +39,35 @@ POSSIBILITY OF SUCH DAMAGE. } update_showconf(); + /** + * show HAProxy config diff + */ + function update_showdiff() { + ajaxCall(url="/api/haproxy/export/diff/", sendData={}, callback=function(data,status) { + diff = ''; + var lines = data['response'].split("\n"); + $.each(lines, function(n, line) { + switch(line.substring(0,1)) { + case '+': + color = '#3bbb33'; + break; + case '-': + color = '#c13928'; + break; + case '@': + color = '#3bb9c3'; + break; + default: + color = '#000000'; + } + diff += '' + line + '
    '; + + }); + $("#showdiff").append(diff); + }); + } + update_showdiff(); + /** * download HAProxy config */ @@ -66,6 +95,7 @@ POSSIBILITY OF SUCH DAMAGE.
    @@ -81,6 +111,12 @@ POSSIBILITY OF SUCH DAMAGE.
    +
    +
    +
    +
    +
    + {{ partial("layout_partials/base_dialog_processing") }} diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index 45d6749ef..fe86bf89c 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -313,29 +313,9 @@ POSSIBILITY OF SUCH DAMAGE. if (data['result'].indexOf('ALERT') > -1) { BootstrapDialog.show({ type: BootstrapDialog.TYPE_DANGER, - title: "{{ lang._('HAProxy config contains critical errors') }}", - message: "{{ lang._('The HAProxy service may not be able to start due to critical errors. Try anyway?') }}", + title: "{{ lang._('HAProxy configtest found critical errors') }}", + message: "{{ lang._('The HAProxy service may not be able to start due to critical errors. Run syntax check for further details.') }}", buttons: [{ - label: '{{ lang._('Continue') }}', - cssClass: 'btn-primary', - action: function(dlg){ - ajaxCall(url="/api/haproxy/service/reconfigure", sendData={}, callback=function(data,status) { - if (status != "success" || data['status'] != 'ok') { - BootstrapDialog.show({ - type: BootstrapDialog.TYPE_WARNING, - title: "{{ lang._('Error reconfiguring HAProxy') }}", - message: data['status'], - draggable: true - }); - } - }); - // when done, disable progress animation - $('[id*="reconfigureAct_progress"]').each(function(){ - $(this).removeClass("fa fa-spinner fa-pulse"); - }); - dlg.close(); - } - }, { icon: 'fa fa-trash-o', label: '{{ lang._('Abort') }}', action: function(dlg){ @@ -385,21 +365,21 @@ POSSIBILITY OF SUCH DAMAGE. if (data['result'].indexOf('ALERT') > -1) { BootstrapDialog.show({ type: BootstrapDialog.TYPE_DANGER, - title: "{{ lang._('HAProxy config contains critical errors') }}", + title: "{{ lang._('HAProxy configtest found critical errors') }}", message: data['result'], draggable: true }); } else if (data['result'].indexOf('WARNING') > -1) { BootstrapDialog.show({ type: BootstrapDialog.TYPE_WARNING, - title: "{{ lang._('HAProxy config contains minor errors') }}", + title: "{{ lang._('HAProxy configtest found minor errors') }}", message: data['result'], draggable: true }); } else { BootstrapDialog.show({ type: BootstrapDialog.TYPE_WARNING, - title: "{{ lang._('HAProxy config test result') }}", + title: "{{ lang._('HAProxy configtest result') }}", message: "{{ lang._('Your HAProxy config contains no errors.') }}", draggable: true }); diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh index cb88ee64d..ca8cd48dc 100755 --- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh +++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh @@ -18,4 +18,14 @@ find /var/haproxy -type d -exec chmod 550 {} \; /usr/local/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php > /dev/null 2>&1 /usr/local/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php > /dev/null 2>&1 +# deploy new config +case "$1" in +deploy) + # run syntax check against newly generated config + if /usr/local/sbin/haproxy -c -f /usr/local/etc/haproxy.conf.staging > /dev/null 2>&1; then + cp /usr/local/etc/haproxy.conf.staging /usr/local/etc/haproxy.conf + fi + ;; +esac + exit 0 diff --git a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf index e23f091f6..07341474e 100644 --- a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf +++ b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf @@ -5,7 +5,7 @@ type:script_output message:setup haproxy service requirements [start] -command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh start +command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh deploy; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh start parameters: type:script message:starting haproxy @@ -17,19 +17,19 @@ type:script message:stopping haproxy [restart] -command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart +command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh deploy; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart parameters: type:script message:restarting haproxy [reload] -command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh reload || /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart +command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh deploy; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh reload || /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart parameters: type:script message:reloading haproxy [configtest] -command:/usr/local/etc/rc.d/haproxy configtest 2>&1 || exit 0 +command:/usr/local/sbin/haproxy -c -f /usr/local/etc/haproxy.conf.staging 2>&1 || exit 0 parameters: type:script_output message:testing haproxy configuration @@ -102,14 +102,20 @@ message:Sync ssl certificates into HAProxy memory for all frontends description:Sync ssl certificates changes into HAProxy memory [showconf] -command:test -f /usr/local/etc/haproxy.conf && cat /usr/local/etc/haproxy.conf +command:test -f /usr/local/etc/haproxy.conf.staging && cat /usr/local/etc/haproxy.conf.staging parameters: type:script_output message:show haproxy config [exportall] -command:/usr/local/bin/zip -r /tmp/haproxy_config_export.zip /tmp/haproxy /usr/local/etc/haproxy.conf +command:/usr/local/bin/zip -r /tmp/haproxy_config_export.zip /tmp/haproxy /usr/local/etc/haproxy.conf.staging parameters: type:script_output message:show haproxy config +[configdiff] +command:/usr/bin/diff -Naur /usr/local/etc/haproxy.conf /usr/local/etc/haproxy.conf.staging; exit 0 +parameters: +type:script_output +message:diff haproxy config + diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/+TARGETS b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/+TARGETS index a8fa7728c..389191f4d 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/+TARGETS +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/+TARGETS @@ -1,3 +1,3 @@ -haproxy.conf:/usr/local/etc/haproxy.conf +haproxy.conf:/usr/local/etc/haproxy.conf.staging rc.conf.d:/etc/rc.conf.d/haproxy sslCerts.yaml:/usr/local/etc/haproxy/sslCerts.yaml \ No newline at end of file From 9ae43dc1f8b14af6957893156eb8e3fc358d6ff3 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Wed, 10 Feb 2021 15:06:07 +0100 Subject: [PATCH 09/17] net/haproxy: add link to Config Diff page, fix direct tab links --- net/haproxy/pkg-descr | 1 + .../mvc/app/views/OPNsense/HAProxy/export.volt | 10 ++++++++++ .../mvc/app/views/OPNsense/HAProxy/index.volt | 2 +- .../mvc/app/views/OPNsense/HAProxy/statistics.volt | 11 +++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 902dc499e..511582ebe 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -20,6 +20,7 @@ Added: Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') * prevent service outage by aborting "Apply" when configtest fails +* fix direct links to individual statistics tabs Changed: * change default SSL version to TLSv1.2 (ssl-min-ver) diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt index ccfbb5f95..9b4d7d072 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt @@ -90,6 +90,16 @@ POSSIBILITY OF SUCH DAMAGE. }); }); + // update history on tab state and implement navigation + if(window.location.hash != "") { + $('a[href="' + window.location.hash + '"]').click() + } + $('.nav-tabs a').on('shown.bs.tab', function (e) { + history.pushState(null, null, e.target.hash); + }); + $(window).on('hashchange', function(e) { + $('a[href="' + window.location.hash + '"]').click() + }); }); diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index fe86bf89c..e9fa6c2e0 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -314,7 +314,7 @@ POSSIBILITY OF SUCH DAMAGE. BootstrapDialog.show({ type: BootstrapDialog.TYPE_DANGER, title: "{{ lang._('HAProxy configtest found critical errors') }}", - message: "{{ lang._('The HAProxy service may not be able to start due to critical errors. Run syntax check for further details.') }}", + message: "{{ lang._('The HAProxy service may not be able to start due to critical errors. Run syntax check for further details or review the changes in the %sConfiguration Diff%s.')|format('','') }}", buttons: [{ icon: 'fa fa-trash-o', label: '{{ lang._('Abort') }}', diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/statistics.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/statistics.volt index 52be520da..1f2c4085d 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/statistics.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/statistics.volt @@ -157,6 +157,17 @@ POSSIBILITY OF SUCH DAMAGE. $("#update-status").click(); $("#update-counters").click(); $("#update-tables").click(); + + // update history on tab state and implement navigation + if(window.location.hash != "") { + $('a[href="' + window.location.hash + '"]').click() + } + $('.nav-tabs a').on('shown.bs.tab', function (e) { + history.pushState(null, null, e.target.hash); + }); + $(window).on('hashchange', function(e) { + $('a[href="' + window.location.hash + '"]').click() + }); }); From d5b7a679b86f9af1e46bf6920c37a38aa15d0ec9 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Mon, 15 Feb 2021 23:44:28 +0100 Subject: [PATCH 10/17] net/haproxy: add basic OCSP stapling support, closes #1430 --- net/haproxy/pkg-descr | 2 + .../HAProxy/forms/generalSettings.xml | 6 ++ .../app/models/OPNsense/HAProxy/HAProxy.xml | 4 ++ .../scripts/OPNsense/HAProxy/exportCerts.php | 6 ++ .../scripts/OPNsense/HAProxy/setup.sh | 9 +++ .../scripts/OPNsense/HAProxy/updateOcsp.sh | 70 +++++++++++++++++++ .../conf/actions.d/actions_haproxy.conf | 9 +++ .../templates/OPNsense/HAProxy/rc.conf.d | 5 ++ 8 files changed, 111 insertions(+) create mode 100755 net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 511582ebe..3c0d71c5f 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -16,6 +16,7 @@ Added: * add config export (#2035) * add config diff * guard against broken config by using a staging config file +* add basic OCSP stapling support (#1430) Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') @@ -31,6 +32,7 @@ Changed: * use new "http-check send" command for HTTP health checks * change default for spreadChecks from 0 to 2 * no longer overwrite live config file when running a syntax check +* make restart/reload commands usable in cron jobs 2.26 diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml index 78d7ce4b2..5869a62e6 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml @@ -21,6 +21,12 @@ checkbox + + haproxy.general.storeOcsp + + checkbox + + haproxy.general.showIntro diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 3cb8e5b2e..89d711a03 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -16,6 +16,10 @@ 0 Y + + 0 + N + 1 diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php index ea4c086f5..7bfa26819 100755 --- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php +++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/exportCerts.php @@ -80,7 +80,13 @@ foreach ($configNodes as $key => $value) { if (!empty((string)$cert->caref)) { $cert = (array)$cert; $ca = ca_chain($cert); + // append the CA to the certificate data $pem_content .= "\n" . $ca; + // additionally export CA to it's own file, + // not required for HAProxy, but makes OCSP handling easier + $output_ca_filename = $export_path . $cert_refid . ".issuer"; + file_put_contents($output_ca_filename, $ca); + chmod($output_ca_filename, 0600); } } // generate pem file for individual certs diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh index ca8cd48dc..8dc393461 100755 --- a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh +++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/setup.sh @@ -1,5 +1,9 @@ #!/bin/sh +if [ -f /etc/rc.conf.d/haproxy ]; then +. /etc/rc.conf.d/haproxy +fi + # NOTE: Keep /var/haproxy on this list, see GH issue opnsense/plugins #39. HAPROXY_DIRS="/var/haproxy /var/haproxy/var/run /tmp/haproxy /tmp/haproxy/ssl /tmp/haproxy/lua /tmp/haproxy/errorfiles /tmp/haproxy/mapfiles" @@ -18,6 +22,11 @@ find /var/haproxy -type d -exec chmod 550 {} \; /usr/local/opnsense/scripts/OPNsense/HAProxy/exportErrorFiles.php > /dev/null 2>&1 /usr/local/opnsense/scripts/OPNsense/HAProxy/exportMapFiles.php > /dev/null 2>&1 +# update OCSP data +if [ "${haproxy_ocsp}" == "YES" ]; then + /usr/local/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh > /dev/null 2>&1 +fi + # deploy new config case "$1" in deploy) diff --git a/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh new file mode 100755 index 000000000..12c4c8724 --- /dev/null +++ b/net/haproxy/src/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh @@ -0,0 +1,70 @@ +#!/bin/sh +# This file is based on: +# https://github.com/acmesh-official/acme.sh/blob/master/deploy/haproxy.sh +# +# Copyright (C) 2021 Neil Pang +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +HAPROXY_DIR="/tmp/haproxy/ssl" + +for _pem in "$HAPROXY_DIR"/*.pem; do + cert_file="$(basename "$_pem")" + _issuer="${HAPROXY_DIR}/${cert_file%.pem}.issuer" + _ocsp="${_pem}.ocsp" + cert_cn="$(openssl x509 -in "$_pem" -noout -text | sed -nE 's/.*Subject:.*CN = ([^,]*)(,.*)?$/\1/p')" + + if [ ! -f "$_issuer" ]; then + continue + fi + + if [ -r "${_issuer}" ]; then + _ocsp_url="$(openssl x509 -noout -ocsp_uri -in "$_pem")" + if [ -n "$_ocsp_url" ]; then + _ocsp_host="$(echo "$_ocsp_url" | cut -d/ -f3)" + subjectdn="$(openssl x509 -in "$_issuer" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)" + issuerdn="$(openssl x509 -in "$_issuer" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)" + if [ "$subjectdn" = "$issuerdn" ]; then + _cafile_argument="-CAfile \"${_issuer}\"" + else + _cafile_argument="" + fi + _openssl_version=$(openssl version | cut -d' ' -f2) + _openssl_major=$(echo "${_openssl_version}" | cut -d '.' -f1) + _openssl_minor=$(echo "${_openssl_version}" | cut -d '.' -f2) + if [ "${_openssl_major}" -eq "1" ] && [ "${_openssl_minor}" -ge "1" ] || [ "${_openssl_major}" -ge "2" ]; then + _header_sep="=" + else + _header_sep=" " + fi + + _openssl_ocsp_cmd="openssl ocsp \ + -issuer \"${_issuer}\" \ + -cert \"${_pem}\" \ + -url \"${_ocsp_url}\" \ + -header Host${_header_sep}\"${_ocsp_host}\" \ + -respout \"${_ocsp}\" \ + -verify_other \"${_issuer}\" \ + ${_cafile_argument} \ + | grep -q \"${_pem}: good\"" + + eval "${_openssl_ocsp_cmd}" + _ret=$? + + if [ "${_ret}" != "0" ]; then + echo "Updating OCSP stapling failed with return code ${_ret}" + fi + fi + fi +done diff --git a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf index 07341474e..1e45bc954 100644 --- a/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf +++ b/net/haproxy/src/opnsense/service/conf/actions.d/actions_haproxy.conf @@ -20,12 +20,14 @@ message:stopping haproxy command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh deploy; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart parameters: type:script +description:Restart HAProxy service message:restarting haproxy [reload] command:/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh deploy; /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh reload || /usr/local/opnsense/scripts/OPNsense/HAProxy/rc-wrapper.sh restart parameters: type:script +description:Reload HAProxy service message:reloading haproxy [configtest] @@ -119,3 +121,10 @@ parameters: type:script_output message:diff haproxy config +[update_ocsp] +command:/usr/local/opnsense/scripts/OPNsense/HAProxy/updateOcsp.sh +parameters: +type:script_output +description:Update HAProxy OCSP data +message:update haproxy ocsp data + diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/rc.conf.d b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/rc.conf.d index 50cee173c..261881284 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/rc.conf.d +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/rc.conf.d @@ -3,6 +3,11 @@ haproxy_enable=YES haproxy_var_script="/usr/local/opnsense/scripts/OPNsense/HAProxy/setup.sh" haproxy_pidfile="/var/run/haproxy.pid" haproxy_config="/usr/local/etc/haproxy.conf" +{% if helpers.exists('OPNsense.HAProxy.general.storeOcsp') and OPNsense.HAProxy.general.storeOcsp|default("0") == "1" %} +haproxy_ocsp=YES +{% else %} +haproxy_ocsp=NO +{% endif %} {% if helpers.exists('OPNsense.HAProxy.general.gracefulStop') and OPNsense.HAProxy.general.gracefulStop|default("0") == "1" %} haproxy_hardstop=NO {% else %} From bf6a08d3381910515f0c1ca33220a4612ae9ea82 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Thu, 18 Feb 2021 21:46:46 +0100 Subject: [PATCH 11/17] net/haproxy: show a message when config files are identical --- .../app/views/OPNsense/HAProxy/export.volt | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt index 9b4d7d072..160d93df9 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt @@ -45,24 +45,28 @@ POSSIBILITY OF SUCH DAMAGE. function update_showdiff() { ajaxCall(url="/api/haproxy/export/diff/", sendData={}, callback=function(data,status) { diff = ''; - var lines = data['response'].split("\n"); - $.each(lines, function(n, line) { - switch(line.substring(0,1)) { - case '+': - color = '#3bbb33'; - break; - case '-': - color = '#c13928'; - break; - case '@': - color = '#3bb9c3'; - break; - default: - color = '#000000'; - } - diff += '' + line + '
    '; + if (data['response'] && data['response'].trim()) { + var lines = data['response'].split("\n"); + $.each(lines, function(n, line) { + switch(line.substring(0,1)) { + case '+': + color = '#3bbb33'; + break; + case '-': + color = '#c13928'; + break; + case '@': + color = '#3bb9c3'; + break; + default: + color = '#000000'; + } + diff += '' + line + '
    '; - }); + }); + } else { + diff = "
    {{ lang._('New and old config files are identical.') }}
    "; + } $("#showdiff").append(diff); }); } From 8189ff71dff5c52f6bf4cd7f0c2d81a1229d3695 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Thu, 18 Feb 2021 23:24:44 +0100 Subject: [PATCH 12/17] net/haproxy: add support for e-mail alerts and mailers, closes #1669 --- net/haproxy/pkg-descr | 1 + .../HAProxy/Api/SettingsController.php | 30 ++++++++ .../OPNsense/HAProxy/IndexController.php | 1 + .../OPNsense/HAProxy/forms/dialogBackend.xml | 6 ++ .../OPNsense/HAProxy/forms/dialogMailer.xml | 61 ++++++++++++++++ .../app/models/OPNsense/HAProxy/HAProxy.xml | 71 +++++++++++++++++++ .../app/models/OPNsense/HAProxy/Menu/Menu.xml | 1 + .../mvc/app/views/OPNsense/HAProxy/index.volt | 50 +++++++++++++ .../templates/OPNsense/HAProxy/haproxy.conf | 40 +++++++++++ 9 files changed, 261 insertions(+) create mode 100644 net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMailer.xml diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 3c0d71c5f..dab4836e5 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -17,6 +17,7 @@ Added: * add config diff * guard against broken config by using a staging config file * add basic OCSP stapling support (#1430) +* add support for e-mail alerts and mailers (#1669) Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php index ef5f8f65d..0cd365dc4 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php @@ -409,4 +409,34 @@ class SettingsController extends ApiMutableModelControllerBase { return $this->searchBase('resolvers.resolver', array('enabled', 'name', 'nameservers'), 'name'); } + + public function getmailerAction($uuid = null) + { + return $this->getBase('mailer', 'mailers.mailer', $uuid); + } + + public function setmailerAction($uuid) + { + return $this->setBase('mailer', 'mailers.mailer', $uuid); + } + + public function addmailerAction() + { + return $this->addBase('mailer', 'mailers.mailer'); + } + + public function delmailerAction($uuid) + { + return $this->delBase('mailers.mailer', $uuid); + } + + public function togglemailerAction($uuid, $enabled = null) + { + return $this->toggleBase('mailers.mailer', $uuid); + } + + public function searchmailersAction() + { + return $this->searchBase('mailers.mailer', array('enabled', 'name', 'mailservers', 'sender', 'recipient'), 'name'); + } } diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php index 141fac3e5..8e2b52f65 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/IndexController.php @@ -53,6 +53,7 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->formDialogGroup = $this->getForm("dialogGroup"); $this->view->formDialogHealthcheck = $this->getForm("dialogHealthcheck"); $this->view->formDialogLua = $this->getForm("dialogLua"); + $this->view->formDialogMailer = $this->getForm("dialogMailer"); $this->view->formDialogMapfile = $this->getForm("dialogMapfile"); $this->view->formDialogResolver = $this->getForm("dialogResolver"); $this->view->formDialogServer = $this->getForm("dialogServer"); diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml index 4744fb03c..a17a99b86 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml @@ -119,6 +119,12 @@ true
    + + backend.linkedMailer + + dropdown + + header diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMailer.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMailer.xml new file mode 100644 index 000000000..cbede5c7c --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogMailer.xml @@ -0,0 +1,61 @@ +
    + + mailer.enabled + + checkbox + Enable this mailer configuration. + + + mailer.name + + text + Choose a name for this mailer configuration. + + + mailer.description + + text + Choose a optional description for this mailer configuration. + + + mailer.mailservers + + select_multiple + + true + true + + Enter ip:port here. Finish with TAB. + + + mailer.sender + + text + + + + mailer.recipient + + text + + + + mailer.loglevel + + dropdown + + + + mailer.timeout + + text + + + + mailer.hostname + + text + + true + +
    diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 89d711a03..7e2086bd9 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -928,6 +928,18 @@ Please specify a value between 1 and 100. N + + + + + Related mailer not found + N + N + 0 N @@ -2623,5 +2635,64 @@ + + + + Y + + + 1 + Y + + + /^[^\t^,^;^\.^\[^\]^\{^\}]{1,255}$/u + Should be a string between 1 and 255 characters. + Y + + + N + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + + + Y + Y + Y + /^((([0-9a-zA-Z._\-\*:\[\]]+:[0-9]+(-[0-9]+)?)([,]){0,1}))*/u + lower + Please provide mailserver addresses, i.e. 192.168.1.1:25. + + + Y + + + Y + + + Y + alert + + emerg + alert + crit + err + warning + notice + info + debug + + + + 30 + 4 + 10000 + Please specify a value between 4 and 10000 seconds. + Y + + + N + + +
    diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml index 520fcc7c3..0d78bf3eb 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Menu/Menu.xml @@ -21,6 +21,7 @@ + diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index e9fa6c2e0..bbb658680 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -212,6 +212,19 @@ POSSIBILITY OF SUCH DAMAGE. } ); + $("#grid-mailers").UIBootgrid( + { search:'/api/haproxy/settings/searchMailers', + get:'/api/haproxy/settings/getMailer/', + set:'/api/haproxy/settings/setMailer/', + add:'/api/haproxy/settings/addMailer/', + del:'/api/haproxy/settings/delMailer/', + toggle:'/api/haproxy/settings/toggleMailer/', + options: { + rowCount:[10,25,50,100,500,1000] + } + } + ); + // hook into on-show event for dialog to extend layout. $('#DialogAcl').on('shown.bs.modal', function (e) { $("#acl\\.expression").change(function(){ @@ -608,6 +621,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._('Map Files') }}
  • {{ lang._('CPU Affinity Rules') }}
  • {{ lang._('Resolvers') }}
  • +
  • {{ lang._('E-Mail Alerts') }}
  • @@ -715,6 +729,7 @@ POSSIBILITY OF SUCH DAMAGE.
  • {{ lang._("%sMap Files:%s A map allows to map a data in input to an other one on output. For example, this makes it possible to map a large number of domains to backend pools without using the GUI. Map files need to be used in %sRules%s, otherwise they are ignored.") | format('', '', '', '') }}
  • {{ lang._("%sCPU Affinity Rules:%s This feature makes it possible to bind HAProxy's processes/threads to a specific CPU (or a CPU set). Furthermore it is possible to select CPU Affinity Rules in %sPublic Services%s to restrict them to a certain set of processes/threads/CPUs.") | format('', '', '', '') }}
  • {{ lang._("%sResolvers:%s This feature allows in-depth configuration of how HAProxy handles name resolution and interacts with name resolvers (DNS). Each resolver configuration can be used in %sBackend Pools%s to apply individual name resolution configurations.") | format('', '', '', '') }}
  • +
  • {{ lang._("%sE-Mail Alerts:%s It is possible to send email alerts when the state of servers changes. Each configuration can be used in %sBackend Pools%s to send e-mail alerts to the configured recipient.") | format('', '', '', '') }}
  • {{ lang._("For more details visit HAProxy's official documentation regarding the %sError Messages%s, %sLua Script%s and the %sMap Files%s features. More information on HAProxy's CPU Affinity is also available %shere%s, %shere%s and %shere%s. A detailed explanation of the resolvers feature can be found %shere%s.") | format('', '', '', '', '', '' ,'', '' ,'', '' ,'', '','', '') }}


    @@ -1149,6 +1164,40 @@ POSSIBILITY OF SUCH DAMAGE. +
    + + + + + + + + + + + + + + + + + + + + +
    {{ lang._('Mailer ID') }}{{ lang._('Enabled') }}{{ lang._('Name') }}{{ lang._('Sender') }}{{ lang._('Recipient') }}{{ lang._('Commands') }}{{ lang._('ID') }}
    + + +
    +
    +
    + + +
    +
    +
    +
    +
    @@ -1242,3 +1291,4 @@ POSSIBILITY OF SUCH DAMAGE. {{ partial("layout_partials/base_dialog",['fields':formDialogMapfile,'id':'DialogMapfile','label':lang._('Edit Map File')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogCpu,'id':'DialogCpu','label':lang._('Edit CPU Affinity Rule')])}} {{ partial("layout_partials/base_dialog",['fields':formDialogResolver,'id':'DialogResolver','label':lang._('Edit Resolver')])}} +{{ partial("layout_partials/base_dialog",['fields':formDialogMailer,'id':'DialogMailer','label':lang._('Edit E-Mail Alert')])}} diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index 8f3ce54f1..64f07b7cb 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -1049,6 +1049,29 @@ resolvers {{resolver.id}} {% endfor %} {%- endif -%} +{# ############################### #} +{# MAILERS #} +{# ############################### #} + +{% if helpers.exists('OPNsense.HAProxy.mailers') %} +{% for mailer in helpers.toList('OPNsense.HAProxy.mailers.mailer') %} +{% if mailer.enabled == '1' %} +# Mailer: {{mailer.name}} +mailers {{mailer.id}} + timeout mail {{mailer.timeout}}s +{% if mailer.mailservers|default("") != "" %} +{% for mailserver in mailer.mailservers.split(",") %} + mailer {{mailserver}} {{mailserver}} +{% endfor %} +{% endif %} + +{% else %} +# Mailer (DISABLED): {{mailer.name}} + +{% endif %} +{% endfor %} +{%- endif -%} + {# ############################### #} {# FRONTENDS #} {# ############################### #} @@ -1353,6 +1376,23 @@ backend {{backend.name}} # health checking is DISABLED {% set healthcheck_enabled = '0' %} {% endif %} +{# # mailer #} +{% if backend.linkedMailer|default("") != "" %} +{% set mailer_data = helpers.getUUID(backend.linkedMailer) %} +{% if mailer_data == {} %} +# ERROR: mailer data not found ({{backend.linkedMailer}}) +{% elif mailer_data.enabled == '0' %} +# NOTE: specified mailer is disabled ({{mailer_data.name}}) +{% else %} + email-alert mailers {{mailer_data.id}} + email-alert from {{mailer_data.sender}} + email-alert to {{mailer_data.recipient}} + email-alert level {{mailer_data.loglevel}} +{% if mailer_data.hostname|default("") != "" %} + email-alert myhostname {{mailer_data.hostname}} +{% endif %} +{% endif %} +{% endif %} {# # NOTE: Usually the frontend and the backend are in the same mode, #} {# # but we have no way to know what frontend uses this backend. #} {# # Hence we can't automatically set the mode and thus need a #} From 63dde5fc65ec670a3f698cf7609d38dc8d0cc289 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Fri, 19 Feb 2021 00:18:01 +0100 Subject: [PATCH 13/17] net/haproxy: add support for custom header checks, closes #1907 --- net/haproxy/pkg-descr | 1 + .../OPNsense/HAProxy/forms/dialogAcl.xml | 85 +++++++++++++++++++ .../app/models/OPNsense/HAProxy/HAProxy.xml | 55 ++++++++++++ .../templates/OPNsense/HAProxy/haproxy.conf | 35 ++++++++ 4 files changed, 176 insertions(+) diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index dab4836e5..9ace5e787 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -18,6 +18,7 @@ Added: * guard against broken config by using a staging config file * add basic OCSP stapling support (#1430) * add support for e-mail alerts and mailers (#1669) +* add support for custom header checks (#1907) Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAcl.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAcl.xml index a0a7a5b7c..3d5bb47cd 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAcl.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogAcl.xml @@ -148,6 +148,91 @@ text + + + header + + + + acl.cust_hdr_beg_name + + text + + + + acl.cust_hdr_beg + + text + + + + + header + + + + acl.cust_hdr_end_name + + text + + + + acl.cust_hdr_end + + text + + + + + header + + + + acl.cust_hdr_name + + text + + + + acl.cust_hdr + + text + + + + + header + + + + acl.cust_hdr_reg_name + + text + + + + acl.cust_hdr_reg + + text + + + + + header + + + + acl.cust_hdr_sub_name + + text + + + + acl.cust_hdr_sub + + text + + header diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 7e2086bd9..211350c1f 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -1466,6 +1466,11 @@ Path regex Path contains subdir Path contains string + HTTP Header starts with + HTTP Header ends with + HTTP Header matches + HTTP Header regex + HTTP Header contains URL parameter contains SSL Client certificate is valid SSL Client certificate verify error result @@ -1563,6 +1568,56 @@ Should be a string between 1 and 255 characters. N + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,1024}$/u + Should be a string between 1 and 1024 characters. + N + + + /^.{1,1024}$/u + Should be a string between 1 and 1024 characters. + N + + + /^.{1,1024}$/u + Should be a string between 1 and 1024 characters. + N + + + /^.{1,1024}$/u + Should be a string between 1 and 1024 characters. + N + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + + + /^.{1,255}$/u + Should be a string between 1 and 255 characters. + N + /^.{1,4096}$/u N diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index 64f07b7cb..5dff7a2f7 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -158,6 +158,41 @@ {% set acl_enabled = '0' %} # ERROR: missing parameters {% endif %} +{% elif acl_data.expression == 'cust_hdr_beg' %} +{% if acl_data.cust_hdr_beg|default("") != "" and acl_data.cust_hdr_beg_name|default("") != "" %} +{% do acl_options.append('hdr_beg(' ~ acl_data.cust_hdr_beg_name ~ ') -i ' ~ acl_data.cust_hdr_beg) %} +{% else %} +{% set acl_enabled = '0' %} + # ERROR: missing parameters +{% endif %} +{% elif acl_data.expression == 'cust_hdr_end' %} +{% if acl_data.cust_hdr_end|default("") != "" and acl_data.cust_hdr_end_name|default("") %} +{% do acl_options.append('hdr_end(' ~ acl_data.cust_hdr_end_name ~ ') -i ' ~ acl_data.cust_hdr_end) %} +{% else %} +{% set acl_enabled = '0' %} + # ERROR: missing parameters +{% endif %} +{% elif acl_data.expression == 'cust_hdr' %} +{% if acl_data.cust_hdr|default("") != "" and acl_data.cust_hdr_name|default("") != "" %} +{% do acl_options.append('hdr(' ~ acl_data.cust_hdr_name ~ ') -i ' ~ acl_data.cust_hdr) %} +{% else %} +{% set acl_enabled = '0' %} + # ERROR: missing parameters +{% endif %} +{% elif acl_data.expression == 'cust_hdr_reg' %} +{% if acl_data.cust_hdr_reg|default("") != "" and acl_data.cust_hdr_reg_name|default("") != "" %} +{% do acl_options.append('hdr_reg(' ~ acl_data.cust_hdr_reg_name ~ ') -i ' ~ acl_data.cust_hdr_reg) %} +{% else %} +{% set acl_enabled = '0' %} + # ERROR: missing parameters +{% endif %} +{% elif acl_data.expression == 'cust_hdr_sub' %} +{% if acl_data.cust_hdr_sub|default("") != "" and acl_data.cust_hdr_sub_name|default("") != "" %} +{% do acl_options.append('hdr_sub(' ~ acl_data.cust_hdr_sub_name ~ ') -i ' ~ acl_data.cust_hdr_sub) %} +{% else %} +{% set acl_enabled = '0' %} + # ERROR: missing parameters +{% endif %} {% elif acl_data.expression == 'url_param' %} {% if acl_data.url_param_value|default("") != "" and acl_data.url_param|default("") != "" %} {% do acl_options.append('url_param(' ~ acl_data.url_param ~ ') -i ' ~ acl_data.url_param_value) %} From 1f07481bc3fe1ec012bfd162ac303434c2300e70 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Sat, 20 Feb 2021 01:41:14 +0100 Subject: [PATCH 14/17] net/haproxy: add support for server templates, closes #1975 --- net/haproxy/pkg-descr | 4 + .../HAProxy/Api/SettingsController.php | 2 +- .../OPNsense/HAProxy/forms/dialogBackend.xml | 16 + .../OPNsense/HAProxy/forms/dialogServer.xml | 58 +++- .../app/models/OPNsense/HAProxy/HAProxy.xml | 70 ++++- .../OPNsense/HAProxy/Migrations/M3_0_0.php | 44 +++ .../mvc/app/views/OPNsense/HAProxy/index.volt | 21 +- .../templates/OPNsense/HAProxy/haproxy.conf | 288 ++++++++++-------- 8 files changed, 365 insertions(+), 138 deletions(-) create mode 100644 net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Migrations/M3_0_0.php diff --git a/net/haproxy/pkg-descr b/net/haproxy/pkg-descr index 9ace5e787..a8d97d695 100644 --- a/net/haproxy/pkg-descr +++ b/net/haproxy/pkg-descr @@ -19,6 +19,9 @@ Added: * add basic OCSP stapling support (#1430) * add support for e-mail alerts and mailers (#1669) * add support for custom header checks (#1907) +* add support for server templates (#1975) +* add support for additional resolver options (#1975) +* add support for resolve-prefer option (#1975) Fixed: * fix maintenance page (python error: 'list' object has no attribute 'strip') @@ -35,6 +38,7 @@ Changed: * change default for spreadChecks from 0 to 2 * no longer overwrite live config file when running a syntax check * make restart/reload commands usable in cron jobs +* relax GUI input validation for servers, move validation to jinja template (#1975) 2.26 diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php index 0cd365dc4..e899a083d 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/Api/SettingsController.php @@ -132,7 +132,7 @@ class SettingsController extends ApiMutableModelControllerBase public function searchServersAction() { - return $this->searchBase('servers.server', array('enabled', 'name', 'address', 'port', 'description'), 'name'); + return $this->searchBase('servers.server', array('enabled', 'name', 'type', 'address', 'port', 'description'), 'name'); } public function getHealthcheckAction($uuid = null) diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml index a17a99b86..31e0eda98 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogBackend.xml @@ -61,6 +61,22 @@ true + + backend.resolverOpts + + select_multiple + + true + + Type option name or choose from list. + + + backend.resolvePrefer + + dropdown + + true + backend.source diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogServer.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogServer.xml index 0eede8c31..1436580cf 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogServer.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/dialogServer.xml @@ -7,9 +7,9 @@ server.name - + text - Name to identify this server. + Name to identify a static server. When creating a server template, then this prefix is used for the server names to be built. server.description @@ -17,6 +17,17 @@ text Description for this server. + + server.type + + dropdown + Either configure a static server or a template to initialize multiple servers with shared parameters. + + + + header + + server.address @@ -24,6 +35,42 @@ Enter server address. + + + header + + + + server.serviceName + + text + + + + server.number + + text + + + + server.linkedResolver + + dropdown + + + + server.resolverOpts + + select_multiple + + true + + Type option name or choose from list. + + + + header + server.port @@ -36,6 +83,13 @@ dropdown + + server.resolvePrefer + + dropdown + + true + server.ssl diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml index 211350c1f..e889fb8f9 100644 --- a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/HAProxy.xml @@ -880,6 +880,24 @@ N N + + N + Y + Y + + allow-dup-ip + ignore-weight + prevent-dup-ip + + + + N + N + + prefer IPv4 + prefer IPv6 [default] + + /^((([0-9a-zA-Z._\-\*:]+)))*/u lower @@ -1197,7 +1215,7 @@
    /^([0-9a-zA-Z\.,_\-:]){0,1024}$/u Please specify a valid servername or IP address. - Y + N
    1 @@ -1213,7 +1231,7 @@ N - Y + N active active [default] @@ -1221,6 +1239,54 @@ disabled + + Y + static + + static + + + + + /^([0-9a-zA-Z\.,_\-:]){0,1024}$/u + Please specify a valid service name. + N + + + /^[0-9]+(-[0-9]+)?/u + Please specify a valid number or range. + N + + + + + + Related resolver not found + N + N + + + N + Y + Y + + allow-dup-ip + ignore-weight + prevent-dup-ip + + + + N + N + + prefer IPv4 + prefer IPv6 [default] + + 0 Y diff --git a/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Migrations/M3_0_0.php b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Migrations/M3_0_0.php new file mode 100644 index 000000000..fff7515d3 --- /dev/null +++ b/net/haproxy/src/opnsense/mvc/app/models/OPNsense/HAProxy/Migrations/M3_0_0.php @@ -0,0 +1,44 @@ +getNodeByReference('servers.server')->iterateItems() as $server) { + $server->type = 'static'; + } + } +} diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt index bbb658680..63ff12973 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/index.volt @@ -230,7 +230,6 @@ POSSIBILITY OF SUCH DAMAGE. $("#acl\\.expression").change(function(){ var service_id = 'table_' + $(this).val(); $(".expression_table").hide(); - // $(".table_"+$(this).val()).show(); $("."+service_id).show(); }); $("#acl\\.expression").change(); @@ -241,7 +240,6 @@ POSSIBILITY OF SUCH DAMAGE. $("#action\\.type").change(function(){ var service_id = 'table_' + $(this).val(); $(".type_table").hide(); - // $(".table_"+$(this).val()).show(); $("."+service_id).show(); }); $("#action\\.type").change(); @@ -308,6 +306,16 @@ POSSIBILITY OF SUCH DAMAGE. $("#healthcheck\\.type").change(); }) + // hook into on-show event for dialog to extend layout. + $('#DialogServer').on('shown.bs.modal', function (e) { + $("#server\\.type").change(function(){ + var service_id = 'table_server_type_' + $(this).val(); + $(".table_server_type").hide(); + $("."+service_id).show(); + }); + $("#server\\.type").change(); + }) + /*********************************************************************** * Commands **********************************************************************/ @@ -647,12 +655,12 @@ POSSIBILITY OF SUCH DAMAGE.

    {{ lang._('Real Servers') }}

    -

    {{ lang._('HAProxy needs to know which servers should be used to serve content. The following minimum information must be provided for each server:') }}

    +

    {{ lang._('HAProxy needs to know which servers should be used to serve content. Either add a static server configuration or use a template to initialize multiple servers at once. The latter one can also be used to discover the available services via DNS SRV records. The following minimum information must be provided for each server:') }}

      -
    • {{ lang._('%sFQDN or IP:%s The IP address or fully-qualified domain name that should be used when communicating with your server.') | format('', '') }}
    • -
    • {{ lang._('%sPort:%s The TCP or UDP port that should be used. If unset, the same port the client connected to will be used.') | format('', '') }}
    • +
    • {{ lang._('%sStatic Servers:%s The IP address or fully-qualified domain name that should be used when communicating with your server. Additionally the TCP or UDP port that should be used. If unset, the same port the client connected to will be used.') | format('', '') }}
    • +
    • {{ lang._('%sServer Templates:%s A prefix is required to build the server names. Additionally a service name or FQDN is required to identify the servers this template initializes') | format('', '') }}
    -

    {{ lang._("Please note that advanced mode settings allow you to disable a certain server or to configure it as a backup server in a Backend Pool. Another neat option is the possibility to adjust a server's weight relative to other servers in the same Backend Pool.") }}

    +

    {{ lang._("Please note that advanced mode settings allow you to adjust a server's weight relative to other servers in the same Backend Pool, in addition to fine-grained health check options.") }}

    {{ lang._('Note that it is possible to directly add options to the HAProxy configuration by using the "option pass-through", a setting that is available for several configuration items. It allows you to implement configurations that are currently not officially supported by this plugin. It is strongly discouraged to rely on this feature. Please report missing features on our GitHub page!') | format('', '') }}


    @@ -809,6 +817,7 @@ POSSIBILITY OF SUCH DAMAGE. {{ lang._('Enabled') }} {{ lang._('Server ID') }} {{ lang._('Server Name') }} + {{ lang._('Type') }} {{ lang._('Server Address') }} {{ lang._('Server Port') }} {{ lang._('Description') }} diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index 5dff7a2f7..c0d06021a 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -1496,135 +1496,169 @@ backend {{backend.name}} {% if server_data == {} %} # ERROR: server data not found ({{server}}) {% else %} -{# # collect optional server parameters #} -{% set server_options = [] %} -{# # check if health check is enabled #} -{% if healthcheck_enabled == '1' %} -{% do server_options.append('check') %} -{# # This can be configured in multiple places. #} -{# # Priority for which value is used: backend > server > health check #} -{% if backend.checkInterval|default("") != "" %} -{% do server_options.append('inter ' ~ backend.checkInterval) %} -{% elif server_data.checkInterval|default("") != "" %} -{% do server_options.append('inter ' ~ server_data.checkInterval) %} -{% elif healthcheck_data.interval|default("") != "" %} -{% do server_options.append('inter ' ~ healthcheck_data.interval) %} -{% endif %} -{# # use a different interval when server is in DOWN state #} -{% if backend.checkDownInterval|default("") != "" %} -{% do server_options.append('downinter ' ~ backend.checkDownInterval) %} -{% elif server_data.checkDownInterval|default("") != "" %} -{% do server_options.append('downinter ' ~ server_data.checkDownInterval) %} -{% endif %} -{# # unhealthy threshold #} -{% if backend.healthCheckFall|default("") != "" %} -{% do server_options.append('fall ' ~ backend.healthCheckFall) %} -{% endif %} -{# # healthy threshold #} -{% if backend.healthCheckRise|default("") != "" %} -{% do server_options.append('rise ' ~ backend.healthCheckRise) %} -{% endif %} -{# # use a different port for health check #} -{% if healthcheck_data.checkport|default("") != "" %} -{# # prefer port from health check template #} -{% do server_options.append('port ' ~ healthcheck_data.checkport) %} -{% elif server_data.checkport|default("") != "" %} -{% do server_options.append('port ' ~ server_data.checkport) %} -{% endif %} -{# # force SSL encryption for health checks #} -{% if healthcheck_data.force_ssl|default('') == '1' %} -{% do server_options.append('check-ssl ') %} -{% endif %} -{# # add all additions from healthchecks here #} -{% do server_options.append(healthcheck_additions|join(' ')) if healthcheck_additions.length != '0' %} -{% endif %} -{# # server weight #} -{% do server_options.append('weight ' ~ server_data.weight) if server_data.weight|default("") != "" %} -{# # server role/mode #} -{% if server_data.mode|default("") != 'active' %} -{% do server_options.append(server_data.mode) %} -{% endif %} -{# # server ssl communication #} -{% if server_data.ssl|default("") == '1' %} -{% do server_options.append('ssl') %} -{# # HTTP/2 #} -{% if backend.http2Enabled|default("") == '1' and backend.ba_advertised_protocols|default("") != "" %} -{# # convert protocols to HAProxy-compatible format #} -{% set alpn_options = backend.ba_advertised_protocols|replace('http10', 'http/1.0')|replace('http11', 'http/1.1') %} -{% do server_options.append('alpn ' ~ alpn_options) %} -{% endif %} -{# # HTTP/2 without TLS #} -{% elif backend.http2Enabled|default("") == '1' and backend.http2Enabled_nontls|default("") == '1' %} -{% do server_options.append('proto h2') %} -{% endif %} -{# # ssl verification can be enabled for two reasons: #} -{# # 1. in server settings: to verify *all* communication to this server #} -{# # 2. in health checks: to verify *only* health check communication to this server #} -{# # When 1. is enabled, health checks are automatically secured. #} -{# # Use-case for 2: when using TCP for server communication, but HTTPS for health checks. #} -{% if server_data.ssl|default("") == '1' or (healthcheck_enabled == '1' and healthcheck_data.force_ssl|default('') == '1') %} -{# # get status of ssl verification #} -{% set ssl_verify_enabled = '0' %} -{% if helpers.exists('OPNsense.HAProxy.general.tuning.sslServerVerify') and OPNsense.HAProxy.general.tuning.sslServerVerify|default("") != 'ignore' %} -{# # NOTE: Global parameter overrides per-server configuration. #} -{% set ssl_verify_enabled = '1' if OPNsense.HAProxy.general.tuning.sslServerVerify|default("") == 'required' %} -{% elif server_data.sslVerify|default("") == '1' %} -{% set ssl_verify_enabled = '1' %} -{% endif %} -{# # configure ssl verification #} -{% if ssl_verify_enabled == '1' %} -{# # enable SSL verification #} -{% do server_options.append('verify required') %} -{# # check for SSL CA #} -{% if server_data.sslCA|default("") != "" %} -{% do server_options.append('ca-file /tmp/haproxy/ssl/' ~ server_data.id ~ '.calist') %} -{% else %} -{# # fallback to system CA Root Certificates #} -{% do server_options.append('ca-file /etc/ssl/cert.pem') %} -{% endif %} -{# # check for SSL CRL #} -{% if server_data.sslCRL|default("") != "" %} -{% do server_options.append('crl-file /tmp/haproxy/ssl/' ~ server_data.sslCRL ~ '.pem') %} -{% endif %} -{# # check for SSL client cert #} -{% if server_data.sslClientCertificate|default("") != "" %} -{% do server_options.append('crt /tmp/haproxy/ssl/' ~ server_data.sslClientCertificate ~ '.pem') %} -{% endif %} +{# # check if all required server parameters are set #} +{% if (server_data.type|default("") == 'static' and server_data.address|default("") == '') or (server_data.type|default("") == 'template' and (server_data.serviceName|default("") == '' or server_data.number|default("") == '')) %} +# ERROR: server is invalid, required parameters not set ({{server_data.name}}) +{% else %} +{# # server type #} +{% set server_basics = [] %} +{% if server_data.type|default("") == 'static' %} +{% do server_basics.append('server ' ~ server_data.name ~ ' ' ~ server_data.address) %} {% else %} -{% do server_options.append('verify none') %} +{% do server_basics.append('server-template ' ~ server_data.name ~ ' ' ~ server_data.number ~ ' ' ~ server_data.serviceName) %} +{% endif %} +{# # collect optional server parameters #} +{% set server_options = [] %} +{# # check if health check is enabled #} +{% if healthcheck_enabled == '1' %} +{% do server_options.append('check') %} +{# # This can be configured in multiple places. #} +{# # Priority for which value is used: backend > server > health check #} +{% if backend.checkInterval|default("") != "" %} +{% do server_options.append('inter ' ~ backend.checkInterval) %} +{% elif server_data.checkInterval|default("") != "" %} +{% do server_options.append('inter ' ~ server_data.checkInterval) %} +{% elif healthcheck_data.interval|default("") != "" %} +{% do server_options.append('inter ' ~ healthcheck_data.interval) %} +{% endif %} +{# # use a different interval when server is in DOWN state #} +{% if backend.checkDownInterval|default("") != "" %} +{% do server_options.append('downinter ' ~ backend.checkDownInterval) %} +{% elif server_data.checkDownInterval|default("") != "" %} +{% do server_options.append('downinter ' ~ server_data.checkDownInterval) %} +{% endif %} +{# # unhealthy threshold #} +{% if backend.healthCheckFall|default("") != "" %} +{% do server_options.append('fall ' ~ backend.healthCheckFall) %} +{% endif %} +{# # healthy threshold #} +{% if backend.healthCheckRise|default("") != "" %} +{% do server_options.append('rise ' ~ backend.healthCheckRise) %} +{% endif %} +{# # use a different port for health check #} +{% if healthcheck_data.checkport|default("") != "" %} +{# # prefer port from health check template #} +{% do server_options.append('port ' ~ healthcheck_data.checkport) %} +{% elif server_data.checkport|default("") != "" %} +{% do server_options.append('port ' ~ server_data.checkport) %} +{% endif %} +{# # force SSL encryption for health checks #} +{% if healthcheck_data.force_ssl|default('') == '1' %} +{% do server_options.append('check-ssl ') %} +{% endif %} +{# # add all additions from healthchecks here #} +{% do server_options.append(healthcheck_additions|join(' ')) if healthcheck_additions.length != '0' %} +{% endif %} +{# # server weight #} +{% do server_options.append('weight ' ~ server_data.weight) if server_data.weight|default("") != "" %} +{# # server role/mode #} +{% if server_data.mode|default("") != 'active' %} +{% do server_options.append(server_data.mode) %} +{% endif %} +{# # server ssl communication #} +{% if server_data.ssl|default("") == '1' %} +{% do server_options.append('ssl') %} +{# # HTTP/2 #} +{% if backend.http2Enabled|default("") == '1' and backend.ba_advertised_protocols|default("") != "" %} +{# # convert protocols to HAProxy-compatible format #} +{% set alpn_options = backend.ba_advertised_protocols|replace('http10', 'http/1.0')|replace('http11', 'http/1.1') %} +{% do server_options.append('alpn ' ~ alpn_options) %} +{% endif %} +{# # HTTP/2 without TLS #} +{% elif backend.http2Enabled|default("") == '1' and backend.http2Enabled_nontls|default("") == '1' %} +{% do server_options.append('proto h2') %} +{% endif %} +{# # ssl verification can be enabled for two reasons: #} +{# # 1. in server settings: to verify *all* communication to this server #} +{# # 2. in health checks: to verify *only* health check communication to this server #} +{# # When 1. is enabled, health checks are automatically secured. #} +{# # Use-case for 2: when using TCP for server communication, but HTTPS for health checks. #} +{% if server_data.ssl|default("") == '1' or (healthcheck_enabled == '1' and healthcheck_data.force_ssl|default('') == '1') %} +{# # get status of ssl verification #} +{% set ssl_verify_enabled = '0' %} +{% if helpers.exists('OPNsense.HAProxy.general.tuning.sslServerVerify') and OPNsense.HAProxy.general.tuning.sslServerVerify|default("") != 'ignore' %} +{# # NOTE: Global parameter overrides per-server configuration. #} +{% set ssl_verify_enabled = '1' if OPNsense.HAProxy.general.tuning.sslServerVerify|default("") == 'required' %} +{% elif server_data.sslVerify|default("") == '1' %} +{% set ssl_verify_enabled = '1' %} +{% endif %} +{# # configure ssl verification #} +{% if ssl_verify_enabled == '1' %} +{# # enable SSL verification #} +{% do server_options.append('verify required') %} +{# # check for SSL CA #} +{% if server_data.sslCA|default("") != "" %} +{% do server_options.append('ca-file /tmp/haproxy/ssl/' ~ server_data.id ~ '.calist') %} +{% else %} +{# # fallback to system CA Root Certificates #} +{% do server_options.append('ca-file /etc/ssl/cert.pem') %} +{% endif %} +{# # check for SSL CRL #} +{% if server_data.sslCRL|default("") != "" %} +{% do server_options.append('crl-file /tmp/haproxy/ssl/' ~ server_data.sslCRL ~ '.pem') %} +{% endif %} +{# # check for SSL client cert #} +{% if server_data.sslClientCertificate|default("") != "" %} +{% do server_options.append('crt /tmp/haproxy/ssl/' ~ server_data.sslClientCertificate ~ '.pem') %} +{% endif %} +{% else %} +{% do server_options.append('verify none') %} +{% endif %} +{% endif %} +{# # resolver #} +{% set resolver_id = '' %} +{% set resolver_opts = '' %} +{% if backend.linkedResolver|default("") != "" %} +{# # prefer backend configuration #} +{% set resolver_id = backend.linkedResolver %} +{% set resolver_opts = backend.resolverOpts %} +{% elif server_data.linkedResolver|default("") != "" and server_data.type|default("") == 'template' %} +{# # use resolver for server template #} +{% set resolver_id = server_data.linkedResolver %} +{% set resolver_opts = server_data.resolverOpts %} +{% endif %} +{% if resolver_id != '' %} +{% set resolver_data = helpers.getUUID(resolver_id) %} +{% do server_options.append('resolvers ' ~ resolver_data.id) %} +{# # additional resolver options #} +{% if resolver_opts != '' %} +{% do server_options.append('resolve-opts ' ~ resolver_opts) %} +{% endif %} +{% endif %} +{# # prefer selected IP family for DNS resolution #} +{% if backend.resolvePrefer|default("") != "" %} +{# # prefer backend configuration #} +{% do server_options.append('resolve-prefer ' ~ backend.resolvePrefer) %} +{% elif server_data.linkedResolver|default("") != "" %} +{% do server_options.append('resolve-prefer ' ~ server_data.resolvePrefer) %} +{% endif %} +{# # source address #} +{% if backend.source|default("") != "" %} +{# # prefer backend configuration #} +{% do server_options.append('source ' ~ backend.source) %} +{% elif server_data.source|default("") != "" %} +{% do server_options.append('source ' ~ server_data.source) %} +{% endif %} +{# # PROXY protocol #} +{% if backend.proxyProtocol|default("") == "v1" %} +{% do server_options.append('send-proxy') %} +{% do server_options.append('check-send-proxy') %} +{% elif backend.proxyProtocol|default("") == "v2" %} +{% do server_options.append('send-proxy-v2') %} +{% do server_options.append('check-send-proxy') %} +{% endif %} +{# # cookie-based persistence #} +{% if backend.persistence|default("") == "cookie" %} +{% do server_options.append('cookie ' ~ server_data.id|replace(".", "")) %} +{% endif %} +{# # server advanced options #} +{% if server_data.advanced|default("") != "" %} +{% do server_options.append(server_data.advanced) %} +{% endif %} +{# # server enabled? #} +{% if server_data.enabled == '1' %} + {{server_basics|join(' ')}}{% if backend.tuning_noport != '1' %}{% if server_data.port|default("") != "" %}:{{server_data.port}}{% endif %}{% endif %} {{server_options|join(' ')}} {% endif %} -{% endif %} -{# # resolver #} -{% if backend.linkedResolver|default("") != "" %} -{% set resolver_data = helpers.getUUID(backend.linkedResolver) %} -{% do server_options.append('resolvers ' ~ resolver_data.id) %} -{% endif %} -{# # source address #} -{% if backend.source|default("") != "" %} -{# # prefer backend configuration #} -{% do server_options.append('source ' ~ backend.source) %} -{% elif server_data.source|default("") != "" %} -{% do server_options.append('source ' ~ server_data.source) %} -{% endif %} -{# # PROXY protocol #} -{% if backend.proxyProtocol|default("") == "v1" %} -{% do server_options.append('send-proxy') %} -{% do server_options.append('check-send-proxy') %} -{% elif backend.proxyProtocol|default("") == "v2" %} -{% do server_options.append('send-proxy-v2') %} -{% do server_options.append('check-send-proxy') %} -{% endif %} -{# # cookie-based persistence #} -{% if backend.persistence|default("") == "cookie" %} -{% do server_options.append('cookie ' ~ server_data.id|replace(".", "")) %} -{% endif %} -{# # server advanced options #} -{% if server_data.advanced|default("") != "" %} -{% do server_options.append(server_data.advanced) %} -{% endif %} -{# # server enabled? #} -{% if server_data.enabled == '1' %} - server {{server_data.name}} {{server_data.address}}:{% if backend.tuning_noport != '1' %}{% if server_data.port|default("") != "" %}{{server_data.port}}{% endif %}{% endif %} {{server_options|join(' ')}} {% endif %} {% endif %} {% endfor %} From f39b0c1648c227ce2984d3851921416a5f49b53e Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Sun, 21 Feb 2021 23:50:00 +0100 Subject: [PATCH 15/17] net/haproxy: ignore mailers that are not in use, refs #1669 --- .../templates/OPNsense/HAProxy/haproxy.conf | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf index c0d06021a..091d1d4d0 100644 --- a/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf +++ b/net/haproxy/src/opnsense/service/templates/OPNsense/HAProxy/haproxy.conf @@ -1091,15 +1091,31 @@ resolvers {{resolver.id}} {% if helpers.exists('OPNsense.HAProxy.mailers') %} {% for mailer in helpers.toList('OPNsense.HAProxy.mailers.mailer') %} {% if mailer.enabled == '1' %} +{# # check if mailer is configured in a backend #} +{% set ns = namespace(mailer_found=false) %} +{% if helpers.exists('OPNsense.HAProxy.backends') %} +{% for backend in helpers.toList('OPNsense.HAProxy.backends.backend') %} +{# # backend must be enabled #} +{% if backend.enabled == '1' and backend.linkedMailer|default('') == mailer['@uuid'] %} +{% set ns.mailer_found = True %} +{% endif %} +{% endfor %} +{% endif %} +{# # only add mailers that are in use to avoid config test warnings #} +{% if ns.mailer_found %} # Mailer: {{mailer.name}} mailers {{mailer.id}} timeout mail {{mailer.timeout}}s -{% if mailer.mailservers|default("") != "" %} -{% for mailserver in mailer.mailservers.split(",") %} +{% if mailer.mailservers|default("") != "" %} +{% for mailserver in mailer.mailservers.split(",") %} mailer {{mailserver}} {{mailserver}} -{% endfor %} -{% endif %} +{% endfor %} +{% endif %} +{% else %} +# NOTE: Mailer {{mailer.name}} ignored: not configured in any backend + +{% endif %} {% else %} # Mailer (DISABLED): {{mailer.name}} From 8433328437b2f82e4bfa88c77ba7ede91a93047d Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Mon, 22 Feb 2021 00:02:46 +0100 Subject: [PATCH 16/17] net/haproxy: show help text when no config file was found --- .../opnsense/mvc/app/views/OPNsense/HAProxy/export.volt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt index 160d93df9..19c31de7a 100644 --- a/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt +++ b/net/haproxy/src/opnsense/mvc/app/views/OPNsense/HAProxy/export.volt @@ -34,7 +34,13 @@ POSSIBILITY OF SUCH DAMAGE. */ function update_showconf() { ajaxCall(url="/api/haproxy/export/config/", sendData={}, callback=function(data,status) { - $("#showconf").text(data['response']); + if (data['response'] && data['response'].trim()) { + $("#showconf").text(data['response']); + } else { + conf_help = "
    {{ lang._('Config file not found. Run a syntax check to create it.') }}
    "; + $("#showconfempty").append(conf_help); + $("#showconf").hide(); + } }); } update_showconf(); @@ -116,6 +122,7 @@ POSSIBILITY OF SUCH DAMAGE.
    +
    
                 

    From 3c74cadb4121cc2f966e484ff26a4a9b363445e1 Mon Sep 17 00:00:00 2001 From: Frank Wall Date: Tue, 23 Feb 2021 17:04:53 +0100 Subject: [PATCH 17/17] net/haproxy: improve help text --- .../app/controllers/OPNsense/HAProxy/forms/generalSettings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml index 5869a62e6..d0efde12b 100644 --- a/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml +++ b/net/haproxy/src/opnsense/mvc/app/controllers/OPNsense/HAProxy/forms/generalSettings.xml @@ -25,7 +25,7 @@ haproxy.general.storeOcsp checkbox - + haproxy.general.showIntro