Git Product home page Git Product logo

ansibleguy / collection_opnsense Goto Github PK

View Code? Open in Web Editor NEW
239.0 239.0 29.0 1.7 MB

Ansible Collection to manage OPNSense firewalls using their API

Home Page: https://opnsense.ansibleguy.net

License: GNU General Public License v3.0

Python 98.91% Shell 1.09%
ansible ansible-collection ansible-modules automation firewall firewall-management frr iac infrastructure-as-code nac network network-as-code networking opnsense opnsense-firewall router routing

collection_opnsense's Introduction

Introduction

I enjoy creating automation templates using the platform Ansible (by Red Hat).

Creating Ansible Roles and Modules/Collections should help others to get started faster.

Feedback is appreciated!

Principles

๐Ÿ’ญ User interaction

Keeping the user interaction clean and simple

  • Per example:

    If a network admin wants to configure a WireGuard VPN-Infrastructure he/she/... should not need to think about the role - just the abstracted topology!

  • Each role should use as few 'top-level' variables as possible

    Most roles will take ONE nested variable (dictionary)

  • Commonly redundant config is not accepable.

    The role should work its magic โœจ and handle it using inheritance, scoping and/or defaults

๐Ÿท Default = Opt-out

Preferring opt-out on optional features

  • IT-Infrastructure is a very sensitive domain.

    I hate it if some role/script does more than it should.

    That can lead to unpredictable results!

  • The roles allow the user to choose the features they want to opt-in.

๐Ÿ“— Documentation

Good documentation

  • The best tool is useless if you can not handle it..

    Documentation is the tools 'interface' and should be clean.

    I can't tell how often I came across a tool with a nice feature-set but could not use it as of the lack of good documentation!

  • Transparency is key when getting to know a role.

    Examples (config => result) are very vital for this.

    Not everybody wants to run the role to see what it actually does do.

๐Ÿ” Security

  • As security is very important in todays IT environment I'm checking my Roles and Modules/Collections for security best-practises.
  • Roles and Modules will at least warn you if unsecure settings are used or will not even fail on you if you use them in an unsecure way.
  • You should always use encrypted connectivity => Automation makes it very easy to add/generate certificates.

Epilog

