Skip to main content

OPNsense API Client

Support Badge (Donate, Support-Licenses)


Lint Unit Test Functional Test PyPI - Version

This is a Python3 client for interacting with the official OPNsense API.

It enables easy management and automation of OPNsense firewalls.

The base-code is a Fork of this OPNsense Ansible-Collection that was refactored for use within raw Python.

This can be useful if you want to automate your Infrastructure and do not use Ansible.

An interactive CLI interface might be added later on.

Intro GIF

Install

pip install oxl-opnsense-client

Get to know the available modules:


Contribute

The codebase of this library will be automatically synced with the upstream code of the OPNsense Ansible-Module!

Thus, new features (and feature-requests) should be made there.

Feel free to report issues/bugs, take part in discussions and add/extend tests.

Note: Only the API-enabled functionalities can be implemented.


Usage

Documentation, Ansible OPNsense-Collection Docs

Docs Uptime

from oxl_opnsense_client import Client

with Client(
    firewall='192.168.10.20',
    port=443,  # default
    credential_file='/tmp/.opnsense.txt',
    # token='0pWN/C3tnXem6OoOp0zc9K5GUBoqBKCZ8jj8nc4LEjbFixjM0ELgEyXnb4BIqVgGNunuX0uLThblgp9Z',
    # secret='Vod5ug1kdSu3KlrYSzIZV9Ae9YFMgugCIZdIIYpefPQVhvp6KKuT7ugUIxCeKGvN6tj9uqduOzOzUlv',
) as c:
    c.test()
    # True

    ### CHECK SUPPORTED MODULES ###
    c.list_modules()
    # ['acme_account', 'acme_action', 'acme_certificate', 'acme_general', 'acme_validation', 'alias', 'alias_multi', 'alias_purge', 'bind_acl', 'bind_blocklist', 'bind_domain', 'bind_general', 'bind_record', 'bind_record_multi', 'cron', 'dhcp_controlagent', 'dhcp_general', 'dhcp_reservation', 'dhcp_subnet', 'dhcrelay_destination', 'dhcrelay_relay', 'dnsmasq_boot', 'dnsmasq_domain', 'dnsmasq_general', 'dnsmasq_host', 'dnsmasq_option', 'dnsmasq_range', 'dnsmasq_tag', 'frr_bfd_general', 'frr_bfd_neighbor', 'frr_bgp_as_path', 'frr_bgp_community_list', 'frr_bgp_general', 'frr_bgp_neighbor', 'frr_bgp_peer_group', 'frr_bgp_prefix_list', 'frr_bgp_redistribution', 'frr_bgp_route_map', 'frr_diagnostic', 'frr_general', 'frr_ospf3_general', 'frr_ospf3_interface', 'frr_ospf3_network', 'frr_ospf3_prefix_list', 'frr_ospf3_redistribution', 'frr_ospf3_route_map', 'frr_ospf_general', 'frr_ospf_interface', 'frr_ospf_network', 'frr_ospf_prefix_list', 'frr_ospf_redistribution', 'frr_ospf_route_map', 'frr_rip', 'gateway', 'group', 'hasync_general', 'hasync_service', 'ids_action', 'ids_general', 'ids_policy', 'ids_policy_rule', 'ids_rule', 'ids_ruleset', 'ids_user_rule', 'interface_bridge', 'interface_gif', 'interface_gre', 'interface_lagg', 'interface_loopback', 'interface_vip', 'interface_vlan', 'interface_vxlan', 'ipsec_auth_local', 'ipsec_auth_remote', 'ipsec_cert', 'ipsec_child', 'ipsec_connection', 'ipsec_general', 'ipsec_manual_spd', 'ipsec_pool', 'ipsec_psk', 'ipsec_vti', 'list', 'monit_alert', 'monit_service', 'monit_test', 'nat_one_to_one', 'nat_source', 'neighbor', 'nginx_general', 'nginx_upstream_server', 'openvpn_client', 'openvpn_client_override', 'openvpn_server', 'openvpn_static_key', 'openvpn_status', 'package', 'postfix_address', 'postfix_domain', 'postfix_general', 'postfix_headercheck', 'postfix_recipient', 'postfix_recipientbcc', 'postfix_sender', 'postfix_senderbcc', 'postfix_sendercanonical', 'privilege', 'raw', 'reload', 'route', 'rule', 'rule_interface_group', 'rule_multi', 'rule_purge', 'savepoint', 'service', 'shaper_pipe', 'shaper_queue', 'shaper_rule', 'snapshot', 'syslog', 'system', 'unbound_acl', 'unbound_dnsbl', 'unbound_dot', 'unbound_forward', 'unbound_general', 'unbound_host', 'unbound_host_alias', 'user', 'webproxy_acl', 'webproxy_auth', 'webproxy_cache', 'webproxy_forward', 'webproxy_general', 'webproxy_icap', 'webproxy_pac_match', 'webproxy_pac_proxy', 'webproxy_pac_rule', 'webproxy_parent', 'webproxy_remote_acl', 'webproxy_traffic', 'wireguard_general', 'wireguard_peer', 'wireguard_server', 'wireguard_show']

    ### CHECK MODULE ARGUMENTS / SPECS ###
    c.module_specs('route')
    # {'specs': {'gateway': {'type': 'str', 'required': True, 'aliases': ['gw'], 'description': 'Specify a valid existing gateway matching the networks ip protocol'}, 'network': {'type': 'str', 'required': True, 'aliases': ['nw', 'net'], 'description': 'Specify a valid network matching the gateways ip protocol'}, 'description': {'type': 'str', 'required': False, 'aliases': ['desc']}, 'match_fields': {'type': 'list', 'required': False, 'elements': 'str', 'description': "Fields that are used to match configured routes with the running config - if any of those fields are changed, the module will think it's a new route", 'choices': ['network', 'gateway', 'description'], 'default': ['network', 'gateway']}, 'reload': {'type': 'bool', 'required': False, 'default': True, 'aliases': ['apply'], 'description': 'If the running config should be reloaded/applied on change - will take some time'}, 'state': {'type': 'str', 'required': False, 'choices': ['present', 'absent'], 'default': 'present'}, 'enabled': {'type': 'bool', 'required': False, 'default': True}}}
    c.module_specs('wireguard_show', stdout=True)
    # prints in pretty-JSON

    ### CREATE ENTRY ###

    c.run_module('syslog', params={'target': '192.168.0.1', 'port': 5303})
    # {'error': None, 'result': {'changed': True, 'diff': {'after': {'uuid': None, 'rfc5424': False, 'enabled': True, 'target': '192.168.0.1', 'transport': 'udp4', 'facility': [], 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'certificate': '', 'port': 5303, 'description': ''}}}}
    c.run_module('list', params={'target': 'syslog'})
    # {'error': None, 'result': {'changed': False, 'data': [{'target': '192.168.0.1', 'enabled': True, 'transport': 'udp4', 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'facility': [], 'certificate': '', 'port': 5303, 'rfc5424': False, 'description': '', 'uuid': '32b1ce94-93d0-4d20-93a2-4fff12d12a54'}]}}

    ### UPDATING ENTRY ###

    c.run_module('syslog', params={'target': '192.168.0.1', 'port': 9941, 'match_fields': ['target']})
    # {'error': None, 'result': {'changed': True, 'diff': {'before': {'uuid': '4930e797-5111-4825-b5bb-c8e60f9d21d5', 'rfc5424': False, 'enabled': True, 'target': '192.168.0.1', 'transport': 'udp4', 'facility': [], 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'certificate': '', 'port': 5304, 'description': ''}, 'after': {'uuid': '4930e797-5111-4825-b5bb-c8e60f9d21d5', 'rfc5424': False, 'enabled': True, 'target': '192.168.0.1', 'transport': 'udp4', 'facility': [], 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'certificate': '', 'port': 9941, 'description': ''}}}}
    c.run_module('list', params={'target': 'syslog'})
    # {'error': None, 'result': {'changed': False, 'data': [{'target': '192.168.0.1', 'enabled': True, 'transport': 'udp4', 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'facility': [], 'certificate': '', 'port': 9941, 'rfc5424': False, 'description': '', 'uuid': '4930e797-5111-4825-b5bb-c8e60f9d21d5'}]}}

    ### DELETING ENTRY ###

    c.run_module('syslog', params={'target': '192.168.0.1', 'port': 5303, 'state': 'absent', 'match_fields': ['target']})
    # {'error': None, 'result': {'changed': True, 'diff': {'before': {'uuid': '2500dadc-ce43-4e23-994e-860516b0ef45', 'rfc5424': False, 'enabled': True, 'target': '192.168.0.1', 'transport': 'udp4', 'facility': [], 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'certificate': '', 'port': 5303, 'description': ''}}}}
    c.run_module('list', params={'target': 'syslog'})
    # {'error': None, 'result': {'changed': False, 'data': []}}
    c.run_module('syslog', params={'target': '192.168.0.1', 'port': 5303, 'state': 'absent'})
    # {'error': None, 'result': {'changed': False, 'diff': {}}}

    ### CHECK MODE (DRY-RUN) ###

    c.run_module('syslog', check_mode=True, params={'target': '192.168.0.1', 'port': 5303})
    # {'error': None, 'result': {'changed': True, 'diff': {'before': {'uuid': '7f3aba31-07ca-4cb9-b93d-dc442a5291c7', 'rfc5424': False, 'enabled': True, 'target': '192.168.0.1', 'transport': 'udp4', 'facility': [], 'program': [], 'level': ['alert', 'crit', 'emerg', 'err', 'info', 'notice', 'warn'], 'certificate': '', 'port': 5303, 'description': ''}}}}
    c.run_module('list', params={'target': 'syslog'})
    # {'error': None, 'result': {'changed': False, 'data': []}}
    c.run_module('syslog', params={'target': '192.168.0.1', 'port': 5303, 'state': 'absent'})
    # {'error': None, 'result': {'changed': False, 'diff': {}}}

