从文本文件中查找数据,并以json格式显示结果



有一个txt文件,我需要在安全、防火墙、仅捕获规则号、源、目标端口和协议下获取值,如果缺少任何密钥,则需要针对没有值的密钥将默认文本打印为"any",同样需要在文件中获取所述密钥的数据

Txt文件数据


security {
firewall {
global-state-policy {
icmp
tcp
udp
}
name Local {
default-action drop
default-log
description "Local firewall rules."
rule 9 {
action accept
source {
address AccountFront
}
}
rule 10 {
action accept
source {
address SoftLayerBack
}
}
rule 11 {
action accept
source {
address SoftLayerFront
}
}
rule 20 {
action accept
description "Allow ping reply"
icmp {
type 0
}
------
------etc

需要这种形式的输出,

RULE_NAME{
9
SOURCE - 'any' if value doesn't exists
DESTINAION
PORT
POROTCOL
10
SOURCE
DESTINAION
PORT
POROTCOL
11
....
}

我写了下面的代码,但它返回空列表。请帮助

name, rule, address, destination, port, protocol= [''] * 6
access_list = []
with open(path + "mci_vyatta_config.txt", 'r') as fh:
for line in fh:
line = line.strip()
if line:
line_to_array = line.split(' ')
if line == "firewall;":
if line.startswith('name '):
name = line_to_array[1]
print(name)
#to_zone = line_to_array[3]
elif line.startswith('rule '):
rule = line_to_array[1]
elif line.startswith('address '):
address = line_to_array[1].replace(";", "")
elif line.startswith('destination '):
destination = line_to_array[1].replace(";", "")
elif line.startswith('port '):
port = line_to_array[1].replace(";", "")
elif line.startswith('protocol '):
port = line_to_array[1].replace(";", "")
elif line.startswith('then {'):
line = next(fh).strip()  # Gets next line in file
access_list.append({'NAME': name,
'RULE': rule,
'SOURCE': address,
'DESTINATION': destination,
'PORT': port,
'PROTOCOL': protocol})
name, rule, address, destination, port, protocol= [''] * 6
return access_list
access_list = read_config("/home/Fathima/workspace/training/")
print(access_list)

有些规则只有源即地址,有些规则只有端口或协议,如果源、目标端口和协议值存在,我们需要打印值,否则需要将关键字显示为"任何">

rule 53 {
action accept
description "Allow inbound to Zabbix agent"
protocol tcp
source {
port ZBX_TCP
}
state enable
}
rule 60 {
action accept
description "Allow UDP ports from VPN peers"
destination {
port IPSecPorts
}
protocol udp
source {
address IPSecPeers
}
}

例如,对于规则53,名称应打印为与规则名称一样的53,协议值应打印为tcp,端口应打印为ZBX_tcp,由于没有提到地址,因此应打印"任何">

这是一个开始。

代码

import re
def parser(filenm):
'''
Parser file containing network configuration information
'''
rule_block = re.compile(r's*rule (?P<rule_number>d+)s+{')  # Line starts a rule block
address_block = re.compile(r's*(?P<address>w+)s+{')    # Start of address info block
end_block = re.compile(r's*}')              # End block

with open(filenm, 'r') as file:
stack = []
bracket_count = 0

for line in file:
line = line.strip()     # Removes leading/trailing whitespace in line which doesn't matter

if line:                # Process only non-blank lines
if (m:=rule_block.match(line)):    # Detected Start a new rule
bracket_count += 1             # Update Open bracket count
nested_type = None

# New Dictionary with rule information
stack.append({"Rule": m.group('rule_number'), 
"SOURCE": "ANY",
"DESTINATION": "ANY",
"PROTOCOL": "ANY"})   # Start new addresses
while (line:=next(file, "").strip()):  # Gets next line in file

if end_block.match(line):  # Reached ending block indicator
bracket_count -= 1     # Update Close bracket count (i.e. close block)
if bracket_count == 0:
nested_type = None
break              # Done with current rule
else:
continue
if (m:=address_block.match(line)): # Address block in rule
nested_type = m.group('address')
bracket_count += 1
continue
data = line.split(maxsplit=1)
if len(data) != 2:
continue  # skip since has incorrect number of words
# Ignore data lines unrelated to desired info
if not data[0] in ['action', 'description', 'state']:
addresses = stack[-1]
if nested_type and data[0].upper()=="ADDRESS":
addresses[nested_type.upper()] = data[1]
elif nested_type and not nested_type in ['source', 'destination', 'protocol']:
addresses['PROTOCOL'] = f"{nested_type.upper()} {' '.join(data)}"
else:
addresses[data[0].upper()] = data[1]


return stack      

def display(info):
'''
Displays the parsing results
'''
print('RULE_NAME {')
for data in info:
print(f't{data["Rule"]}')
for k, v in data.items():
if not "Rule" in k:
print(f'tt{k} {v}')
print('}')

用法

results = parser('ip_rules.txt')
display(results)

输入文件ip_rules.txt

security {
firewall {
global-state-policy {
icmp
tcp
udp
}
name Local {
default-action drop
default-log
description "Local firewall rules."
rule 9 {
action accept
source {
address AccountFront
}
}
rule 10 {
action accept
source {
address SoftLayerBack
}
}
rule 11 {
action accept
source {
address SoftLayerFront
}
}
rule 20 {
action accept
description "Allow ping reply"
icmp {
type 0
}
}
rule 53 {
action accept
description "Allow inbound to Zabbix agent"
protocol tcp
source {
port ZBX_TCP
}
state enable
}
rule 60 {
action accept
description "Allow UDP ports from VPN peers"
destination {
port IPSecPorts
}
protocol udp
source {
address IPSecPeers
}
}
}
}
}

输出

RULE_NAME {
9
SOURCE AccountFront
DESTINATION ANY
PROTOCOL ANY
10
SOURCE SoftLayerBack
DESTINATION ANY
PROTOCOL ANY
11
SOURCE SoftLayerFront
DESTINATION ANY
PROTOCOL ANY
20
SOURCE ANY
DESTINATION ANY
PROTOCOL ICMP type 0
53
SOURCE ANY
DESTINATION ANY
PROTOCOL tcp
PORT ZBX_TCP
60
SOURCE IPSecPeers
DESTINATION ANY
PROTOCOL udp
PORT IPSecPorts
}

Python 3.6兼容版本

不使用海象运营商

import re
def parser(filenm):
'''
Parser file containing network configuration information
'''
rule_block = re.compile(r's*rule (?P<rule_number>d+)s+{')  # Line starts a rule block
address_block = re.compile(r's*(?P<address>w+)s+{')    # Start of address info block
end_block = re.compile(r's*}')              # End block

with open(filenm, 'r') as file:
stack = []
bracket_count = 0

for line in file:
line = line.strip()     # Removes leading/trailing whitespace in line which doesn't matter

if line:                # Process only non-blank lines
m = rule_block.match(line)
if m:    # Detected Start a new rule
bracket_count += 1             # Update Open bracket count
nested_type = None

# New Dictionary with rule information
stack.append({"Rule": m.group('rule_number'), 
"SOURCE": "ANY",
"DESTINATION": "ANY",
"PROTOCOL": "ANY"})   # Start new addresses

line = next(file, "").strip()
while line:
if end_block.match(line):  # Reached ending block indicator
bracket_count -= 1     # Update Close bracket count (i.e. close block)
if bracket_count == 0:
nested_type = None
break              # Done with current rule
else:
line = next(file, "").strip()  # Gets next line in file
continue
m = address_block.match(line)
if m: # Address block in rule
nested_type = m.group('address')
bracket_count += 1
line = next(file, "").strip()  # Gets next line in file
continue
data = line.split(maxsplit=1)
if len(data) != 2:
line = next(file, "").strip()  # Gets next line in file since current line has incorrect number of words
continue
# Ignore data lines unrelated to desired info
if not data[0] in ['action', 'description', 'state']:
addresses = stack[-1]
if nested_type and data[0].upper()=="ADDRESS":
addresses[nested_type.upper()] = data[1]
elif nested_type and not nested_type in ['source', 'destination', 'protocol']:
addresses['PROTOCOL'] = f"{nested_type.upper()} {' '.join(data)}"
else:
addresses[data[0].upper()] = data[1]

break

line = next(file, "").strip()  # Gets next line in file


return stack          

def display(info):
'''
Displays the parsing results
'''
print('RULE_NAME {')
for data in info:
print(f't{data["Rule"]}')
for k, v in data.items():
if not "Rule" in k:
print(f'tt{k} {v}')
print('}')

results = parser('ip_rules.txt')
display(results)

相关内容

最新更新