File Coverage

blib/lib/Ixchel/Actions/suricata_diff.pm
Criterion Covered Total %
statement 20 90 22.2
branch 0 24 0.0
condition 0 3 0.0
subroutine 7 12 58.3
pod 2 5 40.0
total 29 134 21.6


line stmt bran cond sub pod time code
1             package Ixchel::Actions::suricata_diff;
2              
3 1     1   133314 use 5.006;
  1         6  
4 1     1   6 use strict;
  1         2  
  1         42  
5 1     1   7 use warnings;
  1         2  
  1         77  
6 1     1   1057 use File::Temp qw/ tempfile tempdir /;
  1         34156  
  1         114  
7 1     1   640 use File::Copy;
  1         4424  
  1         85  
8 1     1   676 use YAML::yq::Helper;
  1         36443  
  1         59  
9 1     1   10 use base 'Ixchel::Actions::base';
  1         2  
  1         648  
10              
11             =head1 NAME
12              
13             Ixchel::Actions::suricata_diff - Finds the differences between the Ixchel config and current Suricata config.
14              
15             =head1 VERSION
16              
17             Version 0.3.0
18              
19             =cut
20              
21             our $VERSION = '0.3.0';
22              
23             =head1 CLI SYNOPSIS
24              
25             ixchel -a suricata_diff [B<-i> ]
26              
27             =head1 CODE SYNOPSIS
28              
29             use Data::Dumper;
30              
31             my $results=$ixchel->action(action=>'suricata_diff', opts=>{np=>1, });
32              
33             print Dumper($results);
34              
35             =head1 DESCRIPTION
36              
37             If .suricata.auto_sensor_name=0 and .suricata.config.sensor-name and
38             .suricata.instances.$instance.sensor-name are undef, then it will set
39             .suricata.auto_sensor_name=1 for the instance being processed.
40              
41             =head1 FLAGS
42              
43             =head2 -i instance
44              
45             A instance to operate on.
46              
47             =head1 RESULT HASH REF
48              
49             .errors :: A array of errors encountered.
50             .status_text :: A string description of what was done and teh results.
51             .ok :: Set to zero if any of the above errored.
52              
53             =cut
54              
55       0 0   sub new_extra { }
56              
57             sub action_extra {
58 0     0 0   my $self = $_[0];
59              
60 0 0         if ( $self->{config}{suricata}{multi_instance} ) {
61 0           my @instances;
62              
63 0 0         if ( defined( $self->{opts}{i} ) ) {
64 0           @instances = ( $self->{opts}{i} );
65             } else {
66 0           @instances = keys( %{ $self->{config}{suricata}{instances} } );
  0            
67             }
68 0           foreach my $instance (@instances) {
69 0           eval { $self->process_config( instance => $instance ); };
  0            
70 0 0         if ($@) {
71 0           $self->status_add(
72             status => 'Proccessing instance "' . $instance . '" failed ... ' . $@,
73             error => 1
74             );
75             }
76             }
77             } else {
78 0 0         if ( defined( $self->{opts}{i} ) ) {
79 0           $self->status_add(
80             status => '-i may not be used in single instance mode, .suricata.multi_instance=1',
81             error => 1
82             );
83             }
84              
85 0           $self->process_config;
86             } ## end else [ if ( $self->{config}{suricata}{multi_instance...})]
87              
88 0           return undef;
89             } ## end sub action_extra
90              
91             sub short {
92 0     0 1   return 'Finds the differences between the Ixchel config and current Suricata config.';
93             }
94              
95             sub opts_data {
96 0     0 1   return 'i=s
97             w
98             ';
99             }
100              
101             sub process_config {
102 0     0 0   my ( $self, %opts ) = @_;
103              
104 0           my $config_base = $self->{config}{suricata}{config_base};
105              
106 0           my $temp_dir = tempdir( CLEANUP => 1 );
107              
108 0           my $new_dir = $temp_dir . '/new_yamls';
109              
110 0           mkdir($new_dir);
111              
112 0           my $instance_status = '';
113 0           my $instance_part = '';
114 0           my $instance_part2 = '';
115 0 0         if ( defined( $opts{instance} ) ) {
116 0           $instance_part = '-' . $opts{instance};
117 0           $instance_part2 = $opts{instance} . '-';
118 0           $instance_status = 'instance="' . $opts{instance} . '"... ';
119             }
120              
121 0           my $old_config_base = $config_base . '/suricata' . $instance_part . '.yaml';
122 0           my $old_config_include = $config_base . '/' . $instance_part2 . 'include.yaml';
123 0           my $old_config_outputs = $config_base . '/' . $instance_part2 . 'outputs.yaml';
124              
125 0           my $new_config_base = $new_dir . '/suricata' . $instance_part . '.yaml';
126 0           my $new_config_include = $new_dir . '/' . $instance_part2 . 'include.yaml';
127 0           my $new_config_outputs = $new_dir . '/' . $instance_part2 . 'outputs.yaml';
128              
129 0 0         if ( !-f $old_config_base ) {
130 0           $self->status_add( status => $instance_part . ' old config base,"' . $old_config_base . '", does exist' );
131 0           return;
132             }
133              
134 0           my $orig_asn = $self->{config}{suricata}{auto_sensor_name}{enable};
135 0 0 0       if ( !defined( $self->{config}{suricata}{config}{'sensor-name'} )
136             && !defined( $self->{config}{suricata}{ubstabces}{ $opts{instance} }{'sensor-name'} ) )
137             {
138 0           $self->{config}{suricata}{auto_sensor_name}{enable} = 1;
139             }
140              
141 0           eval {
142 0           copy( $old_config_base, $temp_dir . '/old.yaml' );
143 0 0         if ( -f $old_config_include ) {
144 0           copy( $old_config_include, $temp_dir . '/old-include.yaml' );
145             }
146 0 0         if ( -f $old_config_outputs ) {
147 0           copy( $old_config_outputs, $temp_dir . '/old-outputs.yaml' );
148             }
149              
150 0           my $yq = YAML::yq::Helper->new( file => $temp_dir . '/old.yaml' );
151 0 0         if ( -f $temp_dir . '/old-include.yaml' ) {
152 0           $yq->merge_yaml( yaml => $temp_dir . '/old-include.yaml' );
153             }
154 0 0         if ( -f $temp_dir . '/old-outputs.yaml' ) {
155 0           $yq->merge_yaml( yaml => $temp_dir . '/old-outputs.yaml' );
156             }
157 0           $yq->delete( var => '.outputs' );
158 0           $yq->delete( var => '.include' );
159              
160             my $results = $self->{ixchel}
161 0           ->action( action => 'suricata_base', opts => { np => 1, w => 1, i => $opts{instance}, d => $new_dir } );
162             $results = $self->{ixchel}
163 0           ->action( action => 'suricata_include', opts => { np => 1, w => 1, i => $opts{instance}, d => $new_dir } );
164             $results = $self->{ixchel}
165 0           ->action( action => 'suricata_outputs', opts => { np => 1, w => 1, i => $opts{instance}, d => $new_dir } );
166              
167 0           my $new_yq = YAML::yq::Helper->new( file => $new_config_base );
168 0           $new_yq->merge_yaml( yaml => $new_config_include );
169 0           $new_yq->merge_yaml( yaml => $new_config_outputs );
170 0           $new_yq->delete( var => '.outputs' );
171 0           $new_yq->delete( var => '.include' );
172              
173 0           move( $new_config_base, $temp_dir . '/new.yaml' );
174              
175 0           my $diff = $yq->yaml_diff( yaml => $temp_dir . '/new.yaml' );
176              
177 0           $self->status_add( status => $instance_part . " diff... \n" . $diff );
178             };
179 0 0         if ($@) {
180 0           die($@);
181             }
182              
183 0           $self->{config}{suricata}{auto_sensor_name}{enable} = $orig_asn;
184              
185 0           return;
186             } ## end sub process_config
187              
188             1;