mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-15 00:54:41 +00:00
(ids) add action selection in rules tab, extend rule query with installed_action to represent the running configuration. closes https://github.com/opnsense/core/issues/751
This commit is contained in:
parent
16a876d045
commit
642cbe1cce
@ -108,6 +108,12 @@ class SettingsController extends ApiControllerBase
|
||||
$searchPhrase .= " classtype/".$searchTag.' ';
|
||||
}
|
||||
|
||||
// add filter for action
|
||||
if ($this->request->getPost("action", "string", '') != "") {
|
||||
$searchTag = $filter->sanitize($this->request->getPost('action'), "query");
|
||||
$searchPhrase .= " installed_action/".$searchTag.' ';
|
||||
}
|
||||
|
||||
// request list of installed rules
|
||||
$backend = new Backend();
|
||||
$response = $backend->configdpRun("ids query rules", array($itemsPerPage,
|
||||
|
||||
@ -59,6 +59,12 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* link on change event for alert "action" selectionbox
|
||||
*/
|
||||
$('#ruleaction').on('change', function(){
|
||||
$('#grid-installedrules').bootgrid('reload');
|
||||
});
|
||||
|
||||
/**
|
||||
* update list of available alert logs
|
||||
@ -84,13 +90,17 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
}
|
||||
|
||||
/**
|
||||
* Add classtype to rule filter
|
||||
* Add classtype / action to rule filter
|
||||
*/
|
||||
function addRuleFilters(request) {
|
||||
var selected =$('#ruleclass').find("option:selected").val();
|
||||
if ( selected != "") {
|
||||
request['classtype'] = selected;
|
||||
}
|
||||
var selected =$('#ruleaction').find("option:selected").val();
|
||||
if ( selected != "") {
|
||||
request['action'] = selected;
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
@ -557,8 +567,15 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
<div class="bootgrid-header container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 actionBar">
|
||||
<b>Classtype </b>
|
||||
<b>{{ lang._('Classtype') }} </b>
|
||||
<select id="ruleclass" class="selectpicker" data-width="200px"></select>
|
||||
|
||||
<b>{{ lang._('Action') }} </b>
|
||||
<select id="ruleaction" class="selectpicker" data-width="100px">
|
||||
<option value="">{{ lang._('All') }}</option>
|
||||
<option value="drop">{{ lang._('Drop') }}</option>
|
||||
<option value="alert">{{ lang._('Alert') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -30,28 +30,18 @@
|
||||
Install suricata ruleset into opnsense.rules directory
|
||||
"""
|
||||
import os.path
|
||||
from ConfigParser import ConfigParser
|
||||
import lib.rulecache
|
||||
from lib import rule_source_directory
|
||||
|
||||
if __name__ == '__main__':
|
||||
RuleCache = lib.rulecache.RuleCache()
|
||||
|
||||
rule_config_fn = ('%s../rules.config' % rule_source_directory)
|
||||
rule_target_dir = ('%s../opnsense.rules' % rule_source_directory)
|
||||
rule_yaml_list = ('%s../installed_rules.yaml' % rule_source_directory)
|
||||
|
||||
rule_config_fn = ('%s../rules.config' % rule_source_directory)
|
||||
# parse OPNsense rule config
|
||||
rule_updates = {}
|
||||
if os.path.exists(rule_config_fn):
|
||||
cnf = ConfigParser()
|
||||
cnf.read(rule_config_fn)
|
||||
for section in cnf.sections():
|
||||
if section[0:5] == 'rule_':
|
||||
sid = section[5:]
|
||||
rule_updates[sid] = {}
|
||||
for rule_item in cnf.items(section):
|
||||
rule_updates[sid][rule_item[0]] = rule_item[1]
|
||||
rule_updates = RuleCache.list_local_changes()
|
||||
|
||||
# create target rule directory if not existing
|
||||
if not os.path.exists(rule_target_dir):
|
||||
|
||||
@ -34,6 +34,7 @@ import glob
|
||||
import sqlite3
|
||||
import shlex
|
||||
import fcntl
|
||||
from ConfigParser import ConfigParser
|
||||
from lib import rule_source_directory
|
||||
|
||||
|
||||
@ -55,6 +56,24 @@ class RuleCache(object):
|
||||
|
||||
return all_rule_files
|
||||
|
||||
@staticmethod
|
||||
def list_local_changes():
|
||||
# parse OPNsense rule config
|
||||
rule_config_fn = ('%s../rules.config' % rule_source_directory)
|
||||
rule_config_mtime = os.stat(rule_config_fn).st_mtime
|
||||
rule_updates = {}
|
||||
if os.path.exists(rule_config_fn):
|
||||
cnf = ConfigParser()
|
||||
cnf.read(rule_config_fn)
|
||||
for section in cnf.sections():
|
||||
if section[0:5] == 'rule_':
|
||||
sid = section[5:]
|
||||
rule_updates[sid] = {'mtime': rule_config_mtime}
|
||||
for rule_item in cnf.items(section):
|
||||
rule_updates[sid][rule_item[0]] = rule_item[1]
|
||||
return rule_updates
|
||||
|
||||
|
||||
def list_rules(self, filename):
|
||||
""" generator function to list rule file content including metadata
|
||||
:param filename:
|
||||
@ -151,11 +170,11 @@ class RuleCache(object):
|
||||
db = sqlite3.connect(self.cachefile)
|
||||
cur = db.cursor()
|
||||
|
||||
cur.execute("CREATE TABLE stats (timestamp number, files number)")
|
||||
cur.execute("""CREATE TABLE rules (sid number, msg TEXT, classtype TEXT,
|
||||
cur.execute("create table stats (timestamp number, files number)")
|
||||
cur.execute("""create table rules (sid number, msg TEXT, classtype TEXT,
|
||||
rev INTEGER, gid INTEGER, reference TEXT,
|
||||
enabled BOOLEAN, action text, source TEXT)""")
|
||||
|
||||
cur.execute("create table local_rule_changes(sid number primary key, action text, last_mtime number)")
|
||||
last_mtime = 0
|
||||
all_rule_files = self.list_local()
|
||||
for filename in all_rule_files:
|
||||
@ -175,6 +194,36 @@ class RuleCache(object):
|
||||
# release lock
|
||||
fcntl.flock(lock, fcntl.LOCK_UN)
|
||||
|
||||
def update_local_changes(self):
|
||||
""" read local rules.config containing changes on installed ruleset and update to "local_rule_changes" table
|
||||
"""
|
||||
if os.path.exists(self.cachefile):
|
||||
db = sqlite3.connect(self.cachefile)
|
||||
cur = db.cursor()
|
||||
cur.execute('select max(last_mtime) from local_rule_changes')
|
||||
last_mtime = cur.fetchall()[0][0]
|
||||
rule_config_mtime = os.stat(('%s../rules.config' % rule_source_directory)).st_mtime
|
||||
if rule_config_mtime != last_mtime:
|
||||
# make sure only one process is updating this table
|
||||
lock = open(self.cachefile + '.LCK', 'w')
|
||||
try:
|
||||
fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
except IOError:
|
||||
# other process is already creating the cache, wait, let the other process do it's work and return.
|
||||
fcntl.flock(lock, fcntl.LOCK_EX)
|
||||
fcntl.flock(lock, fcntl.LOCK_UN)
|
||||
return
|
||||
# delete and insert local changes
|
||||
cur.execute('delete from local_rule_changes')
|
||||
local_changes = self.list_local_changes()
|
||||
for sid in local_changes:
|
||||
sql_params = (sid, local_changes[sid]['action'], local_changes[sid]['mtime'])
|
||||
cur.execute('insert into local_rule_changes(sid, action, last_mtime) values (?,?,?)', sql_params)
|
||||
db.commit()
|
||||
# release lock
|
||||
fcntl.flock(lock, fcntl.LOCK_UN)
|
||||
|
||||
|
||||
def search(self, limit, offset, filter_txt, sort_by):
|
||||
""" search installed rules
|
||||
:param limit: limit number of rows
|
||||
@ -189,9 +238,15 @@ class RuleCache(object):
|
||||
cur = db.cursor()
|
||||
|
||||
# construct query including filters
|
||||
sql = 'select * from rules '
|
||||
sql = """select *
|
||||
from (
|
||||
select rules.*, case when rc.action is null then rules.action else rc.action end installed_action
|
||||
from rules
|
||||
left join local_rule_changes rc on rules.sid = rc.sid
|
||||
) a
|
||||
"""
|
||||
sql_filters = {}
|
||||
|
||||
additional_search_fields = ['installed_action']
|
||||
for filtertag in shlex.split(filter_txt):
|
||||
fieldnames = filtertag.split('/')[0]
|
||||
searchcontent = '/'.join(filtertag.split('/')[1:])
|
||||
@ -200,7 +255,7 @@ class RuleCache(object):
|
||||
else:
|
||||
sql += ' where ( '
|
||||
for fieldname in map(lambda x: x.lower().strip(), fieldnames.split(',')):
|
||||
if fieldname in self._rule_fields:
|
||||
if fieldname in self._rule_fields or fieldname in additional_search_fields:
|
||||
if fieldname != fieldnames.split(',')[0].strip():
|
||||
sql += ' or '
|
||||
if searchcontent.find('*') == -1:
|
||||
@ -216,7 +271,7 @@ class RuleCache(object):
|
||||
# apply sort order (if any)
|
||||
sql_sort = []
|
||||
for sortField in sort_by.split(','):
|
||||
if sortField.split(' ')[0] in self._rule_fields:
|
||||
if sortField.split(' ')[0] in self._rule_fields or sortField.split(' ')[0] in additional_search_fields:
|
||||
if sortField.split(' ')[-1].lower() == 'desc':
|
||||
sql_sort.append('%s desc' % sortField.split()[0])
|
||||
else:
|
||||
|
||||
@ -45,6 +45,9 @@ if __name__ == '__main__':
|
||||
if rc.is_changed():
|
||||
rc.create()
|
||||
|
||||
# import local changes (if changed)
|
||||
rc.update_local_changes()
|
||||
|
||||
# load parameters, ignore validation here the search method only processes valid input
|
||||
parameters = {'limit': '0', 'offset': '0', 'sort_by': '', 'filter': ''}
|
||||
update_params(parameters)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user