File Coverage

blib/lib/Ixchel/Actions/lilith_config.pm
Criterion Covered Total %
statement 17 81 20.9
branch 0 34 0.0
condition 0 12 0.0
subroutine 6 10 60.0
pod 2 4 50.0
total 25 141 17.7


line stmt bran cond sub pod time code
1             package Ixchel::Actions::lilith_config;
2              
3 1     1   101966 use 5.006;
  1         4  
4 1     1   4 use strict;
  1         2  
  1         25  
5 1     1   4 use warnings;
  1         3  
  1         56  
6 1     1   502 use File::Slurp;
  1         38428  
  1         74  
7 1     1   8 use base 'Ixchel::Actions::base';
  1         1  
  1         527  
8 1     1   389 use Sys::Hostname;
  1         1151  
  1         992  
9              
10             =head1 NAME
11              
12             Ixchel::Actions::lilith_config - Generates the config for Lilith.
13              
14             =head1 VERSION
15              
16             Version 0.2.0
17              
18             =cut
19              
20             our $VERSION = '0.2.0';
21              
22             =head1 CLI SYNOPSIS
23              
24             ixchel -a lilith_config [B<-w>] [B<-o> ]
25              
26             =head1 CODE SYNOPSIS
27              
28             use Data::Dumper;
29              
30             my $results=$ixchel->action(action=>'lilith_config', opts=>{});
31              
32             if ($results->{ok}) {
33             print $results->{config};
34             }else{
35             die('Action errored... '.joined("\n", @{$results->{errors}}));
36             }
37              
38             =head1 FLAGS
39              
40             =head2 -w
41              
42             Write it out.
43              
44             =head2 -o
45              
46             The file to write it out to.
47              
48             Default :: /usr/local/etc/lilith.toml
49              
50             =head1 CONFIG
51              
52             .lilith.config is used for generating the config.
53              
54             =head2 AUTO CONFIG
55              
56             If .lilith.auto_config.enabled=1 is set, then it it will automatically fill out the
57             monitored instances.
58              
59             For single instances setups it is done as below.
60              
61             Suricata -> $hostname-pie -> /var/log/suricata/alert.json
62             Sagan -> $hostname-lae -> /var/log/sagan/alert.json
63             CAPEv2 -> $hostname-malware -> /opt/CAPEv2/log/eve.json
64              
65             For multi-instance it is done as below.
66              
67             Suricata -> $hostname-$instance -> /var/log/suricata/alert-$instance.json
68             Sagan -> $hostname-$instance -> /var/log/sagan/alert-$instance.json
69             CAPEv2 -> $hostname-malware -> /opt/CAPEv2/log/eve.json (or wherever .cape.eve set to)
70              
71             For hostname .lilith.auto_config.full=1 is set, then the full hostname is used.
72             Otherwise it will use the shorthostname via removing everything after the first /\./
73             via s/\.+$//.
74              
75             The variables used for checking which should be enabled are the usual enable ones as below.
76              
77             .suricata.enable
78             .sagan.enable
79             .cape.enable
80              
81             This expects that the instane naming scheme does not overlap and will error if any of them
82             do overlap, including if they are already defined in .lilith.config .
83              
84             =head1 RESULT HASH REF
85              
86             .errors :: A array of errors encountered.
87             .status_text :: A string description of what was done and the results.
88             .ok :: Set to zero if any of the above errored.
89             .config :: The generated config.
90              
91             =cut
92              
93             sub new_extra {
94 0     0 0   my $self = $_[0];
95              
96 0 0         if ( !defined( $self->{opts}{o} ) ) {
97 0           $self->{opts}{o} = '/usr/local/etc/lilith.toml';
98             }
99             }
100              
101             sub action_extra {
102 0     0 0   my $self = $_[0];
103              
104 0           my $config = $self->{config}{lilith}{config};
105 0 0         if ($@) {
106 0           $self->status_add( error => 1, status => 'Errored generating TOML for config ... ' . $@ );
107 0           return undef;
108             }
109              
110             ##
111             ##
112             ## auto config stuff
113             ##
114             ##
115             $self->status_add( status => '.lilith.auto_config.enable=1 .lilith.auto_config.full='
116 0           . $self->{config}{lilith}{auto_config}{full}, );
117 0 0         if ( $self->{config}{lilith}{auto_config}{enabled} ) {
118 0           my $hostname = hostname;
119 0 0         if ( !$self->{config}{lilith}{auto_config}{full} ) {
120 0           $hostname =~ s/\..*$//;
121             }
122 0           $self->status_add( status => 'using hostname "' . $hostname . '"', );
123             ##
124             ## cape auto config
125             ##
126 0 0         if ( $self->{config}{cape}{enable} ) {
127 0           my $instance_name = $hostname . '-malware';
128 0 0         if ( defined( $config->{$instance_name} ) ) {
129 0           $self->status_add(
130             error => 1,
131             status => $instance_name . ' already exists',
132             );
133             }
134             $config->{ $hostname . '-malware' } = {
135             instance => $hostname . '-malware',
136             type => 'cape',
137             eve => $self->{caoe}{eve},
138 0           };
139 0           $self->status_add( status => $instance_name . ': type=cape, eve="' . $self->{vape}{eve} . '"', );
140             } ## end if ( $self->{config}{cape}{enable} )
141             ##
142             ## suricata auto config
143             ##
144 0 0 0       if ( $self->{config}{suricata}{enable} && !$self->{config}{suricata}{multi_instance} ) {
    0 0        
145 0           my $instance_name = $hostname . '-pie';
146 0 0         if ( defined( $config->{$instance_name} ) ) {
147 0           $self->status_add(
148             error => 1,
149             status => $instance_name . ' already exists',
150             );
151             }
152 0           $config->{$instance_name} = {
153             instance => $hostname . '-pie',
154             type => 'suricata',
155             eve => '/var/log/suricata/alert.json',
156             };
157 0           $self->status_add( status => $instance_name . ': type=suricata, eve="/var/log/suricata/alert.json"', );
158             } elsif ( $self->{config}{suricata}{enable} && $self->{config}{suricata}{multi_instance} ) {
159 0           my @instances = keys( %{ $self->{config}{suricata}{instances} } );
  0            
160 0           foreach my $item (@instances) {
161 0           my $instance_name = $hostname . '-' . $item;
162 0 0         if ( defined( $config->{$instance_name} ) ) {
163 0           $self->status_add(
164             error => 1,
165             status => $instance_name . ' already exists',
166             );
167             }
168 0           $config->{$instance_name} = {
169             instance => $instance_name,
170             type => 'suricata',
171             eve => '/var/log/suricata/alert-' . $item . '.json',
172             };
173 0           $self->status_add(
174             status => $instance_name . ': type=suricata, eve="/var/log/suricata/alert-' . $item . '.json"',
175             );
176             } ## end foreach my $item (@instances)
177             } ## end elsif ( $self->{config}{suricata}{enable} && ...)
178             ##
179             ## sagan auto config
180             ##
181 0 0 0       if ( $self->{config}{sagan}{enable} && !$self->{config}{sagan}{multi_instance} ) {
    0 0        
182 0           my $instance_name = $hostname . '-lae';
183 0 0         if ( defined( $config->{$instance_name} ) ) {
184 0           $self->status_add(
185             error => 1,
186             status => $instance_name . ' already exists',
187             );
188             }
189 0           $config->{ $hostname . '-lae' } = {
190             instance => $hostname . '-lae',
191             type => 'sagan',
192             eve => '/var/log/sagan/alert.json',
193             };
194 0           $self->status_add( status => $instance_name . ': type=sagan, eve="/var/log/sagan/alert.json"', );
195             } elsif ( $self->{config}{sagan}{enable} && $self->{config}{suricatsgan}{multi_instance} ) {
196 0           my @instances = keys( %{ $self->{config}{sagan}{instances} } );
  0            
197 0           foreach my $item (@instances) {
198 0           my $instance_name = $hostname . '-' . $item;
199 0 0         if ( defined( $config->{$instance_name} ) ) {
200 0           $self->status_add(
201             error => 1,
202             status => $instance_name . ' already exists',
203             );
204             }
205 0           $config->{$instance_name} = {
206             instance => $instance_name,
207             type => 'suricata',
208             eve => '/var/log/suricata/alert-' . $item . '.json',
209             };
210 0           $self->status_add(
211             status => $instance_name . ': type=sagan, eve="/var/log/sagan/alert-' . $item . '.json"', );
212             } ## end foreach my $item (@instances)
213             } ## end elsif ( $self->{config}{sagan}{enable} && $self...)
214             } ## end if ( $self->{config}{lilith}{auto_config}{...})
215              
216 0           my $toml;
217 0           my $to_eval = 'use TOML::Tiny qw(to_toml); $toml = to_toml($config);';
218 0           eval $to_eval;
219 0 0         if ($@) {
220 0           $self->status_add( error => 1, status => 'Errored generating TOML for config... Is TOML::Tiny installed? cpanm TOML::Tiny ?... ' . $@ );
221 0           return undef;
222             }
223              
224 0           $self->status_add( status => "Lilith Config ...\n" . $toml );
225              
226 0 0         if ( $self->{opts}{w} ) {
227 0           eval { write_file( $self->{opts}{o}, $toml ) };
  0            
228 0 0         if ($@) {
229             $self->status_add(
230             error => 1,
231 0           status => 'Errored writing TOML out to "' . $self->{opts}{o} . '" ... ' . $@
232             );
233 0           return undef;
234             }
235             } ## end if ( $self->{opts}{w} )
236              
237 0           return undef;
238             } ## end sub action_extra
239              
240             sub short {
241 0     0 1   return 'Generates the config for Lilith.';
242             }
243              
244             sub opts_data {
245 0     0 1   return '
246             np
247             w
248             o=s
249             ';
250             }
251              
252             1;