Automation can save time and nerves, enables infrastructure-as-code (with all it's benefits) and scales well.

What are you waiting on? Automate! ๐Ÿ˜„


Have a nice day!

  • AnsibleGuy

collection_opnsense's People

Contributors

ansibleguy avatar atammy-narmi avatar cwerner1 avatar cyatris avatar gjdoornink avatar low-frequency avatar ohartl avatar superstes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

collection_opnsense's Issues

Feature: Add Support for HAProxy

Link to API

https://docs.opnsense.org/development/api/plugins/haproxy.html

Description

I currently run HAProxy as a reverse proxy and SSL offload using ACL's on OPNSense. Currently config is very manual and GUI based. Would love a way to script the addition of:

Real Servers - This is where the IP and Port of the server is configured
Backend Pools
Conditions
Rules
The addition of the new rule to a pre-configured "Public Service" - this is where my http and https rules sit and handle SSL offloading

[alias] - Removing alias fails

Basic info

  • Affected Module: alias

Versions

  • Controller

    • Collection version: 1.1.0

    • Ansible version:
      - ansible: 7.3.0
      - ansible-core: 2.14.3

    • Python version: 3.10.10

  • OPNSense

    • System version: 22.7.11

Describe the bug

Removing a firewall alias fails with the following error message:

TASK [Making sure host alias is absent] *****************************************************************************
fatal: [mgmt-02.home.local]: FAILED! => {"changed": false, "msg": "API call failed | Needed plugin not installed! | Response: {'status_code': 400, 'headers': Headers([('set-cookie', 'PHPSESSID=fd9ced44078aafdedd684f216ea99a9b; path=/'), ('set-cookie', 'PHPSESSID=fd9ced44078aafdedd684f216ea99a9b; path=/; secure; HttpOnly'), ('expires', 'Thu, 19 Nov 1981 08:52:00 GMT'), ('cache-control', 'no-store, no-cache, must-revalidate'), ('pragma', 'no-cache'), ('content-security-policy', \"default-src 'self' ;img-src 'self' ;script-src 'self' 'unsafe-inline' 'unsafe-eval' ;style-src 'self' 'unsafe-inline' 'unsafe-eval' ;\"), ('x-frame-options', 'SAMEORIGIN'), ('x-content-type-options', 'nosniff'), ('x-xss-protection', '1; mode=block'), ('referrer-policy', 'same-origin'), ('content-type', 'application/json'), ('content-length', '89'), ('date', 'Wed, 08 Mar 2023 16:16:26 GMT'), ('server', 'OPNsense')]), '_request': <Request('GET', 'https://fw-01.home.local/api/firewall/filter/get')>, 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'Bad Request', 'network_stream': <httpcore.backends.sync.SyncStream object at 0x7fdc12573850>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream object at 0x7fdc12572140>, '_num_bytes_downloaded': 89, '_decoder': <httpx._decoders.IdentityDecoder object at 0x7fdc12570d60>, '_elapsed': datetime.timedelta(microseconds=15510), '_content': b'{\"message\":\"controller OPNsense\\\\\\\\Firewall\\\\\\\\Api\\\\\\\\FilterController not found\",\"status\":400}'}"}

Expected behavior

The task does not fail and removes the firewall alias.

Debug output

TASK [Making sure host alias is absent] *****************************************************************************
[WARNING]: REQUEST: GET | URL: https://fw-01.home.local/api/firewall/alias/get
[WARNING]: RESPONSE: '{'status_code': 200, 'headers': Headers({'content-type': 'application/json; charset=UTF-8',
'cache-control': 'max-age=180000', 'accept-ranges': 'bytes', 'content-length': '52365', 'date': 'Wed, 08 Mar 2023
16:53:13 GMT', 'server': 'OPNsense'}), '_request': <Request('GET',
'https://fw-01.home.local/api/firewall/alias/get')>, 'next_request': None, 'extensions': {'http_version':
b'HTTP/1.1', 'reason_phrase': b'OK', 'network_stream': <httpcore.backends.sync.SyncStream object at
0x7fac8c98f850>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8',
'stream': <httpx._client.BoundSyncStream object at 0x7fac8c98f160>, '_num_bytes_downloaded': 52365, '_decoder':
<httpx._decoders.IdentityDecoder object at 0x7fac8c98e440>, '_elapsed': datetime.timedelta(microseconds=97353),
'_content': b'{"alias":{"geoip":{"url":""},"aliases":{"alias":{"ee75bd7d-1eaf-4ac6-bbba-
4bcd207ac246":{"enabled":"1","name":"RFC_1918","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"N
etwork(s)","selected":1},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.0.0.0\\/8":{"value":"10.0.0.0\\/8","selected":1},"172.16.0.0\\/12":{"value":"172.16.0.0\\/12","selected":1}
,"192.168.0.0\\/16":{"value":"192.168.0.0\\/16","selected":1}},"categories":[],"description":"Private Networks"},"d7
06d9b6-bba6-40a6-8bf2-
f7feb002e2f7":{"enabled":"1","name":"gitlab_02","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"
Network(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.50.18":{"value":"10.10.50.18","selected":1}},"categories":[],"description":"gitlab-02: managed by terraf
orm"},"7cdc29bc-6a18-4239-8432-
7479aec428f0":{"enabled":"1","name":"gitrunner_02","type":{"host":{"value":"Host(s)","selected":1},"network":{"value
":"Network(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.50.19":{"value":"10.10.50.19","selected":1}},"categories":[],"description":"gitrunner-02: managed by ter
raform"},"26ffe936-0c82-438f-a0eb-
1d4039e67776":{"enabled":"1","name":"mgmt_02","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"Ne
twork(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.50.3":{"value":"10.10.50.3","selected":1}},"categories":[],"description":"mgmt-02: managed by terraform"
},"a892a959-2c4b-4096-9b74-
2e355d7b79ae":{"enabled":"1","name":"pki_02","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"Net
work(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.50.4":{"value":"10.10.50.4","selected":1}},"categories":[],"description":"pki-02: managed by terraform"}
,"5c016c25-b3fb-4adf-b5f7-
daaa2c8541be":{"enabled":"1","name":"fw_01","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"Netw
ork(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.10.1":{"value":"10.10.10.1","selected":1}},"categories":[],"description":"OPNsense Firewall"},"581cd35a-
fca0-436d-a5db-
c0914a58a59f":{"enabled":"1","name":"pve_01","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"Net
work(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"10.10.50.14":{"value":"10.10.50.14","selected":1}},"categories":[],"description":"Proxmox Host"},"cc4574c9-
00fc-4559-8410-
2b5350505fbe":{"enabled":"1","name":"test01","type":{"host":{"value":"Host(s)","selected":1},"network":{"value":"Net
work(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"0","updatefreq":"","conte
nt":{"1.2.3.4":{"value":"1.2.3.4","selected":1}},"categories":[],"description":"test01"},"bogons":{"enabled":"1","na
me":"bogons","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"port":{"
value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":1}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"bogon networks (internal)"},"bogonsv6":{"enabled":"
1","name":"bogonsv6","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"
port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":1}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"bogon networks IPv6 (internal)"},"virusprot":{"enab
led":"1","name":"virusprot","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selecte
d":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL
Table (IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":1}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"overload table for rate limiting (internal)"},"sshl
ockout":{"enabled":"1","name":"sshlockout","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Netwo
rk(s)","selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":0},"external":{"value":"External (advanced)","selected":1}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"abuse lockout table (internal)"},"__wan_network":{"
enabled":"1","name":"__wan_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)",
"selected":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL
(IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"wan net"},"__lan_network":{"enabled":"1","name":"__
lan_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"port":{"
value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"LAN1 net"},"__lo0_network":{"enabled":"1","name":"_
_lo0_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"port":{
"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"Loopback net"},"__opt1_network":{"enabled":"1","nam
e":"__opt1_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"p
ort":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"LAN2 net"},"__opt2_network":{"enabled":"1","name":"
__opt2_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"port"
:{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"LAN3 net"},"__opt5_network":{"enabled":"1","name":"
__opt5_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"port"
:{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_Private net"},"__opt6_network":{"enabled":"1",
"name":"__opt6_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0
},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_IOT net"},"__opt7_network":{"enabled":"1","nam
e":"__opt7_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},"p
ort":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_Guest net"},"__opt3_network":{"enabled":"1","n
ame":"__opt3_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0},
"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_mgmt net"},"__opt4_network":{"enabled":"1"
,"name":"__opt4_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":
0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_dev net"},"__opt8_network":{"enabled":"1",
"name":"__opt8_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0
},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_db net"},"__opt9_network":{"enabled":"1","
name":"__opt9_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected":0}
,"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_wiki net"},"__opt10_network":{"enabled":"1
","name":"__opt10_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected
":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_dash net"},"__opt11_network":{"enabled":"1
","name":"__opt11_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected
":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_photo net"},"__opt12_network":{"enabled":"
1","name":"__opt12_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selecte
d":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL
Table (IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_proxy net"},"__opt13_network":{"enabled":"
1","name":"__opt13_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selecte
d":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL
Table (IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_iot net"},"__opt14_network":{"enabled":"1"
,"name":"__opt14_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selected"
:0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL Table
(IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_monitor net"},"__opt15_network":{"enabled"
:"1","name":"__opt15_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selec
ted":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL
Table (IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_share net"},"__opt16_network":{"enabled":"
1","name":"__opt16_network","type":{"host":{"value":"Host(s)","selected":0},"network":{"value":"Network(s)","selecte
d":0},"port":{"value":"Port(s)","selected":0},"url":{"value":"URL (IPs)","selected":0},"urltable":{"value":"URL
Table (IPs)","selected":0},"geoip":{"value":"GeoIP","selected":0},"networkgroup":{"value":"Network
group","selected":0},"mac":{"value":"MAC address","selected":0},"asn":{"value":"BGP
ASN","selected":0},"dynipv6host":{"value":"Dynamic IPv6 Host","selected":0},"internal":{"value":"Internal
(automatic)","selected":1},"external":{"value":"External (advanced)","selected":0}},"proto":{"IPv4":{"value":"IPv4",
"selected":0},"IPv6":{"value":"IPv6","selected":0}},"interface":{"":{"value":"none","selected":true},"lan":{"value":
"LAN1","selected":0},"opt1":{"value":"LAN2","selected":0},"opt2":{"value":"LAN3","selected":0},"opt7":{"value":"VLAN
_Guest","selected":0},"opt6":{"value":"VLAN_IOT","selected":0},"opt5":{"value":"VLAN_Private","selected":0},"opt10":
{"value":"VLAN_srv_dash","selected":0},"opt8":{"value":"VLAN_srv_db","selected":0},"opt4":{"value":"VLAN_srv_dev","s
elected":0},"opt13":{"value":"VLAN_srv_iot","selected":0},"opt3":{"value":"VLAN_srv_mgmt","selected":0},"opt14":{"va
lue":"VLAN_srv_monitor","selected":0},"opt11":{"value":"VLAN_srv_photo","selected":0},"opt12":{"value":"VLAN_srv_pro
xy","selected":0},"opt15":{"value":"VLAN_srv_share","selected":0},"opt16":{"value":"VLAN_srv_test","selected":0},"op
t9":{"value":"VLAN_srv_wiki","selected":0},"wan":{"value":"WAN","selected":0}},"counters":"","updatefreq":"","conten
t":{"":{"value":"","selected":1}},"categories":[],"description":"VLAN_srv_test net"}}}}}'}'
[WARNING]: NOT MATCHING: 'RFC_1918' != 'test01'
[WARNING]: NOT MATCHING: 'gitlab_02' != 'test01'
[WARNING]: NOT MATCHING: 'gitrunner_02' != 'test01'
[WARNING]: NOT MATCHING: 'mgmt_02' != 'test01'
[WARNING]: NOT MATCHING: 'pki_02' != 'test01'
[WARNING]: NOT MATCHING: 'fw_01' != 'test01'
[WARNING]: NOT MATCHING: 'pve_01' != 'test01'
[WARNING]: REQUEST: GET | URL: https://fw-01.home.local/api/firewall/filter/get
[WARNING]: RESPONSE: '{'status_code': 400, 'headers': Headers([('set-cookie',
'PHPSESSID=ef94cae6ae3486d67e27723ed90d8e98; path=/'), ('set-cookie', 'PHPSESSID=ef94cae6ae3486d67e27723ed90d8e98;
path=/; secure; HttpOnly'), ('expires', 'Thu, 19 Nov 1981 08:52:00 GMT'), ('cache-control', 'no-store, no-cache,
must-revalidate'), ('pragma', 'no-cache'), ('content-security-policy', "default-src 'self' ;img-src 'self' ;script-
src 'self' 'unsafe-inline' 'unsafe-eval' ;style-src 'self' 'unsafe-inline' 'unsafe-eval' ;"), ('x-frame-options',
'SAMEORIGIN'), ('x-content-type-options', 'nosniff'), ('x-xss-protection', '1; mode=block'), ('referrer-policy',
'same-origin'), ('content-type', 'application/json'), ('content-length', '89'), ('date', 'Wed, 08 Mar 2023 16:53:13
GMT'), ('server', 'OPNsense')]), '_request': <Request('GET', 'https://fw-01.home.local/api/firewall/filter/get')>,
'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'Bad Request', 'network_stream':
<httpcore.backends.sync.SyncStream object at 0x7fac8c98f850>}, 'history': [], 'is_closed': True,
'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream object at
0x7fac8c98e740>, '_num_bytes_downloaded': 89, '_decoder': <httpx._decoders.IdentityDecoder object at
0x7fac8c98cca0>, '_elapsed': datetime.timedelta(microseconds=13362), '_content': b'{"message":"controller
OPNsense\\\\Firewall\\\\Api\\\\FilterController not found","status":400}'}'
fatal: [mgmt-02.home.local]: FAILED! => {"changed": false, "msg": "API call failed | Needed plugin not installed! | Response: {'status_code': 400, 'headers': Headers([('set-cookie', 'PHPSESSID=ef94cae6ae3486d67e27723ed90d8e98; path=/'), ('set-cookie', 'PHPSESSID=ef94cae6ae3486d67e27723ed90d8e98; path=/; secure; HttpOnly'), ('expires', 'Thu, 19 Nov 1981 08:52:00 GMT'), ('cache-control', 'no-store, no-cache, must-revalidate'), ('pragma', 'no-cache'), ('content-security-policy', \"default-src 'self' ;img-src 'self' ;script-src 'self' 'unsafe-inline' 'unsafe-eval' ;style-src 'self' 'unsafe-inline' 'unsafe-eval' ;\"), ('x-frame-options', 'SAMEORIGIN'), ('x-content-type-options', 'nosniff'), ('x-xss-protection', '1; mode=block'), ('referrer-policy', 'same-origin'), ('content-type', 'application/json'), ('content-length', '89'), ('date', 'Wed, 08 Mar 2023 16:53:13 GMT'), ('server', 'OPNsense')]), '_request': <Request('GET', 'https://fw-01.home.local/api/firewall/filter/get')>, 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'Bad Request', 'network_stream': <httpcore.backends.sync.SyncStream object at 0x7fac8c98f850>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream object at 0x7fac8c98e740>, '_num_bytes_downloaded': 89, '_decoder': <httpx._decoders.IdentityDecoder object at 0x7fac8c98cca0>, '_elapsed': datetime.timedelta(microseconds=13362), '_content': b'{\"message\":\"controller OPNsense\\\\\\\\Firewall\\\\\\\\Api\\\\\\\\FilterController not found\",\"status\":400}'}"}

Additional context

My Ansible Playbook is triggered by Terraform which in turn is invoked in a Docker container by a CI/CD Pipeline. It connects to my management VM and executes the tasks from there. However local execution also fails.

Ansible Config:

[defaults]
private_key_file=~/.ssh/id_rsa_ansible
remote_user=ansible
host_key_checking=False
inventory=/etc/ansible/hosts

Ansible command used by terraform:

ansible-playbook -i 'mgmt-02.home.local,' -e '${local.firewall_object}' -e '{"fw_object_state":"absent"}' firewall_objects.yml

The local.firewall_object is constructed as follows:

firewall_object = jsonencode({
    fw_object_hostname = var.name
    fw_object_ip = local.ip_address
  })

This results in this json:

{"fw_object_hostname":"HOSTNAME","fw_object_ip":"IP_ADDRESS"}

Reproduce

Tasks

Task(s) that produce the error:

---
- name: Setting up firewall objects
  hosts: all
  gather_facts: no
  module_defaults:
    ansibleguy.opnsense.reload:
      firewall: "fw-01.home.local"
      ssl_verify: false
      api_key: "{{ lookup('ansible.builtin.env', 'OPNSENSE_KEY') }}"
      api_secret: "{{ lookup('ansible.builtin.env', 'OPNSENSE_SECRET') }}"
    ansibleguy.opnsense.alias:
      firewall: "fw-01.home.local"
      ssl_verify: false
      api_key: "{{ lookup('ansible.builtin.env', 'OPNSENSE_KEY') }}"
      api_secret: "{{ lookup('ansible.builtin.env', 'OPNSENSE_SECRET') }}"
      debug: true

  tasks:
    - name: Making sure host alias is {{fw_object_state}}
      ansibleguy.opnsense.alias:
        name: "{{fw_object_hostname|replace('-', '')}}"
        description: "{{fw_object_hostname|replace('-', '')}}"
        content: "{{fw_object_ip}}"
        type: "host"
        state: "{{fw_object_state}}"
        reload: false
      notify: reload_fw_alias

  handlers:
    - name: reload_fw_alias
      ansibleguy.opnsense.reload:
        target: "alias"

Manually reproducable with the following command:

ansible-playbook -i 'mgmt-02.home.local,' -e '{"fw_object_hostname":"test-01","fw_object_ip":"1.2.3.4","fw_object_state":"absent"}' firewall_objects.yml

Hostnames without a dot like "router" are not accepted

When trying to connect to IPv6 only hosts, it seems that this module fails with being unable to resolve the domain name. Example below for the host "rmrouter1", which is reachable at OS level:

TASK [Tmux] *************************************************************************************
fatal: [router1]: FAILED! => {"changed": false, "msg": "Host 'rmrouter1' is neither a valid IP nor Domain-Name!"}

PLAY RECAP **************************************************************************************
router1                    : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

[10:50] nb3:rulematch-ansible% ping -c1 rmrouter1
PING rmrouter1(rmrouter1 (2a0a:e5c0:10:bee::1001)) 56 data bytes
64 bytes from rmrouter1 (2a0a:e5c0:10:bee::1001): icmp_seq=1 ttl=61 time=39.0 ms

--- rmrouter1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 38.956/38.956/38.956/0.000 ms
[10:50] nb3:rulematch-ansible% 

The name is configured in the hosts file:

nb3:~# grep rmrouter1 /etc/hosts
2a0a:e5c0:10:bee::1001 rmrouter1

Problem: package module tests fail

Modules

package

Version

latest

Ansible Version

-

OPNSense Version

latest

OPNSense-Plugin Version

-

Issue

The task always fails. If I run it manually on the same box - it works. Disabled it for now so the other tests can run

Config Ansible

- name: Checking if installed
   ansibleguy.opnsense.list:
   register: opn12
   failed_when: >
     opn12.failed or
     test_app1 not in opn12 | json_query('data[*].name') or
     test_app2 not in opn12 | json_query('data[*].name')
   when: not ansible_check_mode

Config OPNSense

No response

Debug Output

-

Profiling Output

No response

[source_nat] - Rules are not applied

Tasks

Please make sure to go through these steps before opening an issue:

  • Read the documentation of the affected module: Docs

  • Read the troubleshooting info: Info

Basic info

  • Affected Module:
    source_nat

Versions

  • Controller

    • Collection version:
      1.2.6
      (ansible-galaxy collection list | grep opnsense)

    • Ansible & Python version:
      ansible [core 2.15.3]
      python version = 3.11.5
      (ansible --version)

  • OPNSense

    • System version:
      23.7.4
    • Plugin version:
      os-firewall 1.4_1
      os-wireguard 2.1
      (if applicable)

Describe the bug

When Adding nat rules with the moduile source_nat the rules are added under Firewall -> Automation -> Source NAT
But the rules are not applied.
When I manually with the Webui apply the rules under Firewall -> Automation -> Source NAT -> apply than the rules are working.

Expected behavior

When I add source_nat rules I expect that the new rules are applied, not that I have to do this manually in the webui.

Debug output

I enabled debugging and these are the API calls when I try to add 2 rules

2023-09-18 10:48:36:104222 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/addRule
2023-09-18 12:59:16:757571 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-18 12:59:16:982807 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/addRule
2023-09-18 13:01:03:421363 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-18 13:01:03:646326 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/addRule
2023-09-18 13:01:32:032643 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-18 13:01:32:265746 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/addRule
2023-09-18 13:04:20:494033 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-18 13:04:20:722383 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/setRule/3b63ecf0-ee2a-4662-ad1a-8ad911994098
2023-09-18 13:04:49:100628 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-18 13:04:49:328184 | POST => https://xx.xx.xx.xx/api/firewall/source_nat/setRule/3b63ecf0-ee2a-4662-ad1a-8ad911994098
2023-09-21 15:08:42:238500 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
2023-09-21 15:08:42:874805 | GET => https://xx.xx.xx.xx/api/firewall/source_nat/get
~

If the issue is related to time-consumption, you may also add the content of the profiling logs.

2023-09-18 13:01:32:404385 |          6031 function calls (5917 primitive calls) in 0.364 seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.297    0.149    0.297    0.149 {method 'read' of '_ssl._SSLSocket' objects}
        1    0.029    0.029    0.029    0.029 {method 'do_handshake' of '_ssl._SSLSocket' objects}
        1    0.026    0.026    0.026    0.026 {method 'connect' of '_socket.socket' objects}
        1    0.001    0.001    0.002    0.002 {built-in method _socket.getaddrinfo}
        4    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
  705/665    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        5    0.000    0.000    0.000    0.000 {built-in method syslog.syslog}
      6/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:509(_parse)
        3    0.000    0.000    0.000    0.000 {method 'write' of '_ssl._SSLSocket' objects}
        4    0.000    0.000    0.000    0.000 /usr/local/lib/python3.11/site-packages/h11/_headers.py:150(normalize_and_validate)
        4    0.000    0.000    0.001    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_ft1evg_f/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/api.py:112(debug_api)
       12    0.000    0.000    0.001    0.000 /usr/local/lib/python3.11/site-packages/h11/_connection.py:260(_process_event)
        2    0.000    0.000    0.000    0.000 {built-in method io.open}
        2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py:343(raw_decode)
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
     10/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_compiler.py:37(_compile)
        6    0.000    0.000    0.299    0.050 /usr/local/lib/python3.11/site-packages/httpcore/_sync/http11.py:192(_receive_event)
       53    0.000    0.000    0.000    0.000 {method 'fullmatch' of 're.Pattern' objects}
        3    0.000    0.000    0.000    0.000 {method 'poll' of 'select.poll' objects}
       29    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/contextlib.py:104(__init__)


2023-09-18 13:04:20:862065 |          6533 function calls (6419 primitive calls) in 0.360 seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.298    0.149    0.298    0.149 {method 'read' of '_ssl._SSLSocket' objects}
        1    0.025    0.025    0.025    0.025 {method 'do_handshake' of '_ssl._SSLSocket' objects}
        1    0.024    0.024    0.024    0.024 {method 'connect' of '_socket.socket' objects}
        1    0.001    0.001    0.001    0.001 {built-in method _socket.getaddrinfo}
        8    0.000    0.000    0.000    0.000 {built-in method syslog.syslog}
        2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py:343(raw_decode)
        4    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
  862/822    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        4    0.000    0.000    0.001    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_t621k_wm/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/api.py:112(debug_api)
        3    0.000    0.000    0.000    0.000 {method 'write' of '_ssl._SSLSocket' objects}
      6/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:509(_parse)
        4    0.000    0.000    0.000    0.000 /usr/local/lib/python3.11/site-packages/h11/_headers.py:150(normalize_and_validate)
        2    0.000    0.000    0.000    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_t621k_wm/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/base.py:337(build_diff)
        2    0.000    0.000    0.000    0.000 {built-in method io.open}
       12    0.000    0.000    0.001    0.000 /usr/local/lib/python3.11/site-packages/h11/_connection.py:260(_process_event)
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
       53    0.000    0.000    0.000    0.000 {method 'fullmatch' of 're.Pattern' objects}
        6    0.000    0.000    0.299    0.050 /usr/local/lib/python3.11/site-packages/httpcore/_sync/http11.py:192(_receive_event)
        3    0.000    0.000    0.000    0.000 {method 'poll' of 'select.poll' objects}
     10/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_compiler.py:37(_compile)


2023-09-18 13:04:49:471698 |          6533 function calls (6419 primitive calls) in 0.364 seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        2    0.308    0.154    0.308    0.154 {method 'read' of '_ssl._SSLSocket' objects}
        1    0.022    0.022    0.022    0.022 {method 'do_handshake' of '_ssl._SSLSocket' objects}
        1    0.021    0.021    0.021    0.021 {method 'connect' of '_socket.socket' objects}
        1    0.001    0.001    0.002    0.002 {built-in method _socket.getaddrinfo}
        4    0.000    0.000    0.001    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_h0ysbhki/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/api.py:112(debug_api)
        8    0.000    0.000    0.000    0.000 {built-in method syslog.syslog}
        2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py:343(raw_decode)
  862/822    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        4    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
        3    0.000    0.000    0.000    0.000 {method 'write' of '_ssl._SSLSocket' objects}
      6/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:509(_parse)
        4    0.000    0.000    0.000    0.000 /usr/local/lib/python3.11/site-packages/h11/_headers.py:150(normalize_and_validate)
        2    0.000    0.000    0.000    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_h0ysbhki/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/base.py:337(build_diff)
        2    0.000    0.000    0.000    0.000 {built-in method io.open}
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
       12    0.000    0.000    0.001    0.000 /usr/local/lib/python3.11/site-packages/h11/_connection.py:260(_process_event)
        6    0.000    0.000    0.309    0.052 /usr/local/lib/python3.11/site-packages/httpcore/_sync/http11.py:192(_receive_event)
     10/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_compiler.py:37(_compile)
        3    0.000    0.000    0.000    0.000 {method 'poll' of 'select.poll' objects}
        4    0.000    0.000    0.001    0.000 /usr/local/lib/python3.11/site-packages/httpx/_urlparse.py:149(urlparse)


2023-09-21 15:08:42:450430 |          3792 function calls (3702 primitive calls) in 0.206 seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.151    0.151    0.151    0.151 {method 'read' of '_ssl._SSLSocket' objects}
        1    0.023    0.023    0.023    0.023 {method 'connect' of '_socket.socket' objects}
        1    0.022    0.022    0.022    0.022 {method 'do_handshake' of '_ssl._SSLSocket' objects}
        7    0.001    0.000    0.001    0.000 {built-in method posix.stat}
        1    0.001    0.001    0.001    0.001 {built-in method _socket.getaddrinfo}
        3    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
        1    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py:343(raw_decode)
      6/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:509(_parse)
        2    0.000    0.000    0.002    0.001 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_bqyurshm/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/api.py:112(debug_api)
        2    0.000    0.000    0.000    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_bqyurshm/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/base.py:337(build_diff)
      6/2    0.000    0.000    0.001    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:449(_parse_sub)
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
  519/499    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
     10/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_compiler.py:37(_compile)
        1    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/stringprep.py:1(<module>)
        1    0.000    0.000    0.000    0.000 {built-in method io.open}
        2    0.000    0.000    0.000    0.000 {built-in method syslog.syslog}
        1    0.000    0.000    0.000    0.000 {method 'write' of '_ssl._SSLSocket' objects}
        5    0.000    0.000    0.000    0.000 {built-in method builtins.__build_class__}
        2    0.000    0.000    0.000    0.000 /usr/local/lib/python3.11/site-packages/h11/_headers.py:150(normalize_and_validate)


2023-09-21 15:08:43:064619 |          3896 function calls (3806 primitive calls) in 0.183 seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.128    0.128    0.128    0.128 {method 'read' of '_ssl._SSLSocket' objects}
        1    0.023    0.023    0.023    0.023 {method 'do_handshake' of '_ssl._SSLSocket' objects}
        1    0.023    0.023    0.023    0.023 {method 'connect' of '_socket.socket' objects}
        1    0.001    0.001    0.001    0.001 {built-in method _socket.getaddrinfo}
        1    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py:343(raw_decode)
      6/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:509(_parse)
  564/544    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        2    0.000    0.000    0.001    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_1qgcgwwz/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/api.py:112(debug_api)
        2    0.000    0.000    0.000    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_1qgcgwwz/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/base.py:337(build_diff)
        2    0.000    0.000    0.000    0.000 {built-in method marshal.loads}
     10/2    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_compiler.py:37(_compile)
        3    0.000    0.000    0.000    0.000 {built-in method syslog.syslog}
        2    0.000    0.000    0.000    0.000 /var/folders/6n/spmk0cv14s10d35669xt3kf00000gn/T/ansible_ansibleguy.opnsense.source_nat_payload_1qgcgwwz/ansible_ansibleguy.opnsense.source_nat_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/main.py:333(simplify_translate)
      6/2    0.000    0.000    0.001    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/re/_parser.py:449(_parse_sub)
        6    0.000    0.000    0.001    0.000 /usr/local/lib/python3.11/site-packages/h11/_connection.py:260(_process_event)
        2    0.000    0.000    0.000    0.000 /usr/local/lib/python3.11/site-packages/h11/_headers.py:150(normalize_and_validate)
        3    0.000    0.000    0.000    0.000 {method '__exit__' of '_io._IOBase' objects}
        1    0.000    0.000    0.000    0.000 {method 'write' of '_ssl._SSLSocket' objects}
        1    0.000    0.000    0.000    0.000 /usr/local/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/stringprep.py:1(<module>)
        5    0.000    0.000    0.000    0.000 {built-in method builtins.__build_class__}

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Reproduce

Tasks

Task(s) that produce the error:

    - name: Add Outbound NAT for Wireguard to separate based on source address
      ansibleguy.opnsense.source_nat:
        debug: true
        sequence: "{{ item.sequence }}"
        description: "{{ item.description }}"
        interface: "{{ item.interface }}"
        source_net: "{{ item.source_net }}"
        destination: "{{ item.destination }}"
        match_fields: "{{ item.match_fields }}"
        target: "{{ item.target }}"
        log: "{{ item.log }}"
      loop: "{{ opnsense_outbound_nat }}"

Config

Config used for the task(s):

opnsense_outbound_nat:
  - interface: 'lan'
    sequence: '1'
    match_fields: '[''description'']'
    description: 'translate from  AMS'
    source_net: '192.168.255.2/32'
    destination: 'any'
    target: '10.0.0.10/32'
    log: 'true'
  - interface: 'lan'
    sequence: '2'
    match_fields: '[''description'']'
    description: 'translate from OTHER'
    source_net: '192.168.250.4/32'
    destination: 'any'
    target: '10.0.0.20/32'
    log: 'true'

OPNSense config

(If the issue only occurs when non ansible-managed config is modified)

Invalid IDNA hostname

Modules

All modules

Version

ansibleguy.opnsense           1.2.8

Ansible Version

ansible [core 2.15.8]
  config file = /Users/eozhmegov/Repos/nautobot-device-config/ansible.cfg
  configured module search path = ['/Users/eozhmegov/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/eozhmegov/Library/Python/3.9/lib/python/site-packages/ansible
  ansible collection location = /Users/eozhmegov/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.6 (default, Nov 10 2023, 13:38:27) [Clang 15.0.0 (clang-1500.1.0.2.5)] (/Library/Developer/CommandLineTools/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

OPNSense Version

23.7.11

OPNSense-Plugin Version

No response

Issue

I created palybook and tried to create vlan interface but i got an error

Config Ansible

inventory
opnsense:
  hosts:
    opnsense_test:
      ansible_host: 10.64.244.2

role

- name: Add Vlan interface
  ansibleguy.opnsense.interface_vlan:
    debug: true
    profiling: true
    firewall: "10.64.244.2"
    ssl_verify: false
    api_key: "{{ api_key }}"
    api_secret: "{{ api_secret }}"
    description: "{{ item.description }}"
    interface: "{{ item.interface }}"
    vlan: "{{ item.vlan }}"
    state: 'present'
  loop: "{{ vlan_interfaces }}"

playbook

---
- name: opnsense
  hosts: opnsense
  gather_facts: no
  roles:
    - role: interface_vlan
      tags:
        - interface_vlan

Config OPNSense

No response

Debug Output

<10.64.244.2> attempting to start connection
<10.64.244.2> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/local/bin/ansible-connection
<10.64.244.2> found existing local domain socket, using it!
<10.64.244.2> updating play_context for connection
<10.64.244.2> Loading collection ansible.builtin from
<10.64.244.2> local domain socket path is /Users/eozhmegov/.ansible/pc/92153acdae
<10.64.244.2> ESTABLISH LOCAL CONNECTION FOR USER: eozhmegov
<10.64.244.2> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy `"&& mkdir "` echo /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077 `" && echo ansible-tmp-1705655827.2279449-48280-142015464034077="` echo /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077 `" ) && sleep 0'
Using module file /Users/eozhmegov/.ansible/collections/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py
<10.64.244.2> PUT /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/tmp978_1myx TO /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py
<10.64.244.2> EXEC /bin/sh -c 'chmod u+x /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/ /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py && sleep 0'
<10.64.244.2> EXEC /bin/sh -c '/usr/bin/env python3 /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py && sleep 0'
<10.64.244.2> EXEC /bin/sh -c 'rm -f -r /Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py", line 325, in encode_host
    return idna.encode(host.lower()).decode("ascii")
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py", line 360, in encode
    s = alabel(label)
        ^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py", line 269, in alabel
    check_label(label)
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py", line 250, in check_label
    raise InvalidCodepoint('Codepoint {} at position {} of {} not allowed'.format(_unot(cp_value), pos+1, repr(label)))
idna.core.InvalidCodepoint: Codepoint U+002A at position 1 of '*โ€™*โ€™' not allowed

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py", line 107, in <module>
    _ansiballz_main()
  File "/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.interface_vlan', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.interface_vlan', _modlib_path=modlib_path),
  File "<frozen runpy>", line 226, in run_module
  File "<frozen runpy>", line 98, in _run_module_code
  File "<frozen runpy>", line 88, in _run_code
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py", line 74, in <module>
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py", line 70, in main
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py", line 63, in run_module
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/main/interface_vlan.py", line 43, in __init__
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/cls.py", line 19, in __init__
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py", line 24, in __init__
  File "/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py", line 29, in start
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_client.py", line 696, in __init__
    self._mounts: typing.Dict[URLPattern, typing.Optional[BaseTransport]] = {
                                                                            ^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_client.py", line 697, in <dictcomp>
    URLPattern(key): None
    ^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_utils.py", line 370, in __init__
    url = URL(pattern)
          ^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urls.py", line 115, in __init__
    self._uri_reference = urlparse(url, **kwargs)
                          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py", line 245, in urlparse
    parsed_host: str = encode_host(host)
                       ^^^^^^^^^^^^^^^^^
  File "/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py", line 327, in encode_host
    raise InvalidURL(f"Invalid IDNA hostname: {host!r}")
httpx.InvalidURL: Invalid IDNA hostname: '*โ€™*โ€™'
failed: [opnsense_test] (item={'vlan': 1210, 'interface': 'lagg0', 'description': 'Bozon_DMZ'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "description": "Bozon_DMZ",
        "interface": "lagg0",
        "vlan": 1210
    },
    "module_stderr": "Traceback (most recent call last):\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py\", line 325, in encode_host\n    return idna.encode(host.lower()).decode(\"ascii\")\n           ^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py\", line 360, in encode\n    s = alabel(label)\n        ^^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py\", line 269, in alabel\n    check_label(label)\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/idna/core.py\", line 250, in check_label\n    raise InvalidCodepoint('Codepoint {} at position {} of {} not allowed'.format(_unot(cp_value), pos+1, repr(label)))\nidna.core.InvalidCodepoint: Codepoint U+002A at position 1 of '*โ€™*โ€™' not allowed\n\nDuring handling of the above exception, another exception occurred:\n\nTraceback (most recent call last):\n  File \"/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/Users/eozhmegov/.ansible/tmp/ansible-local-48277lki0plgy/ansible-tmp-1705655827.2279449-48280-142015464034077/AnsiballZ_interface_vlan.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.interface_vlan', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.interface_vlan', _modlib_path=modlib_path),\n  File \"<frozen runpy>\", line 226, in run_module\n  File \"<frozen runpy>\", line 98, in _run_module_code\n  File \"<frozen runpy>\", line 88, in _run_code\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py\", line 74, in <module>\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py\", line 70, in main\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/interface_vlan.py\", line 63, in run_module\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/main/interface_vlan.py\", line 43, in __init__\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/cls.py\", line 19, in __init__\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py\", line 24, in __init__\n  File \"/var/folders/vg/53v4gk1d0_92crvnv3gws_dw0000gn/T/ansible_ansibleguy.opnsense.interface_vlan_payload_0rykgfxo/ansible_ansibleguy.opnsense.interface_vlan_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py\", line 29, in start\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_client.py\", line 696, in __init__\n    self._mounts: typing.Dict[URLPattern, typing.Optional[BaseTransport]] = {\n                                                                            ^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_client.py\", line 697, in <dictcomp>\n    URLPattern(key): None\n    ^^^^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_utils.py\", line 370, in __init__\n    url = URL(pattern)\n          ^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urls.py\", line 115, in __init__\n    self._uri_reference = urlparse(url, **kwargs)\n                          ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py\", line 245, in urlparse\n    parsed_host: str = encode_host(host)\n                       ^^^^^^^^^^^^^^^^^\n  File \"/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/httpx/_urlparse.py\", line 327, in encode_host\n    raise InvalidURL(f\"Invalid IDNA hostname: {host!r}\")\nhttpx.InvalidURL: Invalid IDNA hostname: '*โ€™*โ€™'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

Profiling Output

No response

ValueError: ansible_collections.ansibleguy.opnsense.__spec__ is None

Discussed in #15

Originally posted by riffy99 May 9, 2023
Hi, I've spent a good while trying to get up and running but have hit an issue I can't see the cause of. I'm sure I have the correct install, and I've tried on a number of machines with the same result.

My playbook looks like this:

#
---
- hosts: 4D_FW
  connection: local
  gather_facts: no
  tasks:
    - name: Example
      ansibleguy.opnsense.alias:
        firewall: "{{ ansible_host }}"
        api_credential_file: 'api.key'
        ssl_verify: false
    - name: Example_test
      ansibleguy.opnsense.alias:
        name: 'ANSIBLE_TEST1'
        type: 'host'
        content: ['1.1.1.1']

But I'm getting this error:

ASK [Example] *********************************************************************************************************************************************************************
task path: /Users/richard.fry/4d_fw.yml:9
<10.40.0.11> ESTABLISH LOCAL CONNECTION FOR USER: richard.fry
<10.40.0.11> EXEC /bin/sh -c 'echo ~richard.fry && sleep 0'
<10.40.0.11> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /Users/richard.fry/.ansible/tmp `"&& mkdir "` echo /Users/richard.fry/.ansible/tmp/ansible-tmp-1683642816.998871-66703-99538016419058 `" && echo ansible-tmp-1683642816.998871-66703-99538016419058="` echo /Users/richard.fry/.ansible/tmp/ansible-tmp-1683642816.998871-66703-99538016419058 `" ) && sleep 0'
<10.40.0.11> EXEC /bin/sh -c 'rm -f -r /Users/richard.fry/.ansible/tmp/ansible-tmp-1683642816.998871-66703-99538016419058/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/task_executor.py", line 158, in run
    res = self._execute()
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/task_executor.py", line 663, in _execute
    result = self._handler.run(task_vars=variables)
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/plugins/action/normal.py", line 47, in run
    result = merge_hash(result, self._execute_module(task_vars=task_vars, wrap_async=wrap_async))
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/plugins/action/__init__.py", line 861, in _execute_module
    (module_style, shebang, module_data, module_path) = self._configure_module(module_name=module_name, module_args=module_args, task_vars=task_vars)
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/plugins/action/__init__.py", line 231, in _configure_module
    (module_data, module_style, module_shebang) = modify_module(module_name, module_path, module_args, self._templar,
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 1299, in modify_module
    (b_module_data, module_style, shebang) = _find_module_utils(module_name, b_module_data, module_path, module_args, task_vars, templar, module_compression,
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 1139, in _find_module_utils
    recursive_finder(module_name, remote_module_fqn, b_module_data, zf)
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 917, in recursive_finder
    module_info = CollectionModuleUtilLocator(py_module_name, is_ambiguous=is_ambiguous, child_is_redirected=child_is_redirected)
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 812, in __init__
    self._locate()
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 706, in _locate
    if self._find_module(candidate_name_parts):
  File "/Users/richard.fry/Library/Python/3.8/lib/python/site-packages/ansible/executor/module_common.py", line 832, in _find_module
    src = pkgutil.get_data(collection_pkg_name, to_native(os.path.join(resource_base_path, '__init__.py')))
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pkgutil.py", line 619, in get_data
    spec = importlib.util.find_spec(package)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/importlib/util.py", line 114, in find_spec
    raise ValueError('{}.__spec__ is None'.format(name))
ValueError: ansible_collections.ansibleguy.opnsense.__spec__ is None
fatal: [10.40.0.11]: FAILED! => {
    "msg": "Unexpected failure during module execution.",
    "stdout": ""
}

PLAY RECAP *************************************************************************************************************************************************************************
10.40.0.11                 : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

Any pointers would be greatly appreciated.
Thanks, Richard

Feature: Multi-Modules - Refactor Item-Validation

Link to API

Description

I came across some module-code that implements Ansible parameter-validation for items inside a dict

Example:

            extended_query=dict(type='dict', options=dict(
                attributes=dict(type='list', elements='str', required=True),
                where=dict(
                    type='list',
                    elements='dict',
                    options={
                        'attribute': dict(type='str'),
                        'is': dict(type='str', choices=["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]),
                        'value': dict(type='raw'),
                        'or': dict(type='list', elements='dict', options={
                            'attribute': dict(type='str', required=True),
                            'is': dict(type='str', choices=["==", "!=", ">", "<", "in", "eq", "not", "more", "less"], required=True),
                            'value': dict(type='raw', required=True),
                        }),
                    },
                    required_together=[('attribute', 'is', 'value')],
                    mutually_exclusive=[('attribute', 'or')],
                    required_one_of=[('attribute', 'or')],
                ),
            )),

This could make the validation in multi modules simpler and therefor cleaner.

Problem: update of the 'content' field for the alias doesn't work as expected

Modules

alias

Version

ansibleguy.opnsense 1.2.8

Ansible Version

ansible [core 2.14.3]

OPNSense Version

24.1.3_1

OPNSense-Plugin Version

No response

Issue

Dear Ansible Guy,

It seems, that update of an alias is not really working correctly. I have the following situation:

vars/test.yml:
  - { name: "LIST", type: "urltable", content: ['https://ex.net/test'], ufq: 0.5 }

Playbook:

- hosts: localhost
  gather_facts: yes
  vars_files:
    - vars/test.yml
  module_defaults:
    group/ansibleguy.opnsense.all:
      ...

  tasks:
    - name: Configure Firewall Aliases
      ansibleguy.opnsense.alias:
        name: "{{ item.name }}"
        type: "{{ item.type }}"
        content: "{{ item.content }}"
        updatefreq_days: "{{ item.ufq }}"
        state: "{{ item.state | default('present') }}"
        reload: true
      with_items: "{{ aliases }}"

If I run the playbook with ansible-playbook -D opnsense.yml it gives me OK, but doesn't change the value of LIST alias. Is it the expected behaviour? Creation works as expected though.

Thanks!
M.

Config Ansible

no special configuration used

Config OPNSense

No response

Debug Output

PLAY [localhost] ***********************************************************************************************************************

TASK [Gathering Facts] *****************************************************************************************************************
ok: [localhost]

TASK [Configure Firewall Aliases] ******************************************************************************************************
ok: [localhost] => (item={'name': 'LIST', 'type': 'urltable', 'content': ['https://ex.net/test'], 'ufq': 0.5})

PLAY RECAP *****************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Profiling Output

No response

[unbound_host] Problems with matching

Discussed in #19

Originally posted by Bubbgump209 June 29, 2023
For the life of me I can't get an IP to match when using the Unbound host-override.

- name: Remove DNS record from OPNsense1
        ansibleguy.opnsense.unbound_host:
          firewall: 'opnsense1'
          hostname: '{{ hostname[0] }}'
          domain: 'lan'
          value: '{{ HostIP_input }}'
          state: 'absent'
          match_fields: ['hostname', 'domain', 'value']

Here's some debug where the variable sure looks right to me:

TASK [Make FQDN into a fact] ***************************************************
ok: [localhost]

TASK [Lookup host] *************************************************************
ok: [localhost] => {
    "msg": "192.168.73.205"
}

TASK [ansible.builtin.debug] ***************************************************
ok: [localhost] => {
    "HostIP_input": {
        "changed": false,
        "failed": false,
        "msg": "192.168.73.205"
    }
}

TASK [Calculate host name] *****************************************************
ok: [localhost]

TASK [ansible.builtin.debug] ***************************************************
ok: [localhost] => {
    "hostname": [
        "deleteme4",
        "lan"
    ]
}

TASK [ansible.builtin.debug] ***************************************************
ok: [localhost] => {
    "hostname[0]": "deleteme4"
}

TASK [Remove DNS record from OPNsense1] ****************************************
ok: [localhost]

TASK [ansible.builtin.debug] ***************************************************
ok: [localhost] => {
    "wtf": {
        "changed": false,
        "diff": {},
        "failed": false
    }
}

Note the "Lookup host" step is querying Unbound to get the IP - so I know it is correct.
What do I have to do to get the IP to match 'value'?

Feature: Trigger HA-Sync

Link to API

Does not exist - as far as I've seen.
But It would be very useful IF it can be done using the api-key auth..

Description

The action performed by the button at System - High Availibility - Status

The call seems to be very simple:
https://<fw>/status_habackup.php with form-data exec_sync

Could be used like reload - after some changes we want to perform a config-sync.
As a workaround: Currently one can use a cron-job to schedule the config-sync

Problem: unbound_host - duplicate entries

Modules

unbound_host

Version

1.2.8

Ansible Version

ansible [core 2.16.4]

OPNSense Version

OPNsense 24.1.2_1-amd64

OPNSense-Plugin Version

No response

Issue

The module does not recognize when an override already exists. It re-creates them every time.
We have 100+ of them.

Config Ansible

- name: "OPNSENSE | DNS | {{ domain }} | Add hosts override"
  ansibleguy.opnsense.unbound_host:
    domain: "{{ domain }}"
    hostname: "{{ item.key }}"
    value: "{{ item.value.ip | default(item.value) }}"
    record_type: "{% if 'type' in item.value %}\
    {{ item.value.type }}\
    {% elif item.value.ip | default(item.value) | ansible.utils.ipv4 %}\
    A\
    {% else %}\
    AAAA\
    {% endif %}"
    reload: false
    debug: true
  with_dict: "{{ hosts }}"

Config OPNSense

No response

Debug Output

Contains too much information

Profiling Output

No response

Problem: Module httpx not found

Modules

wireguard_server

Version

1.2.8

Ansible Version

2.16.5

OPNSense Version

24.1.5_3

OPNSense-Plugin Version

No response

Issue

I'm trying to use your fantastic collection but when I want to create a wireguard server but i have this error :

  module_stderr: |-
    Traceback (most recent call last):
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/wireguard_server.py", line 14, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/wrapper.py", line 5, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/cls.py", line 3, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py", line 3, in <module>
    ModuleNotFoundError: No module named 'httpx'
  
    During handling of the above exception, another exception occurred:
  
    Traceback (most recent call last):
      File "<stdin>", line 107, in <module>
      File "<stdin>", line 99, in _ansiballz_main
      File "<stdin>", line 47, in invoke_module
      File "<frozen runpy>", line 226, in run_module
      File "<frozen runpy>", line 98, in _run_module_code
      File "<frozen runpy>", line 88, in _run_code
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/wireguard_server.py", line 22, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 32, in module_dependency_error
      File "/tmp/ansible_ansibleguy.opnsense.wireguard_server_payload_uln55_yi/ansible_ansibleguy.opnsense.wireguard_server_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 24, in exit_env
    ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler.AnsibleModuleError: ENVIRONMENTAL ERROR: For this Ansible-module to work you must install its dependencies first: 'python3 -m pip install --upgrade httpx'
  module_stdout: ''
  msg: |-
    MODULE FAILURE
    See stdout/stderr for the exact error
  rc: 1

but the module httpx is instaled :

python3 -m pip install --upgrade httpx
Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: httpx in /home/romain/.local/lib/python3.10/site-packages (0.27.0)
Requirement already satisfied: httpcore==1.* in /home/romain/.local/lib/python3.10/site-packages (from httpx) (1.0.5)
Requirement already satisfied: certifi in /usr/lib/python3/dist-packages (from httpx) (2020.6.20)
Requirement already satisfied: anyio in /usr/lib/python3/dist-packages (from httpx) (3.5.0)
Requirement already satisfied: idna in /usr/lib/python3/dist-packages (from httpx) (3.3)
Requirement already satisfied: sniffio in /usr/lib/python3/dist-packages (from httpx) (1.2.0)
Requirement already satisfied: h11<0.15,>=0.13 in /usr/lib/python3/dist-packages (from httpcore==1.*->httpx) (0.13.0)

Config Ansible

# config file for ansible -- http://ansible.com/
# ==============================================

# nearly all parameters can be overridden in ansible-playbook
# or with command line flags. ansible will read ANSIBLE_CONFIG,
# ansible.cfg in the current working directory, .ansible.cfg in
# the home directory or /etc/ansible/ansible.cfg, whichever it
# finds first

[defaults]

# some basic default values...

inventory      = ./inventory/inventory_hosts
library        = ./library
#remote_tmp     = ~/.ansible/tmp
#local_tmp      = ~/.ansible/tmp
forks          = 20
#poll_interval  = 15
#sudo_user      = root
#ask_sudo_pass = True
#ask_pass      = True
#transport      = smart
#remote_port    = 22
#module_lang    = C
#module_set_locale = False
retries = 3

# plays will gather facts by default, which contain information about
# the remote system.
#
# smart - gather by default, but don't regather if already gathered
# implicit - gather by default, turn off with gather_facts: False
# explicit - do not gather by default, must say gather_facts: True
#gathering = implicit

# by default retrieve all facts subsets
# all - gather all subsets
# network - gather min and network facts
# hardware - gather hardware facts (longest facts to retrieve)
# virtual - gather min and virtual facts
# facter - import facts from facter
# ohai - import facts from ohai
# You can combine them using comma (ex: network,virtual)
# You can negate them using ! (ex: !hardware,!facter,!ohai)
# A minimal set of facts is always gathered.
#gather_subset = all

# some hardware related facts are collected
# with a maximum timeout of 10 seconds. This
# option lets you increase or decrease that
# timeout to something more suitable for the
# environment.
gather_timeout = 30

# additional paths to search for roles in, colon separated
roles_path    = ./roles

# uncomment this to disable SSH key host checking
#host_key_checking = False

# change the default callback
### AFFICHAGE COMPACT OU NON
stdout_callback = yaml
#, yaml
display_skipped_hosts = no
display_ok_hosts = no
#stdout_callback = anstomlog
# enable additional callbacks
#callback_whitelist = timer, mail, profile_roles
callback_whitelist = timer

# Determine whether includes in tasks and handlers are "static" by
# default. As of 2.0, includes are dynamic by default. Setting these
# values to True will make includes behave more like they did in the
# 1.x versions.
#task_includes_static = True
#handler_includes_static = True

# Controls if a missing handler for a notification event is an error or a warning
#error_on_missing_handler = True

# change this for alternative sudo implementations
#sudo_exe = sudo

# What flags to pass to sudo
# WARNING: leaving out the defaults might create unexpected behaviours
#sudo_flags = -H -S -n

# SSH timeout
timeout = 30

# default user to use for playbooks if user is not specified
# (/usr/bin/ansible will use current user as default)
remote_user = deploy

# logging is off by default unless this path is defined
# if so defined, consider logrotate
#log_path = /var/log/ansible.log

# default module name for /usr/bin/ansible
#module_name = command

# use this shell for commands executed under sudo
# you may need to change this to bin/bash in rare instances
# if sudo is constrained
#executable = /bin/sh

# if inventory variables overlap, does the higher precedence one win
# or are hash values merged together?  The default is 'replace' but
# this can also be set to 'merge'.
#hash_behaviour = replace

# by default, variables from roles will be visible in the global variable
# scope. To prevent this, the following option can be enabled, and only
# tasks and handlers within the role will see the variables there
#private_role_vars = yes

# list any Jinja2 extensions to enable here:
#jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n

# if set, always use this private key file for authentication, same as
# if passing --private-key to ansible or ansible-playbook
#private_key_file = /path/to/file

# If set, configures the path to the Vault password file as an alternative to
# specifying --vault-password-file on the command line.
#vault_password_file = ./.ansible_vault

# format of string {{ ansible_managed }} available within Jinja2
# templates indicates to users editing templates files will be replaced.
# replacing {file}, {host} and {uid} and strftime codes with proper values.
#ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}
# {file}, {host}, {uid}, and the timestamp can all interfere with idempotence
# in some situations so the default is a static string:
#ansible_managed = Ansible managed

# by default, ansible-playbook will display "Skipping [host]" if it determines a task
# should not be run on a host.  Set this to "False" if you don't want to see these "Skipping"
# messages. NOTE: the task header will still be shown regardless of whether or not the
# task is skipped.
#display_skipped_hosts = True

# by default, if a task in a playbook does not include a name: field then
# ansible-playbook will construct a header that includes the task's action but
# not the task's args.  This is a security feature because ansible cannot know
# if the *module* considers an argument to be no_log at the time that the
# header is printed.  If your environment doesn't have a problem securing
# stdout from ansible-playbook (or you have manually specified no_log in your
# playbook on all of the tasks where you have secret information) then you can
# safely set this to True to get more informative messages.
#display_args_to_stdout = False

# by default (as of 1.3), Ansible will raise errors when attempting to dereference
# Jinja2 variables that are not set in templates or action lines. Uncomment this line
# to revert the behavior to pre-1.3.
#error_on_undefined_vars = False

# by default (as of 1.6), Ansible may display warnings based on the configuration of the
# system running ansible itself. This may include warnings about 3rd party packages or
# other conditions that should be resolved if possible.
# to disable these warnings, set the following value to False:
#system_warnings = True

# by default (as of 1.4), Ansible may display deprecation warnings for language
# features that should no longer be used and will be removed in future versions.
# to disable these warnings, set the following value to False:
#deprecation_warnings = True

# (as of 1.8), Ansible can optionally warn when usage of the shell and
# command module appear to be simplified by using a default Ansible module
# instead.  These warnings can be silenced by adjusting the following
# setting or adding warn=yes or warn=no to the end of the command line
# parameter string.  This will for example suggest using the git module
# instead of shelling out to the git command.
# command_warnings = False


# set plugin path directories here, separate with colons
#action_plugins     = /usr/share/ansible/plugins/action
#cache_plugins      = /usr/share/ansible/plugins/cache
callback_plugins   = ./plugins/callback
#connection_plugins = /usr/share/ansible/plugins/connection
#lookup_plugins     = ./plugins/lookup
#inventory_plugins  = /usr/share/ansible/plugins/inventory
#vars_plugins       = /usr/share/ansible/plugins/vars
#filter_plugins     = /usr/share/ansible/plugins/filter
#test_plugins       = /usr/share/ansible/plugins/test
#strategy_plugins   = /usr/local/lib/python3.7/dist-packages/ansible_mitogen/plugins/strategy/
#strategy	   = mitogen_linear

# by default callbacks are not loaded for /bin/ansible, enable this if you
# want, for example, a notification or logging callback to also apply to
# /bin/ansible runs
#bin_ansible_callbacks = False


# don't like cows?  that's unfortunate.
# set to 1 if you don't want cowsay support or export ANSIBLE_NOCOWS=1
#nocows = 1

# set which cowsay stencil you'd like to use by default. When set to 'random',
# a random stencil will be selected for each task. The selection will be filtered
# against the `cow_whitelist` option below.
#cow_selection = default
#cow_selection = random

# when using the 'random' option for cowsay, stencils will be restricted to this list.
# it should be formatted as a comma-separated list with no spaces between names.
# NOTE: line continuations here are for formatting purposes only, as the INI parser
#       in python does not support them.
#cow_whitelist=bud-frogs,bunny,cheese,daemon,default,dragon,elephant-in-snake,elephant,eyes,\
#              hellokitty,kitty,luke-koala,meow,milk,moofasa,moose,ren,sheep,small,stegosaurus,\
#              stimpy,supermilker,three-eyes,turkey,turtle,tux,udder,vader-koala,vader,www

# don't like colors either?
# set to 1 if you don't want colors, or export ANSIBLE_NOCOLOR=1
#nocolor = 1

# if set to a persistent type (not 'memory', for example 'redis') fact values
# from previous runs in Ansible will be stored.  This may be useful when
# wanting to use, for example, IP information from one group of servers
# without having to talk to them in the same playbook run to get their
# current IP information.
#fact_caching = memory
fact_caching_connection = .cache
fact_caching_timeout = 60
fact_caching = jsonfile

# retry files
# When a playbook fails by default a .retry file will be created in ~/
# You can disable this feature by setting retry_files_enabled to False
# and you can change the location of the files by setting retry_files_save_path

retry_files_enabled = False
#retry_files_save_path = ~/.ansible-retry

# squash actions
# Ansible can optimise actions that call modules with list parameters
# when looping. Instead of calling the module once per with_ item, the
# module is called once with all items at once. Currently this only works
# under limited circumstances, and only with parameters named 'name'.
#squash_actions = apk,apt,dnf,homebrew,package,pacman,pkgng,yum,zypper

# prevents logging of task data, off by default
#no_log = False

# prevents logging of tasks, but only on the targets, data is still logged on the master/controller
#no_target_syslog = False

# controls whether Ansible will raise an error or warning if a task has no
# choice but to create world readable temporary files to execute a module on
# the remote machine.  This option is False by default for security.  Users may
# turn this on to have behaviour more like Ansible prior to 2.1.x.  See
# https://docs.ansible.com/ansible/become.html#becoming-an-unprivileged-user
# for more secure ways to fix this than enabling this option.
#allow_world_readable_tmpfiles = False

# controls the compression level of variables sent to
# worker processes. At the default of 0, no compression
# is used. This value must be an integer from 0 to 9.
#var_compression_level = 9

# controls what compression method is used for new-style ansible modules when
# they are sent to the remote system.  The compression types depend on having
# support compiled into both the controller's python and the client's python.
# The names should match with the python Zipfile compression types:
# * ZIP_STORED (no compression. available everywhere)
# * ZIP_DEFLATED (uses zlib, the default)
# These values may be set per host via the ansible_module_compression inventory
# variable
#module_compression = 'ZIP_DEFLATED'

# This controls the cutoff point (in bytes) on --diff for files
# set to 0 for unlimited (RAM may suffer!).
#max_diff_size = 1048576

[privilege_escalation]
become=True
become_method=sudo
#become_user=root
#become_ask_pass=False

[paramiko_connection]

# uncomment this line to cause the paramiko connection plugin to not record new host
# keys encountered.  Increases performance on new host additions.  Setting works independently of the
# host key checking setting above.
#record_host_keys=False

# by default, Ansible requests a pseudo-terminal for commands executed under sudo. Uncomment this
# line to disable this behaviour.
#pty=False

[ssh_connection]

# ssh arguments to use
# Leaving off ControlPersist will result in poor performance, so use
# paramiko on older platforms rather than removing it, -C controls compression use
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o PreferredAuthentications=publickey,password -o StrictHostKeyChecking=accept-new
#ssh_args = -C -o ControlMaster=no -o ControlPersist=no -o ControlPath=none

# The path to use for the ControlPath sockets. This defaults to
# "%(directory)s/ansible-ssh-%%h-%%p-%%r", however on some systems with
# very long hostnames or very long path names (caused by long user names or
# deeply nested home directories) this can exceed the character limit on
# file socket names (108 characters for most platforms). In that case, you
# may wish to shorten the string below.
#
# Example:
control_path = %(directory)s/%%h-%%r
#control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r

# Enabling pipelining reduces the number of SSH operations required to
# execute a module on the remote server. This can result in a significant
# performance improvement when enabled, however when using "sudo:" you must
# first disable 'requiretty' in /etc/sudoers
#
# By default, this option is disabled to preserve compatibility with
# sudoers configurations that have requiretty (the default on many distros).
#
pipelining = true

# Control the mechanism for transfering files
#   * smart = try sftp and then try scp [default]
#   * True = use scp only
#   * False = use sftp only
#scp_if_ssh = smart
# Control the mechanism for transferring files (new)
# If set, this will override the scp_if_ssh option
#   * sftp  = use sftp to transfer files
#   * scp   = use scp to transfer files
#   * piped = use 'dd' over SSH to transfer files
#   * smart = try sftp, scp, and piped, in that order [default]
transfer_method = smart


# if False, sftp will not use batch mode to transfer files. This may cause some
# types of file transfer failures impossible to catch however, and should
# only be disabled if your sftp version has problems with batch mode
#sftp_batch_mode = False

[accelerate]
#accelerate_port = 5099
#accelerate_timeout = 30
#accelerate_connect_timeout = 5.0

# The daemon timeout is measured in minutes. This time is measured
# from the last activity to the accelerate daemon.
#accelerate_daemon_timeout = 30

# If set to yes, accelerate_multi_key will allow multiple
# private keys to be uploaded to it, though each user must
# have access to the system via SSH to add a new key. The default
# is "no".
#accelerate_multi_key = yes

[selinux]
# file systems that require special treatment when dealing with security context
# the default behaviour that copies the existing context or uses the user default
# needs to be changed to use the file system dependent context.
#special_context_filesystems=nfs,vboxsf,fuse,ramfs

# Set this to yes to allow libvirt_lxc connections to work without SELinux.
#libvirt_lxc_noseclabel = yes

[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan

Config OPNSense

The "default" one.

Debug Output

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler.AnsibleModuleError: ENVIRONMENTAL ERROR: For this Ansible-module to work you must install its dependencies first: 'python3 -m pip install --upgrade httpx'
fatal: [SRV]: FAILED! => changed=false 
  module_stderr: |-
    Traceback (most recent call last):
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/alias.py", line 14, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/helper/wrapper.py", line 5, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/cls.py", line 3, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/api.py", line 3, in <module>
    ModuleNotFoundError: No module named 'httpx'
  
    During handling of the above exception, another exception occurred:
  
    Traceback (most recent call last):
      File "<stdin>", line 107, in <module>
      File "<stdin>", line 99, in _ansiballz_main
      File "<stdin>", line 47, in invoke_module
      File "<frozen runpy>", line 226, in run_module
      File "<frozen runpy>", line 98, in _run_module_code
      File "<frozen runpy>", line 88, in _run_code
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/alias.py", line 21, in <module>
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 32, in module_dependency_error
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_4vswmnbd/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 24, in exit_env
    ansible_collections.ansibleguy.opnsense.plugins.module_utils.base.handler.AnsibleModuleError: ENVIRONMENTAL ERROR: For this Ansible-module to work you must install its dependencies first: 'python3 -m pip install --upgrade httpx'
  module_stdout: ''
  msg: |-
    MODULE FAILURE
    See stdout/stderr for the exact error
  rc: 1

Profiling Output

No response

Problem: wireguard_server - no tunnel address parameter

Modules

wireguard_server

https://github.com/opnsense/plugins/blob/master/net/wireguard-go/src/opnsense/mvc/app/models/OPNsense/Wireguard/Server.xml#L40

Version

1.2.8

Ansible Version

ansible [core 2.14.5]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/rath/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/rath/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/rath/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/rath/.local/bin/ansible
  python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True

OPNSense Version

23.7.10_1

OPNSense-Plugin Version

2.5_2

Issue

It seems the tunnel_address field/parameter is not implemented.
https://github.com/ansibleguy/collection_opnsense/blob/latest/plugins/modules/wireguard_server.py#L29
https://opnsense.ansibleguy.net/en/latest/modules/wireguard.html#ansibleguy-opnsense-wireguard-server

Config Ansible

-

Config OPNSense

No response

Debug Output

-

Profiling Output

No response

ModuleNotFoundError: No module named 'ansible.errors'

Tasks

Please make sure to go through these steps before opening an issue:

  • Read the documentation of the affected module: Docs

  • Read the troubleshooting info: Info

Basic info

  • Affected Module:

Versions

  • Controller

    • Collection version: 1.2.2

      (ansible-galaxy collection list | grep opnsense)

    • Ansible & Python version: 2.15.0

      (ansible --version)

  • OPNSense

    • System version: 23.1.8

    • Plugin version:

      (if applicable)

Describe the bug

Cannot run any task due to `ModuleNotFoundError: No module named 'ansible.errors'

Expected behavior

Task run successfully

Debug output

Set the debug option and copy its output.

TASK [opnsense : check opnsense items] ********************************************************************************
task path: /home/mangkoran/sch/sem-8/psm/pve-ansible/pve/roles/opnsense/tasks/main.yml:1
<10.10.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<10.10.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' 10.10.1.3 '/bin/sh -c '"'"'echo ~root && sleep
0'"'"''
<10.10.1.3> (0, b'/root\n', b'')
<10.10.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<10.10.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' 10.10.1.3 '/bin/sh -c '"'"'( umask 77 && mkdir
-p "` echo /root/.ansible/tmp `"&& mkdir "` echo /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265 `" && echo ansible-tmp-1687235576.8458383-27128-128500511019265="` echo /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265 `" ) && sleep 0'"'"''
<10.10.1.3> (0, b'ansible-tmp-1687235576.8458383-27128-128500511019265=/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265\n', b'')
Using module file /home/mangkoran/.ansible/collections/ansible_collections/ansibleguy/opnsense/plugins/modules/list.py
<10.10.1.3> PUT /home/mangkoran/.ansible/tmp/ansible-local-27114japdiieu/tmp2e58stmt TO /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py
<10.10.1.3> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' '[10.10.1.3]'
<10.10.1.3> (0, b'sftp> put /home/mangkoran/.ansible/tmp/ansible-local-27114japdiieu/tmp2e58stmt /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py\n', b'')
<10.10.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<10.10.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' 10.10.1.3 '/bin/sh -c '"'"'chmod u+x /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/ /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py && sleep 0'"'"''
<10.10.1.3> (0, b'', b'')
<10.10.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<10.10.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' -tt 10.10.1.3 '/bin/sh -c '"'"'/usr/bin/env python3 /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py && sleep 0'"'"''
<10.10.1.3> (1, b'Traceback (most recent call last):\r\n  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 107, in <module>\r\n    _ansiballz_main()\r\n  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 99, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 47, in invoke_module\r\n    runpy.run_module(mod_name=\'ansible_collections.ansibleguy.opnsense.plugins.modules.list\', init_globals=dict(_module_fqn=\'ansible_collections.ansibleguy.opnsense.plugins.modules.list\', _modlib_path=modlib_path),\r\n  File "/usr/local/lib/python3.9/runpy.py", line 225, in run_module\r\n    return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File "/usr/local/lib/python3.9/runpy.py", line 97, in _run_module_code\r\n    _run_code(code, mod_globals, init_globals,\r\n  File "/usr/local/lib/python3.9/runpy.py", line 87,
in _run_code\r\n    exec(code, run_globals)\r\n  File "/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/list.py", line 11, in <module>\r\n  File "<frozen zipimport>", line 259, in load_module\r\n  File "/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 1, in <module>\r\nModuleNotFoundError: No module named \'ansible.errors\'\r\n', b'Shared connection to 10.10.1.3 closed.\r\n')
<10.10.1.3> Failed to connect to the host via ssh: Shared connection to 10.10.1.3 closed.
<10.10.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<10.10.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o 'ControlPath="/home/mangkoran/.ansible/cp/6fe2c6f04f"' 10.10.1.3 '/bin/sh -c '"'"'rm -f -r /root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/ > /dev/null 2>&1 && sleep 0'"'"''
<10.10.1.3> (0, b'', b'')
The full traceback is:
Traceback (most recent call last):
  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 107, in <module>
    _ansiballz_main()
  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.list', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.list', _modlib_path=modlib_path),
  File "/usr/local/lib/python3.9/runpy.py", line 225, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/local/lib/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/local/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/list.py", line 11, in <module>
  File "<frozen zipimport>", line 259, in load_module
  File "/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 1, in <module>
ModuleNotFoundError: No module named 'ansible.errors'
fatal: [opnsense1]: FAILED! => {
    "changed": false,
    "module_stderr": "Shared connection to 10.10.1.3 closed.\r\n",
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py\", line 107, in <module>\r\n    _ansiballz_main()\r\n  File \"/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py\", line 99, in _ansiballz_main\r\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n  File \"/root/.ansible/tmp/ansible-tmp-1687235576.8458383-27128-128500511019265/AnsiballZ_list.py\", line 47, in invoke_module\r\n    runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.list', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.list', _modlib_path=modlib_path),\r\n  File \"/usr/local/lib/python3.9/runpy.py\", line 225, in run_module\r\n
return _run_module_code(code, init_globals, run_name, mod_spec)\r\n  File \"/usr/local/lib/python3.9/runpy.py\", line 97, in _run_module_code\r\n    _run_code(code, mod_globals, init_globals,\r\n  File \"/usr/local/lib/python3.9/runpy.py\", line 87, in _run_code\r\n    exec(code, run_globals)\r\n  File \"/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/list.py\", line 11, in <module>\r\n  File \"<frozen zipimport>\", line 259, in load_module\r\n  File \"/tmp/ansible_ansibleguy.opnsense.list_payload_rodaew31/ansible_ansibleguy.opnsense.list_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py\", line 1, in <module>\r\nModuleNotFoundError: No module named 'ansible.errors'\r\n",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

Screenshots

Additional context

Reproduce

Tasks

Task(s) that produce the error:

- name: check opnsense items
  ansibleguy.opnsense.list:
    target: 'syslog'
    debug: true
  register: syslog

Config

Config used for the task(s):

OPNSense config

Problem: Unbound DNS-over-TLS should not require a domain

Modules

ansibleguy.opnsense.unbound_dot

Version

1.2.8

Ansible Version

ansible [core 2.16.3]
python version = 3.10.12

OPNSense Version

24.1.2_1

OPNSense-Plugin Version

No response

Issue

It is valid to not have a domain to forward all queries.

image

failed: [localhost] (item={'address': '9.9.9.9', 'hostname': 'dns.quad9.net'}) => {"ansible_loop_var": "item", "changed": false, "item": {"address": "9.9.9.9", "hostname": "dns.quad9.net"}, "msg": "Value '' is an invalid domain!"}

Even when I list unbound_dot, it is the case:

{"domain": "", "enabled": true, "port": 853, "target": "9.9.9.9", "uuid": "<redacted>", "verify": "dns.quad9.net"}

Config Ansible

- name: Unbound DNS-over-TLS
      ansibleguy.opnsense.unbound_dot:
        domain: "{{ item.domain | default('') }}"
        target: "{{ item.address }}"
        port: "853"
        verify: "{{ item.hostname }}"
      loop:
        -
          address: 9.9.9.9
          hostname: dns.quad9.net

Config OPNSense

No response

Debug Output

N/A

Profiling Output

No response

IPv4+IPv6 network parsing error in wireguard

When trying to add a wireguard server with 2 IPs, 1 IPv6 address and one 1 IPv4, I get the following error:

"Allowed-ip entry '2a0a:e5c0::1/64' is neither a valid IP-address nor a valid network!"

Adding this address manually to opnsense however works, and it's fine according to sipcalc.

% sipcalc 2a0a:e5c0::1/64
-[ipv6 : 2a0a:e5c0::1/64] - 0

[IPV6 INFO]
Expanded Address	- 2a0a:e5c0:0000:0000:0000:0000:0000:0001
Compressed address	- 2a0a:e5c0::1
Subnet prefix (masked)	- 2a0a:e5c0:0:0:0:0:0:0/64
Address ID (masked)	- 0:0:0:0:0:0:0:1/64
Prefix address		- ffff:ffff:ffff:ffff:0:0:0:0
Prefix length		- 64
Address type		- Aggregatable Global Unicast Addresses
Network range		- 2a0a:e5c0:0000:0000:0000:0000:0000:0000 -
			  2a0a:e5c0:0000:0000:ffff:ffff:ffff:ffff

The problem seems to stem from the usage of ip_network:

>>> ipaddress.ip_network("2a0a:e5c0::1/64")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.10/ipaddress.py", line 79, in ip_network
    return IPv6Network(address, strict)
  File "/usr/lib/python3.10/ipaddress.py", line 2216, in __init__
    raise ValueError('%s has host bits set' % self)
ValueError: 2a0a:e5c0::1/64 has host bits set

Using strict=False fixes this:

>>> ipaddress.ip_network("2a0a:e5c0::1/64", strict=False)
IPv6Network('2a0a:e5c0::/64')

The same issue happens for IPv4 + IPv6. The correct patch is probably in helper/main.py. I am not sure if there are situations in which we only want to allow a network without host part, but in case of wireguard, for setting the in-tunnel address, the host part is required.

Problem: wireguard_peer - always changed

Modules

wireguard_peer

Version

latest

Ansible Version

-

OPNSense Version

24.1.7

OPNSense-Plugin Version

No response

Issue

The endpoint is always shown as changed.

Config Ansible

See tests

Config OPNSense

No response

Debug Output

-

Profiling Output

No response

Problem: API changes opnsense >= 24.1

Modules

ansibleguy.opnsense.wireguard_show

Version

ansibleguy.opnsense 1.2.8

Ansible Version

ansible [core 2.16.3]
  config file = /../ansible.cfg
  configured module search path = ['/.../.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /.../.local/lib/python3.10/site-packages/ansible
  ansible collection location = /.../vendor
  executable location = /.../.local/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

OPNSense Version

24.1.1

OPNSense-Plugin Version

No response

Issue

This module was targeting the os-wireguard plugin. But since 24.1 this plugin is included in opnsense-core, but seem to have "breaking" changes for this module at least.

Example that breaks (since /api/wireguard/service/showconf endpoint has been removed and replaced with another endpoint, which also changed format and contents)

- name: Get WireGuard config
  ansibleguy.opnsense.wireguard_show:
    target: config
  register: wireguard_config_raw

Those changes are also not reflected in the OPNsense API docs yet :(

There may be other breaking changes when upgrading OPNsense to 24.1 or above. Can you check for those in your test system?

Config Ansible

none

Config OPNSense

No response

Debug Output

fatal: [router.w8s.me]: FAILED! => changed=false 
  msg: 'API call failed | Response: {''status_code'': 400, ''headers'': Headers([(''set-cookie'', ''PHPSESSID=7feece4a740c5109dc2c923bbb871d7f; path=/''), (''set-cookie'', ''PHPSESSID=7feece4a740c5109dc2c923bbb871d7f; path=/; secure; HttpOnly''), (''expires'', ''Thu, 19 Nov 1981 08:52:00 GMT''), (''cache-control'', ''no-store, no-cache, must-revalidate''), (''pragma'', ''no-cache''), (''content-security-policy'', "default-src ''self'' ;img-src ''self'' ;script-src ''self'' ''unsafe-inline'' ''unsafe-eval'' ;style-src ''self'' ''unsafe-inline'' ''unsafe-eval'' ;"), (''x-frame-options'', ''SAMEORIGIN''), (''x-content-type-options'', ''nosniff''), (''x-xss-protection'', ''1; mode=block''), (''referrer-policy'', ''same-origin''), (''content-type'', ''application/json''), (''strict-transport-security'', ''max-age=31536000''), (''content-length'', ''52''), (''date'', ''Wed, 07 Feb 2024 13:39:45 GMT''), (''server'', ''OPNsense'')]), ''_request'': <Request(''GET'', ''https://router/api/wireguard/service/showconf'')>,
    ''next_request'': None, ''extensions'': {''http_version'': b''HTTP/1.1'', ''reason_phrase'': b''Bad Request'', ''network_stream'': <httpcore._backends.sync.SyncStream object at 0x7fdf466e3610>}, ''history'': [], ''is_closed'': True, ''is_stream_consumed'': True, ''default_encoding'': ''utf-8'', ''stream'': <httpx._client.BoundSyncStream object at 0x7fdf466e3070>, ''_num_bytes_downloaded'': 52, ''_decoder'': <httpx._decoders.IdentityDecoder object at 0x7fdf466e27a0>, ''_elapsed'': datetime.timedelta(microseconds=37623), ''_content'': b''{"message":"action showconf not found","status":400}''}'

Profiling Output

No response

Feature: Device name for VLAN interface

Link to API

https://docs.opnsense.org/development/api/core/interfaces.html#id4

Description

When creating VLAN interfaces I noticed the device name being auto generated to "vlan01", "vlan02", ...
This is a bit confusing when you're not creating VLANs with consecutive tags, so you're ending up with:

  • vlan01 -> tag 27
  • vlan02 -> tag 52

This makes managing the VLANs unnecessary complicated.
From my understanding of the API documentation this feature should be already present in the API and therefore also be implemented in the collection.

As a workaround for now renaming the interfaces manually is possible, but kind of defeats the purpose of automation.

Problem: rule_multi diff is always changed due to different format of interface

Modules

ansibleguy.opnsense.rule_multi

Version

1.2.7

Ansible Version

ansible [core 2.15.7]

OPNSense Version

23.7.9

OPNSense-Plugin Version

os-firewall 1.4_2

Issue

This is the "change" reported when rerunning a rule after the first time without changes to the code. This is not expected behavior, since ansible roles should be idempotent.

Clearly the interface is reported back in a different format and there was no actual change.

changed: [router01] => changed=true 
  diff:
    after:
      nc_ipv4_icmp:
        action: pass
        description: nc_ipv4_icmp
        destination_invert: false
        destination_net: any
        destination_port: ''
        direction: in
        enabled: true
        interface: opt5
        ip_protocol: inet
        log: true
        protocol: ICMP
        quick: true
        sequence: 1
        source_invert: false
        source_net: any
        source_port: ''
        uuid: 89965ce3-6209-4ea2-a035-6e28efb28a9a
    before:
      nc_ipv4_icmp:
        action: pass
        description: nc_ipv4_icmp
        destination_invert: false
        destination_net: any
        destination_port: ''
        direction: in
        enabled: true
        interface:
        - opt5
        ip_protocol: inet
        log: true
        protocol: ICMP
        quick: true
        sequence: 1
        source_invert: false
        source_net: any
        source_port: ''
        uuid: 89965ce3-6209-4ea2-a035-6e28efb28a9a
  invocation:
    module_args:
      api_credential_file: null
      api_key: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
      api_port: 443
      api_secret: VALUE_SPECIFIED_IN_NO_LOG_PARAMETER
      debug: true
      defaults: {}
      enabled: null
      fail_processing: true
      fail_verification: true
      firewall: router01
      key_field: description
      match_fields:
      - description
      output_info: false
      override: {}
      reload: true
      rules:
        nc_ipv4_icmp:
          interface: opt5
          protocol: ICMP
      ssl_ca_file: null
      ssl_verify: true
      state: present
      timeout: null

Config Ansible

[defaults]
nocows = True

Config OPNSense

NA

Debug Output

NA

Profiling Output

No response

Problem: shaper parameter-descriptions missing

Modules

shaper_pipe / shaper_queue

Version

latest

Ansible Version

-

OPNSense Version

-

OPNSense-Plugin Version

No response

Issue

Parameter descriptions of module are missing

Config Ansible

-

Config OPNSense

No response

Debug Output

-

Profiling Output

No response

[frr_bgp_prefix_list] - Unable create prefix list with more subnets

Basic info

  • Affected Module:
    frr_bgp_prefix_list

Versions

  • Controller

    • Collection version:

      (ansible-galaxy collection list | grep opnsense)
      ansibleguy.opnsense 1.0.15

    • Ansible version:

      (python3 -m pip list | grep ansible or apt policy ansible)
      ansible-compat 2.2.0
      ansible-core 2.13.4
      ansible-lint 6.6.0
      ansible-pylibssh 0.0.0

    • Python version:
      Python 3.10.8

  • OPNSense

    • System version:
      OPNsense 22.7.9-amd64

    • Plugin version:
      os-frr (installed) | 1.31

Describe the bug

If you use the prefix list module, you cannot (by Opnsense design) create a list with multiple prefixes directly, and you must create multiple inserts with the same name but different sequence numbers.

Expected behavior

Try to mach prefix list name with seq number to change right rule

Screenshots

image

Reproduce

Tasks

Task(s) that produce the error:

---
- name: Creating prefix-list
  ansibleguy.opnsense.frr_bgp_prefix_list:
    name: "{{ prefix.name }}"
    network: "{{ item.network }}"
    seq: "{{ item.seq }}"
    action: "{{ item.action }}"
  loop: "{{ prefix.networks }}"
    - name: Creating BGP prefix-list
      include_tasks: "tasks/opnsense-prefix_list-each.yaml"
      loop: "{{ opnsense_bgp_prefix_lists }}"
      loop_control:
        loop_var: prefix
        label: "{{ prefix.name }}"

Config

Config used for the task(s):

opnsense_bgp_prefix_lists:
  - name: "AdvertiseNewNetwork"
    networks:
      - network: "10.7.120.0/28"
        seq: 100
        action: 'permit'
      - network: "10.0.255.48/28"
        seq: 101
        action: 'permit'

[list] - Error parsing metadata

I am having issues with doing the example https://opnsense.ansibleguy.net/en/latest/modules/2_list.html
Probably doing something wrong.

ansibleguy.opnsense 1.2.0
ansible-base 2.10.8
ansible-lint 5.4.0

I am getting the current output

[WARNING]: errors were encountered during the plugin load for ansibleguy.opnsense.list: ["error parsing
collection metadata: unhashable type: 'dict'"]

PLAY [Test Alias] *******************************************************************************************

TASK [Pulling aliases] **************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: ansible_collections.ansibleguy.opnsense.__spec__ is None
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
...ignoring

TASK [Printing] *********************************************************************************************
ok: [localhost] => {
    "existing_aliases.data": "VARIABLE IS NOT DEFINED!"
}

TASK [Pulling routes] ***************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ValueError: ansible_collections.ansibleguy.opnsense.__spec__ is None
fatal: [localhost]: FAILED! => {"msg": "Unexpected failure during module execution.", "stdout": ""}
...ignoring

TASK [Printing] *********************************************************************************************
ok: [localhost] => {
    "existing_routes.data": "VARIABLE IS NOT DEFINED!"
}

PLAY RECAP **************************************************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=2 

Playbook has follows

- name: Test Alias
  hosts: localhost
  gather_facts: no
  module_defaults:
    group/ansibleguy.opnsense.all:
      firewall: "router.example.com"
      api_port: 8443
      api_credential_file: 'apikey.txt'
      ssl_verify: false
      debug: true


  tasks:
    - name: Pulling aliases
      ansibleguy.opnsense.list:
        target: 'alias'
      register: existing_aliases
      ignore_errors: true

    - name: Printing
      ansible.builtin.debug:
        var: existing_aliases.data

    
    - name: Pulling routes
      ansibleguy.opnsense.list:
        target: 'route'
      register: existing_routes
      ignore_errors: true


    - name: Printing
      ansible.builtin.debug:
        var: existing_routes.data

Problem: IPSec Docs missing examples

Modules

For all ipsec modules except cert/psk

Version

latest

Ansible Version

-

OPNSense Version

-

OPNSense-Plugin Version

No response

Issue

Config Ansible

-

Config OPNSense

No response

Debug Output

-

Profiling Output

No response

Problem: interface_vip error 'A network address is required'

Modules

ansibleguy.opnsense.interface_vip

Version

1.2.7

Ansible Version

2.14.2

OPNSense Version

23.7.8_1

OPNSense-Plugin Version

os-firewall: 1.4_2

Issue

I'm using the following ansible task:

- name: Ensure existence of Virtual IP adress ansibleguy.opnsense.interface_vip: description: Test interface: wan address: xyz.178.77.182 cidr: 27

and got the response 'A network address is required.'
I think address and cidr should be enough to get this ip-alias working.

Config Ansible

[defaults] callback_plugins= ./callbacks stdout_callback = anstomlog retry_files_enabled = False collections_paths = collections

Config OPNSense

root@OPNsense:~ # ifconfig wan

wan: flags=8863 metric 0 mtu 1500 description: WAN (wan) options=80028 ether 0c:70:51:ec:00:01 inet6 fe80::e70:51ff:feec:1%wan prefixlen 64 scopeid 0x2 inet xyz.178.77.173 netmask 0xffffffe0 broadcast xyz.178.77.191 media: Ethernet autoselect (10Gbase-T ) status: active nd6 options=23

Debug Output

vhpfwnat-gns3-01` | FAILED | 826ms { - msg: API call failed | Error: {'vip.network': ['A network address is required.']} | Response: {'status_code': 200, 'headers': Headers({'content-type': 'application/json; charset=UTF-8', 'content-length': '84', 'date': 'Fri, 24 Nov 2023 13:17:32 GMT', 'server': 'OPNsense'}), '_request': , 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'OK', 'network_stream': }, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': , '_num_bytes_downloaded': 84, '_decoder': , '_elapsed': datetime.timedelta(microseconds=32617), '_content': b'{"result":"failed","validations":{"vip.network":["A network address is required."]}}'} - changed: False }

Profiling Output

No response

Problem: Upgrade doesn't actually upgrade

Modules

ansibleguy.opnsense.system

Version

1.2.8

Ansible Version

2.12.5.post0

OPNSense Version

22.7_4

OPNSense-Plugin Version

No response

Issue

I want to upgrade the opnsense version. The task runs successfully, but I'm still on the old version.

Config Ansible

- name: Run audit
      ansibleguy.opnsense.system:
        action: 'audit'
    - name: Pull updates
      ansibleguy.opnsense.system:
        action: 'update'
    - name: Start upgrade - will wait until finished
      ansibleguy.opnsense.system:
        action: 'upgrade'
        timeout: 240  # depends on your download speed and firmware-version

Config OPNSense

No response

Debug Output

TASK [Run audit] ***************************************************************
changed: [unclebob]
TASK [Pull updates] ************************************************************
changed: [unclebob]
TASK [Start upgrade - will wait until finished] ********************************
[WARNING]: 2024-03-06 21:11:42 | Waiting download & upgrade to finish..
[WARNING]: 2024-03-06 21:12:27 | Got response!
changed: [unclebob]

Profiling Output

No response

[wireguard_peer] Problems adding multiple peers

Basic info

  • Affected Module: WireGuard

Versions

  • Controller
    • Collection version: ansibleguy.opnsense 1.2.3
    • Ansible & Python version:
ansible [core 2.15.1]
  config file = None
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True
  • OPNSense
    • System version: 23.1.10_1-amd64
    • Plugin version: 1.13_5

Describe the bug

I have an inventory group with 4 wireguard clients defined which I am trying to add as peers on opnsense.
Ansible reports all 4 added, however with each run of the playbook, only the first host is added.

So for example:
When no peers from the inventory exist on opnsense, this is the output of ansible:

TASK [add peer on opnsense] ***************************
changed: [host1 -> localhost]
changed: [host2 -> localhost]
changed: [host3 -> localhost]
changed: [host4 -> localhost]

Inspecting the actual opnsense config, i can see that host1 was successfully created, but all others are missing.

Without changing anything in the opnsense web gui, i run the playbook again and get this output:

TASK [add peer on opnsense] ***************************
ok: [host1 -> localhost]
changed: [host2 -> localhost]
changed: [host3 -> localhost]
changed: [host4 -> localhost]

Now it recognizes that host1 already exists and creates the remaining 3. Inspecting the web ui again, i can see that now host1 and host2 exist, but host3 and host4 are still missing.

So every time I run the playbook it really only creates 1 peer.

I suspect this has something to do with the reload/save mechanism on opnsense

I feel like this might be an issue on the OpnSense API side, since the debug output from the plugin looks ok to me.
But on the other hand I can't be the first person to run into this and couldn't find anything on this issue

Is there some sort of trick to still be able to use this plugin for this use-case? Am I missing something?

I tried to reproduce this behavior for better debugging on the OpnSense side with a simple python script that creates some hosts and gets a list of all peers inbetween each call to /api/wireguard/client/addClient (see bottom of this post) and i am not able to reproduce the issue this plugin seems to be facing. Is it possible that ansible caches the responses from /api/wireguard/client/get ? Am i using the plugin wrong somehow?

Expected behavior

all 4 hosts get added as peer

Debug output

Output for host3, when host1 and host2 already exist.

[WARNING]: RESPONSE: '{'status_code': 200, 'headers': Headers({'content-type': 'application/json; charset=UTF-8', 'cache-control': 'max-age=180000', 'accept-ranges': 'bytes', 'content-length': '1503', 'date': 'Fri, 28
Jul 2023 21:43:24 GMT', 'server': 'OPNsense'}), '_request': <Request('GET', 'https://XXXXXXXXXXXXXXXXXX/api/wireguard/client/get')>, 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'OK',
'network_stream': <httpcore._backends.sync.SyncStream object at 0x7fe08acc3c10>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream
object at 0x7fe08acc08b0>, '_num_bytes_downloaded': 1503, '_decoder': <httpx._decoders.IdentityDecoder object at 0x7fe08acc2fe0>, '_elapsed': datetime.timedelta(microseconds=265281), '_content': b'{"client":{"clients":
{"client":{"25854852-e33e-471e-b5ac-
40da89064eb8":{"enabled":"1","name":"some-host","pubkey":"XXXXXXXXXXXXXXXXXX","psk":"","tunneladdress":{"10.10.10.21\\/32":{"value":"10.10.10.21\\/32","selected":1}},"serveraddress":"","serverpo
rt":"","keepalive":""},"e3da4828-7ded-4f47-9b41-
804c70f5b01b":{"enabled":"1","name":"another-host","pubkey":"XXXXXXXXXXXXXXXXXX","psk":"","tunneladdress":{"10.0.10.0\\/24":{"value":"10.0.10.0\\/24","selected":1},"XXXXXXXXXXXXXXXXXX":{"val
ue":"XXXXXXXXXXXXXXXXXX","selected":1}},"serveraddress":"XXXXXXXXXXXXXXXXXX","serverport":"51820","keepalive":""},"f79c8486-e12c-4fb2-aae7-
4e723ee22a9b":{"enabled":"1","name":"and-another-host-that-has-nothing-to-do-with-this","pubkey":"XXXXXXXXXXXXXXXXXX","psk":"","tunneladdress":{"10.10.10.20\\/32":{"value":"10.10.10.20\\/32","selected":1}},"serveraddress":"","serverp
ort":"","keepalive":""},"52413188-fe7d-4873-b724-174fa73248e7":{"enabled":"1","name":"host1","pubkey":"XXXXXXXXXXXXXXXXXX","psk":"","tunneladdress":{"10.10.11.12\\/32":{"value":"10.10.11.12\\/32","selected":1}},"serveraddress":"XXXXXXXXXXXXXXXXXX","serverport":"51820","keepalive":"
25"},"64dcca12-f264-4cd1-bee2-d4e4b38da9d4":{"enabled":"1","name":"host2","pubkey":"XXXXXXXXXXXXXXXXXX=","psk":"","tunneladdress":{"10.10.11.13\\/32":{"value":"10.10.11.13\\/32","selected":1}},"serveraddress":"XXXXXXXXXXXXXXXXXX","serverport":"51820","keepalive":"25"}
}}}}'}'
[WARNING]: NOT MATCHING: 'some-host' != 'host3'
[WARNING]: NOT MATCHING: 'another-host' != 'host3'
[WARNING]: NOT MATCHING: 'and-another-host-that-has-nothing-to-do-with-this' != 'host3'
[WARNING]: NOT MATCHING: 'host1' != 'host3'
[WARNING]: NOT MATCHING: 'host2' != 'host3'
[WARNING]: REQUEST: POST | URL: https://XXXXXXXXXXXXXXXXXX/api/wireguard/client/addClient | HEADERS: '{'Content-Type': 'application/json'}' | DATA: '{"client": {"name": "host3", "enabled": 1, "pubkey":
"XXXXXXXXXXXXXXXXXX", "psk": "", "serverport": "51820", "tunneladdress": "10.10.11.11/32", "serveraddress": "XXXXXXXXXXXXXXXXXX", "keepalive": "25"}}'
[WARNING]: RESPONSE: '{'status_code': 200, 'headers': Headers({'content-type': 'application/json; charset=UTF-8', 'content-length': '64', 'date': 'Fri, 28 Jul 2023 21:43:25 GMT', 'server': 'OPNsense'}), '_request':
<Request('POST', 'https://XXXXXXXXXXXXXXXXXX/api/wireguard/client/addClient')>, 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'OK', 'network_stream':
<httpcore._backends.sync.SyncStream object at 0x7fe08acc3c10>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream object at
0x7fe08acc2b60>, '_num_bytes_downloaded': 64, '_decoder': <httpx._decoders.IdentityDecoder object at 0x7fe08acc3130>, '_elapsed': datetime.timedelta(microseconds=226650), '_content':
b'{"result":"saved","uuid":"82a81321-b148-441a-821e-ad5e7a5bdfb4"}'}'
[WARNING]: RESPONSE: '{'status_code': 200, 'headers': Headers({'content-type': 'application/json; charset=UTF-8', 'content-length': '15', 'date': 'Fri, 28 Jul 2023 21:43:30 GMT', 'server': 'OPNsense'}), '_request':
<Request('POST', 'https://XXXXXXXXXXXXXXXXXX/api/wireguard/service/reconfigure')>, 'next_request': None, 'extensions': {'http_version': b'HTTP/1.1', 'reason_phrase': b'OK', 'network_stream':
<httpcore._backends.sync.SyncStream object at 0x7fe08acc3c10>}, 'history': [], 'is_closed': True, 'is_stream_consumed': True, 'default_encoding': 'utf-8', 'stream': <httpx._client.BoundSyncStream object at
0x7fe08acc09a0>, '_num_bytes_downloaded': 15, '_decoder': <httpx._decoders.IdentityDecoder object at 0x7fe08acc25f0>, '_elapsed': datetime.timedelta(seconds=4, microseconds=642319), '_content': b'{"status":"ok"}'}'

Reproduce

Tasks

Task(s) that produce the error:

    - name: add peer on opnsense
      ansibleguy.opnsense.wireguard_peer:
        name: '{{ inventory_hostname }}'
        allowed_ips: '{{ wireguard_address }}'
        endpoint: '{{ ansible_host }}'
        port: '{{ wireguard_listenport | default(51820) }}'
        public_key: '{{ pubkey }}'
        keepalive: 25
        enabled: true
        debug: false
        state: 'present'
        reload: true
      delegate_to: localhost

python script for debugging

import json
import requests

api_key = ''
api_secret = ''
base_url = 'https://opnsense.local/api/wireguard/'

def get_and_print_peers_from_api():
    r = requests.get(base_url+'client/get', auth=(api_key, api_secret))
    for k,v in json.loads(r.text)['client']['clients']['client'].items():
        if v['name'].startswith('TEST_'):
            print(f" - {v['name']}")

def add_peer(name):
    data = {
        "client": {"name": name,
                   "enabled": 1,
                   "pubkey": "Rk9PQkFSCg==",
                   "serverport": 51820,
                   "tunneladdress": "127.0.0.1",
                   "serveraddress": "127.0.0.1",
                   "keepalive": 25
                   }
            }
    r = requests.post(base_url+'client/addClient', json=data, auth=(api_key, api_secret))
    print(r)

print('Initial config:')
get_and_print_peers_from_api()

for host in ['TEST_host1', 'TEST_host2', 'TEST_host3', 'TEST_host4']:
    print('')
    print(f'adding host {host}')
    add_peer(host)
    print('')
    print('hosts present in api:')
    get_and_print_peers_from_api()

Add unbound host override randomly missing hosts

Modules

ansibleguy.opnsense.unbound_host
ansibleguy.opnsense.reload

Version

ansibleguy.opnsense 1.2.7

Ansible Version

ansible [core 2.16.1]

OPNSense Version

23.7.10_1

OPNSense-Plugin Version

No response

Issue

Adding 12 hosts to unbound host override for vm's that are deployed with fixed ip addresses.
Relevant piece of ansible code:

- name: Extract domain from FQDN
  set_fact:
    domain_name: "{{ inventory_hostname | regex_replace('^[^\\.]+\\.', '') }}"
  delegate_to: localhost

- name: Adding build hosts to opnSense Unbound host overrides
  ansibleguy.opnsense.unbound_host:
    hostname: "{{ inventory_hostname | split('.') | first }}"
    domain: "{{ domain_name }}"
    value: "{{ ks.ip_address }}"
  delegate_to: localhost
  delegate_facts: true

- name: Reloading Unbounda
  ansibleguy.opnsense.reload:
    target: 'unbound'
  delegate_to: localhost
  delegate_facts: true
  run_once: true

Task output:

TASK [configure_system : Adding build hosts to opnSense Unbound host overrides] ******************************
Saturday 23 December 2023  18:37:02 +0100 (0:00:00.070)       0:00:00.100 ***** 
changed: [rocky-client-test-03.lab.domain.net -> localhost]
changed: [rocky-client-test-02.lab.domain.net -> localhost]
changed: [rocky-client-test-01.lab.domain.net -> localhost]
changed: [rocky-client-test-04.lab.domain.net -> localhost]
changed: [rocky-client-test-05.lab.domain.net -> localhost]
changed: [rocky-client-test-09.lab.domain.net -> localhost]
changed: [rocky-client-test-10.lab.domain.net -> localhost]
changed: [rocky-client-test-08.lab.domain.net -> localhost]
changed: [rocky-client-test-07.lab.domain.net -> localhost]
changed: [rocky-client-test-06.lab.domain.net -> localhost]
changed: [rocky-client-test-11.lab.domain.net -> localhost]
changed: [rocky-client-test-12.lab.domain.net -> localhost]

The result in opnSense:

rocky-client-test-02 lab.domain.net A (IPv4 address) 10.0.0.22
rocky-client-test-03 lab.domain.net A (IPv4 address) 10.0.0.23
rocky-client-test-06 lab.domain.net A (IPv4 address) 10.0.0.26
rocky-client-test-07 lab.domain.net A (IPv4 address) 10.0.0.27
rocky-client-test-10 lab.domain.net A (IPv4 address) 10.0.0.30
rocky-client-test-11 lab.domain.net A (IPv4 address) 10.0.0.31
rocky-client-test-12 lab.domain.net A (IPv4 address) 10.0.0.32

Then I run it again and the output says:

TASK [configure_system : Adding build hosts to opnSense Unbound host overrides] ******************************
Saturday 23 December 2023  18:46:54 +0100 (0:00:00.066)       0:00:00.096 ***** 
ok: [rocky-client-test-03.lab.domain.net -> localhost]
ok: [rocky-client-test-02.lab.domain.net -> localhost]
ok: [rocky-client-test-07.lab.domain.net -> localhost]
ok: [rocky-client-test-06.lab.domain.net -> localhost]
changed: [rocky-client-test-05.lab.domain.net -> localhost]
changed: [rocky-client-test-04.lab.domain.net -> localhost]
changed: [rocky-client-test-01.lab.domain.net -> localhost]
changed: [rocky-client-test-09.lab.domain.net -> localhost]
changed: [rocky-client-test-08.lab.domain.net -> localhost]
ok: [rocky-client-test-12.lab.domain.net -> localhost]
ok: [rocky-client-test-10.lab.domain.net -> localhost]
ok: [rocky-client-test-11.lab.domain.net -> localhost]

In opnsense it adds:

rocky-client-test-04 lab.domain.net	A (IPv4 address) 10.0.0.24
rocky-client-test-08 lab.domain.net	A (IPv4 address) 10.0.0.28

I run it again and the task throws an error:

TASK [configure_system : Adding build hosts to opnSense Unbound host overrides] ******************************
Saturday 23 December 2023  18:48:40 +0100 (0:00:00.062)       0:00:00.093 ***** 
ok: [rocky-client-test-04.lab.domain.net -> localhost]
ok: [rocky-client-test-03.lab.domain.net -> localhost]
ok: [rocky-client-test-02.lab.domain.net -> localhost]
ok: [rocky-client-test-06.lab.domain.net -> localhost]
ok: [rocky-client-test-07.lab.domain.net -> localhost]
ok: [rocky-client-test-08.lab.domain.net -> localhost]
ok: [rocky-client-test-10.lab.domain.net -> localhost]
ok: [rocky-client-test-11.lab.domain.net -> localhost]
fatal: [rocky-client-test-01.lab.domain.net -> localhost]: FAILED! => changed=false 
  msg: 'API call failed | Response: {''status_code'': 500, ''headers'': Headers({''content-type'': ''application/json;charset=utf-8'', ''strict-transport-security'': ''max-age=31536000'', ''content-length'': ''603'', ''date'': ''Sat, 23 Dec 2023 17:48:43 GMT'', ''server'': ''OPNsense''}), ''_request'': <Request(''POST'', ''https://singularity.internal.domain.net/api/unbound/service/reconfigure'')>, ''next_request'': None, ''extensions'': {''http_version'': b''HTTP/1.1'', ''reason_phrase'': b''Internal Server Error'', ''network_stream'': <httpcore._backends.sync.SyncStream object at 0x106549fd0>}, ''history'': [], ''is_closed'': True, ''is_stream_consumed'': True, ''default_encoding'': ''utf-8'', ''stream'': <httpx._client.BoundSyncStream object at 0x106588f10>, ''_num_bytes_downloaded'': 603, ''_decoder'': <httpx._decoders.IdentityDecoder object at 0x106588410>, ''_elapsed'': datetime.timedelta(microseconds=737992), ''_content'': b''{"errorMessage":"Template generation failed for internal
    service \\"unbound\\". See backend log for details.","errorTrace":"#0 [internal function]: OPNsense\\\\Base\\\\ApiMutableServiceControllerBase->reconfigureAction()\\n#1 [internal function]: Phalcon\\\\Dispatcher\\\\AbstractDispatcher->callActionMethod(Object(OPNsense\\\\Unbound\\\\Api\\\\ServiceController), \''reconfigureActi...\'', Array)\\n#2 [internal function]: Phalcon\\\\Dispatcher\\\\AbstractDispatcher->dispatch()\\n#3 /usr/local/opnsense/www/api.php(24): Phalcon\\\\Mvc\\\\Application->handle(\''/api/unbound/se...\'')\\n#4 {main}","errorTitle":"Configuration exception"}'', ''_encoding'': ''utf-8'', ''_text'': ''{"errorMessage":"Template generation failed for internal service \\"unbound\\". See backend log for details.","errorTrace":"#0 [internal function]: OPNsense\\\\Base\\\\ApiMutableServiceControllerBase->reconfigureAction()\\n#1 [internal function]: Phalcon\\\\Dispatcher\\\\AbstractDispatcher->callActionMethod(Object(OPNsense\\\\Unbound\\\\Api\\\\ServiceController), \''reconfigureActi...\'',
    Array)\\n#2 [internal function]: Phalcon\\\\Dispatcher\\\\AbstractDispatcher->dispatch()\\n#3 /usr/local/opnsense/www/api.php(24): Phalcon\\\\Mvc\\\\Application->handle(\''/api/unbound/se...\'')\\n#4 {main}","errorTitle":"Configuration exception"}''}'
ok: [rocky-client-test-12.lab.domain.net -> localhost]
^C [ERROR]: User interrupted execution

I run it again, final host is added (not posting task output its what you'd expect). In opnsense I got all 12 hosts now.

Config Ansible

[defaults]
interpreter_python = auto_silent
stdout_callback = yaml
inventory = ./inventory.ini
roles_path = ./roles
library = ./modules
collections_path = ./collections
vault_password_file = ../.packer_deploy_vaultpass
host_key_checking = false
remote_tmp = /tmp/$USER/ansible
callbacks_enabled = timer, profile_tasks
become_method = sudo
become_user = root


### Config OPNSense

```bash
Im not sure what to post? The entire opnsense xml would show way too much private info. Ask specifics and I can post those.

Debug Output

The error appeared only once. Most of the runs, it adds one or more hosts without error.

Profiling Output

No response

[General] - No module named 'ansible.errors'

Tasks

Please make sure to go through these steps before opening an issue:

  • [ โœ…] Read the documentation of the affected module: Docs

  • [ โœ…] Read the troubleshooting info: Info

Basic info

  • Affected Module:

Versions

  • Controller

    • [ โœ…] Collection version: 1.2.3

      (ansible-galaxy collection list | grep opnsense)

    • [:white_check_mark: ] Ansible & Python version:
      ansible [core 2.15.0]
      config file = /home/mhulsman/ansible/project/opnsense/ansible.cfg
      configured module search path = ['/home/mhulsman/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
      ansible python module location = /usr/lib/python3.11/site-packages/ansible
      ansible collection location = /home/mhulsman/ansible/project/opnsense/collections
      executable location = /usr/bin/ansible
      python version = 3.11.4 (main, Jun 30 2023, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/usr/bin/python3.11)
      jinja version = 3.1.2
      libyaml = True

      (ansible --version)

  • OPNSense

    • [:white_check_mark: ] System version: 23.1

    • Plugin version:

      (if applicable)

Describe the bug

Cannot run any task due to the error: ModuleNotFoundError: No module named 'ansible.errors'
I found Issue #18 but that is not solving my problems.
I use localhost as executioner, that did not work
Also using connection: local that also did not work
Firewall as FQDN or IP number, the same error
I have httpx installed
When using curl to list aliases I get the proper output.
Used the downloaded apikey.txt and even used the api_key and api_secret

Expected behavior

working modules

Debug output

Set the debug option and copy its output.

TASK [pulling Aliases] ***************************************************************************************************************************************************************************************************************************
task path: /home/mhulsman/ansible/project/opnsense/playbooks/test.yml:12
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: mhulsman
<127.0.0.1> EXEC /bin/sh -c 'echo ~mhulsman && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/mhulsman/.ansible/tmp `"&& mkdir "` echo /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026 `" && echo ansible-tmp-1690296870.3732345-6303-144439777606026="` echo /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026 `" ) && sleep 0'
Using module file /home/mhulsman/ansible/project/opnsense/collections/ansible_collections/ansibleguy/opnsense/plugins/modules/alias.py
<127.0.0.1> PUT /home/mhulsman/.ansible/tmp/ansible-local-6299jrwgpmo6/tmp51crmd38 TO /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/ /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/env python3 /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 107, in <module>
    _ansiballz_main()
  File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.alias', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.alias', _modlib_path=modlib_path),
  File "/usr/lib64/python3.9/runpy.py", line 225, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib64/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib64/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_ansibleguy.opnsense.alias_payload_ry14nyt7/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/alias.py", line 10, in <module>
  File "<frozen zipimport>", line 259, in load_module
  File "/tmp/ansible_ansibleguy.opnsense.alias_payload_ry14nyt7/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 1, in <module>
ModuleNotFoundError: No module named 'ansible.errors'
fatal: [localhost]: FAILED! => changed=false
  module_stderr: |-
    Traceback (most recent call last):
      File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 107, in <module>
        _ansiballz_main()
      File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 99, in _ansiballz_main
        invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
      File "/home/mhulsman/.ansible/tmp/ansible-tmp-1690296870.3732345-6303-144439777606026/AnsiballZ_alias.py", line 47, in invoke_module
        runpy.run_module(mod_name='ansible_collections.ansibleguy.opnsense.plugins.modules.alias', init_globals=dict(_module_fqn='ansible_collections.ansibleguy.opnsense.plugins.modules.alias', _modlib_path=modlib_path),
      File "/usr/lib64/python3.9/runpy.py", line 225, in run_module
        return _run_module_code(code, init_globals, run_name, mod_spec)
      File "/usr/lib64/python3.9/runpy.py", line 97, in _run_module_code
        _run_code(code, mod_globals, init_globals,
      File "/usr/lib64/python3.9/runpy.py", line 87, in _run_code
        exec(code, run_globals)
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_ry14nyt7/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/modules/alias.py", line 10, in <module>
      File "<frozen zipimport>", line 259, in load_module
      File "/tmp/ansible_ansibleguy.opnsense.alias_payload_ry14nyt7/ansible_ansibleguy.opnsense.alias_payload.zip/ansible_collections/ansibleguy/opnsense/plugins/module_utils/base/handler.py", line 1, in <module>
    ModuleNotFoundError: No module named 'ansible.errors'
  module_stdout: ''
  msg: |-
    MODULE FAILURE
    See stdout/stderr for the exact error
  rc: 1

If the issue is related to time-consumption, you may also add the content of the profiling logs.

Screenshots

Additional context

Reproduce

Tasks

Task(s) that produce the error:

- hosts: localhost
  gather_facts: no
  module_defaults:
    ansibleguy.opnsense.alias:
      firewall: 'v1fw4a01.hulsman.local'
      api_credential_file: '/home/mhulsman/ansible/project/opnsense/apikey.tx'
      ssl_verify: false

  tasks:
    - name: pulling Aliases
      ansibleguy.opnsense.alias:
        name: 'ANSIBLE_TEST1'
        content: ['1.1.1.1']
        debug: true

Config

Config used for the task(s):

- name: placeholder

OPNSense config

(If the issue only occurs when non ansible-managed config is modified)

Problem: route_map - diff for links

Modules

frr_bgp_route_map and possible others

Version

latest

Ansible Version

ansible [core 2.15.3]
  config file = None
  configured module search path = ['/home/superstes/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/superstes/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/superstes/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/superstes/.local/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

OPNSense Version

23.7.9

OPNSense-Plugin Version

No response

Issue

The linked items are shown by their UUID in diff-before and by their NAME in diff-after.
Should be UUID or NAME in both for diff to work correctly

Config Ansible

See test for mentioned module

Config OPNSense

See test for mentioned module

Debug Output

--- before
+++ after
@@ -6,9 +6,7 @@
     "enabled": true,
     "id": 65,
     "name": "ANSIBLE_TEST_2_1",
-    "prefix_list": [
-        "973b256f-9c7d-4446-b9f6-a832b8b29577"
-    ],
+    "prefix_list": "{'ANSIBLE_TEST_3_1': [50, 51]}",
     "set": "",
     "uuid": "5edd26e6-0bb3-4856-aa2a-599cb21101f7"
 }

Profiling Output

No response

Problem: Unable to see Key file when using via docker

Modules

NA

Version

stable

Ansible Version

stable

OPNSense Version

latest

OPNSense-Plugin Version

NA

Issue

Been plugging away at this for days and am just hitting a wall. I have a docker semaphore install. The requirements and such are all working fine, it just cant see the api key file

For the purposes of testing this - the key file is in the same repo as the playbook

i have tried
api_credential_file: '{{ playbook_dir }}/testkey.key'
api_credential_file: './testkey.key'

all i want to do is get it to restart unbound and a few other services but having a right nightmare

Config Ansible

- name: Restart Unbound on OpnSense Hosts
  hosts: "{{ hosts | default('all') }}"
  gather_facts: no
  module_defaults:
    group/ansibleguy.opnsense.all:
      firewall: "{{ ansible_host }}"
      api_credential_file: '{{ playbook_dir }}/testkey.key'

  tasks:
    - name: Restarting Unbound DNS service
      ansibleguy.opnsense.service:
        name: 'unbound'
        action: 'restart'

Config OPNSense

NA

Debug Output

FAILED! => {"changed": false, "msg": "Provided 'api_credential_file' at path '/tmp/semaphore/repository_1_29/playbooks/testing/testkey.key' does not exist!"}
1:04:42 PM

Profiling Output

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.