Skip to content

v9.3 feat: OPNsense standalone import module#4761

Draft
tpurschke wants to merge 26 commits into
CactuseSecurity:developfrom
tpurschke:feat/opnsense-import-module
Draft

v9.3 feat: OPNsense standalone import module#4761
tpurschke wants to merge 26 commits into
CactuseSecurity:developfrom
tpurschke:feat/opnsense-import-module

Conversation

@tpurschke

@tpurschke tpurschke commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Cherry-picks the new OPNsense (25ff) import module from #4742 onto develop, isolated to just the importer module plus the minimal wiring needed to make it functional.

Big thanks to our first time contributor https://github.com/nox-x !

Adds initial support for importing OPNsense firewall configs via the full config.xml core backup API.

What's included

  • New roles/importer/files/importer/fw_modules/opnsense25ff/ importer package (parser, normalizer, sanitizer, model, helper, fwcommon)
  • Wire OPNsense25common into common.get_module dispatch (package name opnsensestandalone25ff)
  • Register OPNsense standalone / 25ff device type (dev_typ_id=30) in fworch-fill-stm.sql
  • Add importer dependencies xmltodict and netaddr_pydantic to requirements.txt
  • Add OPNsense importer API documentation

What's intentionally NOT included

Only the opnsense25ff module and its required wiring were picked from #4742. The unrelated dependency version downgrades present in that branch (it predates current develop) were excluded.

