This commit is contained in:
Ad Schellevis
2020-03-12 17:47:10 +01:00
parent 0e8b82886d
commit e52e381aed
5 changed files with 296 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
Firewall
~~~~~~~~
The firewall API plugin is a first step into migrating the legacy firewall components from OPNsense, although it does contain
a user interface, it's main focus is only to provide machine to machine interaction between custom applications and OPNsense
for selected features.
.. csv-table:: Resources (FilterController.php)
:header: "Method", "Module", "Controller", "Command", "Parameters"
:widths: 4, 15, 15, 30, 40
"``POST``","firewall","filter","addRule",""
"``POST``","firewall","filter","apply","$rollback_revision=null"
"``POST``","firewall","filter","cancelRollback","$rollback_revision"
"``POST``","firewall","filter","delRule","$uuid"
"``GET``","firewall","filter","getRule","$uuid=null"
"``POST``","firewall","filter","revert","$revision"
"``POST``","firewall","filter","savepoint",""
"``*``","firewall","filter","searchRule",""
"``POST``","firewall","filter","setRule","$uuid"
"``POST``","firewall","filter","toggleRule","$uuid,$enabled=null"
-----------------------
Concept
-----------------------
The firewall plugin injects rules in the standard OPNsense firewall while maintaining visibility on them in the
standard user interface.
We use our standard :code:`ApiMutableModelControllerBase` to allow crud operations on rule entries and offer a set of
specific actions to apply the new configuration.
Since firewall rules can be quite sensitive with a higher risk of lockout, we also support a rollback mechanism here,
which offers the ability to rollback this components changes.
.. blockdiag::
:scale: 100%
diagram init {
savepoint [label = "savepoint()"];
administration [label = "administration"];
apply [label = "apply(savepoint)"];
cancelRollback [label = "cancelRollback(sp)"];
savepoint -> administration -> apply ;
apply -> cancelRollback [label = ".. 60s", style = dashed];
}
The diagram above contains the basic steps to change rules, apply and eventually rollback if not being able to access the machine again.
When calling :code:`savepoint()` a new config revision will be created and the timestamp will be returned for later use.
If the :code:`cancelRollback(savepoint)` is not called within 60 seconds, the firewall will rollback to the previous state
identified by the savepoint timestamp (if available).
.. Note::
The examples in this document disable certificate validation, make sure when using this in a production environment to
remove the :code:`verify=False` from the :code:`requests` calls
.. Tip::
The number of versions kept can be configured as "backup count" in :menuselection:`System -> Configuration -> History`.
This affectively determines within how many configuration changes you can still rollback, if the backup is removed, a rollback
will keep the current state (do nothing).
-----------------------
Administration example
-----------------------
Administrative endpoints are pretty standard use of :code:`ApiMutableModelControllerBase`, the example below searches for
a rule named "OPNsense_fw_api_testrule_1", when not found one will be added otherwise it will print the internal uuid.
Inline you will find a brief description of the steps performed.
.. literalinclude:: firewall.sample_create.py
:language: python
:linenos:
:caption: administrative_example.py
.. Tip::
Since our model contains default values for most attributes, we only need to feed the changes if we would like to keep the
defaults. In this case the TCP/IP version was IPv4 by default for example. In most cases one would like to set all relevant properties
in case defaults change over time.
-----------------------
Apply / revert example
-----------------------
This example will disable the rule created in the previous example and apply the changes using a savepoint, since we're not
calling :code:`cancelRollback(savepoint)` it will revert after 60 seconds to the original state.
.. literalinclude:: firewall.savepoint.py
:language: python
:linenos:
:caption: savepoint_example.py
.. Note::
The savepoint will only revert this components changes, other changes won't be affected by this revert, for example
add an additional interface between savepoint and revert won't be affected.

View File

