有一个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)