Notes / open TODOs (carried over from #4742)

This is an initial, still-WIP module. Known open items from the source PR:

  • rule_num updates after rule sequence changes emit value-mismatch warnings
  • handling of FWO services vs. OPNsense aliases needs improvement
  • NAT rule normalization/import not yet implemented
  • test coverage could be increased
  • sample config file (demo/test purposes) could be added

tpurschke and others added 2 commits June 14, 2026 06:53
Adds an initial OPNsense (25ff) firewall importer that reads the full
config.xml core backup via the OPNsense API, cherry-picked from CactuseSecurity#4742.

- new fw_modules/opnsense25ff importer package (parser, normalizer,
  sanitizer, model, helper, fwcommon)
- wire OPNsense25common into common.get_module dispatch
- register 'OPNsense standalone' 25ff device type in stm_dev_typ
- add xmltodict and netaddr_pydantic importer dependencies
- add OPNsense importer API documentation

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Introduce version 9.3 with upgrade/9.3.sql registering the
'OPNsense standalone' 25ff device type so existing installs pick up
the new import module on upgrade.

- add roles/database/files/upgrade/9.3.sql (stm_dev_typ id 30)
- bump product_version 9.1.7 -> 9.3
- record 9.3 in develop revision history and version-feature overview

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tpurschke tpurschke marked this pull request as draft June 14, 2026 06:25
@tpurschke tpurschke requested a review from Y4nnikH June 14, 2026 20:31
@tpurschke

Copy link
Copy Markdown
Contributor Author

@Y4nnikH could you have a preliminary look at this new (externally provided, see PR #4742) import module?

@tpurschke tpurschke changed the title feat: add OPNsense standalone import module v9.4 feat: OPNsense standalone import module Jun 14, 2026
@tpurschke tpurschke changed the title v9.4 feat: OPNsense standalone import module v9.3 feat: OPNsense standalone import module Jun 14, 2026
@tpurschke tpurschke self-assigned this Jun 15, 2026
@nox-x

nox-x commented Jun 17, 2026

Copy link
Copy Markdown
diff --git a/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py b/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
index 5cbe2912e..4d93353b0 100644
--- a/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
+++ b/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
@@ -22,7 +22,6 @@ from fw_modules.opnsense25ff.opnsense_model import (
 from fw_modules.opnsense25ff.opnsense_parser import parse_opnsense_config
 from fwo_base import ConfigAction, sort_and_join
 from fwo_base import generate_hash_from_dict as fwo_base_generate_hash_from_dict
-from fwo_const import RULE_NUM_NUMERIC_STEPS
 from fwo_log import FWOLogger
 from model_controllers.fwconfigmanagerlist_controller import FwConfigManagerListController
 from model_controllers.import_state_controller import ImportStateController
@@ -558,7 +557,6 @@ def _upsert_rulebase_rule(
 
 def _create_rulebases_from_access_rules(os_config: OPNsenseConfig, mgm_uid: str) -> list[Rulebase]:
     rbs_dict: dict[str, Rulebase] = {}
-    rule_num = 0
 
     for rule in os_config.access_rules:
         r_normalized = _create_normalized_rule_from_access_rule(rule)
@@ -566,10 +564,6 @@ def _create_rulebases_from_access_rules(os_config: OPNsenseConfig, mgm_uid: str)
         if rule_uid is None:
             FWOLogger.warning(f"[*] skipping OPNsense rule without uid:\n    {rule}")
             continue
-        # update rule priority
-        r_normalized.rule_num = int(rule_num)
-        r_normalized.rule_num_numeric = float(rule_num)
-        rule_num += RULE_NUM_NUMERIC_STEPS
         rulebase_name = _access_rule_rulebase_name(rule, os_config)
         if rulebase_name is not None:
             _upsert_rulebase_rule(rbs_dict, rulebase_name, mgm_uid, rule_uid, r_normalized)

would fix this open issue:

rule_num updates after rule sequence changes emit value-mismatch warnings

impact:

  • rule_num_numeric is calculated by import controller
  • rule_num remains 0 from a database perspective

I'm currently not sure if suppressing the warnings is worth this impact.

@tpurschke

Copy link
Copy Markdown
Contributor Author
diff --git a/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py b/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
index 5cbe2912e..4d93353b0 100644
--- a/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
+++ b/roles/importer/files/importer/fw_modules/opnsense25ff/opnsense_normalizer.py
@@ -22,7 +22,6 @@ from fw_modules.opnsense25ff.opnsense_model import (
 from fw_modules.opnsense25ff.opnsense_parser import parse_opnsense_config
 from fwo_base import ConfigAction, sort_and_join
 from fwo_base import generate_hash_from_dict as fwo_base_generate_hash_from_dict
-from fwo_const import RULE_NUM_NUMERIC_STEPS
 from fwo_log import FWOLogger
 from model_controllers.fwconfigmanagerlist_controller import FwConfigManagerListController
 from model_controllers.import_state_controller import ImportStateController
@@ -558,7 +557,6 @@ def _upsert_rulebase_rule(
 
 def _create_rulebases_from_access_rules(os_config: OPNsenseConfig, mgm_uid: str) -> list[Rulebase]:
     rbs_dict: dict[str, Rulebase] = {}
-    rule_num = 0
 
     for rule in os_config.access_rules:
         r_normalized = _create_normalized_rule_from_access_rule(rule)
@@ -566,10 +564,6 @@ def _create_rulebases_from_access_rules(os_config: OPNsenseConfig, mgm_uid: str)
         if rule_uid is None:
             FWOLogger.warning(f"[*] skipping OPNsense rule without uid:\n    {rule}")
             continue
-        # update rule priority
-        r_normalized.rule_num = int(rule_num)
-        r_normalized.rule_num_numeric = float(rule_num)
-        rule_num += RULE_NUM_NUMERIC_STEPS
         rulebase_name = _access_rule_rulebase_name(rule, os_config)
         if rulebase_name is not None:
             _upsert_rulebase_rule(rbs_dict, rulebase_name, mgm_uid, rule_uid, r_normalized)

would fix this open issue:

rule_num updates after rule sequence changes emit value-mismatch warnings

impact:

* `rule_num_numeric` is calculated by import controller

* `rule_num` remains `0` from a database perspective

I'm currently not sure if suppressing the warnings is worth this impact.

thanks, as rule_num is deprecated and will be removed, you patch is perfectly fine.

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants