#!perl

use warnings;
use strict;
use Getopt::Long qw(:config no_ignore_case);
use Pod::Usage   qw( pod2usage );
use Check::SuricataFlows;

=head1 NAME

check_sureicataflows - A Nagios style check to see if a Suricata flows EVE JSON contains bi-directional flows.

=head1 SYNOPSIS

check_suricataflows [B<-f> <flows.json>] [B<-a> <alert count>] [B<-w> <warn count>]
[B<-t> <seconds>] [<-m> <max lines>] [B<-s> <sensor>]

check_suricataflows [B<-f> <flows.json>] [B<-a> <alert count>] [B<-w> <warn count>]
[B<-t> <seconds>] [<-m> <max lines>] B<-s> <sensor> [B<-s> <sensor>]

check_suricataflows -h/--help

check_suricataflows -v/--version

=head1 DESCRIPTION

This reads the Suricata EVE JSON flow data file.

    .timestamp :: Used for double checking to make sure we don't read farther
        back than we need to.

If the following is found, the entry is checked.

    .dest_ip
    .src_ip
    .flow.pkts_toclient
    .flow.pkts_toserver

Bi-directional is when .flow.pkts_toclient and .flow.pkts_toserver are both greater
than zero.

Uni-directional is when only .flow.pkts_toclient or .flow.pkts_toserver is greater
than zero and the other is zero.

If all entries found are uni-directional then it is safe to assume the monitored span
is misconfigured.

If more than one Suricata instance is appending to the file, you will likely want to use
-s to specify each sensor name to check for.

=head1 FLAGS

=head2 -f <flows.json>

The flows EVE JSON location.

Default: /var/log/suricata/flows/current/flow.json

=head2 -a <alert count>

Alert if the number of bidirectional flows are less than this.

Default: 10

=head2 -w <warn count>

Warn if the number of directional flows are less than this.

Default: 20

=head2 -t <seconds>

How far back into the file to read in seconds.

Default: 300

=head2 -m <max lines>

Max number of lines to read in.

=head2 -s <sensor>

Sensor names to check for. May used more than once.

If used then each of the specified sensors is checked for. It is
checked from .host in the JSON and the variable for setting that
in the Suricata config is .sensor-name .

If more than once Suricata instance is appending to the file, then
you will most likely want to use this.

=cut

sub version {
	print 'check_networkspans v. ' . $Check::NetworkSpans::VERSION . "\n";
}

sub help {
	pod2usage( -exitval => 255, -verbose => 2, -output => \*STDOUT );
}

my $help;
my $version;
my $flow_file;
my $alert_count;
my $warn_count;
my $read_back_time;
my $max_lines;
my @sensor_names;
GetOptions(
	'version' => \$version,
	'v'       => \$version,
	'help'    => \$help,
	'h'       => \$help,
	'f=s'     => \$flow_file,
	'a=i'     => \$alert_count,
	'w=i'     => \$warn_count,
	't=i'     => \$read_back_time,
	'm=i'     => \$max_lines,
	's=s'     => \@sensor_names,
);

if ($help) {
	&help;
	exit 255;
}
if ($version) {
	&version;
	exit 255;
}

my $flow_checker;
eval {
	$flow_checker = Check::SuricataFlows->new(
		max_lines      => $max_lines,
		read_back_time => $read_back_time,
		warn_count     => $warn_count,
		alert_count    => $alert_count,
		flow_file      => $flow_file,
		sensor_names   => \@sensor_names,
	);
};
if ($@) {
	print 'Failed to call Check::SuricataFlows->new... ' . $@ . "\n";
	exit 3;
}

my $results;
eval { $results = $flow_checker->run; };
if ($@) {
	print 'Failed to call $flow_checker->run... ' . $@ . "\n";
	exit 3;
}

print $results->{status};
exit $results->{status_code};
