i have some config files (exports from firewall reports in fact) using that kind of structure :
policies {
apply-groups default-log;
from-zone Trust to-zone DMZ {
policy policy-66 {
match {
source-address g_DMZ_SRV_;
destination-address g_DMZ_SRV;
application any;
}
then {
permit;
}
}
policy policy-9 {
match {
source-address g_h_OpenMail-Server;
destination-address g_in_DMZ_Exchange;
application t_1023;
}
then {
permit;
}
}
}
from-zone DMZ to-zone Blabla {
policy policy-68 {
match {
source-address g_DMZ_SRV_2_;
destination-address g_DMZ_SRV_3;
application T_22-ssh;
}
then {
permit;
}
}
policy policy-95 {
match {
source-address g_h_OpenMail-Server-2;
source-address 1.2.0.3;
destination-address g_in_DMZ_Exchange-1;
destination-address 10.25.32.64;
application t_1024;
}
then {
permit;
}
}
}
}
and I would like to parse it in Perl, in order to build a hash for example (or simply put conditions to treat the data) that I could exploit afterwards, e.g something like:
Trust-to-DMZ
policy-66
source => g_DMZ_SRV
destination => blabla
policy-44
source => source1
source2
source3
destination => dest1
ports => port1
DMZ-to-Trust
policy-XX
i wanted wanted to know :
if you knew some modules helpîng in such a task (i suppose i could use Text::Balanced, i found some examples in a few other posts)
if there was some methods/best practices in doing this to avoid dirty work ?
i suppose i could "count" the number of braces and do loops in loops.. but it would be dirty.
isn't there an easier solution or module doing this automatically ? (like modules exist for XML files for example, XML::Simple putting the contents of an XML into a hash, i would expect something similar for that kind of stuff ?)
otherwise i'll start coding something dirty and post my progress here
thanks!
edit on June 8th, just so you know, it works with a dirty dirty dirty code like that (I'm not a developer, apologies), which is not really what I want as it's not adaptable.. and clearly dirty as hell you have been warned! :) so don't look at it if you don't want blood in your eyes
use warnings;
use lib '/opt/csm/64-bit/cpan/5.16.3-2013.03/lib';
use Data::Dumper;
my ( $policies_flag, $fromzone_flag, $policy_flag, $match_flag, $zone_flag ) = ( 0,0,0,0,0 );
my ( $details_flag, $clos_flag, $then_flag, $permit_flag, $clos2_flag, $final_flag ) = ( 0,0,0,0,0,0 );
my $fromzone;
my $tozone;
my %pols;
my $clos_counter;
die "Usage: $0 <path_to_file>" if $ARGV[0] eq '';
open D, '<', $ARGV[0] or die "cannot open $ARGV[0] for read\n";
@data = <D>;
close D;
OUTER: foreach my $str (@data) {
next if $str =~ /^$/;
next if $str =~ /apply-groups/;
chomp $str;
if ( $str =~ /\s*policies\s+\{/ ) {
$policies_flag = 1;
next OUTER;
}
# policies
if ($policies_flag == 1) {
if ($str =~ /from-zone\s\S+\sto-zone\s\S+\s\{$/) {
next if $str =~ /(<|>)/;
( $fromzone, $tozone ) = ( split(/\s+/,$str) )[2,4];
$fromzone_flag = 1;
next OUTER;
}
# from-zone
if ($fromzone_flag == 1) {
if ($str =~ /policy\s+\S+\s+\{/) {
$policy_flag = 1;
$clos_counter=0;
( $policy_name ) = ( split(/\s+/, $str) )[2];
$pols{$policy_name}{from_zone} = "$fromzone";
$pols{$policy_name}{to_zone} = "$tozone";
next OUTER;
}
# pol
if ($policy_flag == 1) {
if ($str =~ /match\s+\{/) {
$match_flag = 1;
next OUTER;
}
}
# match
if ($match_flag == 1) {
if ($str =~ /\S+\s+\S+;$/) {
$details_flag = 1;
if ($str =~ /source-address/) {
( $sources ) = ( split(/\s+/, $str) )[2];
$sources =~ s/;//;
push( @{$pols{$policy_name}{sources}}, "$sources");
} elsif ($str =~ /destination-address/) {
( $dests ) = ( split(/\s+/, $str) )[2];
$dests =~ s/;//;
push( @{$pols{$policy_name}{destinations}}, "$dests");
} elsif ($str =~ /application/) {
( $ports ) = ( split(/\s+/, $str) )[2];
$ports =~ s/;//;
push( @{$pols{$policy_name}{ports}}, "$ports");
}
next OUTER;
}
}
# rest
if ($details_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 0) {
$clos_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# then
if ($clos_flag == 1) {
if ($str =~ /\s*then\s+\{$/) {
$then_flag = 1;
next OUTER;
}
}
# permit
if ($then_flag == 1) {
if ($str =~ /\s*permit;$/) {
$permit_flag = 1;
$pols{$policy_name}{action} = ( split(/\s+/,$str) )[1];
next OUTER;
}
}
# clos2
if ($permit_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 1) {
$clos2_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# final close
if ($clos2_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 2) {
$final_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# ultimate zone
if ($final_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 3) {
$zone_flag = 1;
$clos_counter++;
next OUTER;
}
}
}
# ulti pols
if ($zone_flag == 1) {
if ($str =~ /\s*\}\s*$/) {
if ($clos_counter == 4) {
$clos_counter++;
last OUTER;
}
}
}
}
}
}
print Dumper(\%pols);
which gives:
$VAR1 = {
'policy-68' => {
'ports' => [
'T_22-ssh'
],
'sources' => [
'g_DMZ_SRV_2_'
],
'to_zone' => 'Blabla',
'from_zone' => 'DMZ',
'action' => 'permit;',
'destinations' => [
'g_DMZ_SRV_3'
]
},
'policy-9' => {
'ports' => [
't_1023'
],
'sources' => [
'g_h_OpenMail-Server'
],
'to_zone' => 'DMZ',
'from_zone' => 'Trust',
'action' => 'permit;',
'destinations' => [
'g_in_DMZ_Exchange'
]
},
'policy-66' => {
'ports' => [
'any'
],
'sources' => [
'g_DMZ_SRV_'
],
'to_zone' => 'DMZ',
'from_zone' => 'Trust',
'action' => 'permit;',
'destinations' => [
'g_DMZ_SRV'
]
},
'policy-95' => {
'ports' => [
't_1024'
],
'sources' => [
'g_h_OpenMail-Server-2',
'1.2.0.3'
],
'to_zone' => 'Blabla',
'from_zone' => 'DMZ',
'action' => 'permit;',
'destinations' => [
'g_in_DMZ_Exchange-1',
'10.25.32.64'
]
}
};