Credentials

from oxl_opnsense_client import Client

# use the API credentials-file as downloaded from the WebUI
c = Client(firewall='<IP>', credential_file='/home/<YOU>/.opnsense.txt')

# use the token/key pair directly
c = Client(firewall='<IP>', token='<TOKEN>', secret='<SECRET>')

SSL Verification

from oxl_opnsense_client import Client

# provide the path to your custom CA public-key
c = Client(
    firewall='<IP>',
    credential_file='/home/<YOU>/.opnsense.txt',
    ssl_ca_file='/home/<YOU>/ca.crt',
)

# ONLY USE FOR TESTING PURPOSES => you can disable the certificate-verification
c = Client(
    firewall='<IP>',
    credential_file='/home/<YOU>/.opnsense.txt',
    ssl_verify=False,
)

Debug Output

This will show you the performed API calls and their JSON payload.

from oxl_opnsense_client import Client
c = Client(
    firewall='<IP>',
    credential_file='/home/<YOU>/.opnsense.txt',
    debug=True,
)

c.run_module('syslog', params={'target': '192.168.0.1', 'port': 5303})
# INFO: REQUEST: GET | URL: https://172.17.1.52/api/syslog/settings/get
# INFO: RESPONSE: '{'status_code': 200, '_request': <Request('GET', 'https://172.17.1.52/api/syslog/settings/get')>, '_num_bytes_downloaded': 123, '_elapsed': datetime.timedelta(microseconds=194859), '_content': b'{"syslog":{"general":{"enabled":"1","loglocal":"1","maxpreserve":"31","maxfilesize":""},"destinations":{"destination":[]}}}'}'
# INFO: REQUEST: POST | URL: https://172.17.1.52/api/syslog/settings/addDestination | HEADERS: '{'Content-Type': 'application/json'}' | DATA: '{"destination": {"rfc5424": 0, "enabled": 1, "hostname": "192.168.0.1", "transport": "udp4", "facility": "", "program": "", "level": "alert,crit,emerg,err,info,notice,warn", "certificate": "", "port": 5303, "description": ""}}'
# INFO: RESPONSE: '{'status_code': 200, '_request': <Request('POST', 'https://172.17.1.52/api/syslog/settings/addDestination')>, '_num_bytes_downloaded': 64, '_elapsed': datetime.timedelta(microseconds=61852), '_content': b'{"result":"saved","uuid":"ed90d52a-63ac-4d7c-a35b-4f250350f85d"}'}'
# INFO: REQUEST: POST | URL: https://172.17.1.52/api/syslog/service/reconfigure | HEADERS: '{}'
# INFO: RESPONSE: '{'status_code': 200, '_request': <Request('POST', 'https://172.17.1.52/api/syslog/service/reconfigure')>, '_num_bytes_downloaded': 15, '_elapsed': datetime.timedelta(microseconds=657156), '_content': b'{"status":"ok"}'}'

