mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-15 09:04:39 +00:00
Firewall: Diagnostics: States Dump - refactor to MVC.
o add api endpoint and ui to kill states using filter (kill by host or network as well) o show ruleids in service control spot to filter states for a specific (auto-generated) rule o support passing a ruleid to the ui page to limit selection, e.g. /ui/diagnostics/firewall/states#d0953c4424f27d5249027086b4599999
This commit is contained in:
parent
512b83463b
commit
63bdff8cf3
@ -166,16 +166,20 @@ class FirewallController extends ApiControllerBase
|
||||
}
|
||||
]);
|
||||
$searchPhrase = '';
|
||||
$ruleLabel = '';
|
||||
$ruleId = '';
|
||||
$itemsPerPage = $this->request->getPost('rowCount', 'int', 9999);
|
||||
$currentPage = $this->request->getPost('current', 'int', 1);
|
||||
|
||||
if ($this->request->getPost('ruleid', 'string', '') != '') {
|
||||
$ruleId = $filter->sanitize($this->request->getPost('ruleid'), 'query');
|
||||
}
|
||||
|
||||
if ($this->request->getPost('searchPhrase', 'string', '') != '') {
|
||||
$searchPhrase = $filter->sanitize($this->request->getPost('searchPhrase'), 'query');
|
||||
}
|
||||
|
||||
$response = (new Backend())->configdpRun('filter list states', [$searchPhrase, $itemsPerPage,
|
||||
($currentPage - 1) * $itemsPerPage, $ruleLabel]);
|
||||
($currentPage - 1) * $itemsPerPage, $ruleId]);
|
||||
$response = json_decode($response, true);
|
||||
if ($response != null) {
|
||||
foreach ($response['details'] as &$row) {
|
||||
@ -214,4 +218,51 @@ class FirewallController extends ApiControllerBase
|
||||
}
|
||||
return ['result' => ""];
|
||||
}
|
||||
|
||||
/**
|
||||
* drop pf states by filter and/or rule id
|
||||
*/
|
||||
public function killStatesAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$filter = new Filter([
|
||||
'query' => function ($value) {
|
||||
return preg_replace("/[^0-9,a-z,A-Z, ,\/,*,\-,_,.,\#]/", "", $value);
|
||||
},
|
||||
'hexval' => function ($value) {
|
||||
return preg_replace("/[^0-9,a-f,A-F]/", "", $value);
|
||||
}
|
||||
]);
|
||||
$ruleid = null;
|
||||
$filterString = null;
|
||||
if (!empty($this->request->getPost('filter'))) {
|
||||
$filterString = $filter->sanitize($this->request->getPost('filter'), 'query');
|
||||
}
|
||||
if (!empty($this->request->getPost('ruleid'))) {
|
||||
$ruleid = $filter->sanitize($this->request->getPost('ruleid'), 'hexval');
|
||||
}
|
||||
if ($filterString != null || $ruleid != null) {
|
||||
$response = (new Backend())->configdpRun("filter kill states", [$filterString, $ruleid]);
|
||||
$response = json_decode($response, true);
|
||||
if ($response != null) {
|
||||
return ["result" => "ok", "dropped_states" => $response['dropped_states']];
|
||||
}
|
||||
}
|
||||
}
|
||||
return ["result" => "failed"];
|
||||
}
|
||||
|
||||
/**
|
||||
* return rule'ids and descriptions from running config
|
||||
*/
|
||||
public function listRuleIdsAction()
|
||||
{
|
||||
if ($this->request->isGet()) {
|
||||
$response = json_decode((new Backend())->configdpRun("filter list rule_ids"), true);
|
||||
if ($response != null) {
|
||||
return ["items" => $response];
|
||||
}
|
||||
}
|
||||
return ["items" => []];
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +177,7 @@
|
||||
<pattern>ui/diagnostics/firewall/states*</pattern>
|
||||
<pattern>api/diagnostics/firewall/query_states*</pattern>
|
||||
<pattern>api/diagnostics/firewall/del_state*</pattern>
|
||||
<pattern>api/diagnostics/firewall/kill_states*</pattern>
|
||||
</patterns>
|
||||
</page-diagnostics-showstates>
|
||||
<page-diagnostics-statessummary>
|
||||
|
||||
@ -68,17 +68,86 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
},
|
||||
requestHandler:function(request){
|
||||
if ($("#ruleid").val() != "") {
|
||||
request['ruleid'] = $("#ruleid").val();
|
||||
}
|
||||
return request;
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
grid_states.on('loaded.rs.jquery.bootgrid', function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
if ($(".search-field").val() !== "") {
|
||||
$("#actKillStates").show();
|
||||
} else {
|
||||
$("#actKillStates").hide();
|
||||
}
|
||||
});
|
||||
|
||||
// collect rule id's
|
||||
ajaxGet("/api/diagnostics/firewall/list_rule_ids", {}, function(data, status){
|
||||
if (data.items) {
|
||||
for (let i=0; i < data.items.length ; ++i) {
|
||||
$("#ruleid").append($("<option/>").val(data.items[i]['id']).text(data.items[i]['descr']));
|
||||
}
|
||||
$("#service_status_container").append($("#ruleid"));
|
||||
$("#ruleid").change(function(){
|
||||
$("#grid-states").bootgrid("reload");
|
||||
});
|
||||
let init_state = window.location.hash.substr(1);
|
||||
if (init_state) {
|
||||
$("#ruleid").val(init_state);
|
||||
$("#ruleid").change();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#actKillStates").click(function(){
|
||||
BootstrapDialog.show({
|
||||
type:BootstrapDialog.TYPE_DANGER,
|
||||
title: "{{ lang._('Delete all filtered states') }}",
|
||||
message: "{{ lang._('Are you sure you do want to kill all states matching the provided search criteria?') }}",
|
||||
buttons: [{
|
||||
label: "{{ lang._('No') }}",
|
||||
action: function(dialogRef) {
|
||||
dialogRef.close();
|
||||
}}, {
|
||||
label: "{{ lang._('Yes') }}",
|
||||
action: function(dialogRef) {
|
||||
let params = {'filter': $(".search-field").val()};
|
||||
if ($("#ruleid").val() != "") {
|
||||
params['ruleid'] = $("#ruleid").val();
|
||||
}
|
||||
ajaxCall('/api/diagnostics/firewall/kill_states/', params, function(data, status){
|
||||
$("#grid-states").bootgrid("reload");
|
||||
dialogRef.close();
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
// move kill states button
|
||||
$("div.search.form-group").before($("#actKillStates"));
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<div style="display:none">
|
||||
<div class="btn-group" id="actKillStates" style="margin-right:20px;">
|
||||
<button class="btn btn-danger" style="cursor: pointer;" data-toggle="tooltip" title="{{ lang._('kill all matched states') }}">
|
||||
<span class="fa fa-remove"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<select id="ruleid">
|
||||
<option value="">{{ lang._("select rule") }}</option>
|
||||
</select>
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#grid-states">{{ lang._('States') }}</a></li>
|
||||
</ul>
|
||||
|
||||
52
src/opnsense/scripts/filter/kill_states.py
Executable file
52
src/opnsense/scripts/filter/kill_states.py
Executable file
@ -0,0 +1,52 @@
|
||||
#!/usr/local/bin/python3
|
||||
|
||||
"""
|
||||
Copyright (c) 2021 Ad Schellevis <ad@opnsense.org>
|
||||
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.
|
||||
"""
|
||||
import argparse
|
||||
import ujson
|
||||
import subprocess
|
||||
from lib.states import query_states
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
result = dict()
|
||||
# parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--filter', help='filter results', default='')
|
||||
parser.add_argument('--label', help='label / rule id', default='')
|
||||
inputargs = parser.parse_args()
|
||||
|
||||
# collect all unique state id's
|
||||
commands = dict()
|
||||
for record in query_states(rule_label=inputargs.label, filter_str=inputargs.filter):
|
||||
commands[record['id']] = "/sbin/pfctl -k id -k %s" % record['id']
|
||||
|
||||
# drop list of states in chunks
|
||||
chunk_size = 500
|
||||
commands = list(commands.values())
|
||||
for chunk in [commands[i:i + chunk_size] for i in range(0, len(commands), chunk_size)]:
|
||||
sp = subprocess.run([";\n".join(chunk)], capture_output=True, text=True, shell=True)
|
||||
print(ujson.dumps({'dropped_states': len(commands)}))
|
||||
44
src/opnsense/scripts/filter/list_rule_ids.py
Executable file
44
src/opnsense/scripts/filter/list_rule_ids.py
Executable file
@ -0,0 +1,44 @@
|
||||
#!/usr/local/bin/python3
|
||||
|
||||
"""
|
||||
Copyright (c) 2021 Ad Schellevis <ad@opnsense.org>
|
||||
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.
|
||||
"""
|
||||
import ujson
|
||||
from lib.states import fetch_rule_labels
|
||||
HEX_DIGITS = set("0123456789abcdef")
|
||||
|
||||
result = list()
|
||||
unique_ids = set()
|
||||
for record in fetch_rule_labels().values():
|
||||
if len(record['rid']) == 32 and set(record['rid']).issubset(HEX_DIGITS):
|
||||
if record['rid'] not in unique_ids:
|
||||
if record['descr'] != "":
|
||||
result.append({'id': record['rid'], 'descr': record['descr']})
|
||||
else:
|
||||
result.append({'id': record['rid'], 'descr': "-- %s" % record['rid']})
|
||||
unique_ids.add(record['rid'])
|
||||
|
||||
result = sorted(result, key=lambda k: k['descr'])
|
||||
print(ujson.dumps(result))
|
||||
@ -42,11 +42,11 @@ if __name__ == '__main__':
|
||||
parser.add_argument('--offset', help='offset results', default='')
|
||||
inputargs = parser.parse_args()
|
||||
|
||||
# apply offset and limit
|
||||
result = {
|
||||
'details': query_states(rule_label=inputargs.label, filter_str=inputargs.filter)
|
||||
}
|
||||
result['total_entries'] = len(result['details'])
|
||||
# apply offset and limit
|
||||
if inputargs.offset.isdigit():
|
||||
result['details'] = result['details'][int(inputargs.offset):]
|
||||
if inputargs.limit.isdigit() and len(result['details']) >= int(inputargs.limit):
|
||||
|
||||
@ -41,6 +41,11 @@ parameters: --filter=%s --limit=%s --offset=%s --label=%s
|
||||
type:script_output
|
||||
message:request pf states
|
||||
|
||||
[list.rule_ids]
|
||||
command:/usr/local/opnsense/scripts/filter/list_rule_ids.py
|
||||
parameters:
|
||||
type:script_output
|
||||
message:request active rule id's and descriptions
|
||||
|
||||
[list.pfsync]
|
||||
command:/usr/local/opnsense/scripts/filter/list_pfsync.py
|
||||
@ -114,6 +119,12 @@ parameters: -k id -k %s/%s 2>&1 && exit 0
|
||||
type:script_output
|
||||
message:kill pf state ( %s %s )
|
||||
|
||||
[kill.states]
|
||||
command:/usr/local/opnsense/scripts/filter/kill_states.py
|
||||
parameters: --filter=%s --label=%s
|
||||
type:script_output
|
||||
message:kill pf states
|
||||
|
||||
[find_table_references]
|
||||
command:/usr/local/opnsense/scripts/filter/find_table_references.py
|
||||
parameters: %s
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user