Skip to content Skip to sidebar Skip to footer

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"