diff --git a/plist b/plist
index f864e2510..2df05c1b2 100644
--- a/plist
+++ b/plist
@@ -605,6 +605,7 @@
/usr/local/opnsense/mvc/app/models/OPNsense/Firewall/static_aliases/core.json
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/FieldTypes/PolicyContentField.php
+/usr/local/opnsense/mvc/app/models/OPNsense/IDS/FieldTypes/PolicyRulesField.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/IDS.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/Menu/Menu.xml
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php
index db0fe1bac..9d03ca039 100644
--- a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php
+++ b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php
@@ -42,6 +42,22 @@ class SettingsController extends ApiMutableModelControllerBase
{
protected static $internalModelName = 'ids';
protected static $internalModelClass = '\OPNsense\IDS\IDS';
+ private $modelHandle = null;
+
+ /**
+ * Get (or create) model object
+ * @return null|BaseModel
+ * @throws \ReflectionException
+ */
+ protected function getModel()
+ {
+ if ($this->modelHandle == null) {
+ $this->modelHandle = (new \ReflectionClass(static::$internalModelClass))->newInstance();
+ }
+
+ return $this->modelHandle;
+ }
+
/**
* Query non layered model items
@@ -699,7 +715,11 @@ class SettingsController extends ApiMutableModelControllerBase
*/
public function searchPolicyRuleAction()
{
- return $this->searchBase("rules.rule", array("sid", "enabled", "action"), "sid");
+ /* XXX: toggle search backend data for rule information as this action can be rather slow and we don't want
+ to enforce this on all callers */
+ $this->getModel()->rules->rule->queryRuleInfo();
+ $this->modelHandle = null;
+ return $this->searchBase("rules.rule", ["sid", "msg", "source", "enabled", "action"], "sid");
}
/**
@@ -762,7 +782,7 @@ class SettingsController extends ApiMutableModelControllerBase
}
/**
- * return then number of custom defined policy rules
+ * return the number of custom defined policy rules
*/
public function checkPolicyRuleAction()
{
diff --git a/src/opnsense/mvc/app/models/OPNsense/IDS/FieldTypes/PolicyRulesField.php b/src/opnsense/mvc/app/models/OPNsense/IDS/FieldTypes/PolicyRulesField.php
new file mode 100644
index 000000000..a1b8d4d5c
--- /dev/null
+++ b/src/opnsense/mvc/app/models/OPNsense/IDS/FieldTypes/PolicyRulesField.php
@@ -0,0 +1,70 @@
+configdRun('ids list rules'), true) ?? [];
+ }
+ foreach ($this->iterateItems() as $node) {
+ $rule = static::$internalRuleData[(string)$node->sid] ?? [];
+ foreach (['msg', 'source'] as $fieldname) {
+ $field = new TextField();
+ $field->setInternalIsVirtual();
+ $field->setValue($rule[$fieldname] ?? '');
+ $node->addChildNode($fieldname, $field);
+ }
+ }
+ }
+ }
+}
diff --git a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
index 5819bdd78..64dd84bf8 100644
--- a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
@@ -4,7 +4,7 @@
OPNsense IDS
-
+
Sid should be a number.
Y
diff --git a/src/opnsense/mvc/app/views/OPNsense/IDS/policy.volt b/src/opnsense/mvc/app/views/OPNsense/IDS/policy.volt
index 1bdd7a08c..e25d9e2f5 100644
--- a/src/opnsense/mvc/app/views/OPNsense/IDS/policy.volt
+++ b/src/opnsense/mvc/app/views/OPNsense/IDS/policy.volt
@@ -162,6 +162,8 @@ POSSIBILITY OF SUCH DAMAGE.
| {{ lang._('SID') }} |
{{ lang._('Enabled') }} |
+ {{ lang._('Msg') }} |
+ {{ lang._('Source') }} |
{{ lang._('Action') }} |
{{ lang._('Commands') }} |
{{ lang._('ID') }} |
diff --git a/src/opnsense/scripts/suricata/lib/rulecache.py b/src/opnsense/scripts/suricata/lib/rulecache.py
index ab4ac2040..2665cb982 100755
--- a/src/opnsense/scripts/suricata/lib/rulecache.py
+++ b/src/opnsense/scripts/suricata/lib/rulecache.py
@@ -474,3 +474,13 @@ class RuleCache(object):
result[record[0]] = list()
result[record[0]].append(record[1])
return result
+
+ def list_rule_metadata(self):
+ result = {}
+ if os.path.exists(self.cachefile):
+ db = sqlite3.connect(self.cachefile)
+ cur = db.cursor()
+ cur.execute("SELECT sid, msg, source FROM rules")
+ for record in cur.fetchall():
+ result[record[0]] = {'msg': record[1], 'source': record[2]}
+ return result
diff --git a/src/opnsense/scripts/suricata/listRuleMetadata.py b/src/opnsense/scripts/suricata/listRuleMetadata.py
index 6d9e52aa1..0d82af63c 100755
--- a/src/opnsense/scripts/suricata/listRuleMetadata.py
+++ b/src/opnsense/scripts/suricata/listRuleMetadata.py
@@ -1,7 +1,7 @@
#!/usr/local/bin/python3
"""
- Copyright (c) 2020 Ad Schellevis
+ Copyright (c) 2020-2023 Ad Schellevis
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,7 @@
script to fetch all metadata types from the installed suricata rules using the shared rule cache
"""
+import argparse
import ujson
from lib.rulecache import RuleCache
@@ -38,4 +39,11 @@ if __name__ == '__main__':
if rc.is_changed():
rc.create()
- print(ujson.dumps(rc.list_metadata()))
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--mode', help='fetch mode', default='properties', choices=['properties', 'rules'])
+ args = parser.parse_args()
+
+ if args.mode == 'properties':
+ print(ujson.dumps(rc.list_metadata()))
+ else:
+ print(ujson.dumps(rc.list_rule_metadata()))
diff --git a/src/opnsense/service/conf/actions.d/actions_ids.conf b/src/opnsense/service/conf/actions.d/actions_ids.conf
index 88a342a4a..75a31dd25 100644
--- a/src/opnsense/service/conf/actions.d/actions_ids.conf
+++ b/src/opnsense/service/conf/actions.d/actions_ids.conf
@@ -1,9 +1,15 @@
[list.rulemetadata]
command:/usr/local/opnsense/scripts/suricata/listRuleMetadata.py
-parameters:
+parameters: --mode properties
type:script_output
message:request suricata rule metadata
+[list.rules]
+command:/usr/local/opnsense/scripts/suricata/listRuleMetadata.py
+parameters: --mode rules
+type:script_output
+message:request suricata rules
+
[list.installablerulesets]
command:/usr/local/opnsense/scripts/suricata/listInstallableRulesets.py
parameters: