diff options
| author | sarthurdev <965089+sarthurdev@users.noreply.github.com> | 2024-04-26 14:32:52 +0200 | 
|---|---|---|
| committer | sarthurdev <965089+sarthurdev@users.noreply.github.com> | 2024-04-26 15:49:00 +0200 | 
| commit | 456419c7930405b80d322586736734f707affaed (patch) | |
| tree | f0f86b8800e573742e0a2c37e14f1f9be1557f58 | |
| parent | aa15f74818ca2cb35696315cc5cb0c57335f6911 (diff) | |
| download | vyos-1x-456419c7930405b80d322586736734f707affaed.tar.gz vyos-1x-456419c7930405b80d322586736734f707affaed.zip  | |
firewall: T6257: Show member information for dynamic groups in op-mode
| -rwxr-xr-x | src/op_mode/firewall.py | 78 | 
1 files changed, 70 insertions, 8 deletions
diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py index 25554b781..442c186cc 100755 --- a/src/op_mode/firewall.py +++ b/src/op_mode/firewall.py @@ -16,6 +16,7 @@  import argparse  import ipaddress +import json  import re  import tabulate  import textwrap @@ -89,10 +90,38 @@ def get_nftables_details(family, hook, priority):          out[rule_id] = rule      return out -def output_firewall_vertical(rules, headers): +def get_nftables_group_members(family, table, name): +    prefix = 'ip6' if family == 'ipv6' else 'ip' +    out = [] + +    try: +        results_str = cmd(f'sudo 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']: +                if isinstance(elem, str): +                    out.append(elem) +                elif isinstance(elem, dict) and 'elem' in elem: +                    out.append(elem['elem']) + +    return out + +def output_firewall_vertical(rules, headers, adjust=True):      for rule in rules: -        adjusted_rule = rule + [""] * (len(headers) - len(rule)) # account for different header length, like default-action -        transformed_rule = [[header, textwrap.fill(adjusted_rule[i].replace('\n', ' '), 65)] for i, header in enumerate(headers)] # create key-pair list from headers and rules lists; wrap at 100 char +        adjusted_rule = rule + [""] * (len(headers) - len(rule)) if adjust else rule # account for different header length, like default-action +        transformed_rule = [[header, textwrap.fill(adjusted_rule[i].replace('\n', ' '), 65)] for i, header in enumerate(headers) if i < len(adjusted_rule)] # create key-pair list from headers and rules lists; wrap at 100 char          print(tabulate.tabulate(transformed_rule, tablefmt="presto"))          print() @@ -453,6 +482,7 @@ def show_firewall_group(name=None):          return out      rows = [] +    header_tail = []      for group_type, group_type_conf in firewall['group'].items():          ## @@ -479,21 +509,53 @@ def show_firewall_group(name=None):                  rows.append(row)          else: +            if not args.detail: +                header_tail = ['Timeout', 'Expires'] +              for dynamic_type in ['address_group', 'ipv6_address_group']: +                family = 'ipv4' if dynamic_type == 'address_group' else 'ipv6' +                prefix = 'DA_' if dynamic_type == 'address_group' else 'DA6_'                  if dynamic_type in firewall['group']['dynamic_group']:                      for dynamic_name, dynamic_conf in firewall['group']['dynamic_group'][dynamic_type].items():                          references = find_references(dynamic_type, dynamic_name)                          row = [dynamic_name, textwrap.fill(dynamic_conf.get('description') or '', 50), dynamic_type + '(dynamic)', '\n'.join(references) or 'N/D'] -                        row.append('N/D') -                        rows.append(row) + +                        members = get_nftables_group_members(family, 'vyos_filter', f'{prefix}{dynamic_name}') + +                        if not members: +                            if args.detail: +                                row.append('N/D') +                            else: +                                row += ["N/D"] * 3 +                            rows.append(row) +                            continue + +                        for idx, member in enumerate(members): +                            val = member.get('val', 'N/D') +                            timeout = str(member.get('timeout', 'N/D')) +                            expires = str(member.get('expires', 'N/D')) + +                            if args.detail: +                                row.append(f'{val} (timeout: {timeout}, expires: {expires})') +                                continue + +                            if idx > 0: +                                row = [""] * 4 + +                            row += [val, timeout, expires] +                            rows.append(row) + +                        if args.detail: +                            header_tail += [""] * (len(members) - 1) +                            rows.append(row)      if rows:          print('Firewall Groups\n')          if args.detail: -            header = ['Name', 'Description','Type', 'References', 'Members'] -            output_firewall_vertical(rows, header) +            header = ['Name', 'Description', 'Type', 'References', 'Members'] + header_tail +            output_firewall_vertical(rows, header, adjust=False)          else: -            header = ['Name', 'Type', 'References', 'Members'] +            header = ['Name', 'Type', 'References', 'Members'] + header_tail              for i in rows:                  rows[rows.index(i)].pop(1)              print(tabulate.tabulate(rows, header))  | 
