###
### Script pro detekci uzivatelu s nebezpecnym heslem z T-Potu pro monitoring Icinga
###

#!/usr/bin/perl

use Search::Elasticsearch;
use JSON;
use DateTime;
use Data::Dumper;
use List::MoreUtils qw(uniq);

# Konfigurace připojení k Elasticsearch s autentizací
my $es = Search::Elasticsearch->new(
    nodes => ['http://127.0.0.1:64298'],
    cxn_pool => 'Static::NoPing',  # Zamezí automatickému pingování serverů
    auth => 'basic',  # Použije autentizaci HTTP Basic
    auth_params => {
        username => '',
        password => ''
    }
);

# Aktuální čas v UTC
my $now = DateTime->now(time_zone => 'UTC');

# Nastavení časového pásma
# my $time_zone = 'Europe/Prague';  # Časové pásmo pro Prahu
# $now->set_time_zone($time_zone);

# Vytvoření kopie pro posledních 100 minut
my $from_date = $now->clone()->subtract(minutes => 8);

# To samé jako aktuální čas
my $to_date = $now;

# Konverze do formátu ISO 8601
                                    # 2024-04-10T11:35:04.945Z
my $from_iso = $from_date->strftime('%Y-%m-%dT%H:%M:%S.000Z');
my $to_iso = $to_date->strftime('%Y-%m-%dT%H:%M:%S.000Z');
my $index_date = $from_date->strftime('logstash-%Y.%m.%d');
# print "From: $from_iso\n";
# print "To: $to_iso\n";
# print "Index: $index_date\n";


# Dotaz s časovým rozsahem
my $results = $es->search(
    index => $index_date,
    body => {
        query => {
            bool => {
                must => {
                    match => { type => 'Heralding' }
                },
                filter => {
                    range => {
                        '@timestamp' => {
                            # >=from_iso AND =<to_iso
                            gte => $from_iso,
                            lte => $to_iso,
                        }
                    }
                }
            }
        },
        _source => ['username', 'password', '@timestamp', 'message']  # specifikace sloupců k vrácení
    }
);

# Kontrola chyby
if ($results->{'error'}) {
    die "Chyba při dotazu na Elasticsearch: " . $results->{'error'};
}
print @results;
# Zpracování výsledků
my @hits = @{$results->{'hits'}->{'hits'}};
# print "Pocet nalezenych zaznamu: " . scalar(@hits) . "\n";
my @formatted_results;
foreach my $hit (@hits) {
    # print Dumper($hit);
    push @formatted_results, $hit->{'_source'};
}
# print @formatted_results;
# check if the user has a password
my $alert = 0;
my @alert_users;
foreach my $hit (@formatted_results) {
    # print Dumper($hit);
    if (check_password($hit->{'password'}) && check_username($hit->{'username'})) {
        $alert = 1;
        push @alert_users, $hit->{'username'} . " " . $hit->{'password'};
    }
}

if ($alert) {
    print "Nalezeni uzivatele s nebezpecnym heslem: \n";
    # sort and uniq the array
    @alert_users = sort @alert_users;
    @alert_users = uniq(@alert_users);
    foreach my $user (@alert_users) {
        print "$user\n";
    }
    exit 2;
} else {
    print "Nenalezeni uzivatele s nebezpecnym heslem\n";
    exit 0;
}



### SUBS ###

sub check_password {
    my $password = shift;
    if (length($password) > 10 && $password =~ /\d/ && $password =~  /[A-Z]/) {
        return 1;
    }
    return 0;
}

sub check_username {
    my $username = shift;
    if ($username =~ /^[a-zA-Z]{3}\d{3,5}$/) {
        return 1;
    }
    return 0;
}
