Finding Data From Text File And Displaying Result In Json Format
There's a txt file and i need to fetch values under security , firewall, capture only rule number, source, destination port and protocol, if any of the keys are missing need to pri
Solution 1:
Here's a start.
Code
import re
defparser(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 blockwithopen(filenm, 'r') as file:
stack = []
bracket_count = 0for line in file:
line = line.strip() # Removes leading/trailing whitespace in line which doesn't matterif line: # Process only non-blank linesif (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 addresseswhile (line:=next(file, "").strip()): # Gets next line in fileif 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 = Nonebreak# Done with current ruleelse:
continueif (m:=address_block.match(line)): # Address block in rule
nested_type = m.group('address')
bracket_count += 1continue
data = line.split(maxsplit=1)
iflen(data) != 2:
continue# skip since has incorrect number of words# Ignore data lines unrelated to desired infoifnot 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 andnot nested_type in ['source', 'destination', 'protocol']:
addresses['PROTOCOL'] = f"{nested_type.upper()}{' '.join(data)}"else:
addresses[data[0].upper()] = data[1]
return stack
defdisplay(info):
'''
Displays the parsing results
'''print('RULE_NAME {')
for data in info:
print(f'\t{data["Rule"]}')
for k, v in data.items():
ifnot"Rule"in k:
print(f'\t\t{k}{v}')
print('}')
Usage
results = parser('ip_rules.txt')
display(results)
Input File 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
}
}
}
}
}
Output
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 Compatiable Version
Doesn't use Walrus operator
import re
defparser(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 blockwithopen(filenm, 'r') as file:
stack = []
bracket_count = 0for line in file:
line = line.strip() # Removes leading/trailing whitespace in line which doesn't matterif 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 = Nonebreak# Done with current ruleelse:
line = next(file, "").strip() # Gets next line in filecontinue
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 filecontinue
data = line.split(maxsplit=1)
iflen(data) != 2:
line = next(file, "").strip() # Gets next line in file since current line has incorrect number of wordscontinue# Ignore data lines unrelated to desired infoifnot 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 andnot 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 filereturn stack
defdisplay(info):
'''
Displays the parsing results
'''print('RULE_NAME {')
for data in info:
print(f'\t{data["Rule"]}')
for k, v in data.items():
ifnot"Rule"in k:
print(f'\t\t{k}{v}')
print('}')
results = parser('ip_rules.txt')
display(results)
Post a Comment for "Finding Data From Text File And Displaying Result In Json Format"