@@ -0,0 +1,99 @@
{{ title }}
{{ title_underline }}
The firewall API plugin is a first step into migrating the legacy firewall components from OPNsense, although it does contain
a user interface, it's main focus is only to provide machine to machine interaction between custom applications and OPNsense
for selected features.
{% for controller in controllers %}
.. csv-table:: {{controller.type}} ({{controller.filename}})
:header: "Method", "Module", "Controller", "Command", "Parameters"
:widths: 4, 15, 15, 30, 40
{% for endpoint in controller.endpoints %}
"``{{endpoint.method}}``","{{endpoint.module}}","{{endpoint.controller}}","{{endpoint.command}}","{{endpoint.parameters}}"
{%- endfor %}
{% endfor %}
-----------------------
Concept
-----------------------
The firewall plugin injects rules in the standard OPNsense firewall while maintaining visibility on them in the
standard user interface.
We use our standard :code:`ApiMutableModelControllerBase` to allow crud operations on rule entries and offer a set of
specific actions to apply the new configuration.
Since firewall rules can be quite sensitive with a higher risk of lockout, we also support a rollback mechanism here,
which offers the ability to rollback this components changes.
.. blockdiag::
:scale: 100%
diagram init {
savepoint [label = "savepoint()"];
administration [label = "administration"];
apply [label = "apply(savepoint)"];
cancelRollback [label = "cancelRollback(sp)"];
savepoint -> administration -> apply ;
apply -> cancelRollback [label = ".. 60s", style = dashed];
}
The diagram above contains the basic steps to change rules, apply and eventually rollback if not being able to access the machine again.
When calling :code:`savepoint()` a new config revision will be created and the timestamp will be returned for later use.
If the :code:`cancelRollback(savepoint)` is not called within 60 seconds, the firewall will rollback to the previous state
identified by the savepoint timestamp (if available).
.. Note::
The examples in this document disable certificate validation, make sure when using this in a production environment to
remove the :code:`verify=False` from the :code:`requests` calls
.. Tip::
The number of versions kept can be configured as "backup count" in :menuselection:`System -> Configuration -> History`.
This affectively determines within how many configuration changes you can still rollback, if the backup is removed, a rollback
will keep the current state (do nothing).
-----------------------
Administration example
-----------------------
Administrative endpoints are pretty standard use of :code:`ApiMutableModelControllerBase`, the example below searches for
a rule named "OPNsense_fw_api_testrule_1", when not found one will be added otherwise it will print the internal uuid.
Inline you will find a brief description of the steps performed.
.. literalinclude:: firewall.sample_create.py
:language: python
:linenos:
:caption: administrative_example.py
.. Tip::
Since our model contains default values for most attributes, we only need to feed the changes if we would like to keep the
defaults. In this case the TCP/IP version was IPv4 by default for example. In most cases one would like to set all relevant properties
in case defaults change over time.
-----------------------
Apply / revert example
-----------------------
This example will disable the rule created in the previous example and apply the changes using a savepoint, since we're not
calling :code:`cancelRollback(savepoint)` it will revert after 60 seconds to the original state.
.. literalinclude:: firewall.savepoint.py
:language: python
:linenos:
:caption: savepoint_example.py
.. Note::
The savepoint will only revert this components changes, other changes won't be affected by this revert, for example
add an additional interface between savepoint and revert won't be affected.

View File

@@ -0,0 +1,44 @@
#!/usr/bin/env python3.7
import requests
import json
# key + secret from downloaded apikey.txt
api_key="3RhWOno+HwvtmT406I6zw8of8J6n9FOKlWK6U0B+K7stt/fDaJg7bjeF3QAshlScYqC+3o5THy3vQViW"
api_secret="uaBk27NKhQCZSDpfAlG6YJ473MzvsCNiED6kzbYuykzU05fCRkcJADhDm5nxbZt8yREC74ZpvD/vbcEx"
# define the basics, hostname to use and description used to identify our test rule
rule_description='OPNsense_fw_api_testrule_1'
remote_uri="https://192.168.1.1"
# search for rule
r = requests.get(
"%s/api/firewall/filter/searchRule?current=1&rowCount=7&searchPhrase=%s" % (
remote_uri, rule_description
),
auth=(api_key, api_secret), verify=False
)
if r.status_code == 200:
response = json.loads(r.text)
if len(response['rows']) == 0:
# create a new rule, identified by rule_description allowing traffic from
# 192.168.0.0/24 to 10.0.0.0/24 using TCP protocol
data = {"rule" :
{
"description": rule_description,
"source_net": "192.168.0.0/24",
"protocol": "TCP",
"destination_net": "10.0.0.0/24"
}
}
r = requests.post(
"%s/api/firewall/filter/addRule" % remote_uri, auth=(api_key, api_secret), verify=False, json=data
)
if r.status_code == 200:
print("created : %s" % json.loads(r.text)['uuid'])
else:
print("error : %s" % r.text)
else:
for row in response['rows']:
print ("found uuid %s" % row['uuid'])

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3.7
import requests
import json
# key + secret from downloaded apikey.txt
api_key="3RhWOno+HwvtmT406I6zw8of8J6n9FOKlWK6U0B+K7stt/fDaJg7bjeF3QAshlScYqC+3o5THy3vQViW"
api_secret="uaBk27NKhQCZSDpfAlG6YJ473MzvsCNiED6kzbYuykzU05fCRkcJADhDm5nxbZt8yREC74ZpvD/vbcEx"
# define the basics, hostname to use and description used to identify our test rule
rule_description='OPNsense_fw_api_testrule_1'
remote_uri="https://192.168.1.1"
# search for rule
r = requests.get(
"%s/api/firewall/filter/searchRule?current=1&rowCount=7&searchPhrase=%s" % (
remote_uri, rule_description
),
auth=(api_key, api_secret), verify=False
)
if r.status_code == 200:
response = json.loads(r.text)
if len(response['rows']) > 0:
rule_uuid = response['rows'][0]['uuid']
r = requests.post("%s/api/firewall/filter/savepoint" % remote_uri, auth=(api_key, api_secret), verify=False)
if r.status_code == 200:
sp_response = json.loads(r.text)
# disable rule
r = requests.post("%s/api/firewall/filter/toggleRule/%s/0" % (remote_uri, rule_uuid),
auth=(api_key, api_secret), verify=False
)
# apply changes, revert to sp_response['revision'] after 60 seconds
r = requests.post("%s/api/firewall/filter/apply/%s" % (remote_uri, sp_response['revision']),
auth=(api_key, api_secret), verify=False
)
print("revert to revision %s in 60 seconds (%s changed)" % (sp_response['revision'], rule_uuid))
else:
print("rule %s not found" % rule_description)