This information is also logged to files:

ls /tmp/opnsense_client/
# api_calls.log  syslog.log

The module-specific logs contain performance-profiling.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oxl_opnsense_client-26.1.11.tar.gz (222.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oxl_opnsense_client-26.1.11-py3-none-any.whl (499.8 kB view details)

Uploaded Python 3

File details

Details for the file oxl_opnsense_client-26.1.11.tar.gz.

File metadata

  • Download URL: oxl_opnsense_client-26.1.11.tar.gz
  • Upload date:
  • Size: 222.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for oxl_opnsense_client-26.1.11.tar.gz
Algorithm Hash digest
SHA256 1af4032230202f390e525d0936773d2f341074befc4d7ea31d88a11763437f62
MD5 50046f92d67abf12969cc9cb7a728144
BLAKE2b-256 acc39893938be7afab73c77206dca0d82ebefe9eb3a13b3374f435570b97d821

See more details on using hashes here.

File details

Details for the file oxl_opnsense_client-26.1.11-py3-none-any.whl.

File metadata

File hashes

Hashes for oxl_opnsense_client-26.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 a14f805040366025139026fcd2dfb15c8a7eb11a81db5483451791ef816cd7f6
MD5 448e2d9a29d3f1ef4a237c2e3f0f0c72
BLAKE2b-256 f43a444b131dc07acbde6ef46e1ee04307616eddd0620c2296fab8b4250fbb09

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page