Add frontend for:

show diff multi
apply diff multi
apply all
This commit is contained in:
Andreas Stuerz
2021-03-02 08:33:03 +01:00
parent 593c84dbb2
commit 1b96e4f16c
4 changed files with 166 additions and 70 deletions
@@ -47,6 +47,9 @@ class MaintenanceController extends ApiControllerBase
*/
public function searchCertificateDiffAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->getData(
["cert_diff_list"],
["rowCount", "current", "searchPhrase", "sort"]
@@ -59,6 +62,9 @@ class MaintenanceController extends ApiControllerBase
*/
public function searchServerAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->getData(
["server_status_list"],
["rowCount", "current", "searchPhrase", "sort"]
@@ -71,18 +77,38 @@ class MaintenanceController extends ApiControllerBase
*/
public function certSyncAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->syncCerts(
["cert_sync"],
["frontend_ids"]
);
}
/**
* sync certificate for frontends
* @return array|mixed
*/
public function certSyncBulkAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->syncCerts(
["cert_sync_bulk"]
);
}
/**
* show certificate diff for frontends
* @return array|mixed
*/
public function certDiffAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->getData(
["cert_diff"],
["frontend_ids"]
@@ -95,6 +121,9 @@ class MaintenanceController extends ApiControllerBase
*/
public function certActionsAction()
{
$backend = new Backend();
$backend->configdRun('template reload OPNsense/HAProxy');
return $this->getData(
["cert_actions"],
["frontend_ids"]
@@ -48,8 +48,10 @@ POSSIBILITY OF SUCH DAMAGE.
message += `<b>{{ lang._('REMOVE:') }} ${remove.cert}:</b></br>`;
message += `<pre>${remove.messages.join("</br>")}</pre>`;
});
message += `</br>`;
});
message += `<b>{{ lang._('CERTIFICATES:') }}</b></br></br>`;
deleted.forEach(function(del) {
message += `<b>{{ lang._('DELETE:') }} ${del.cert}:</b></br>`;
message += `<pre>${del.messages.join("</br>")}</pre>`;
@@ -58,6 +60,53 @@ POSSIBILITY OF SUCH DAMAGE.
return message;
}
function showDiffDialog(payload) {
$.post('/api/haproxy/maintenance/certDiff', payload, function(data) {
BootstrapDialog.show({
type: BootstrapDialog.TYPE_INFO,
title: "{{ lang._('Diff between configured and remote ssl certificates') }}",
message: `<pre>${data}</pre>`,
buttons: [{
label: '{{ lang._('Close') }}',
action: function(dialog){
dialog.close();
}
}]
});
});
}
function applyDiffDialog(payload, requested_count) {
$.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>';
stdDialogConfirm('{{ lang._('Confirmation Required') }}',
question,
'{{ lang._('Yes') }}', '{{ lang._('Cancel') }}', function() {
$.post('/api/haproxy/maintenance/certSync', payload, function(data) {
modified_count = data.result.add_count + data.result.remove_count + data.result.update_count;
if (requested_count != modified_count) {
var error_msg = syncErrorMessage(data.result.modified, data.result.deleted);
BootstrapDialog.show({
type: BootstrapDialog.TYPE_DANGER,
title: "{{ lang._('Error applying ssl certificates to HAProxy') }}",
message: error_msg,
buttons: [{
label: '{{ lang._('Close') }}',
action: function(dialog){
dialog.close();
}
}]
});
}
$("#grid-certificates").bootgrid("reload");
});
});
});
}
$("#grid-certificates").bootgrid('destroy');
var grid_certificates = $("#grid-certificates").UIBootgrid({
@@ -88,21 +137,7 @@ POSSIBILITY OF SUCH DAMAGE.
var payload = {
'frontend_ids': frontend_ids,
};
$.post('/api/haproxy/maintenance/certDiff', payload, function(data) {
BootstrapDialog.show({
type: BootstrapDialog.TYPE_INFO,
title: "{{ lang._('Diff between configured and remote ssl certificates') }}",
message: `<pre>${data}</pre>`,
buttons: [{
label: '{{ lang._('Close') }}',
action: function(dialog){
dialog.close();
}
}]
});
});
showDiffDialog(payload);
});
grid_certificates.find("*[data-action=applyDiff]").off().on("click", function(e) {
@@ -111,57 +146,76 @@ POSSIBILITY OF SUCH DAMAGE.
var row = rows.filter(function(row) {
return row.id == row_id;
})[0];
var requested_count = row.total_count;
var frontend_ids = row.id
var payload = {
'frontend_ids': frontend_ids,
};
$.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>';
stdDialogConfirm('{{ lang._('Confirmation Required') }}',
question,
'{{ lang._('Yes') }}', '{{ lang._('Cancel') }}', function() {
$.post('/api/haproxy/maintenance/certSync', payload, function(data) {
modified_count = data.result.add_count + data.result.remove_count + data.result.update_count;
if (requested_count != modified_count) {
var error_msg = syncErrorMessage(data.result.modified, data.result.deleted);
BootstrapDialog.show({
type: BootstrapDialog.TYPE_DANGER,
title: "{{ lang._('Error applying ssl certificates to HAProxy') }}",
message: error_msg,
buttons: [{
label: '{{ lang._('Close') }}',
action: function(dialog){
dialog.close();
}
}]
});
}
$("#grid-certificates").bootgrid("reload");
});
});
});
applyDiffDialog(payload, requested_count);
});
grid_certificates.find("*[data-action=showDiffBulk]").off().on("click", function(e) {
var rows = $("#grid-certificates").bootgrid("getSelectedRows");
console.log('Show diff for multi')
var payload = {
'frontend_ids': rows.join()
};
if (rows != undefined && rows.length > 0) {
showDiffDialog(payload);
}
});
grid_certificates.find("*[data-action=applyDiffBulk]").off().on("click", function(e) {
var rows = $("#grid-certificates").bootgrid("getSelectedRows");
console.log('Apply diff for multi')
var frontend_ids = rows.join();
var all_rows = $("#grid-certificates").bootgrid("getCurrentRows");
var requested_count = 0;
all_rows.forEach(function(row) {
if (rows.indexOf(row.id) != -1) {
requested_count = requested_count + row.total_count;
}
});
var payload = {
'frontend_ids': frontend_ids,
};
if (rows != undefined && rows.length > 0) {
applyDiffDialog(payload, requested_count);
}
});
});
// Apply all changes
$("*[data-action=applyDiffAll]").off().on("click", function(e) {
$('[id*="applyDiffAll_progress"]').each(function(){
$(this).addClass("fa fa-spinner fa-pulse");
});
var all_rows = $("#grid-certificates").bootgrid("getCurrentRows");
var requested_count = 0;
all_rows.forEach(function(row) {
requested_count = requested_count + row.total_count;
});
var payload = {};
$.post('/api/haproxy/maintenance/certSyncBulk', payload, function(data) {
modified_count = data.result.add_count + data.result.remove_count + data.result.update_count;
if (requested_count != modified_count) {
var error_msg = syncErrorMessage(data.result.modified, data.result.deleted);
BootstrapDialog.show({
type: BootstrapDialog.TYPE_DANGER,
title: "{{ lang._('Error applying ssl certificates to HAProxy') }}",
message: error_msg,
buttons: [{
label: '{{ lang._('Close') }}',
action: function(dialog){
dialog.close();
}
}]
});
}
$("#grid-certificates").bootgrid("reload");
$("#applyDiffAll_progress").removeClass("fa fa-spinner fa-pulse");
});
});
// grid-status
$("#grid-status").bootgrid('destroy');
@@ -436,12 +490,18 @@ POSSIBILITY OF SUCH DAMAGE.
<tr>
<td></td>
<td>
<button data-action="showDiff" title="{{ lang._('Show diff between configured ssl certificates and certificates from HAProxy memory.') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-info-circle"></span></button>
<button data-action="applyDiff" title="{{ lang._('Apply diff and sync certificates into HAProxy memory.') }}" type="button" class="btn btn-xs btn-default"><span class="fa fa-refresh"></span></button>
<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>
</td>
</tr>
</tfoot>
</table>
<div class="col-md-12">
<hr/>
<button data-action="applyDiffAll" class="btn btn-primary" type="button"><b>{{ lang._('Apply') }}</b><i id="applyDiffAll_progress" class=""></i></button>
<br/>
<br/>
</div>
</div>
</div>
@@ -170,22 +170,24 @@ class Diff(SyncWithTarget):
print(json.dumps(self.status))
if self.output_format == 'raw':
print("## STATUS ##")
for frontend_id, crt_list in self.status.items():
print(f"CRT_LIST: {crt_list['path']}")
print(f" FRONTEND NAME: {crt_list['frontend_name']}")
print(f" FRONTEND ID: {frontend_id}")
print(f" LOCAL CERTS: {crt_list['local_certs']}")
print(f" REMOTE CERTS: {crt_list['remote_certs']}")
print(f" LOCAL DEFAULT: {crt_list['local_default']}")
print(f" REMOTE DEFAULT: {crt_list['remote_default']}")
print(f"FRONTEND NAME: {crt_list['frontend_name']}")
print(f" CONFIG:")
for cert_id, cert in crt_list['certs'].items():
print()
print(f" CERT: {cert['path']}")
print(f" LOCAL: {cert['local']}")
print(f" REMOTE: {cert['remote']}")
print()
if cert['path'] == crt_list['local_default']:
print(f" CERT (Default):")
else:
print(f" CERT:")
print(f" Serial: {cert['local']['Serial']}")
print(f" Issuer: {cert['local']['Issuer']}")
print(f" Subject: {cert['local']['Subject']}")
print(f" ACTIVE:")
for cert in crt_list['remote_certs']:
meta = self._execute_remote_cmd(cmds.showSslCert, certfile=cert.split(":")[0])
print(f" CERT:")
print(f" Serial: {meta['Serial']}")
print(f" Issuer: {meta['Issuer']}")
print(f" Subject: {meta['Subject']}")
def show_actions(self):
""" Shows what will be synced to target """
@@ -198,18 +200,22 @@ class Diff(SyncWithTarget):
if self.output_format == 'raw':
for diff in self.diff:
print(f"FRONTEND: {diff['frontend_name']}")
print(f" CRT-LIST: {diff['path']}")
for update in diff['update']:
print(f" CERT NEW / UPDATE:")
print(f" Cert: {update['certfile']}")
print(f" Serial: {update['meta'].get('Serial', None)}")
print(f" Issuer: {update['meta'].get('Issuer', None)}")
print(f" Subject: {update['meta'].get('Subject', None)}")
print()
else:
if not diff['update']:
print(f" CERT UPDATE: []")
print(f" CERT NEW / UPDATE: []")
for add in diff['add']:
print(f" CERT ADD:")
print(f" Cert: {add['certfile']}")
print(f" Serial: {add['meta'].get('Serial', None)}")
print(f" Issuer: {add['meta'].get('Issuer', None)}")
print(f" Subject: {add['meta'].get('Subject', None)}")
@@ -220,6 +226,7 @@ class Diff(SyncWithTarget):
for remove in diff['remove']:
print(f" CERT REMOVE:")
print(f" Cert: {remove['certfile']}")
print(f" Serial: {remove['meta'].get('Serial', None)}")
print(f" Issuer: {remove['meta'].get('Issuer', None)}")
print(f" Subject: {remove['meta'].get('Subject', None)}")
@@ -227,6 +234,7 @@ class Diff(SyncWithTarget):
else:
if not diff['remove']:
print(f" CERT REMOVE: []")
print()
def show_transactions(self):
@@ -308,11 +316,10 @@ class Diff(SyncWithTarget):
'messages': messages
})
if "Success!" in output:
if "deleted in crtlist" in output:
sync['remove_count'] += 1
sync_item['remove_count'] += 1
#modified_items = sync_item['update_count'] + sync_item['add_count'] + sync_item['remove_count']
sync['modified'].append(sync_item)
# delete unused certs operation - haproxy does not allow to delete certs in use
@@ -97,7 +97,7 @@ type:script_output
message:Show diff between configured ssl certificates and certs from HAProxy memory for multiple frontends
[cert_sync]
command:/usr/local/opnsense/scripts/OPNsense/HAProxy/syncCerts.py
command:configctl template reload OPNsense/HAProxy 2 > /dev/null; /usr/local/opnsense/scripts/OPNsense/HAProxy/syncCerts.py
parameters: sync --frontend-ids %s --output json
type:script_output
message:Sync ssl certificates into HAProxy memory for multiple frontends
@@ -109,7 +109,7 @@ type:script_output
message:Show diff between configured ssl certificates and certs from HAProxy memory for all frontends
[cert_sync_bulk]
command:/usr/local/opnsense/scripts/OPNsense/HAProxy/syncCerts.py sync --output json
command:configctl template reload OPNsense/HAProxy 2 > /dev/null; /usr/local/opnsense/scripts/OPNsense/HAProxy/syncCerts.py sync --output json
parameters:
type:script_output
message:Sync ssl certificates into HAProxy memory for all frontends