summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/package-smoketest.yml1
-rw-r--r--data/templates/ipsec/charon_systemd.conf.j218
-rw-r--r--python/vyos/frrender.py6
-rw-r--r--python/vyos/kea.py8
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py2
-rwxr-xr-xsrc/op_mode/firewall.py113
6 files changed, 118 insertions, 30 deletions
diff --git a/.github/workflows/package-smoketest.yml b/.github/workflows/package-smoketest.yml
index 2c90fed39..5ed764217 100644
--- a/.github/workflows/package-smoketest.yml
+++ b/.github/workflows/package-smoketest.yml
@@ -42,6 +42,7 @@ jobs:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
+ submodules: true
- name: Build vyos-1x package
run: |
cd packages/vyos-1x; dpkg-buildpackage -uc -us -tc -b
diff --git a/data/templates/ipsec/charon_systemd.conf.j2 b/data/templates/ipsec/charon_systemd.conf.j2
new file mode 100644
index 000000000..368aa1ae3
--- /dev/null
+++ b/data/templates/ipsec/charon_systemd.conf.j2
@@ -0,0 +1,18 @@
+# Generated by ${vyos_conf_scripts_dir}/vpn_ipsec.py
+
+charon-systemd {
+
+ # Section to configure native systemd journal logger, very similar to the
+ # syslog logger as described in LOGGER CONFIGURATION in strongswan.conf(5).
+ journal {
+
+ # Loglevel for a specific subsystem.
+ # <subsystem> = <default>
+
+{% if log.level is vyos_defined %}
+ # Default loglevel.
+ default = {{ log.level }}
+{% endif %}
+ }
+
+}
diff --git a/python/vyos/frrender.py b/python/vyos/frrender.py
index ba44978d1..8d469e3e2 100644
--- a/python/vyos/frrender.py
+++ b/python/vyos/frrender.py
@@ -60,6 +60,10 @@ def get_frrender_dict(conf, argv=None) -> dict:
from vyos.configdict import get_dhcp_interfaces
from vyos.configdict import get_pppoe_interfaces
+ # We need to re-set the CLI path to the root level, as this function uses
+ # conf.exists() with an absolute path form the CLI root
+ conf.set_level([])
+
# Create an empty dictionary which will be filled down the code path and
# returned to the caller
dict = {}
@@ -599,8 +603,10 @@ def get_frrender_dict(conf, argv=None) -> dict:
dict.update({'vrf' : vrf})
if os.path.exists(frr_debug_enable):
+ print(f'---- get_frrender_dict({conf}) ----')
import pprint
pprint.pprint(dict)
+ print('-----------------------------------')
return dict
diff --git a/python/vyos/kea.py b/python/vyos/kea.py
index c7947af3e..9fc5dde3d 100644
--- a/python/vyos/kea.py
+++ b/python/vyos/kea.py
@@ -483,10 +483,10 @@ def kea_get_domain_from_subnet_id(config, inet, subnet_id):
if option['name'] == 'domain-name':
return option['data']
- # domain-name is not found in subnet, fallback to shared-network pool option
- for option in network['option-data']:
- if option['name'] == 'domain-name':
- return option['data']
+ # domain-name is not found in subnet, fallback to shared-network pool option
+ for option in network['option-data']:
+ if option['name'] == 'domain-name':
+ return option['data']
return None
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index 71a503e61..2754314f7 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -64,6 +64,7 @@ swanctl_dir = '/etc/swanctl'
charon_conf = '/etc/strongswan.d/charon.conf'
charon_dhcp_conf = '/etc/strongswan.d/charon/dhcp.conf'
charon_radius_conf = '/etc/strongswan.d/charon/eap-radius.conf'
+charon_systemd_conf = '/etc/strongswan.d/charon-systemd.conf'
interface_conf = '/etc/strongswan.d/interfaces_use.conf'
swanctl_conf = f'{swanctl_dir}/swanctl.conf'
@@ -745,6 +746,7 @@ def generate(ipsec):
render(charon_conf, 'ipsec/charon.j2', ipsec)
render(charon_dhcp_conf, 'ipsec/charon/dhcp.conf.j2', ipsec)
render(charon_radius_conf, 'ipsec/charon/eap-radius.conf.j2', ipsec)
+ render(charon_systemd_conf, 'ipsec/charon_systemd.conf.j2', ipsec)
render(interface_conf, 'ipsec/interfaces_use.conf.j2', ipsec)
render(swanctl_conf, 'ipsec/swanctl.conf.j2', ipsec)
diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py
index 7a3ab921d..086536e4e 100755
--- a/src/op_mode/firewall.py
+++ b/src/op_mode/firewall.py
@@ -148,6 +148,38 @@ def get_nftables_group_members(family, table, name):
return out
+def get_nftables_remote_group_members(family, table, name):
+ prefix = 'ip6' if family == 'ipv6' else 'ip'
+ out = []
+
+ try:
+ results_str = cmd(f'nft -j list set {prefix} {table} {name}')
+ results = json.loads(results_str)
+ except:
+ return out
+
+ if 'nftables' not in results:
+ return out
+
+ for obj in results['nftables']:
+ if 'set' not in obj:
+ continue
+
+ set_obj = obj['set']
+ if 'elem' in set_obj:
+ for elem in set_obj['elem']:
+ # search for single IP elements
+ if isinstance(elem, str):
+ out.append(elem)
+ # search for prefix elements
+ elif isinstance(elem, dict) and 'prefix' in elem:
+ out.append(f"{elem['prefix']['addr']}/{elem['prefix']['len']}")
+ # search for IP range elements
+ elif isinstance(elem, dict) and 'range' in elem:
+ out.append(f"{elem['range'][0]}-{elem['range'][1]}")
+
+ return out
+
def output_firewall_vertical(rules, headers, adjust=True):
for rule in rules:
adjusted_rule = rule + [""] * (len(headers) - len(rule)) if adjust else rule # account for different header length, like default-action
@@ -556,32 +588,8 @@ def show_firewall_group(name=None):
header_tail = []
for group_type, group_type_conf in firewall['group'].items():
- ##
- if group_type != 'dynamic_group':
-
- for group_name, group_conf in group_type_conf.items():
- if name and name != group_name:
- continue
-
- references = find_references(group_type, group_name)
- row = [group_name, textwrap.fill(group_conf.get('description') or '', 50), group_type, '\n'.join(references) or 'N/D']
- if 'address' in group_conf:
- row.append("\n".join(sorted(group_conf['address'])))
- elif 'network' in group_conf:
- row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network)))
- elif 'mac_address' in group_conf:
- row.append("\n".join(sorted(group_conf['mac_address'])))
- elif 'port' in group_conf:
- row.append("\n".join(sorted(group_conf['port'])))
- elif 'interface' in group_conf:
- row.append("\n".join(sorted(group_conf['interface'])))
- elif 'url' in group_conf:
- row.append(group_conf['url'])
- else:
- row.append('N/D')
- rows.append(row)
-
- else:
+ # interate over dynamic-groups
+ if group_type == 'dynamic_group':
if not args.detail:
header_tail = ['Timeout', 'Expires']
@@ -628,6 +636,59 @@ def show_firewall_group(name=None):
header_tail += [""] * (len(members) - 1)
rows.append(row)
+ # iterate over remote-groups
+ elif group_type == 'remote_group':
+ for remote_name, remote_conf in group_type_conf.items():
+ if name and name != remote_name:
+ continue
+
+ references = find_references(group_type, remote_name)
+ row = [remote_name, textwrap.fill(remote_conf.get('description') or '', 50), group_type, '\n'.join(references) or 'N/D']
+ members = get_nftables_remote_group_members("ipv4", 'vyos_filter', f'R_{remote_name}')
+
+ if 'url' in remote_conf:
+ # display only the url if no members are found for both views
+ if not members:
+ if args.detail:
+ header_tail = ['Remote URL']
+ row.append('N/D')
+ row.append(remote_conf['url'])
+ else:
+ row.append(remote_conf['url'])
+ rows.append(row)
+ else:
+ # display all table elements in detail view
+ if args.detail:
+ header_tail = ['Remote URL']
+ row += [' '.join(members)]
+ row.append(remote_conf['url'])
+ rows.append(row)
+ else:
+ row.append(remote_conf['url'])
+ rows.append(row)
+
+ # catch the rest of the group types
+ else:
+ for group_name, group_conf in group_type_conf.items():
+ if name and name != group_name:
+ continue
+
+ references = find_references(group_type, group_name)
+ row = [group_name, textwrap.fill(group_conf.get('description') or '', 50), group_type, '\n'.join(references) or 'N/D']
+ if 'address' in group_conf:
+ row.append("\n".join(sorted(group_conf['address'])))
+ elif 'network' in group_conf:
+ row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network)))
+ elif 'mac_address' in group_conf:
+ row.append("\n".join(sorted(group_conf['mac_address'])))
+ elif 'port' in group_conf:
+ row.append("\n".join(sorted(group_conf['port'])))
+ elif 'interface' in group_conf:
+ row.append("\n".join(sorted(group_conf['interface'])))
+ else:
+ row.append('N/D')
+ rows.append(row)
+
if rows:
print('Firewall Groups\n')
if args.detail: