1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-17 00:07:37 +02:00
Files
jc/jc/parsers/iptables.py

286 lines
7.3 KiB
Python
Raw Normal View History

2022-03-04 13:27:39 -08:00
"""jc - JSON Convert `iptables` command output parser
2020-08-05 16:51:58 -07:00
Supports `-vLn` and `--line-numbers` for all tables.
2019-10-22 15:42:29 -07:00
2020-08-05 13:32:59 -07:00
Usage (cli):
2019-12-12 09:47:14 -08:00
2020-08-05 16:51:58 -07:00
$ sudo iptables -L -t nat | jc --iptables
2022-08-15 13:51:48 -07:00
or
2019-10-22 15:42:29 -07:00
2020-08-05 16:51:58 -07:00
$ jc iptables -L -t nat
2019-10-22 15:42:29 -07:00
2020-08-05 13:32:59 -07:00
Usage (module):
2022-01-18 15:38:03 -08:00
import jc
result = jc.parse('iptables', iptables_command_output)
2021-04-08 15:53:06 -07:00
Schema:
[
{
"chain": string,
"rules": [
{
"num" integer,
"pkts": integer,
"bytes": integer, # converted based on suffix
"target": string,
"prot": string,
"opt": string, # "--" = Null
"in": string,
"out": string,
"source": string,
"destination": string,
"options": string
}
]
}
]
2019-10-22 15:42:29 -07:00
Examples:
2019-11-11 18:30:46 -08:00
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p
[
2019-10-22 16:40:27 -07:00
{
2019-11-11 18:30:46 -08:00
"chain": "PREROUTING",
"rules": [
{
"num": 1,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_direct",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 2,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_ZONES_SOURCE",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 3,
"pkts": 2183,
"bytes": 186000,
"target": "PREROUTING_ZONES",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": 4,
"pkts": 0,
"bytes": 0,
"target": "DOCKER",
"prot": "all",
"opt": null,
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere",
"options": "ADDRTYPE match dst-type LOCAL"
}
]
2019-10-22 16:40:27 -07:00
},
2019-11-11 18:30:46 -08:00
...
2019-10-22 16:40:27 -07:00
]
2019-11-11 18:30:46 -08:00
$ sudo iptables --line-numbers -v -L -t nat | jc --iptables -p -r
[
2019-10-22 16:40:27 -07:00
{
2019-11-11 18:30:46 -08:00
"chain": "PREROUTING",
"rules": [
{
"num": "1",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_direct",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "2",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_ZONES_SOURCE",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "3",
"pkts": "2183",
"bytes": "186K",
"target": "PREROUTING_ZONES",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere"
},
{
"num": "4",
"pkts": "0",
"bytes": "0",
"target": "DOCKER",
"prot": "all",
"opt": "--",
"in": "any",
"out": "any",
"source": "anywhere",
"destination": "anywhere",
"options": "ADDRTYPE match dst-type LOCAL"
}
]
2019-10-22 16:40:27 -07:00
},
2019-11-11 18:30:46 -08:00
...
2019-10-22 16:40:27 -07:00
]
2019-10-22 15:42:29 -07:00
"""
2019-11-07 08:07:43 -08:00
import jc.utils
2019-10-22 15:42:29 -07:00
2019-12-13 20:01:51 -08:00
class info():
2021-04-08 15:53:06 -07:00
"""Provides parser metadata (version, author, etc.)"""
2022-06-30 09:24:05 -07:00
version = '1.8'
description = '`iptables` command parser'
2019-12-13 20:01:51 -08:00
author = 'Kelly Brazil'
author_email = 'kellyjonbrazil@gmail.com'
compatible = ['linux']
2020-02-11 18:09:21 -08:00
magic_commands = ['iptables']
tags = ['command']
2019-12-13 20:01:51 -08:00
2020-02-03 16:11:58 -08:00
__version__ = info.version
2021-04-08 15:53:06 -07:00
def _process(proc_data):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:28:10 -08:00
Final processing to conform to the schema.
Parameters:
2019-11-14 16:36:00 -08:00
2021-01-04 18:01:16 -08:00
proc_data: (List of Dictionaries) raw structured data to process
2019-11-12 11:28:10 -08:00
Returns:
2021-04-08 15:53:06 -07:00
List of Dictionaries. Structured data to conform to the schema.
2019-11-11 18:30:46 -08:00
"""
2019-11-04 16:59:14 -08:00
for entry in proc_data:
for rule in entry['rules']:
int_list = ['num', 'pkts']
2021-04-18 16:33:47 -07:00
for key in rule:
if key in int_list:
2021-04-18 13:01:25 -07:00
rule[key] = jc.utils.convert_to_int(rule[key])
2019-11-04 16:59:14 -08:00
if 'bytes' in rule:
multiplier = 1
if rule['bytes'][-1] == 'K':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 3
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('K')
elif rule['bytes'][-1] == 'M':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 6
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('M')
elif rule['bytes'][-1] == 'G':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 9
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('G')
elif rule['bytes'][-1] == 'T':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 12
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('T')
elif rule['bytes'][-1] == 'P':
2020-06-22 10:47:34 -07:00
multiplier = 10 ** 15
2019-11-04 16:59:14 -08:00
rule['bytes'] = rule['bytes'].rstrip('P')
try:
2021-04-18 13:01:25 -07:00
bytes_int = jc.utils.convert_to_int(rule['bytes'])
2019-11-04 16:59:14 -08:00
rule['bytes'] = bytes_int * multiplier
2019-11-06 08:47:54 -06:00
except (ValueError):
2019-11-04 16:59:14 -08:00
rule['bytes'] = None
if 'opt' in rule:
if rule['opt'] == '--':
rule['opt'] = None
return proc_data
2019-11-07 08:07:43 -08:00
def parse(data, raw=False, quiet=False):
2019-11-11 18:30:46 -08:00
"""
2019-11-12 11:17:33 -08:00
Main text parsing function
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Parameters:
2019-11-14 16:36:00 -08:00
2019-11-12 11:17:33 -08:00
data: (string) text data to parse
2022-01-21 07:42:03 -08:00
raw: (boolean) unprocessed output if True
2019-11-12 11:17:33 -08:00
quiet: (boolean) suppress warning messages if True
2019-11-11 18:30:46 -08:00
2019-11-12 11:17:33 -08:00
Returns:
2021-01-04 18:01:16 -08:00
List of Dictionaries. Raw or processed structured data.
2019-11-11 18:30:46 -08:00
"""
jc.utils.compatibility(__name__, info.compatible, quiet)
jc.utils.input_type_check(data)
2019-11-05 22:42:48 -06:00
2019-11-04 16:59:14 -08:00
raw_output = []
2019-10-22 15:42:29 -07:00
chain = {}
headers = []
if jc.utils.has_data(data):
2019-10-22 15:42:29 -07:00
2020-06-22 10:47:34 -07:00
for line in list(filter(None, data.splitlines())):
2019-10-22 15:42:29 -07:00
if line.startswith('Chain'):
2020-06-22 10:47:34 -07:00
if chain:
raw_output.append(chain)
chain = {}
headers = []
2019-10-22 15:42:29 -07:00
parsed_line = line.split()
2019-10-22 15:42:29 -07:00
chain['chain'] = parsed_line[1]
chain['rules'] = []
2019-10-22 15:42:29 -07:00
continue
2019-10-22 15:42:29 -07:00
elif line.startswith('target') or line.find('pkts') == 1 or line.startswith('num'):
headers = [h for h in ' '.join(line.lower().strip().split()).split() if h]
headers.append("options")
2019-10-22 15:42:29 -07:00
continue
2019-10-22 15:42:29 -07:00
else:
rule = line.split(maxsplit=len(headers) - 1)
temp_rule = dict(zip(headers, rule))
if temp_rule:
chain['rules'].append(temp_rule)
if chain:
raw_output.append(chain)
2019-11-04 16:59:14 -08:00
if raw:
return raw_output
else:
2021-04-08 15:53:06 -07:00
return _process(raw_output)