mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
Merge pull request #2254 from fraenki/haproxy_300a
net/haproxy: finishing touches for release 3.0
This commit is contained in:
@@ -9,7 +9,8 @@ Plugin Changelog
|
||||
3.0
|
||||
|
||||
Added:
|
||||
* new feature to change server state and weight on-the-fly (#2213)
|
||||
* add new maintenance page to change server state and weight on-the-fly (#2213)
|
||||
* add new commands to update SSL certificates in runtime (#2244, #1882)
|
||||
* 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
|
||||
@@ -22,11 +23,12 @@ Added:
|
||||
* add support for server templates (#1975)
|
||||
* add support for additional resolver options (#1975)
|
||||
* add support for resolve-prefer option (#1975)
|
||||
* add pre-defined cron jobs to maintenance page
|
||||
|
||||
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
|
||||
* prevent the deletion of items that are still referenced elsewhere (core/#1897)
|
||||
|
||||
Changed:
|
||||
* change default SSL version to TLSv1.2 (ssl-min-ver)
|
||||
@@ -40,6 +42,9 @@ Changed:
|
||||
* make restart/reload commands usable in cron jobs
|
||||
* relax GUI input validation for servers, move validation to jinja template (#1975)
|
||||
|
||||
Deprecated:
|
||||
* nbproc is deprecated and will be removed in os-haproxy 4.0
|
||||
|
||||
2.26
|
||||
|
||||
Fixed:
|
||||
|
||||
+102
-2
@@ -31,16 +31,21 @@
|
||||
|
||||
namespace OPNsense\HAProxy\Api;
|
||||
|
||||
use OPNsense\Base\ApiControllerBase;
|
||||
use OPNsense\Base\ApiMutableModelControllerBase;
|
||||
use OPNsense\Core\Backend;
|
||||
use OPNsense\Core\Config;
|
||||
use OPNsense\Cron\Cron;
|
||||
use OPNsense\HAProxy\HAProxy;
|
||||
|
||||
/**
|
||||
* Class MaintenanceController
|
||||
* @package OPNsense\HAProxy
|
||||
*/
|
||||
class MaintenanceController extends ApiControllerBase
|
||||
class MaintenanceController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'haproxy';
|
||||
protected static $internalModelClass = '\OPNsense\HAProxy\HAProxy';
|
||||
|
||||
/**
|
||||
* jQuery bootstrap certificates diff list
|
||||
* @return array|mixed
|
||||
@@ -268,4 +273,99 @@ class MaintenanceController extends ApiControllerBase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* create new cron job or return already available one
|
||||
* @return array status action
|
||||
*/
|
||||
public function fetchCronIntegrationAction()
|
||||
{
|
||||
$result = array("result" => "no change");
|
||||
|
||||
if ($this->request->isPost()) {
|
||||
$mdlHaproxy = $this->getModel();
|
||||
$backend = new Backend();
|
||||
|
||||
// Define possible cron jobs with their configd actions
|
||||
$cronjobs = array(
|
||||
'syncCerts' => 'cert_sync_bulk',
|
||||
'updateOcsp' => 'update_ocsp',
|
||||
'reloadService' => 'reload',
|
||||
'restartService' => 'restart',
|
||||
);
|
||||
|
||||
// Iterate over all possible cron jobs
|
||||
foreach ($cronjobs as $cron => $cron_action) {
|
||||
|
||||
// Name of the item that holds the cron UUID
|
||||
$cron_ref = "${cron}Cron";
|
||||
|
||||
// Check if the cron job is enabled or disabled
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron == "1") {
|
||||
// Check if a cron job already exists
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron_ref == "") {
|
||||
|
||||
// Create new cron job
|
||||
$mdlCron = new Cron();
|
||||
// NOTE: Only configd actions are valid commands for cronjobs
|
||||
// and they *must* provide a description that is not empty.
|
||||
$cron_uuid = $mdlCron->newDailyJob(
|
||||
"HAProxy",
|
||||
"haproxy ${cron_action}",
|
||||
"Added by HAProxy plugin",
|
||||
"*",
|
||||
"1"
|
||||
);
|
||||
$mdlHaproxy->maintenance->cronjobs->$cron_ref = $cron_uuid;
|
||||
|
||||
// Save updated configuration.
|
||||
if ($mdlCron->performValidation()->count() == 0) {
|
||||
$mdlCron->serializeToConfig();
|
||||
// save data to config, do not validate because the current in memory model doesn't know about the
|
||||
// cron item just created.
|
||||
$mdlHaproxy->serializeToConfig($validateFullModel = false, $disable_validation = true);
|
||||
Config::getInstance()->save();
|
||||
// Refresh the crontab
|
||||
$backend->configdRun('template reload OPNsense/Cron');
|
||||
// (res)start daemon
|
||||
$backend->configdRun("cron restart");
|
||||
$this->getLogger()->error("HAProxy: successfully created cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "new";
|
||||
$result['uuid'] = $cron_uuid;
|
||||
} else {
|
||||
$this->getLogger()->error("HAProxy: unable to create cron job $cron");
|
||||
$result['result'] = "unable to add cron";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if a cron job exists
|
||||
if ((string)$mdlHaproxy->maintenance->cronjobs->$cron_ref != "") {
|
||||
|
||||
// Clean existin entry
|
||||
$cron_uuid = (string)$mdlHaproxy->maintenance->cronjobs->$cron_ref;
|
||||
$mdlHaproxy->maintenance->cronjobs->$cron_ref = "";
|
||||
|
||||
// Delete the cronjob item
|
||||
$mdlCron = new Cron();
|
||||
if ($mdlCron->jobs->job->del($cron_uuid)) {
|
||||
// If item is removed, serialize to config and save
|
||||
$mdlCron->serializeToConfig();
|
||||
$mdlHaproxy->serializeToConfig($validateFullModel = false, $disable_validation = true);
|
||||
Config::getInstance()->save();
|
||||
// Regenerate the crontab
|
||||
$backend->configdRun('template reload OPNsense/Cron');
|
||||
// (res)start daemon
|
||||
$backend->configdRun("cron restart");
|
||||
$this->getLogger()->error("HAProxy: successfully deleted cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "deleted";
|
||||
} else {
|
||||
$this->getLogger()->error("HAProxy: unable to delete cron job $cron ($cron_uuid)");
|
||||
$result['result'] = "unable to delete cron";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2016 Frank Wall
|
||||
* Copyright (C) 2016-2021 Frank Wall
|
||||
* Copyright (C) 2015 Deciso B.V.
|
||||
*
|
||||
* All rights reserved.
|
||||
@@ -44,6 +44,7 @@ class SettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
protected static $internalModelName = 'haproxy';
|
||||
protected static $internalModelClass = '\OPNsense\HAProxy\HAProxy';
|
||||
protected static $internalModelUseSafeDelete = true;
|
||||
|
||||
public function getFrontendAction($uuid = null)
|
||||
{
|
||||
|
||||
+3
-3
@@ -45,7 +45,7 @@ class StatisticsController extends ApiControllerBase
|
||||
* get info
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function infoAction($zoneid = 0)
|
||||
public function infoAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$responseRaw = $backend->configdRun("haproxy statistics info");
|
||||
@@ -57,7 +57,7 @@ class StatisticsController extends ApiControllerBase
|
||||
* get counters
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function countersAction($zoneid = 0)
|
||||
public function countersAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$responseRaw = $backend->configdRun("haproxy statistics stat");
|
||||
@@ -69,7 +69,7 @@ class StatisticsController extends ApiControllerBase
|
||||
* get tables
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function tablesAction($zoneid = 0)
|
||||
public function tablesAction()
|
||||
{
|
||||
$backend = new Backend();
|
||||
$responseRaw = $backend->configdRun("haproxy statistics table");
|
||||
|
||||
+1
@@ -41,5 +41,6 @@ class MaintenanceController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
// choose template
|
||||
$this->view->pick('OPNsense/HAProxy/maintenance');
|
||||
$this->view->maintenanceCronjobsForm = $this->getForm("maintenanceCronjobs");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -7,14 +7,14 @@
|
||||
<id>haproxy.general.tuning.root</id>
|
||||
<label>Run as root</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Enable or disable HAProxy running as root.<br/><div class="text-info"><b>NOTE:</b> Enabling root could be a security issue but it's required by some feature.</div>]]></help>
|
||||
<help><![CDATA[Enable or disable HAProxy running as user root. Enabling this option is strongly discouraged.<br/><div class="text-info"><b>NOTE:</b> Running as user root could be a security issue but it may be required by some features.</div>]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.general.tuning.nbproc</id>
|
||||
<label>HAProxy processes</label>
|
||||
<label>HAProxy processes (DEPRECATED)</label>
|
||||
<type>text</type>
|
||||
<help><![CDATA[Number of HAProxy processes to start.<br/><div class="text-info"><b>NOTE:</b> You may experience random issues in multi-process mode. For more information about the "nbproc" option please see the HAProxy Documentation.</div>]]></help>
|
||||
<help><![CDATA[Number of HAProxy processes to start.<br/><div class="text-info"><b>WARNING:</b> This option is deprecated and will be removed in a future version of HAProxy, threads should be used instead.</div>]]></help>
|
||||
<advanced>true</advanced>
|
||||
</field>
|
||||
<field>
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
<form>
|
||||
<field>
|
||||
<label>Sync SSL certificate changes</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_syncCerts</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.syncCerts</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically sync SSL certificate changes into the running HAProxy service. This is most useful when using short-lived Let's Encrypt certificates, but changes to other certificates will also be synced. Note that when using the Let's Encrypt plugin, it is also possible to use an <a target="_blank" href="/ui/acmeclient/actions">Automation</a> instead of this cron job.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Update OCSP data for SSL certificates</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_updateOcsp</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.updateOcsp</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically fetch OCSP data for all configured SSL certificates. Note that OCSP support needs to be enabled in <a target="_blank" href="/ui/haproxy#general-settings">HAProxy service settings</a>.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Reload HAProxy service</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_reloadService</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.reloadService</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically perform a reload of the HAProxy service. This may cause a minor service disruption, depending on the configuration. A nightly reload could be used to apply configuration changes outside of business hours, or to workaround a bug.]]></help>
|
||||
</field>
|
||||
<field>
|
||||
<label>Restart HAProxy service</label>
|
||||
<type>header</type>
|
||||
<style>table_cron table_cron_restartService</style>
|
||||
</field>
|
||||
<field>
|
||||
<id>haproxy.maintenance.cronjobs.restartService</id>
|
||||
<label>Enable</label>
|
||||
<type>checkbox</type>
|
||||
<help><![CDATA[Periodically perform a full restart of the HAProxy service. This will cause a notable service disruption. A full restart is required in some cases where a reload does not work as expected (i.e. due to long-running connections and very high timeout values).]]></help>
|
||||
</field>
|
||||
</form>
|
||||
@@ -2815,5 +2815,81 @@
|
||||
</hostname>
|
||||
</mailer>
|
||||
</mailers>
|
||||
<maintenance>
|
||||
<cronjobs>
|
||||
<syncCerts type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</syncCerts>
|
||||
<syncCertsCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</syncCertsCron>
|
||||
<updateOcsp type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</updateOcsp>
|
||||
<updateOcspCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</updateOcspCron>
|
||||
<reloadService type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</reloadService>
|
||||
<reloadServiceCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</reloadServiceCron>
|
||||
<restartService type="BooleanField">
|
||||
<default>0</default>
|
||||
<Required>N</Required>
|
||||
</restartService>
|
||||
<restartServiceCron type="ModelRelationField">
|
||||
<Model>
|
||||
<queues>
|
||||
<source>OPNsense.Cron.Cron</source>
|
||||
<items>jobs.job</items>
|
||||
<display>description</display>
|
||||
<filters>
|
||||
<origin>/HAProxy/</origin>
|
||||
</filters>
|
||||
</queues>
|
||||
</Model>
|
||||
<ValidationMessage>Related cron not found.</ValidationMessage>
|
||||
<Required>N</Required>
|
||||
</restartServiceCron>
|
||||
</cronjobs>
|
||||
</maintenance>
|
||||
</items>
|
||||
</model>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{#
|
||||
|
||||
Copyright (C) 2016-2017 Frank Wall
|
||||
Copyright (C) 2016-2021 Frank Wall
|
||||
OPNsense® is Copyright © 2014 – 2015 by Deciso B.V.
|
||||
All rights reserved.
|
||||
|
||||
|
||||
@@ -28,6 +28,72 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
#}
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
|
||||
// Get cronjobs
|
||||
var cronjobs_data_get_map = {'frm_cronjobs':"/api/haproxy/maintenance/get"};
|
||||
// load initial data
|
||||
mapDataToFormUI(cronjobs_data_get_map).done(function(data){
|
||||
// Add link to cron job edit page: First iterate over all cron settings.
|
||||
// FIXME: Oh boy, this is ugly. Should be refactored.
|
||||
$.each(data.frm_cronjobs.haproxy.maintenance.cronjobs, function(key, value) {
|
||||
// Check if cron setting is enabled.
|
||||
if (value == 1) {
|
||||
// Find the matching cron job reference.
|
||||
cron_cfg = key + 'Cron';
|
||||
$.each(data.frm_cronjobs.haproxy.maintenance.cronjobs, function(cronkey, cronvalue) {
|
||||
// Check if it is the correct entry for this cron setting.
|
||||
if (cronkey == cron_cfg) {
|
||||
// Get the cron job UUID.
|
||||
$.each(cronvalue, function(refkey, refvalue) {
|
||||
// Only the "selected" item belongs to this entry.
|
||||
if (refvalue.selected == 1) {
|
||||
// Find the correct container for this cron setting.
|
||||
content_id = "[id=\"haproxy.maintenance.cronjobs." + key + "\"]";
|
||||
$(content_id).each(function(){
|
||||
// Finally add the link to the cron job edit page.
|
||||
cron_link = "<br><a href=\"/ui/cron/item/open/" + refkey + "\"><span class=\"fa fa-pencil\"></span> {{ lang._('Configure cron job') }}</a>";
|
||||
$(this).closest("td").append(cron_link);
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
formatTokenizersUI();
|
||||
$('.selectpicker').selectpicker('refresh');
|
||||
});
|
||||
|
||||
// Save & reconfigure cron to activate changes
|
||||
$('[id*="saveAndReconfigureAct"]').each(function(){
|
||||
$(this).click(function(){
|
||||
// set progress animation
|
||||
$('[id*="saveAndReconfigureAct_progress"]').each(function(){
|
||||
$(this).addClass("fa fa-spinner fa-pulse");
|
||||
});
|
||||
|
||||
// extract the form id from the button id
|
||||
var frm_id = "frm_" + $(this).attr("id").split('_')[1]
|
||||
|
||||
// save data for this tab
|
||||
saveFormToEndpoint(url="/api/haproxy/maintenance/set",formid=frm_id,callback_ok=function(){
|
||||
// Handle cron integration
|
||||
ajaxCall(url="/api/haproxy/maintenance/fetchCronIntegration", sendData={}, callback=function(data,status) {
|
||||
});
|
||||
|
||||
// when done, disable progress animation
|
||||
$('[id*="saveAndReconfigureAct_progress"]').each(function(){
|
||||
$(this).removeClass("fa fa-spinner fa-pulse");
|
||||
// reload page to show or hide links to cron edit page
|
||||
setTimeout(function () {
|
||||
window.location.reload(true)
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// grid-certificates
|
||||
function syncErrorMessage(modified, deleted) {
|
||||
message = ``;
|
||||
@@ -64,7 +130,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
$.post('/api/haproxy/maintenance/certDiff', payload, function(data) {
|
||||
BootstrapDialog.show({
|
||||
type: BootstrapDialog.TYPE_INFO,
|
||||
title: "{{ lang._('Diff between configured and active ssl certificates') }}",
|
||||
title: "{{ lang._('Diff between configured and active SSL certificates') }}",
|
||||
message: `<pre>${data}</pre>`,
|
||||
buttons: [{
|
||||
label: '{{ lang._('Close') }}',
|
||||
@@ -80,7 +146,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
$.post('/api/haproxy/maintenance/certActions', payload, function(data_actions) {
|
||||
question = ''
|
||||
question += `<pre>${data_actions}</pre>`;
|
||||
question += '<b>{{ lang._('Apply ssl certificates to HaProxy?') }}</b></br></br>';
|
||||
question += '<b>{{ lang._('Apply SSL certificates to HAProxy?') }}</b></br></br>';
|
||||
|
||||
stdDialogConfirm('{{ lang._('Confirmation Required') }}',
|
||||
question,
|
||||
@@ -92,7 +158,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
var error_msg = syncErrorMessage(data.result.modified, data.result.deleted);
|
||||
BootstrapDialog.show({
|
||||
type: BootstrapDialog.TYPE_DANGER,
|
||||
title: "{{ lang._('Error applying ssl certificates to HAProxy') }}",
|
||||
title: "{{ lang._('Error applying SSL certificates to HAProxy') }}",
|
||||
message: error_msg,
|
||||
buttons: [{
|
||||
label: '{{ lang._('Close') }}',
|
||||
@@ -124,8 +190,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
formatters: {
|
||||
"commands": function (column, row) {
|
||||
buttons = ""
|
||||
buttons += "<button type=\"button\" data-action=\"showDiff\" title=\"{{ lang._('Show diff between configured ssl certificates and certificates from HAProxy memory.') }}\" class=\"btn btn-xs btn-default\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-info-circle\"></span></button>"
|
||||
buttons += " <button type=\"button\" data-action=\"applyDiff\" title=\"{{ lang._('Apply diff and sync certificates into HAProxy memory.') }}\" class=\"btn btn-xs btn-default\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-refresh\"></span></button>"
|
||||
buttons += "<button type=\"button\" data-action=\"showDiff\" title=\"{{ lang._('Show diff') }}\" class=\"btn btn-xs btn-default\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-info-circle\"></span></button>"
|
||||
buttons += " <button type=\"button\" data-action=\"applyDiff\" title=\"{{ lang._('Apply changes') }}\" class=\"btn btn-xs btn-default\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-refresh\"></span></button>"
|
||||
return buttons;
|
||||
},
|
||||
},
|
||||
@@ -202,7 +268,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
var error_msg = syncErrorMessage(data.result.modified, data.result.deleted);
|
||||
BootstrapDialog.show({
|
||||
type: BootstrapDialog.TYPE_DANGER,
|
||||
title: "{{ lang._('Error applying ssl certificates to HAProxy') }}",
|
||||
title: "{{ lang._('Error applying SSL certificates to HAProxy') }}",
|
||||
message: error_msg,
|
||||
buttons: [{
|
||||
label: '{{ lang._('Close') }}',
|
||||
@@ -234,10 +300,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
formatters: {
|
||||
"commands": function (column, row) {
|
||||
buttons = ""
|
||||
buttons += "<button type=\"button\" title=\"{{ lang._('Set administrative state to ready. Puts the server in normal mode.') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"ready\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-check\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Set administrative state to drain. Removes the server from load balancing but still allows it to be health checked and to accept new persistent connections') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"drain\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-sort-amount-desc\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Set administrative state to maintenance. Disables any traffic to the server as well as any health checks.') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"maint\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-wrench\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Change server weight.') }}\" class=\"btn btn-xs btn-default command-set-weight\" data-weight=\"" + row.weight + "\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-balance-scale\"></span></button>"
|
||||
buttons += "<button type=\"button\" title=\"{{ lang._('Set state to ready') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"ready\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-check\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Set state to drain') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"drain\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-sort-amount-desc\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Set state to maintenance') }}\" class=\"btn btn-xs btn-default command-set-state\" data-state=\"maint\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-wrench\"></span></button>"
|
||||
buttons += " <button type=\"button\" title=\"{{ lang._('Change server weight') }}\" class=\"btn btn-xs btn-default command-set-weight\" data-weight=\"" + row.weight + "\" data-row-id=\"" + row.id + "\"><span class=\"fa fa-balance-scale\"></span></button>"
|
||||
return buttons;
|
||||
},
|
||||
},
|
||||
@@ -344,7 +410,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
});
|
||||
question += '</ul>';
|
||||
question += '<b>{{ lang._('State: ') }}' + state + '</b></br></br>';
|
||||
question += '{{ lang._('Set administrative state for all selected server?') }} </br></br>';
|
||||
question += '{{ lang._('Set administrative state for all selected servers?') }} </br></br>';
|
||||
|
||||
stdDialogConfirm('{{ lang._('Confirmation Required') }}',
|
||||
question,
|
||||
@@ -389,7 +455,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
question += '<div class="form-group" style="display: block;">';
|
||||
question += '<input class="form-control" id="newBulkWeight" value="" type="text"/>';
|
||||
question += '</div>';
|
||||
question += '{{ lang._('Set weight for all selected server?') }} </br></br>';
|
||||
question += '{{ lang._('Set weight for all selected servers?') }} </br></br>';
|
||||
|
||||
stdDialogConfirm('{{ lang._('Confirmation Required') }}',
|
||||
question,
|
||||
@@ -425,12 +491,24 @@ 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()
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<ul class="nav nav-tabs" role="tablist" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#server"><b>{{ lang._('Server') }}</b></a></li>
|
||||
<li class="active"><a data-toggle="tab" href="#server"><b>{{ lang._('Servers') }}</b></a></li>
|
||||
<li><a data-toggle="tab" href="#ssl-certs"><b>{{ lang._('SSL Certificates') }}</b></a></li>
|
||||
<li><a data-toggle="tab" href="#cronjobs"><b>{{ lang._('Cron Jobs') }}</b></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="content-box tab-content">
|
||||
@@ -440,11 +518,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="id" data-type="string" data-identifier="true" data-visible="false">{{ lang._('id') }}</th>
|
||||
<th data-column-id="pxname" data-type="string">{{ lang._('Proxy') }}</th>
|
||||
<th data-column-id="svname" data-type="string">{{ lang._('Server') }}</th>
|
||||
<th data-column-id="pxname" data-width="9em" data-type="string">{{ lang._('Virtual Service') }}</th>
|
||||
<th data-column-id="svname" data-width="9em" data-type="string">{{ lang._('Real Server') }}</th>
|
||||
<th data-column-id="addr" data-type="string">{{ lang._('Address') }}</th>
|
||||
<th data-column-id="status" data-type="string">{{ lang._('Status') }}</th>
|
||||
<th data-column-id="check_status" data-type="string">{{ lang._('Check Status') }}</th>
|
||||
<th data-column-id="check_status" data-width="8em" data-type="string">{{ lang._('Check Status') }}</th>
|
||||
<th data-column-id="weight" data-type="string">{{ lang._('Weight') }}</th>
|
||||
<th data-column-id="scur" data-type="string">{{ lang._('Sessions') }}</th>
|
||||
<th data-column-id="bin" data-type="string">{{ lang._('Bytes in') }}</th>
|
||||
@@ -461,14 +539,24 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set administrative state to ready for all selected items.') }}" data-state="ready" type="button" class="btn btn-xs btn-default"><span class="fa fa-check"></span></button>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set administrative state to drain for all selected items.') }}" data-state="drain" type="button" class="btn btn-xs btn-default"><span class="fa fa-sort-amount-desc"></span></button>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set administrative state to maintenance for all selected items.') }}" data-state="maint" type="button" class="btn btn-xs btn-default"><span class="fa fa-wrench"></span></button>
|
||||
<button data-action="setWeightBulk" title="{{ lang._('Change server weight for all selected items.') }}" data-weight="" type="button" class="btn btn-xs btn-default"><span class="fa fa-balance-scale"></span></button>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set state to ready (bulk)') }}" data-state="ready" type="button" class="btn btn-xs btn-default"><span class="fa fa-check"></span></button>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set state to drain (bulk)') }}" data-state="drain" type="button" class="btn btn-xs btn-default"><span class="fa fa-sort-amount-desc"></span></button>
|
||||
<button data-action="setStateBulk" title="{{ lang._('Set state to maintenance (bulk)') }}" data-state="maint" type="button" class="btn btn-xs btn-default"><span class="fa fa-wrench"></span></button>
|
||||
<button data-action="setWeightBulk" title="{{ lang._('Change server weight (bulk)') }}" data-weight="" type="button" class="btn btn-xs btn-default"><span class="fa fa-balance-scale"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="col-md-12">
|
||||
<p>{{ lang._("%sChoose a command to change a server's state in runtime:%s") | format('<b>', '</b>') }}</p>
|
||||
<ul>
|
||||
<li><span class="fa fa-check"></span> {{ lang._('%sSet state to ready:%s This puts the server in normal mode.') | format('<b>', '</b>') }}</li>
|
||||
<li><span class="fa fa-sort-amount-desc"></span> {{ lang._('%sSet state to drain:%s This removes the server from load balancing. Health checks will continue to run and it still accepts new persistent connections.') | format('<b>', '</b>') }}</li>
|
||||
<li><span class="fa fa-wrench"></span> {{ lang._('%sSet state to maintenance:%s This disables any traffic to the server. Health checks will also be disabled.') | format('<b>', '</b>') }}</li>
|
||||
<li><span class="fa fa-balance-scale"></span> {{ lang._("%sChange server weight:%s Adjust the server's weight relative to other servers. Servers will receive a load proportional to their weight.") | format('<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._('%sNOTE:%s These changes will not be persisted across restarts of HAProxy.') | format('<b>', '</b>') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="ssl-certs" class="tab-pane fade in">
|
||||
@@ -490,8 +578,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="showDiffBulk" title="{{ lang._('Show diff between configured ssl certificates and certificates from HAProxy memory for selected frontends.') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-info-circle"></span></button>
|
||||
<button data-action="applyDiffBulk" title="{{ lang._('Apply diff and sync certificates into HAProxy memory for selected frontends.') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-refresh"></span></button>
|
||||
<button data-action="showDiffBulk" title="{{ lang._('Show diff (bulk)') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-info-circle"></span></button>
|
||||
<button data-action="applyDiffBulk" title="{{ lang._('Apply changes (bulk)') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-refresh"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
@@ -502,6 +590,29 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<br/>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<p>{{ lang._("%sApply SSL certificate changes in runtime:%s") | format('<b>', '</b>') }}</p>
|
||||
<ul>
|
||||
<li><span class="fa fa-info-circle"></span> {{ lang._('%sShow diff:%s Show difference between configured SSL certificates and SSL certificates from the running HAProxy service.') | format('<b>', '</b>') }}</li>
|
||||
<li><span class="fa fa-refresh"></span> {{ lang._('%sApply changes:%s Apply all changes by syncing all shown SSL certificates into running HAProxy service.') | format('<b>', '</b>') }}</li>
|
||||
</ul>
|
||||
<p>{{ lang._('%sNOTE:%s Changes can only be applied for Public Services that already exist in the running HAProxy service. When adding or removing Public Services HAProxy must be reloaded or restarted.') | format('<b>', '</b>') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="cronjobs" class="tab-pane fade in">
|
||||
<div class="content-box" style="padding-bottom: 1.5em;">
|
||||
{{ partial("layout_partials/base_form",['fields':maintenanceCronjobsForm,'id':'frm_cronjobs'])}}
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<button class="btn btn-primary" id="saveAndReconfigureAct_cronjobs" type="button"><b>{{ lang._('Apply') }}</b> <i id="saveAndReconfigureAct_progress"></i></button>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<br/>
|
||||
{{ lang._('%sNOTE:%s When enabling multiple cron jobs, please adjust them so that they do not run at the same time. Check the %scron settings page%s for more cron job details and additional customization options.') | format('<b>', '</b>', '<a href="/ui/cron">', '</a>') }}
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2018 Frank Wall
|
||||
* Copyright (C) 2016-2021 Frank Wall
|
||||
* Copyright (C) 2015 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
|
||||
@@ -113,7 +113,7 @@ command:configctl template reload OPNsense/HAProxy 2 > /dev/null; /usr/local/opn
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Sync ssl certificates into HAProxy memory for all frontends
|
||||
description:Sync ssl certificates changes into HAProxy memory
|
||||
description:Sync SSL certificate changes into running HAProxy service
|
||||
|
||||
[showconf]
|
||||
command:test -f /usr/local/etc/haproxy.conf.staging && cat /usr/local/etc/haproxy.conf.staging
|
||||
|
||||
@@ -836,8 +836,8 @@ userlist {{object.name | regex_replace ("[^A-Za-z0-9]","")}}
|
||||
{#- ############################### -#}
|
||||
|
||||
global
|
||||
{# # NOTE: Running as root could be a security issue, but is required for some features. #}
|
||||
{% if OPNsense.HAProxy.general.tuning.root != "1" %}
|
||||
# NOTE: Could be a security issue, but required for some feature.
|
||||
uid 80
|
||||
{% endif %}
|
||||
gid 80
|
||||
@@ -1106,11 +1106,11 @@ resolvers {{resolver.id}}
|
||||
# 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
|
||||
@@ -1518,10 +1518,10 @@ backend {{backend.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 %}
|
||||
{% if server_data.type|default("") == 'template' %}
|
||||
{% do server_basics.append('server-template ' ~ server_data.name ~ ' ' ~ server_data.number ~ ' ' ~ server_data.serviceName) %}
|
||||
{% else %}
|
||||
{% do server_basics.append('server ' ~ server_data.name ~ ' ' ~ server_data.address) %}
|
||||
{% endif %}
|
||||
{# # collect optional server parameters #}
|
||||
{% set server_options = [] %}
|
||||
@@ -1627,11 +1627,15 @@ backend {{backend.name}}
|
||||
{% if backend.linkedResolver|default("") != "" %}
|
||||
{# # prefer backend configuration #}
|
||||
{% set resolver_id = backend.linkedResolver %}
|
||||
{% set resolver_opts = backend.resolverOpts %}
|
||||
{% if backend.resolverOpts|default("") != "" %}
|
||||
{% set resolver_opts = backend.resolverOpts %}
|
||||
{% endif %}
|
||||
{% 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 %}
|
||||
{% if server_data.resolverOpts|default("") != "" %}
|
||||
{% set resolver_opts = server_data.resolverOpts %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if resolver_id != '' %}
|
||||
{% set resolver_data = helpers.getUUID(resolver_id) %}
|
||||
|
||||
Reference in New Issue
Block a user