From 75372116092d861ab829d52f3d245325696cee66 Mon Sep 17 00:00:00 2001 From: PiBa-NL Date: Sat, 7 Feb 2015 17:50:48 +0100 Subject: haproxy-devel, 0.17, acl's are merged when duplicates exist, better client certificate handling, checkbox options for allowing no/invalid client certs instead of the 'none'-ca which wasn't 'user friendly'. --- config/haproxy-devel/haproxy.inc | 106 +++++++++++++-------- config/haproxy-devel/haproxy.xml | 6 ++ config/haproxy-devel/haproxy_global.php | 4 +- config/haproxy-devel/haproxy_listeners.php | 6 +- config/haproxy-devel/haproxy_listeners_edit.php | 88 ++++++++++++----- .../haproxy-devel/pkg/haproxy_upgrade_config.inc | 16 ++++ pkg_config.10.xml | 2 +- pkg_config.8.xml | 2 +- pkg_config.8.xml.amd64 | 2 +- 9 files changed, 164 insertions(+), 68 deletions(-) diff --git a/config/haproxy-devel/haproxy.inc b/config/haproxy-devel/haproxy.inc index e9b0f9e3..a7394cf3 100644 --- a/config/haproxy-devel/haproxy.inc +++ b/config/haproxy-devel/haproxy.inc @@ -68,12 +68,12 @@ $a_acltypes["path_regex"] = array('name' => 'Path regex:', $a_acltypes["path_contains"] = array('name' => 'Path contains:', 'mode' => 'http', 'syntax' => 'path_dir -i %1$s'); $a_acltypes["ssl_c_verify_code"] = array('name' => 'SSL Client certificate verify error result:', - 'mode' => 'http', 'syntax' => 'ssl_fc_has_crt ssl_c_verify %1$s'); + 'mode' => 'http', 'syntax' => 'ssl_c_verify %1$s', 'require_client_cert' => '1'); // ssl_c_verify result codes: https://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS $a_acltypes["ssl_c_verify"] = array('name' => 'SSL Client certificate valid.', - 'mode' => 'http', 'syntax' => 'ssl_fc_has_crt ssl_c_verify 0 '); + 'mode' => 'http', 'syntax' => 'ssl_c_verify 0', 'novalue' => '1', 'require_client_cert' => '1'); $a_acltypes["ssl_c_ca_commonname"] = array('name' => 'SSL Client issued by CA common-name:', - 'mode' => 'http', 'syntax' => 'ssl_c_i_dn(CN) %1$s'); + 'mode' => 'http', 'syntax' => 'ssl_c_i_dn(CN) %1$s', 'require_client_cert' => '1'); $a_acltypes["source_ip"] = array('name' => 'Source IP matches IP or Alias:', 'mode' => '', 'syntax' => 'src %1$s'); $a_acltypes["backendservercount"] = array('name' => 'Minimum count usable servers:', @@ -151,9 +151,13 @@ $a_closetypes['forceclose'] = array('name' => 'forceclose', 'syntax' => 'forcecl global $a_servermodes; $a_servermodes = array(); $a_servermodes["active"]['name'] = "active"; +$a_servermodes["active"]['sign'] = ""; $a_servermodes["backup"]['name'] = "backup"; +$a_servermodes["backup"]['sign'] = "*"; $a_servermodes["disabled"]['name'] = "disabled"; +$a_servermodes["disabled"]['sign'] = "?"; $a_servermodes["inactive"]['name'] = "inactive"; +$a_servermodes["inactive"]['sign'] = "-"; // http://www.exceliance.fr/sites/default/files/biblio/aloha_load_balancer_haproxy_cookie_persistence_methods_memo.pdf global $a_cookiemode; @@ -1036,7 +1040,6 @@ function haproxy_writeconf($configpath) { fwrite ($fd, "{$frontendinfo}"); - $allow_none = false; $advancedextra = array(); $ca_file = ""; $first = true; @@ -1046,10 +1049,9 @@ function haproxy_writeconf($configpath) { if (!empty($ca['cert_ca'])){ haproxy_write_certificate_crt($filename, $ca['cert_ca'], false, !$first); $first = false; - } else - $allow_none = true; + } } - $verify = $allow_none ? "verify optional" : "verify required"; + $verify = $bind['sslclientcert-none'] == 'yes' ? "verify optional" : "verify required"; $ca_file = " ca-file $filename $verify"; } $crl_file = ""; @@ -1062,15 +1064,11 @@ function haproxy_writeconf($configpath) { } $crl_file = " crl-file $filename"; } - - if($bind['type'] == "http") { - // ssl offloading is only possible in http mode. - $ssl_info = $bind['ssl_info'].$ca_file.$crl_file; - $advanced_bind = $bind['advanced_bind']; - } else { - $ssl_info = ""; - $advanced_bind = ""; - } + $advanced_bind = $bind['advanced_bind']; + $ssl_info = $bind['ssl_info']; + $ssl_info .= $ca_file . $crl_file; + if ($bind['sslclientcert-invalid']) + $ssl_info .= " crt-ignore-err all"; $useipv4 = false; $useipv6 = false; @@ -1165,6 +1163,8 @@ function haproxy_writeconf($configpath) { $inspectdelay = 0; $i = 0; + $acllist = array(); + $acl_newid = 0; foreach ($bind['config'] as $frontend) { $a_acl = get_frontend_acls($frontend); @@ -1187,12 +1187,27 @@ function haproxy_writeconf($configpath) { $a_acl_combine = array(); foreach ($a_acl as $entry) { $name = $entry['ref']['name']; - $a_acl_combine[$name][] = $entry['ref']; + + $acl = array(); + $acl['ref'] = $entry['ref']; + $acltype = haproxy_find_acl($entry['ref']['expression']); + $acl['acltype'] = $acltype; + if (!isset($acltype)) + continue; + $a_acl_combine[$name][] = $acl; + + if (isset($acltype['require_client_cert'])){ + $acl = array(); + $acl['ref']['expression'] = "ssl_c_used"; + $acl['acltype']['syntax'] = "ssl_c_used"; + $acl['acltype']['novalue'] = 1; + $a_acl_combine[$name][] = $acl; + } } + $certacl = ""; $y = 0; foreach($ipv as $ipversion => $ipversionoptions) { - $certacls = array(); $useracls = array(); $poolname = $frontend['backend_serverpool'] . "_" . strtolower($bind['type'])."_".$ipversion; if (!isset($a_pendingpl[$poolname])) { @@ -1210,10 +1225,9 @@ function haproxy_writeconf($configpath) { foreach ($a_acl_combine as $a_usebackend) { $aclnames = ""; - foreach ($a_usebackend as $entry) { - $acl = haproxy_find_acl($entry['expression']); - if (!$acl) - continue; + foreach ($a_usebackend as $entry2) { + $entry = $entry2['ref']; + $acl = $entry2['acltype']; // Filter out acls for different modes if ($acl['mode'] != '' && $acl['mode'] != strtolower($bind['type'])) @@ -1231,33 +1245,49 @@ function haproxy_writeconf($configpath) { $not = $entry['not'] == "yes" ? "!" : ""; - $aclname = $i . "_" . $entry['name']; - if ($entry['certacl']) - $certacls[] = $aclname . " "; - else + unset($aclkey); + foreach($acllist as $aclid => $aclitem) { + if ($aclitem['expr'] == $expr) { + $aclkey = $aclid; + } + } + if (isset($aclkey)) { + $aclname = $acllist[$aclkey]['aclname']; + } else { + $aclkey = $acl_newid++; + if ($entry['certacl']) { + $aclname = "aclcrt_".$frontend['name']; + $certacl = $aclname; + } else { + $aclname = "aclusr_{$entry['expression']}"; + if (!isset($acl['novalue'])) + $aclname .= "_{$entry['value']}"; + $aclname = haproxy_escape_acl_name($aclname); + $i++; + } + $acllist[$aclkey]['aclname'] = $aclname; + $acllist[$aclkey]['expr'] = $expr; + $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"; + } + if (!isset($entry['certacl'])) $useracls[$y] .= $not . $aclname . " "; - $config_acls .= "\tacl\t\t\t" . $aclname . "\t" . $expr . "\n"; - if ($acl['inspect-delay'] != '') $inspectdelay = $acl['inspect-delay']; if ($acl['advancedoptions'] != '') $advancedextra[$acl['syntax']] = $acl['advancedoptions']."\n"; - $i++; } $y++; } - if (count($certacls) == 0) $certacls[] = ""; // add empty item to enter foreach loop at least once. if (count($useracls) == 0) $useracls[] = ""; // add empty item to enter foreach loop at least once. - $backendacl = ""; - foreach($useracls as $useracl) - foreach($certacls as $certacl) - $backendacl .= "|| {$useracl}{$certacl}{$ipversionoptions['acl']}"; - $backendacl = substr($backendacl, 3); - $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; - //$config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; + foreach($useracls as $useracl) { + $backendacl = ""; + $backendacl .= "|| {$useracl}{$certacl}{$ipversionoptions['acl']}"; + $backendacl = substr($backendacl, 3); + $config_usebackends .= "\tuse_backend\t\t" . $poolname . " if " . $backendacl . "\n"; + } } } @@ -1842,7 +1872,7 @@ function get_frontend_acls($frontend) { continue; $not = $entry['not'] == "yes" ? "not " : ""; $acl_item = array(); - $acl_item['descr'] = $acl['name'] . ": " . $entry['value']; + $acl_item['descr'] = $acl['name'] . " " . (isset($acl['novalue']) ? "" : $entry['value']); $acl_item['ref'] = $entry; $result[] = $acl_item; diff --git a/config/haproxy-devel/haproxy.xml b/config/haproxy-devel/haproxy.xml index 27199ee4..e4fe3610 100644 --- a/config/haproxy-devel/haproxy.xml +++ b/config/haproxy-devel/haproxy.xml @@ -52,6 +52,12 @@
Services
/haproxy_listeners.php + + HAProxy Stats + Stats of HAProxy +
Status
+ /haproxy_stats.php?haproxystats=1 +
HAProxy haproxy.sh diff --git a/config/haproxy-devel/haproxy_global.php b/config/haproxy-devel/haproxy_global.php index cad3795a..60c2fd9d 100755 --- a/config/haproxy-devel/haproxy_global.php +++ b/config/haproxy-devel/haproxy_global.php @@ -191,7 +191,7 @@ function enable_change(enable_change) {
- value="" /> per Backend. + value="" /> per process.
@@ -253,7 +253,7 @@ function enable_change(enable_change) {
Defaults to 1 if left blank ( CPU core(s) detected).
- Note : Consider leaving this value empty or 1 because in multi-process mode (nbproc > 1) memory is not shared between the processes, which could result in random behaviours for several options like ACL's, sticky connections and some others.
+ Note : Consider leaving this value empty or 1 because in multi-process mode (nbproc > 1) memory is not shared between the processes, which could result in random behaviours for several options like ACL's, sticky connections, stats pages, admin maintenance options and some others.
For more information about the "nbproc" option please see HAProxy Documentation diff --git a/config/haproxy-devel/haproxy_listeners.php b/config/haproxy-devel/haproxy_listeners.php index ef7e01c4..db1f3ff2 100644 --- a/config/haproxy-devel/haproxy_listeners.php +++ b/config/haproxy-devel/haproxy_listeners.php @@ -247,10 +247,12 @@ function js_callback(req) { $backend_serverpool_hint = gettext("Servers in pool:"); if (is_array($servers)){ foreach($servers as $server){ + $srvstatus = $server['status']; + $status = $a_servermodes[$srvstatus]['sign']; if (isset($server['forwardto']) && $server['forwardto'] != "") - $backend_serverpool_hint .= "\n[".$server['forwardto']."]"; + $backend_serverpool_hint .= "\n{$status}[{$server['forwardto']}]"; else - $backend_serverpool_hint .= "\n".$server['address'].":".$server['port']; + $backend_serverpool_hint .= "\n{$status}{$server['address']}:{$server['port']}"; } } } diff --git a/config/haproxy-devel/haproxy_listeners_edit.php b/config/haproxy-devel/haproxy_listeners_edit.php index a13eca80..d8841c33 100644 --- a/config/haproxy-devel/haproxy_listeners_edit.php +++ b/config/haproxy-devel/haproxy_listeners_edit.php @@ -70,8 +70,8 @@ uasort($a_pools, haproxy_compareByName); global $simplefields; $simplefields = array('name','desc','status','secondary','primary_frontend','type','forwardfor','httpclose','extaddr','backend_serverpool', - 'max_connections','client_timeout','port','ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadaclnondefault','advanced_bind', - 'ssloffloadacladditional','ssloffloadacladditionalnondefault', + 'max_connections','client_timeout','port','advanced_bind', + 'ssloffloadcert','dcertadv','ssloffload','ssloffloadacl','ssloffloadacladditional','sslclientcert-none','sslclientcert-invalid', 'socket-stats', 'dontlognull','dontlog-normal','log-separate-errors','log-detailed'); @@ -105,8 +105,6 @@ $fields_sslCertificates[0]['size']="500px"; $fields_sslCertificates[0]['items']=&$servercerts; $certs_ca = haproxy_get_certificates('ca'); -$ca_none['']['name']="(None), allows for client without a (valid) certificate to connect. Make sure to add appropriate acl's."; -$certs_ca = $ca_none + $certs_ca; $fields_caCertificates=array(); $fields_caCertificates[0]['name']="cert_ca"; $fields_caCertificates[0]['columnheader']="Certificates authorities"; @@ -248,9 +246,9 @@ if ($_POST) { $a_certificates = haproxy_htmllist_get_values($fields_sslCertificates); $pconfig['a_certificates'] = $a_certificates; $a_clientcert_ca = haproxy_htmllist_get_values($fields_caCertificates); - $pconfig['a_clientcert_ca'] = $a_clientcert_ca; + $pconfig['clientcert_ca'] = $a_clientcert_ca; $a_clientcert_crl = haproxy_htmllist_get_values($fields_crlCertificates); - $pconfig['a_clientcert_crl'] = $a_clientcert_crl; + $pconfig['clientcert_crl'] = $a_clientcert_crl; $a_acl = haproxy_htmllist_get_values($fields_aclSelectionList); $pconfig['a_acl'] = $a_acl; @@ -262,17 +260,31 @@ if ($_POST) { foreach($a_acl as $acl) { $acl_name = $acl['name']; $acl_value = $acl['value']; - + + $acltype = haproxy_find_acl($acl['expression']); if (preg_match("/[^a-zA-Z0-9\.\-_]/", $acl_name)) $input_errors[] = "The field 'Name' contains invalid characters."; - if (!preg_match("/.{1,}/", $acl_value)) - $input_errors[] = "The field 'Value' is required."; + if (!isset($acltype['novalue'])) + if (!preg_match("/.{1,}/", $acl_value)) + $input_errors[] = "The field 'Value' is required."; if (!preg_match("/.{2,}/", $acl_name)) $input_errors[] = "The field 'Name' is required with at least 2 characters."; } - + foreach($a_extaddr as $extaddr) { + $ports = explode(",",$extaddr['extaddr_port']); + foreach($ports as $port){ + if ($port && !is_numeric($port) && !is_portoralias($port)) + $input_errors[] = "The field 'Port' value '".htmlspecialchars($port)."' is not a number or alias thereof."; + } + + if ($extaddr['extaddr'] == 'custom') { + $extaddr_custom = $extaddr['extaddr_custom']; + if (empty($extaddr_custom) || (!is_ipaddroralias($extaddr_custom))) + $input_errors[] = sprintf(gettext("%s is not a valid source IP address or alias."),$extaddr_custom); + } + } if (!$input_errors) { $backend = array(); if(isset($id) && $a_backend[$id]) @@ -331,6 +343,7 @@ $primaryfrontends = get_haproxy_frontends($excludefrontend); ?>