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: