Skip to content

Commit

Permalink
Implement checking for nested alias content
Browse files Browse the repository at this point in the history
  • Loading branch information
jiuka committed Jan 14, 2025
1 parent 9a52237 commit 248050a
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 45 deletions.
65 changes: 45 additions & 20 deletions plugins/module_utils/helper/alias.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
from re import match as regex_match
from typing import Callable
from ipaddress import ip_network, ip_address

from ansible.module_utils.basic import AnsibleModule

from ansible_collections.ansibleguy.opnsense.plugins.module_utils.defaults.main import \
BUILTIN_ALIASES, BUILTIN_INTERFACE_ALIASES_REG
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.validate import \
is_valid_mac_address, is_valid_url
is_valid_mac_address, is_valid_url, is_valid_domain
from ansible_collections.ansibleguy.opnsense.plugins.module_utils.helper.main import \
get_selected


def validate_values(cnf: dict, error_func: Callable) -> None:
def validate_values(cnf: dict, error_func: Callable, existing_entries: dict) -> None:
v_type = cnf['type']

if isinstance(existing_entries, dict):
existing_entries = {
a['name']: get_selected(a['type'])
for a in existing_entries.values()
}
else:
existing_entries = {
a['name']: a['type']
for a in existing_entries
}

for value in cnf['content']:
error = f"Value '{value}' is invalid for type '{v_type}'!"

if v_type == 'port':
if value in existing_entries and existing_entries[value] == 'port':
continue

if str(value).find(':') != -1:
to_check = value.split(':')

Expand All @@ -39,24 +56,32 @@ def validate_values(cnf: dict, error_func: Callable) -> None:
if not is_valid_url(value):
error_func(error)

# unable to check because of alias-nesting support
# if v_type == 'network':
# value = value[1:] if value.startswith('!') else value
#
# try:
# ip_network(value)
#
# except ValueError:
# error_func(error)

# unable to check because of alias-nesting support and ip-ranges
# if v_type == 'host':
# try:
# ip_address(value)
#
# except ValueError:
# if not is_valid_domain(value):
# error_func(error)
elif v_type == 'network':
if value in existing_entries and existing_entries[value] in ['network', 'host']:
continue

value = value[1:] if value.startswith('!') else value

try:
ip_network(value)

except ValueError:
error_func(error)

elif v_type == 'host':
if value in existing_entries and existing_entries[value] in ['network', 'host']:
continue

if is_valid_domain(value):
continue

for _value in value.split('-', 1):
_value = _value[1:] if _value.startswith('!') else _value
try:
ip_address(_value)

except ValueError:
error_func(error)


def check_purge_filter(module: AnsibleModule, existing_rule: dict) -> bool:
Expand Down
6 changes: 3 additions & 3 deletions plugins/module_utils/main/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ def check(self) -> None:
f"must be shorter than {self.MAX_ALIAS_LEN} characters",
)

if self.p['state'] == 'present':
validate_values(error_func=self._error, cnf=self.p)

self.b.find(match_fields=[self.FIELD_ID])

if self.p['state'] == 'present':
validate_values(error_func=self._error, cnf=self.p, existing_entries=self.existing_entries)

if self.p['state'] == 'present':
self.r['diff']['after'] = self.b.build_diff(data=self.p)

Expand Down
85 changes: 64 additions & 21 deletions tests/alias.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,23 +138,30 @@
name: 'ANSIBLE_TEST_1_2_HOST3'
type: 'host'
content: ['ANSIBLE_TEST_1_2_HOST2', 'ANSIBLE_TEST_1_2_HOST1']
register: opnhost2
failed_when: opnhost2.failed != ansible_check_mode

- name: Adding ip range
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_HOST4'
type: 'host'
content: '1.1.1.1-1.1.1.4'

# NOTE: cannot fail as validation was disabled because of alias-nesting and ip-range support
# - name: Adding invalid host
# ansibleguy.opnsense.alias:
# name: 'ANSIBLE_TEST_1_2_HOST3'
# type: 'host'
# content: "{{ item }}"
# register: opnhost1
# failed_when: not opnhost1.failed
# loop:
# - ['1.1.1.n']
- name: Adding exclusion
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_HOST5'
type: 'host'
content: '!1.1.1.1'

- name: Adding invalid host
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_HOST3'
type: 'host'
content: "{{ item }}"
register: opnhost1
failed_when: not opnhost1.failed
loop:
- ['1.1.1.n']

# networks

Expand All @@ -170,16 +177,23 @@
type: 'network'
content: ['192.168.0.0/24', '192.168.1.0/24']

