File Coverage

blib/lib/Farly/ASA/Filter.pm
Criterion Covered Total %
statement 105 108 97.2
branch 33 38 86.8
condition 3 3 100.0
subroutine 11 11 100.0
pod 0 4 0.0
total 152 164 92.6


line stmt bran cond sub pod time code
1             package Farly::ASA::Filter;
2            
3 10     10   36797 use 5.008008;
  10         45  
  10         712  
4 10     10   53 use strict;
  10         16  
  10         267  
5 10     10   46 use warnings;
  10         24  
  10         254  
6 10     10   46 use Carp;
  10         117  
  10         661  
7 10     10   972 use Log::Any qw($log);
  10         2245  
  10         51  
8            
9             our $VERSION = '0.26';
10            
11             sub new {
12 6     6 0 1575 my ($class) = @_;
13            
14 6         37 my $self = {
15             FILE => undef,
16             PREPARSE => [],
17             OG_INDEX => {}, #object-group to type mapping
18             ACL_ID => {}, #for inserting line numbers
19             };
20 6         20 bless $self, $class;
21            
22 6         55 $log->info("$self NEW");
23            
24 6         24 return $self;
25             }
26            
27             sub set_file {
28 6     6 0 20 my ( $self, $file ) = @_;
29 6         21 $self->{FILE} = $file;
30 6         67 $log->info( "$self set FILE to " . $self->{FILE} );
31             }
32            
33             sub append {
34 365     365 0 532 my ( $self, $string ) = @_;
35 365 50       725 defined($string)
36             or confess " $self attempted to append undefined string to PREPARSE";
37 365         372 push @{ $self->{PREPARSE} }, $string;
  365         1265  
38             }
39            
40             sub run {
41 6     6 0 400 my ($self) = @_;
42            
43 6         19 my $file = $self->{FILE};
44            
45 6         19 my $interface_options = "nameif|security-level|ip address"; #shutdown
46 6         16 my $object_options = "host|range|subnet|service";
47 6         17 my $group_options = "network-object|port-object|group-object|protocol-object|description|icmp-object|service-object";
48 6         16 my $unsupported_acl_type = "ethertype|standard|webtype";
49            
50 6         821 while ( my $line = $file->getline() ) {
51            
52 295         11338 $log->trace("$self SCAN $line");
53            
54 295 100       1226 if ( $line =~ /^hostname (\S+)/ ) {
55 6         34 $self->append($line);
56 6         179 next;
57             }
58 289 100       712 if ( $line =~ /^name (\S+) (\S+)/ ) {
59 12         38 $self->append($line);
60 12         303 next;
61             }
62 277 100       574 if ( $line =~ /^interface/ ) {
63 6         39 $self->_process_section( $line, $interface_options, 1 );
64 6         539 next;
65             }
66 271 100       664 if ( $line =~ /^object\s/ ) {
67 35         86 $self->_process_section( $line, $object_options );
68 35         846 next;
69             }
70 236 100       610 if ( $line =~ /^object-group (\S+) (\S+)/ ) {
71 77         162 my $type = $1;
72 77         125 my $id = $2;
73 77         239 $self->{OG_INDEX}->{$id} = $type;
74 77         295 $log->debug("added OG_INDEX $id $type");
75 77         271 $self->_process_section( $line, $group_options );
76 77         1794 next;
77             }
78 159 50       2424 if ( $line =~ /^access-list (.*) $unsupported_acl_type/ ) {
79 0         0 $log->info("$self SKIPPED access-list '$line'");
80 0         0 next;
81             }
82            
83             #access-list outside-in line 3 extended permit tcp OG_NETWORK internal OG_SERVICE highports host 192.168.2.1 eq 80
84 159 100       461 if ( $line =~ /^access-list/ ) {
85 94         229 my $p_line = $self->_process_acl($line);
86 94         554 $log->debug("$self pre-processed line '$p_line'");
87 94         363 $self->append($p_line);
88 94         2545 next;
89             }
90 65 100       151 if ( $line =~ /^access-group/ ) {
91 6         27 $self->append($line);
92 6         155 next;
93             }
94 59 100       1303 if ( $line =~ /^route/ ) {
95 10         39 $self->append($line);
96             }
97             }
98            
99 6         189 return @{ $self->{PREPARSE} };
  6         200  
100             }
101            
102             sub _process_section {
103 118     118   198 my ( $self, $header, $options, $full_sect ) = @_;
104            
105 118         174 my $file = $self->{FILE};
106 118         416 my $pos = $file->getpos();
107 118         2911 my $line = $file->getline();
108            
109 118         3424 $log->debug("$header");
110 118         299 my $header_pos = $pos;
111            
112 118   100     671 while ( $line && $line =~ /^\s/ ) {
113            
114 277 100       7110 if ( $line =~ /^\s(?=$options)/ ) {
115 249         832 $log->debug("$line");
116 249 100       831 if ( defined($full_sect) ) {
117 18         142 $header .= $line;
118             }
119             else {
120 231         769 $self->append( $header . $line );
121             }
122             }
123             else {
124 28         70 chomp($line);
125 28         139 $log->warn("unknown option in line '$line'");
126             }
127            
128 277         881 $pos = $file->getpos();
129 277         6676 $line = $file->getline();
130             }
131            
132 118 100       3724 if ( defined($full_sect) ) {
133 6         25 $self->append($header);
134             }
135            
136 118 50       271 if ( $pos eq $header_pos ) {
137 0         0 $log->warn("empty section : '$header'");
138             }
139            
140 118         1139 $file->setpos($pos);
141             }
142            
143             sub _process_acl {
144 94     94   153 my ( $self, $line ) = @_;
145            
146             # add line number to configuration access-list
147 94 50       328 if ( $line =~ /^access-list (\S+)/ ) {
148 94         176 my $acl_id = $1;
149 94 100       254 if ( !$self->{ACL_ID}->{$acl_id} ) {
150 11         39 $self->{ACL_ID}->{$acl_id} = 1;
151             }
152             else {
153 83         154 $self->{ACL_ID}->{$acl_id}++;
154             }
155 94         281 my $line_count = $self->{ACL_ID}->{$acl_id};
156 94         788 $line =~ s/access-list $acl_id/access-list $acl_id line $line_count/;
157             }
158            
159             # translate "object-group" to OG_ format
160 94 100       293 if ( $line =~ /object-group/ ) {
161            
162 36         274 my @lineArr = split( /\s+/, $line );
163            
164 36         121 while (@lineArr) {
165 444         725 my $string = shift @lineArr;
166 444 100       1197 if ( $string =~ /object-group/ ) {
167 66         127 my $og_ID = shift @lineArr;
168            
169 66 50       209 my $og_type = $self->{OG_INDEX}->{$og_ID}
170             or confess "no object-group type for $og_ID";
171            
172 66         146 my $new_og_type = "OG_" . uc($og_type);
173 66         983 $line =~ s/object-group $og_ID/$new_og_type $og_ID/;
174             }
175             }
176             }
177            
178 94         235 return $line;
179             }
180            
181             1;
182             __END__