# NOTE: cannot fail as validation was disabled because of alias-nesting support
# - name: Adding invalid network
# ansibleguy.opnsense.alias:
# name: 'ANSIBLE_TEST_1_2_NET3'
# type: 'network'
# content: "{{ item }}"
# register: opnnet1
# failed_when: not opnnet1.failed
# loop:
# - ['192.168.0.0/240']
- name: Adding invalid network
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_NET3'
type: 'network'
content: "{{ item }}"
register: opnnet1
failed_when: not opnnet1.failed
loop:
- ['192.168.0.0/240']

- name: Adding nested network
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_NET3'
type: 'network'
content: ['ANSIBLE_TEST_1_2_NET1', 'ANSIBLE_TEST_1_2_NET2']
register: opnnet2
failed_when: opnnet2.failed != ansible_check_mode

# ports

Expand Down Expand Up @@ -211,6 +225,30 @@
type: 'port'
content: '9000:9500'

- name: Adding nested ports
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_PORT5'
type: 'port'
content:
- 'ANSIBLE_TEST_1_2_PORT1'
- 'ANSIBLE_TEST_1_2_PORT2'
register: opnport2
failed_when: opnport2.failed != ansible_check_mode

# mac

- name: Adding mac
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_MAC1'
type: 'mac'
content: f4:90:ea:00:00:01

- name: Adding multiple macs
ansibleguy.opnsense.alias:
name: 'ANSIBLE_TEST_1_2_MAC2'
type: 'mac'
content: ['f4:90:ea:00:00:01', 'f4:90:ea:00:00:02']

# urls

- name: Adding url
Expand Down Expand Up @@ -336,13 +374,18 @@
- 'ANSIBLE_TEST_1_2_URL1'
- 'ANSIBLE_TEST_1_2_URL2'
- 'ANSIBLE_TEST_1_2_URL3'
- 'ANSIBLE_TEST_1_2_PORT5'
- 'ANSIBLE_TEST_1_2_PORT1'
- 'ANSIBLE_TEST_1_2_PORT2'
- 'ANSIBLE_TEST_1_2_PORT3'
- 'ANSIBLE_TEST_1_2_PORT4'
- 'ANSIBLE_TEST_1_2_MAC1'
- 'ANSIBLE_TEST_1_2_MAC2'
- 'ANSIBLE_TEST_1_2_NET3'
- 'ANSIBLE_TEST_1_2_NET1'
- 'ANSIBLE_TEST_1_2_NET2'
- 'ANSIBLE_TEST_1_2_NET3'
- 'ANSIBLE_TEST_1_2_NET4'
- 'ANSIBLE_TEST_1_2_HOST5'
- 'ANSIBLE_TEST_1_2_HOST4'
- 'ANSIBLE_TEST_1_2_HOST3'
- 'ANSIBLE_TEST_1_2_HOST2'
Expand Down
40 changes: 39 additions & 1 deletion tests/alias_multi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
ANSIBLE_TEST_2_8:
ANSIBLE_TEST_2_9:
ANSIBLE_TEST_2_10:
ANSIBLE_TEST_2_11:
ANSIBLE_TEST_2_12:
ANSIBLE_TEST_2_13:
ANSIBLE_TEST_2_14:
state: 'absent'
register: opn1
failed_when: >
Expand Down Expand Up @@ -157,12 +161,46 @@
opn6.changed
when: not ansible_check_mode

- name: Adding nested aliases
ansibleguy.opnsense.alias_multi:
aliases:
# hosts
ANSIBLE_TEST_2_12:
content: ['ANSIBLE_TEST_2_1', 'ANSIBLE_TEST_2_2']

# networks
ANSIBLE_TEST_2_13:
type: 'network'
content: ['ANSIBLE_TEST_2_3', 'ANSIBLE_TEST_2_4']

# ports
ANSIBLE_TEST_2_14:
type: 'port'
content: ['ANSIBLE_TEST_2_5', 'ANSIBLE_TEST_2_6']

reload: false # geoip and urltable take LONG time

register: opn7
failed_when: >
opn7.failed or
not opn7.changed
when: not ansible_check_mode

- name: Listing aliases
ansibleguy.opnsense.list:
register: opn4
failed_when: >
'data' not in opn4 or
opn4.data | length != 11
opn4.data | length != 14
when: not ansible_check_mode

- name: Removing nesting
ansibleguy.opnsense.alias_multi:
aliases:
ANSIBLE_TEST_2_12:
ANSIBLE_TEST_2_13:
ANSIBLE_TEST_2_14:
state: 'absent'
when: not ansible_check_mode

- name: Removing
Expand Down

0 comments on commit 248050a

Please sign in to comment.