diff --git a/extras/pandora_gotty/README.md b/extras/pandora_gotty/README.md index 2e261c2e53..c31e228c46 100644 --- a/extras/pandora_gotty/README.md +++ b/extras/pandora_gotty/README.md @@ -1 +1 @@ -To create the .deb and .rpm package need to hace docker installed on main system and execit `build_all_docker.sh` \ No newline at end of file +To create the .deb and .rpm package need to hace docker installed on main system and execit `build_all_docker.sh` diff --git a/pandora_agents/pc/Linux/pandora_agent.conf b/pandora_agents/pc/Linux/pandora_agent.conf index 0a3a48950c..6284c748f9 100644 --- a/pandora_agents/pc/Linux/pandora_agent.conf +++ b/pandora_agents/pc/Linux/pandora_agent.conf @@ -300,3 +300,7 @@ module_plugin grep_log /var/log/syslog Syslog ssh #module_exec echo 5 #module_description Postcondition test module #module_end + +# This plugin runs several security checks in a Linux system + +#module_plugin pandora_security_check \ No newline at end of file diff --git a/pandora_agents/unix/DEBIAN/control b/pandora_agents/unix/DEBIAN/control index 1e5d17a506..fb1cbfc2d3 100644 --- a/pandora_agents/unix/DEBIAN/control +++ b/pandora_agents/unix/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-agent-unix -Version: 7.0NG.773.3-231011 +Version: 7.0NG.773.3-231019 Architecture: all Priority: optional Section: admin diff --git a/pandora_agents/unix/DEBIAN/make_deb_package.sh b/pandora_agents/unix/DEBIAN/make_deb_package.sh index 6d71887328..db62eab155 100644 --- a/pandora_agents/unix/DEBIAN/make_deb_package.sh +++ b/pandora_agents/unix/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.773.3-231011" +pandora_version="7.0NG.773.3-231019" echo "Test if you has the tools for to make the packages." whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null diff --git a/pandora_agents/unix/pandora_agent b/pandora_agents/unix/pandora_agent index 6712d85707..f3babe0ab1 100755 --- a/pandora_agents/unix/pandora_agent +++ b/pandora_agents/unix/pandora_agent @@ -1031,7 +1031,7 @@ my $Sem = undef; my $ThreadSem = undef; use constant AGENT_VERSION => '7.0NG.773.3'; -use constant AGENT_BUILD => '231011'; +use constant AGENT_BUILD => '231019'; # Agent log default file size maximum and instances use constant DEFAULT_MAX_LOG_SIZE => 600000; diff --git a/pandora_agents/unix/pandora_agent.redhat.spec b/pandora_agents/unix/pandora_agent.redhat.spec index 2651e76f6b..9068f935ba 100644 --- a/pandora_agents/unix/pandora_agent.redhat.spec +++ b/pandora_agents/unix/pandora_agent.redhat.spec @@ -4,7 +4,7 @@ %global __os_install_post %{nil} %define name pandorafms_agent_linux %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.redhat_bin.spec b/pandora_agents/unix/pandora_agent.redhat_bin.spec index 934a423b89..5fe622218b 100644 --- a/pandora_agents/unix/pandora_agent.redhat_bin.spec +++ b/pandora_agents/unix/pandora_agent.redhat_bin.spec @@ -5,7 +5,7 @@ %define name pandorafms_agent_linux_bin %define source_name pandorafms_agent_linux %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 Summary: Pandora FMS Linux agent, binary version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent.spec b/pandora_agents/unix/pandora_agent.spec index 0fdd28b09f..4a55842d23 100644 --- a/pandora_agents/unix/pandora_agent.spec +++ b/pandora_agents/unix/pandora_agent.spec @@ -4,7 +4,7 @@ %global __os_install_post %{nil} %define name pandorafms_agent_linux %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 Summary: Pandora FMS Linux agent, PERL version Name: %{name} diff --git a/pandora_agents/unix/pandora_agent_installer b/pandora_agents/unix/pandora_agent_installer index ae5854da47..12b0a802a6 100755 --- a/pandora_agents/unix/pandora_agent_installer +++ b/pandora_agents/unix/pandora_agent_installer @@ -10,7 +10,7 @@ # ********************************************************************** PI_VERSION="7.0NG.773.3" -PI_BUILD="231011" +PI_BUILD="231019" OS_NAME=`uname -s` FORCE=0 diff --git a/pandora_agents/unix/plugins/pandora_security_check b/pandora_agents/unix/plugins/pandora_security_check new file mode 100644 index 0000000000..0ad845639b --- /dev/null +++ b/pandora_agents/unix/plugins/pandora_security_check @@ -0,0 +1,631 @@ +#!/usr/bin/perl +################################################################################ +# Author: Enrique Martin Garcia +# Copyright: 2023, PandoraFMS +# Maintainer: Operations department +# Version: 1.0 +################################################################################ + +use strict; +use warnings; + +use Getopt::Long; +use File::Basename; +use File::Spec; +use Digest::MD5 qw(md5_hex); +use Scalar::Util 'looks_like_number'; +use Socket; + +# Define signal handlers +sub sigint_handler { + print STDERR "\nInterrupted by user\n"; + exit 0; +} + +sub sigterm_handler { + print STDERR "Received SIGTERM signal.\n"; + exit 0; +} + +$SIG{INT} = \&sigint_handler; +$SIG{TERM} = \&sigterm_handler; + +# Add lib dir path +my $lib_dir = File::Spec->catdir(dirname($0), 'lib'); +unshift @INC, $lib_dir; + +### +# GLOBALS +################## + +my %options = (); + +my $modules_group = 'Security'; + +my $b_ports = 'PORTS'; +my $b_files = 'FILES'; +my $b_passwords = 'PASSWORDS'; + +my @blocks = ($b_ports, $b_files, $b_passwords); +my $configuration_block; + +my $integrity_file = '/tmp/' . md5_hex(File::Spec->rel2abs($0)) . '.integrity'; + +# Enable all checks by default +my $check_selinux = 1; +my $check_ssh_root_access = 1; +my $check_ssh_root_keys = 1; +my $check_ports = 1; +my $check_files = 1; +my $check_passwords = 1; + +# Include all values for checks by default +my $include_defaults = 1; + +# Initialize check lists +my @l_ports = ( + 80, + 22 +); +my @l_files = ( + '/etc/shadow', + '/etc/passwd', + '/etc/hosts', + '/etc/resolv.conf', + '/etc/ssh/sshd_config', + '/etc/rsyslog.conf' +); + +my @l_passwords = ( + '123456', + '12345678', + '123456789', + '12345', + '1234567', + 'password', + '1password', + 'abc123', + 'qwerty', + '111111', + '1234', + 'iloveyou', + 'sunshine', + 'monkey', + '1234567890', + '123123', + 'princess', + 'baseball', + 'dragon', + 'football', + 'shadow', + 'soccer', + 'unknown', + '000000', + 'myspace1', + 'purple', + 'fuckyou', + 'superman', + 'Tigger', + 'buster', + 'pepper', + 'ginger', + 'qwerty123', + 'qwerty1', + 'peanut', + 'summer', + '654321', + 'michael1', + 'cookie', + 'LinkedIn', + 'whatever', + 'mustang', + 'qwertyuiop', + '123456a', + '123abc', + 'letmein', + 'freedom', + 'basketball', + 'babygirl', + 'hello', + 'qwe123', + 'fuckyou1', + 'love', + 'family', + 'yellow', + 'trustno1', + 'jesus1', + 'chicken', + 'diamond', + 'scooter', + 'booboo', + 'welcome', + 'smokey', + 'cheese', + 'computer', + 'butterfly', + '696969', + 'midnight', + 'princess1', + 'orange', + 'monkey1', + 'killer', + 'snoopy ', + 'qwerty12 ', + '1qaz2wsx ', + 'bandit', + 'sparky', + '666666', + 'football1', + 'master', + 'asshole', + 'batman', + 'sunshine1', + 'bubbles', + 'friends', + '1q2w3e4r', + 'chocolate', + 'Yankees', + 'Tinkerbell', + 'iloveyou1', + 'abcd1234', + 'flower', + '121212', + 'passw0rd', + 'pokemon', + 'StarWars', + 'iloveyou2', + '123qwe', + 'Pussy', + 'angel1' +); + +### +# ARGS PARSER +################## + +my $HELP = <] + [--conf ] + +Optional arguments: + -h, --help Show this help message and exit + --check_selinux {0,1} Enable/Disable check SElinux module + --check_ssh_root_access {0,1} Enable/Disable check SSH root access module + --check_ssh_root_keys {0,1} Enable/Disable check SSH root keys module + --check_ports {0,1} Enable/Disable check ports module + --check_files {0,1} Enable/Disable check files module + --check_passwords {0,1} Enable/Disable check passwords module + --include_defaults {0,1} Enable/Disable default plugin checks for ports, files and passwords + --integrity_file Path to integrity check file + Default: $integrity_file + --conf Path to plugin configuration file + Available configuration blocks: + [$b_ports], [$b_files] and [$b_passwords] + Content example: + [$b_ports] + 3306 + 443 + [$b_files] + /etc/httpd/httpd.conf + /etc/my.cnf + [$b_passwords] + pandora + PANDORA + P4nd0r4 + +EO_HELP + +sub help { + my ($extra_message) = @_; + print $HELP; + print $extra_message if defined($extra_message); + exit 0; +} + +sub parse_bool_arg { + my ($arg, $default) = @_; + + if (defined $options{$arg}) { + if (looks_like_number($options{$arg}) && ($options{$arg} == 1 || $options{$arg} == 0)) { + return $options{$arg}; + } else { + help("Invalid value for argument: $arg\n"); + } + } else { + return $default; + } +} + +# Parse arguments +GetOptions( + "help|h" => \$options{help}, + "check_selinux=s" => \$options{check_selinux}, + "check_ssh_root_access=s" => \$options{check_ssh_root_access}, + "check_ssh_root_keys=s" => \$options{check_ssh_root_keys}, + "check_ports=s" => \$options{check_ports}, + "check_files=s" => \$options{check_files}, + "check_passwords=s" => \$options{check_passwords}, + "include_defaults=s" => \$options{include_defaults}, + "integrity_file=s" => \$options{integrity_file}, + "conf=s" => \$options{conf} +); + +help() if ($options{help}); + +$check_selinux = parse_bool_arg('check_selinux', $check_selinux); +$check_ssh_root_access = parse_bool_arg('check_ssh_root_access', $check_ssh_root_access); +$check_ssh_root_keys = parse_bool_arg('check_ssh_root_keys', $check_ssh_root_keys); +$check_ports = parse_bool_arg('check_ports', $check_ports); +$check_files = parse_bool_arg('check_files', $check_files); +$check_passwords = parse_bool_arg('check_passwords', $check_passwords); + +$include_defaults = parse_bool_arg('include_defaults', $include_defaults); + +if (!$include_defaults) { + @l_ports = (); + @l_files = (); + @l_passwords = (); +} + +$integrity_file = $options{integrity_file} if defined $options{integrity_file}; + +parse_configuration($options{conf}) if defined $options{conf}; + +### +# FUNCTIONS +################## + +# Function to parse configuration file +sub parse_configuration { + my ($conf_file) = @_; + + open my $conf_fh, '<', $conf_file or die "Error opening configuration file [$conf_file]: $!\n"; + + while (my $line = <$conf_fh>) { + chomp $line; + $line =~ s/^\s+//; + $line =~ s/\s+$//; + + if ($line =~ /^\[($b_ports|$b_files|$b_passwords)\]$/) { + $configuration_block = $1; + } + elsif ($configuration_block) { + if ($configuration_block eq $b_ports) { + push @l_ports, $line; + } + elsif ($configuration_block eq $b_files) { + push @l_files, $line; + } + elsif ($configuration_block eq $b_passwords) { + push @l_passwords, $line; + } + } + } + + close $conf_fh; +} + +# Function to print module XML to STDOUT +sub print_xml_module { + my ($m_name, $m_type, $m_desc, $m_value) = @_; + + print "\n"; + print "\t\n"; + print "\t$m_type\n"; + print "\t\n"; + print "\t\n"; + print "\t$modules_group\n"; + print "\n"; +} + +# Make unique array +sub uniq { + my %seen; + return grep { !$seen{$_}++ } @_; +} + +### +# MAIN +################## + +# Check SELinux status +if ($check_selinux) { + my $value = 0; + my $desc = 'SELinux is disabled.'; + + my $output = `sestatus 2> /dev/null`; + if ($? == 0) { + if ($output =~ /SELinux status: enabled/) { + $value = 1; + $desc = 'SELinux is enabled.'; + } + } else { + $value = 0; + $desc = 'Can not determine if SELinux is enabled.'; + } + + print_xml_module('SELinux status', 'generic_proc', $desc, $value); +} + +# Check if SSH allows root access +if ($check_ssh_root_access) { + my $value = 1; + my $desc = 'SSH does not allow root access.'; + + my $ssh_config_file = '/etc/ssh/sshd_config'; + if (-e $ssh_config_file && open my $ssh_fh, '<', $ssh_config_file) { + while (my $line = <$ssh_fh>) { + chomp $line; + $line =~ s/^\s+//; + $line =~ s/\s+$//; + next if $line =~ /^$/ or $line =~ /^#/; + my ($option, $val) = split /\s+/, $line, 2; + if ($option eq 'PermitRootLogin' && lc($val) ne 'no') { + $value = 0; + $desc = 'SSH config allows root access.'; + last; + } + } + close $ssh_fh; + } else { + $value = 0; + $desc = 'Can not read '.$ssh_config_file.' to check if root access allowed.'; + } + + print_xml_module('SSH root access status', 'generic_proc', $desc, $value); +} + +# Specific function for recursive directory check +sub find_files { + my ($dir) = @_; + + my @files = (); + + opendir my $dh, $dir or return; + while (my $file = readdir $dh) { + next if $file eq '.' or $file eq '..'; + + my $file_path = File::Spec->catfile($dir, $file); + if (-f $file_path) { + push @files, $file_path; + } elsif (-d $file_path) { + push @files, find_files($file_path); + } + } + closedir $dh; + + return @files; +} + +# Check if /root has SSH keys +if ($check_ssh_root_keys) { + my $value = 1; + my $desc = 'SSH root keys not found.'; + + my $ssh_keys = {'private' => [], 'public' => []}; + + my $ssh_dir = '/root/.ssh'; + my @all_files = find_files($ssh_dir); + foreach my $file (@all_files) { + if (open my $fh, '<:raw', $file) { + my $content = ''; + while(my $l = <$fh>) { + $content .= $l; + } + if ($content) { + my ($filename, $directories) = fileparse($file); + if ($content =~ /-----BEGIN RSA PRIVATE KEY-----.*?-----END RSA PRIVATE KEY-----/s) { + push @{$ssh_keys->{'private'}}, $file; + } elsif ($content =~ /ssh-rsa/ && $filename ne 'known_hosts' && $filename ne 'authorized_keys') { + push @{$ssh_keys->{'public'}}, $file; + } + } + } + } + + if (@{$ssh_keys->{'private'}} > 0 || @{$ssh_keys->{'public'}} > 0) { + $value = 0; + $desc = "SSH root keys found:\n" . join("\n", @{$ssh_keys->{'private'}}, @{$ssh_keys->{'public'}}); + } + + print_xml_module('SSH root keys status', 'generic_proc', $desc, $value); +} + +# Check authorized ports +if ($check_ports) { + my $value = 1; + my $desc = 'No unauthorized ports found.'; + + my @open_ports; + my @not_allowed_ports; + + my @net_tcp_files = ('/proc/net/tcp', '/proc/net/tcp6'); + foreach my $net_tcp_file (@net_tcp_files) { + if (-e $net_tcp_file && open my $tcp_fh, '<', $net_tcp_file) { + while (my $line = <$tcp_fh>) { + chomp $line; + my @parts = split /\s+/, $line; + if (scalar @parts >= 12) { + my $local_addr_hex = (split /:/, $parts[2])[0]; + my $local_port_hex = (split /:/, $parts[2])[1]; + my $state = $parts[4]; + + # Check if the connection is in state 0A (listening) + if ($state eq "0A") { + my $local_addr_4 = join('.', reverse split(/\./, inet_ntoa(pack("N", hex($local_addr_hex))))); + my $local_addr_6 = join(':', map { hex($_) } unpack("(A4)*", $local_addr_hex)); + + # Skip localhost listening ports + if ($local_addr_4 eq "127.0.0.1" || $local_addr_6 eq "0:0:0:0:0:0:0:1") { + next; + } + + my $local_port = hex($local_port_hex); + push @open_ports, $local_port; + } + } + } + close $tcp_fh; + } + } + @open_ports = uniq(@open_ports); + + my %allowed_ports; + foreach my $port (@l_ports) { + $allowed_ports{$port} = 1; + } + + foreach my $port (@open_ports) { + if (!exists $allowed_ports{$port}) { + push @not_allowed_ports, $port; + } + } + + if (@not_allowed_ports) { + $value = 0; + $desc = "Unauthorized ports found:\n" . join("\n", @not_allowed_ports); + } + + print_xml_module('Authorized ports status', 'generic_proc', $desc, $value); +} + +# Check files integrity +if ($check_files) { + my $value = 1; + my $desc = 'No changed files found.'; + + my %integrity; + + my $can_check_files = 0; + + if (-e $integrity_file) { + if (-r $integrity_file && -w $integrity_file) { + # Read integrity file content + open my $integrity_fh, '<', $integrity_file; + while (my $line = <$integrity_fh>) { + chomp $line; + if ($line =~ /^\s*(.*?)=(.*?)\s*$/) { + $integrity{$1} = $2; + } + } + close $integrity_fh; + $can_check_files = 1; + } else { + $value = 0; + $desc = 'Integrity check file can not be read or written: ' . $integrity_file; + } + } else { + if (open my $integrity_fh, '>', $integrity_file) { + close $integrity_fh; + $can_check_files = 1; + } else { + $value = 0; + $desc = 'Integrity check file can not be created: ' . $integrity_file; + } + } + + if ($can_check_files) { + # Check each file integrity + my @errored_files; + my @no_integrity_files; + + # Create unique check files list + @l_files = uniq(@l_files); + + foreach my $file (@l_files) { + my $file_key = md5_hex($file); + if (open my $fh, '<:raw', $file) { + my $md5 = Digest::MD5->new; + $md5->addfile($fh); + my $file_md5 = $md5->hexdigest; + chomp $file_md5; + close $fh; + + if (exists $integrity{$file_key} && $integrity{$file_key} ne $file_md5) { + push @no_integrity_files, $file; + } + $integrity{$file_key} = $file_md5; + } else { + push @errored_files, $file; + } + } + + # Overwrite integrity file content + open my $file_handle, '>', $integrity_file; + print $file_handle map { "$_=$integrity{$_}\n" } keys %integrity; + close $file_handle; + + # Check module status + if (@no_integrity_files) { + $value = 0; + $desc = "Changed files found:\n" . join("\n", @no_integrity_files); + } + + if (@errored_files) { + $value = 0; + $desc .= "\nUnable to check integrity of some files:\n" . join("\n", @errored_files); + } + } + + print_xml_module('Files check status', 'generic_proc', $desc, $value); +} + +# Check weak passwords +if ($check_passwords) { + my $value = 1; + my $desc = 'No insecure passwords found.'; + + # Create unique check passwords list + @l_passwords = uniq(@l_passwords); + + my @insecure_users; + + my $shadow_file = '/etc/shadow'; + if (-e $shadow_file && -r $shadow_file) { + open my $shadow_fh, '<', $shadow_file; + while (my $line = <$shadow_fh>) { + chomp $line; + my ($username, $password_hash, @rest) = split /:/, $line; + + # Skip users with no password hash + if ($password_hash ne "*" && $password_hash ne "!!" && $password_hash ne "!locked") { + my $salt = substr($password_hash, 0, rindex($password_hash, '$') + 1); + my $user_hash = crypt($username, $salt); + if ($user_hash eq $password_hash) { + push @insecure_users, $username; + } else { + foreach my $weak_password (@l_passwords) { + my $weak_password_hash = crypt($weak_password, $salt); + + if ($weak_password_hash eq $password_hash) { + push @insecure_users, $username; + last; + } + } + } + } + } + close $shadow_fh; + } else { + $value = 0; + $desc = 'Can not read '.$shadow_file.' to check passwords.'; + } + + if (@insecure_users) { + $value = 0; + $desc = "Users with insecure passwords found:\n" . join("\n", @insecure_users); + } + + print_xml_module('Insecure passwords status', 'generic_proc', $desc, $value); +} \ No newline at end of file diff --git a/pandora_agents/win32/installer/pandora.mpi b/pandora_agents/win32/installer/pandora.mpi index a3543a5145..17bd3b95d5 100644 --- a/pandora_agents/win32/installer/pandora.mpi +++ b/pandora_agents/win32/installer/pandora.mpi @@ -186,7 +186,7 @@ UpgradeApplicationID {} Version -{231011} +{231019} ViewReadme {Yes} diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index 23a04f98fa..1edf51aab3 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -30,7 +30,7 @@ using namespace Pandora; using namespace Pandora_Strutils; #define PATH_SIZE _MAX_PATH+1 -#define PANDORA_VERSION ("7.0NG.773.3 Build 231011") +#define PANDORA_VERSION ("7.0NG.773.3 Build 231019") string pandora_path; string pandora_dir; diff --git a/pandora_agents/win32/versioninfo.rc b/pandora_agents/win32/versioninfo.rc index d4cd471aed..d9b1937bd0 100644 --- a/pandora_agents/win32/versioninfo.rc +++ b/pandora_agents/win32/versioninfo.rc @@ -11,7 +11,7 @@ BEGIN VALUE "LegalCopyright", "Pandora FMS" VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "ProductName", "Pandora FMS Windows Agent" - VALUE "ProductVersion", "(7.0NG.773.3(Build 231011))" + VALUE "ProductVersion", "(7.0NG.773.3(Build 231019))" VALUE "FileVersion", "1.0.0.0" END END diff --git a/pandora_console/DEBIAN/control b/pandora_console/DEBIAN/control index 4c917cbe13..c30a3c80db 100644 --- a/pandora_console/DEBIAN/control +++ b/pandora_console/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-console -Version: 7.0NG.773.3-231011 +Version: 7.0NG.773.3-231019 Architecture: all Priority: optional Section: admin diff --git a/pandora_console/DEBIAN/make_deb_package.sh b/pandora_console/DEBIAN/make_deb_package.sh index c540258156..d37ca4444c 100644 --- a/pandora_console/DEBIAN/make_deb_package.sh +++ b/pandora_console/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.773.3-231011" +pandora_version="7.0NG.773.3-231019" package_pear=0 package_pandora=1 diff --git a/pandora_console/extensions/quick_shell.php b/pandora_console/extensions/quick_shell.php index ac3d1d22c5..b03fe77f58 100644 --- a/pandora_console/extensions/quick_shell.php +++ b/pandora_console/extensions/quick_shell.php @@ -192,7 +192,7 @@ function quickShell() 'name' => 'form-sent', 'value' => true, ], - ] + ], ], ], false, @@ -292,7 +292,6 @@ function quickShellSettings() ui_require_css_file('discovery'); // Gotty settings. Internal communication (WS). - if (isset($config['gotty_ssh_enabled']) === false) { config_update_value('gotty_ssh_enabled', 1); } diff --git a/pandora_console/extras/mr/66.sql b/pandora_console/extras/mr/66.sql index 606bcea909..b7b2b400d7 100644 --- a/pandora_console/extras/mr/66.sql +++ b/pandora_console/extras/mr/66.sql @@ -117,6 +117,22 @@ INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES -- Insert into tdiscovery_apps_executions INSERT IGNORE INTO `tdiscovery_apps_executions` (`id`, `id_app`, `execution`) VALUES (1, @id_app, ''_exec1_' -g '__taskGroup__' --host '_host_' --port '_port_' --user '_user_' --password '_password_' --vm '_scanVM_' --lxc '_scanLXC_' --backups '_scanBackups_' --nodes '_scanNodes_' --transfer_mode tentacle --tentacle_address '_tentacleIP_' --tentacle_port '_tentaclePort_' --as_discovery_plugin 1'); +-- Insert new SAP APP +SET @short_name = 'pandorafms.sap.deset'; +SET @name = 'SAP R3 - Deset'; +SET @section = 'app'; +SET @description = 'Monitor SAP R3 environments'; +SET @version = '1.0'; +INSERT IGNORE INTO `tdiscovery_apps` (`id_app`, `short_name`, `name`, `section`, `description`, `version`) VALUES ('', @short_name, @name, @section, @description, @version); +SELECT @id_app := `id_app` FROM `tdiscovery_apps` WHERE `short_name` = @short_name; + +-- Insert into tdiscovery_apps_scripts +INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES (@id_app, '_exec1_', 'bin/pandora_sap_deset'); +INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES (@id_app, '_java_', 'bin/lib/jre/bin/java'); + +-- Insert into tdiscovery_apps_executions +INSERT IGNORE INTO `tdiscovery_apps_executions` (`id`, `id_app`, `execution`) VALUES (1, @id_app, ''_exec1_' --conf '_tempfileConf_' --custom_modules '_tempfileCustomModules_''); + -- Insert new EC2 APP SET @short_name = 'pandorafms.aws.ec2'; SET @name = 'Amazon EC2'; @@ -202,5 +218,54 @@ ALTER TABLE `treport_content` ADD COLUMN `ignore_skipped` INT NOT NULL DEFAULT ALTER TABLE `treport_content` ADD COLUMN `status_of_check` TINYTEXT; ALTER TABLE `tservice` ADD COLUMN `enable_horizontal_tree` TINYINT NOT NULL DEFAULT 0; +INSERT INTO tmodule_group (name) SELECT ('Security') WHERE NOT EXISTS (SELECT name FROM tmodule_group WHERE LOWER(name) = 'security'); + +SET @tmodule_name = 'CPU'; +SET @tmodule_description = 'CPU'; +SET @id_os = 2; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'Brand;Clock;Model' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); + +SET @tmodule_name = 'RAM'; +SET @tmodule_description = 'RAM'; +SET @id_os = 2; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'Size' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); + +SET @tmodule_name = 'NIC'; +SET @tmodule_description = 'NIC'; +SET @id_os = 2; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'NIC;Mac;Speed' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); + +SET @tmodule_name = 'Software'; +SET @tmodule_description = 'Software'; +SET @id_os = 2; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'PKGINST;VERSION;NAME' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); + +SET @tmodule_name = 'Security'; +SET @tmodule_description = 'Hardening plugin for security compliance analysis'; +SET @id_os = 1; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'ID:STATUS' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); + +SET @tmodule_name = 'Security'; +SET @tmodule_description = 'Hardening plugin for security compliance analysis'; +SET @id_os = 9; + +INSERT INTO tmodule_inventory (`id_os`, `name`, `description`, `interpreter`, `data_format`, `code`, `block_mode`,`script_mode`) +SELECT * FROM (SELECT @id_os id_os, @tmodule_name name, @tmodule_description description, '' interpreter, 'ID:STATUS' data_format, '' code, '0' block_mode, 2 script_mode) AS tmp +WHERE NOT EXISTS (SELECT name, description FROM tmodule_inventory WHERE name = @tmodule_name and description = @tmodule_description and id_os = @id_os); COMMIT; diff --git a/pandora_console/godmode/agentes/module_manager_editor_common.php b/pandora_console/godmode/agentes/module_manager_editor_common.php index f70af23627..d9a0d3ba22 100644 --- a/pandora_console/godmode/agentes/module_manager_editor_common.php +++ b/pandora_console/godmode/agentes/module_manager_editor_common.php @@ -1668,6 +1668,12 @@ ui_require_jquery_file('json'); diff --git a/pandora_console/operation/events/sound_events.php b/pandora_console/operation/events/sound_events.php index 7c04359f98..0bec0e65d8 100644 --- a/pandora_console/operation/events/sound_events.php +++ b/pandora_console/operation/events/sound_events.php @@ -32,6 +32,7 @@ require_once '../../include/config.php'; require_once '../../include/functions.php'; require_once '../../include/functions_db.php'; require_once '../../include/functions_events.php'; +require_once '../../include/functions_ui.php'; require_once '../../include/auth/mysql.php'; require_once $config['homedir'].'/include/class/HTML.class.php'; @@ -127,7 +128,7 @@ $output = '
'; // Content tabs. $output .= '
'; $output .= '

'; - $output .= __('Console configuration'); + $output .= __('Console configuration').ui_print_help_tip(__('Warning: Minimizing this window will cause the Acoustic Console to not work as expected'), true); $output .= '

'; $inputs = []; @@ -334,6 +335,7 @@ $output = '
'; ); $output .= '
'; $output .= '
'; + $output .= html_print_div(['id' => 'forced_title_layer', 'class' => 'forced_title_layer', 'hidden' => true]); echo $output; ?> diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 6b98ffb55b..3794a30ae3 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -205,6 +205,10 @@ if ($access_console_node === true) { $sub['operation/inventory/inventory']['refr'] = 0; } + $sub['operation/custom_fields/custom_fields_view']['text'] = __('Custom fields view'); + $sub['operation/custom_fields/custom_fields_view']['id'] = 'Custom fields view'; + $sub['operation/custom_fields/custom_fields_view']['refr'] = 0; + if ($config['activate_netflow'] || $config['activate_sflow']) { $sub['network_traffic'] = [ 'text' => __('Network'), diff --git a/pandora_console/pandora_console.redhat.spec b/pandora_console/pandora_console.redhat.spec index bf360c321e..cc85b26a7c 100644 --- a/pandora_console/pandora_console.redhat.spec +++ b/pandora_console/pandora_console.redhat.spec @@ -1,9 +1,12 @@ # # Pandora FMS Console # +%global _missing_build_ids_terminate_build 0 +%define __strip /bin/true +%define debug_package %{nil} %define name pandorafms_console %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.rhel7.spec b/pandora_console/pandora_console.rhel7.spec index c78f5b2532..14cc3baf6b 100644 --- a/pandora_console/pandora_console.rhel7.spec +++ b/pandora_console/pandora_console.rhel7.spec @@ -1,9 +1,12 @@ # # Pandora FMS Console # +%global _missing_build_ids_terminate_build 0 +%define __strip /bin/true +%define debug_package %{nil} %define name pandorafms_console %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 # User and Group under which Apache is running %define httpd_name httpd diff --git a/pandora_console/pandora_console.spec b/pandora_console/pandora_console.spec index 8389808c10..0c5906ab20 100644 --- a/pandora_console/pandora_console.spec +++ b/pandora_console/pandora_console.spec @@ -3,7 +3,7 @@ # %define name pandorafms_console %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 %define httpd_name httpd # User and Group under which Apache is running %define httpd_name apache2 diff --git a/pandora_console/pandoradb_data.sql b/pandora_console/pandoradb_data.sql index 22db03654e..b6c361a393 100644 --- a/pandora_console/pandoradb_data.sql +++ b/pandora_console/pandoradb_data.sql @@ -246,7 +246,8 @@ INSERT INTO `tmodule_group` VALUES (6,'Performance'), (7,'Database'), (8,'Enviromental'), -(9,'Users'); +(9,'Users'), +(10,'Security'); UNLOCK TABLES; @@ -2727,6 +2728,22 @@ INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES -- Insert into tdiscovery_apps_executions INSERT IGNORE INTO `tdiscovery_apps_executions` (`id`, `id_app`, `execution`) VALUES (1, @id_app, ''_exec1_' -g '__taskGroup__' --host '_host_' --port '_port_' --user '_user_' --password '_password_' --vm '_scanVM_' --lxc '_scanLXC_' --backups '_scanBackups_' --nodes '_scanNodes_' --transfer_mode tentacle --tentacle_address '_tentacleIP_' --tentacle_port '_tentaclePort_' --as_discovery_plugin 1'); +-- Insert new SAP APP +SET @short_name = 'pandorafms.sap.deset'; +SET @name = 'SAP R3 - Deset'; +SET @section = 'app'; +SET @description = 'Monitor SAP R3 environments'; +SET @version = '1.0'; +INSERT IGNORE INTO `tdiscovery_apps` (`id_app`, `short_name`, `name`, `section`, `description`, `version`) VALUES ('', @short_name, @name, @section, @description, @version); +SELECT @id_app := `id_app` FROM `tdiscovery_apps` WHERE `short_name` = @short_name; + +-- Insert into tdiscovery_apps_scripts +INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES (@id_app, '_exec1_', 'bin/pandora_sap_deset'); +INSERT IGNORE INTO `tdiscovery_apps_scripts` (`id_app`, `macro`, `value`) VALUES (@id_app, '_java_', 'bin/lib/jre/bin/java'); + +-- Insert into tdiscovery_apps_executions +INSERT IGNORE INTO `tdiscovery_apps_executions` (`id`, `id_app`, `execution`) VALUES (1, @id_app, ''_exec1_' --conf '_tempfileConf_' --custom_modules '_tempfileCustomModules_''); + -- Insert new EC2 APP SET @short_name = 'pandorafms.aws.ec2'; SET @name = 'Amazon EC2'; diff --git a/pandora_plugins/message_app_connectors/discord/.gitignore b/pandora_plugins/message_app_connectors/discord/.gitignore index 5ceb3864c2..9c10928fd9 100644 --- a/pandora_plugins/message_app_connectors/discord/.gitignore +++ b/pandora_plugins/message_app_connectors/discord/.gitignore @@ -1 +1,3 @@ -venv +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/discord/pandora_discord_cli.py b/pandora_plugins/message_app_connectors/discord/pandora_discord_cli.py index 715657da28..1efa696d19 100644 --- a/pandora_plugins/message_app_connectors/discord/pandora_discord_cli.py +++ b/pandora_plugins/message_app_connectors/discord/pandora_discord_cli.py @@ -1,4 +1,4 @@ -import requests, argparse, sys, os +import requests, argparse, sys, os, signal from datetime import datetime from re import search from base64 import b64decode @@ -26,6 +26,18 @@ parser.add_argument('--tmp_dir', help='Temporary path to store graph images', de args = parser.parse_args() +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + ### Functions: def parse_dic(cValues): """convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """ diff --git a/pandora_plugins/message_app_connectors/gchat/.gitignore b/pandora_plugins/message_app_connectors/gchat/.gitignore new file mode 100644 index 0000000000..9c10928fd9 --- /dev/null +++ b/pandora_plugins/message_app_connectors/gchat/.gitignore @@ -0,0 +1,3 @@ +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/gchat/pandora-gchat-cli.py b/pandora_plugins/message_app_connectors/gchat/pandora-gchat-cli.py index 4584768ec7..b062cc34ed 100644 --- a/pandora_plugins/message_app_connectors/gchat/pandora-gchat-cli.py +++ b/pandora_plugins/message_app_connectors/gchat/pandora-gchat-cli.py @@ -1,8 +1,4 @@ -import requests -import argparse -import sys -import os -import json +import requests, signal, argparse, sys, os, json ### Variables and arg parser ### parser = argparse.ArgumentParser(description='Google chat webhook conector') @@ -23,6 +19,18 @@ parser.add_argument('--btn_url', help='button url', args = parser.parse_args() +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + # classes diff --git a/pandora_plugins/message_app_connectors/ilert/.gitignore b/pandora_plugins/message_app_connectors/ilert/.gitignore new file mode 100644 index 0000000000..9c10928fd9 --- /dev/null +++ b/pandora_plugins/message_app_connectors/ilert/.gitignore @@ -0,0 +1,3 @@ +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/ilert/pandora_ilert.py b/pandora_plugins/message_app_connectors/ilert/pandora_ilert.py new file mode 100644 index 0000000000..33f9654a6e --- /dev/null +++ b/pandora_plugins/message_app_connectors/ilert/pandora_ilert.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "PandoraFMS Team" +__copyright__ = "Copyright 2023, PandoraFMS" +#__credits__ = ["Rob Knight", "Peter Maxwell", "Gavin Huttley", "Matthew Wakefield"] +__maintainer__ = "Projects/QA department" +__status__ = "Test" +__version__ = "1" + +import requests, json, sys, argparse, signal, re,datetime + +current_date=datetime.datetime.now() +info= f""" +PandoraFMS ilert integration. +Version: {__version__} +""" + +parser = argparse.ArgumentParser(description= info, formatter_class=argparse.RawTextHelpFormatter) +parser.add_argument('-a', '--api_key', help='Api key from ilert', required=True) +parser.add_argument('-t', '--event_type', help='Type of the created event. Can be "alert" or "resolved".', type=str, required=True) +parser.add_argument('-k', '--event_key', help='Title of the event, used as key', type=str, required=True) +parser.add_argument('-T', '--title', help='Title of the event.', type=str, required=True) +parser.add_argument('-d', '--description', help='Description of the event', type=str, default='') +parser.add_argument('-A', '--agent_name', help='pandorafms agent name', type=str, default='') +parser.add_argument('-p', '--priority', help='priority', type=str, default='') +parser.add_argument('-m', '--module_name', help='priority', type=str, default='') +parser.add_argument('-D', '--module_data', help='priority', type=str, default='') +parser.add_argument('-C', '--created_date', help='event date', type=str, default=current_date) + +args = parser.parse_args() + +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + +# Functions + +def post_url(url, data=None, headers={"Accept": "application/json"},): + try : + data = requests.post(url, data=data, headers=headers) + result_data = data.status_code + except Exception as e : + print (f"[red]Error[/red] posting data from {url} {e}", file = sys.stderr ) + sys.exit() + return result_data + +if __name__ == "__main__": + # Prepare data + url = f"https://api.ilert.com/api/v1/events/pandorafms/{args.api_key}" + + payload = { + "eventType": args.event_type, + "title": args.title, + "description": args.description, + "incidentKey": args.event_key, + "details": { + "agentName": args.agent_name, + "createdAt": str(args.created_date), + "priority": args.priority, + "moduleName": args.module_name, + "moduleData": args.module_data + } + } + + response=post_url(url, data=json.dumps(payload)) + + if response == 202: print ("Alert has been submitted!") + print (f"http_code: {response}", file=sys.stderr) + diff --git a/pandora_plugins/message_app_connectors/ilert/requirements.txt b/pandora_plugins/message_app_connectors/ilert/requirements.txt new file mode 100644 index 0000000000..b8d86d56d7 --- /dev/null +++ b/pandora_plugins/message_app_connectors/ilert/requirements.txt @@ -0,0 +1,8 @@ +altgraph==0.17.3 +certifi==2023.7.22 +charset-normalizer==3.3.0 +idna==3.4 +pyinstaller==5.13.0 +pyinstaller-hooks-contrib==2023.7 +requests==2.31.0 +urllib3==2.0.5 diff --git a/pandora_plugins/message_app_connectors/ms-teams/.gitignore b/pandora_plugins/message_app_connectors/ms-teams/.gitignore new file mode 100644 index 0000000000..9c10928fd9 --- /dev/null +++ b/pandora_plugins/message_app_connectors/ms-teams/.gitignore @@ -0,0 +1,3 @@ +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/ms-teams/pandora-msteams-cli.py b/pandora_plugins/message_app_connectors/ms-teams/pandora-msteams-cli.py index f0d4ac89a8..e387b447dd 100755 --- a/pandora_plugins/message_app_connectors/ms-teams/pandora-msteams-cli.py +++ b/pandora_plugins/message_app_connectors/ms-teams/pandora-msteams-cli.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import argparse, pymsteams +import argparse, pymsteams, signal parser = argparse.ArgumentParser(description='MS Teams connector') parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True) @@ -16,6 +16,18 @@ parser.add_argument('--button_desc', help='Pandora button description', default= args = parser.parse_args() +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + ### Functions: def parse_dic(cValues): """convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """ diff --git a/pandora_plugins/message_app_connectors/ms-teams/pandora-teams-cli.py b/pandora_plugins/message_app_connectors/ms-teams/pandora-teams-cli.py deleted file mode 100755 index 4bd997b38f..0000000000 --- a/pandora_plugins/message_app_connectors/ms-teams/pandora-teams-cli.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -import argparse, pymsteams - -parser = argparse.ArgumentParser(description='MsTeams connector') -parser.add_argument('-d', '--data', help='Data in coma separate keypairs. Ex: test=5,house=2', required=True) -parser.add_argument('-u', '--url', help='Teams webhook URL', required=True) -parser.add_argument('-t', '--alert_tittle', help='Alert tittle', default='PandoraFMS alert fired') -parser.add_argument('-D', '--alert_desc', help='Alert description', default='Alert Fired') -parser.add_argument('-m', '--message', help='Alert message', default='') -parser.add_argument('-T','--tittle_color', help='Alert tittle descripcion in HEX EX: 53e514', default="53e514") -parser.add_argument('--sub_desc', help='Alert sub description', default='Alert Fired') -parser.add_argument('--thumb', help='Custom thumbnail url', default="https://pandorafms.com/images/alerta_roja.png") -parser.add_argument('--button', help='Pandora button Url', default='https://pandorafms.com') -parser.add_argument('--button_desc', help='Pandora button description', default='Open web console') - -args = parser.parse_args() - -### Functions: -def parse_dic(cValues): - """convert coma separate keypairs into a dic. EX "test=5,house=8,market=2" wil return "{'test': '5', 'casa': '8', 'mercado': '2'}" """ - data={} - try : - for kv in cValues.split(","): - k,v = kv.strip().split("=") - data[k.strip()]=v.strip() - except Exception as e : - print(f"Warning, error parsing keypairs values: {e}") - return data - -def add_embed_itmes(data): - """iterate dictionary and set webhook fields, one for eacj keypair""" - for k, v in data.items() : - myMessageSection.addFact(f"{k}:", v) - -##Main - -# You must create the connectorcard object with the Microsoft Webhook URL -myTeamsMessage = pymsteams.connectorcard(args.url) - -# Set Summary -myTeamsMessage.summary(args.message) - -# Set Alert tittle -myTeamsMessage.title(args.alert_tittle) - -# Set link buttom -myTeamsMessage.addLinkButton(args.button_desc, args.button) - -# Set message color -myTeamsMessage.color(args.tittle_color) - -# create the section -myMessageSection = pymsteams.cardsection() - -# Section Title -myMessageSection.title(args.message) - -# Activity Elements -myMessageSection.activityTitle(args.alert_desc) -myMessageSection.activitySubtitle(args.sub_desc) -myMessageSection.activityImage(args.thumb) - -# Facts are key value pairs displayed in a list. -data = parse_dic(args.data) -add_embed_itmes(data) - -# Section Text -# myMessageSection.text("This is my section text") - -# Section Images -# myMessageSection.addImage("http://i.imgur.com/c4jt321l.png", ititle="This Is Fine") - -# Add your section to the connector card object before sending -myTeamsMessage.addSection(myMessageSection) - -# Then send the card -try: - myTeamsMessage.send() -except Exception as e : - print(f"Error sending to message: {e}") \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/slack/.gitignore b/pandora_plugins/message_app_connectors/slack/.gitignore index 5ceb3864c2..9c10928fd9 100644 --- a/pandora_plugins/message_app_connectors/slack/.gitignore +++ b/pandora_plugins/message_app_connectors/slack/.gitignore @@ -1 +1,3 @@ -venv +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/slack/pandora-slack-cli.py b/pandora_plugins/message_app_connectors/slack/pandora-slack-cli.py index 5eb24fc865..8247bc1a5b 100644 --- a/pandora_plugins/message_app_connectors/slack/pandora-slack-cli.py +++ b/pandora_plugins/message_app_connectors/slack/pandora-slack-cli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import requests, argparse, sys, os +import requests, argparse, sys, os, signal from slack_sdk import WebClient from slack_sdk.errors import SlackApiError from datetime import datetime @@ -26,6 +26,18 @@ parser.add_argument('--tmp_dir', help='Temporary path to store graph images', de args = parser.parse_args() filename = None +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + #Functions def parse_dic(cValues): @@ -126,7 +138,7 @@ def send_message(message, channel, client, feddback=None): assert e.response["ok"] is False assert e.response["error"] # str like 'invalid_auth', 'channel_not_found' print(f"Got an Slack auth error: {e.response['error']}") - exit() + sys.exit() def send_image(imagepath, channel, client) : """Send file as slack bot""" @@ -177,4 +189,4 @@ if args.footer: send_message(args.footer, args.channel, client) try: os.remove(filename) except: - exit() \ No newline at end of file + sys.exit() \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/telegram-bot-cli/.gitignore b/pandora_plugins/message_app_connectors/telegram-bot-cli/.gitignore new file mode 100644 index 0000000000..9c10928fd9 --- /dev/null +++ b/pandora_plugins/message_app_connectors/telegram-bot-cli/.gitignore @@ -0,0 +1,3 @@ +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/telegram-bot-cli/pandora-telegram-cli.py b/pandora_plugins/message_app_connectors/telegram-bot-cli/pandora-telegram-cli.py index 8ee7520355..e7da24df83 100644 --- a/pandora_plugins/message_app_connectors/telegram-bot-cli/pandora-telegram-cli.py +++ b/pandora_plugins/message_app_connectors/telegram-bot-cli/pandora-telegram-cli.py @@ -1,4 +1,4 @@ -import requests, argparse, json, sys, os +import requests, argparse, json, sys, os, signal from datetime import datetime from base64 import b64decode @@ -27,7 +27,19 @@ def parse_dic(cValues): print(f"Warning, error parsing keypairs values: {e}") return data +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + +#Functions def parse_api_conf(cConf): """Check apiconfiguration parameters """ if args.api_conf : diff --git a/pandora_plugins/message_app_connectors/vonage/.gitignore b/pandora_plugins/message_app_connectors/vonage/.gitignore new file mode 100644 index 0000000000..9c10928fd9 --- /dev/null +++ b/pandora_plugins/message_app_connectors/vonage/.gitignore @@ -0,0 +1,3 @@ +build +dist +*spec \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/vonage/pandora_vonage.py b/pandora_plugins/message_app_connectors/vonage/pandora_vonage.py new file mode 100644 index 0000000000..a233367042 --- /dev/null +++ b/pandora_plugins/message_app_connectors/vonage/pandora_vonage.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__author__ = "PandoraFMS Team" +__copyright__ = "Copyright 2023, PandoraFMS" +#__credits__ = ["Rob Knight", "Peter Maxwell", "Gavin Huttley", "Matthew Wakefield"] +__maintainer__ = "Projects/QA department" +__status__ = "Test" +__version__ = "1" + +import vonage, json, sys, argparse, signal, re,datetime + +current_date=datetime.datetime.now() +info= f""" +PandoraFMS vonage integration. +Version: {__version__} +""" + +parser = argparse.ArgumentParser(description= info, formatter_class=argparse.RawTextHelpFormatter) +parser.add_argument('-a', '--api_key', help='Client key from vonage', required=True) +parser.add_argument('-s', '--secret', help='Secret key from vonage".', type=str, required=True) +parser.add_argument('-m', '--message', help='Title of the event, used as key', type=str, required=True) +parser.add_argument('-n', '--phone_number', help='Phone number to send sms with country code. Ex: "+34555444111,+34777444222" could be a coma separated list of numbers', type=str, required=True) +parser.add_argument('-f', '--from_alias', help='From number/string data', type=str, default="PandoraFMS") +parser.add_argument('-v', '--verbose', help='Debug information', action='store_true') + + +args = parser.parse_args() + +# Define a function to handle the SIGINT signal +def sigint_handler(signal, frame): + print ('\nInterrupted by user') + sys.exit(0) +signal.signal(signal.SIGINT, sigint_handler) + +# Define a function to handle the SIGTERM signal +def sigterm_handler(signum, frame): + print("Received SIGTERM signal.") + sys.exit(0) +signal.signal(signal.SIGTERM, sigterm_handler) + +# Functions + +def convet_list_comma (data:str): + if "," in data: + result = data.split(",") + else: + result = [] + result.append(data) + return result + + +if __name__ == "__main__": + # Prepare data + client = vonage.Client(key=args.api_key, secret=args.secret) + + try: + numbers=convet_list_comma(args.phone_number) + except Exception as e: + print (f"Error: {e}") + sys.exit() + + for number in numbers : + responseData = client.sms.send_message( + { + "from": args.from_alias, + "to": number, + "text": args.message, + } + ) + + if responseData["messages"][0]["status"] == "0": + print("Message sent successfully.") + else: + print(f"Message failed with error: {responseData['messages'][0]['error-text']}") + + #debug + if args.verbose == True: print (f"Debug: {responseData}") \ No newline at end of file diff --git a/pandora_plugins/message_app_connectors/vonage/requirements.txt b/pandora_plugins/message_app_connectors/vonage/requirements.txt new file mode 100644 index 0000000000..674ae0e1b7 --- /dev/null +++ b/pandora_plugins/message_app_connectors/vonage/requirements.txt @@ -0,0 +1,16 @@ +certifi==2023.7.22 +cffi==1.16.0 +charset-normalizer==3.3.0 +cryptography==41.0.4 +Deprecated==1.2.14 +idna==3.4 +pycparser==2.21 +pydantic==1.10.13 +PyJWT==2.8.0 +pytz==2023.3.post1 +requests==2.31.0 +typing_extensions==4.8.0 +urllib3==2.0.6 +vonage==3.9.1 +vonage-jwt==1.0.0 +wrapt==1.15.0 diff --git a/pandora_server/DEBIAN/control b/pandora_server/DEBIAN/control index 3b708ba708..cb23277387 100644 --- a/pandora_server/DEBIAN/control +++ b/pandora_server/DEBIAN/control @@ -1,5 +1,5 @@ package: pandorafms-server -Version: 7.0NG.773.3-231011 +Version: 7.0NG.773.3-231019 Architecture: all Priority: optional Section: admin diff --git a/pandora_server/DEBIAN/make_deb_package.sh b/pandora_server/DEBIAN/make_deb_package.sh index 62955a603f..d3ae735539 100644 --- a/pandora_server/DEBIAN/make_deb_package.sh +++ b/pandora_server/DEBIAN/make_deb_package.sh @@ -14,7 +14,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -pandora_version="7.0NG.773.3-231011" +pandora_version="7.0NG.773.3-231019" package_cpan=0 package_pandora=1 diff --git a/pandora_server/conf/pandora_server.conf.new b/pandora_server/conf/pandora_server.conf.new index 7aba09011f..2dfa5825b1 100644 --- a/pandora_server/conf/pandora_server.conf.new +++ b/pandora_server/conf/pandora_server.conf.new @@ -153,6 +153,9 @@ dataserver_smart_queue 1 discoveryserver 1 +# discovery_threads. Each thread will scan a different scantask. +discovery_threads 1 + # Discovery SAP (PANDORA FMS ENTERPRISE ONLY) # java /usr/bin/java diff --git a/pandora_server/lib/PandoraFMS/Config.pm b/pandora_server/lib/PandoraFMS/Config.pm index 983c907cb0..679c4033a6 100644 --- a/pandora_server/lib/PandoraFMS/Config.pm +++ b/pandora_server/lib/PandoraFMS/Config.pm @@ -46,7 +46,7 @@ our @EXPORT = qw( # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.773.3"; -my $pandora_build = "231011"; +my $pandora_build = "231019"; our $VERSION = $pandora_version." ".$pandora_build; # Setup hash diff --git a/pandora_server/lib/PandoraFMS/Core.pm b/pandora_server/lib/PandoraFMS/Core.pm index b8f42b1734..58815a4ff9 100644 --- a/pandora_server/lib/PandoraFMS/Core.pm +++ b/pandora_server/lib/PandoraFMS/Core.pm @@ -7689,6 +7689,9 @@ sub safe_mode($$$$$$) { elsif ($known_status == MODULE_CRITICAL) { logger($pa_config, "Disabling safe mode for agent " . $agent->{'nombre'}, 10); db_do($dbh, 'UPDATE tagente_modulo SET disabled=0 WHERE id_agente=? AND id_agente_modulo!=?', $agent->{'id_agente'}, $module->{'id_agente_modulo'}); + + # Prevent the modules from becoming unknown! + db_do ($dbh, 'UPDATE tagente_estado SET utimestamp = ? WHERE id_agente = ? AND id_agente_modulo!=?', time(), $agent->{'id_agente'}, $module->{'id_agente_modulo'}); } } diff --git a/pandora_server/lib/PandoraFMS/DB.pm b/pandora_server/lib/PandoraFMS/DB.pm index 22ee1611fa..c0ee332f64 100644 --- a/pandora_server/lib/PandoraFMS/DB.pm +++ b/pandora_server/lib/PandoraFMS/DB.pm @@ -814,14 +814,21 @@ sub get_plugin_id ($$) { ########################################################################## ## Return module group ID given the module group name. ########################################################################## -sub get_module_group_id ($$) { - my ($dbh, $module_group_name) = @_; +sub get_module_group_id ($$;$) { + my ($dbh, $module_group_name, $case_insensitve) = @_; + $case_insensitve = 0 unless defined($case_insensitve); + if (!defined($module_group_name) || $module_group_name eq '') { return 0; } - my $rc = get_db_value ($dbh, "SELECT id_mg FROM tmodule_group WHERE name = ?", safe_input($module_group_name)); + my $rc; + if($case_insensitve == 0) { + $rc = get_db_value ($dbh, "SELECT id_mg FROM tmodule_group WHERE name = ?", safe_input($module_group_name)); + } else { + $rc = get_db_value ($dbh, "SELECT id_mg FROM tmodule_group WHERE LOWER(name) = ?", lc(safe_input($module_group_name))); + } return defined ($rc) ? $rc : -1; } diff --git a/pandora_server/lib/PandoraFMS/DataServer.pm b/pandora_server/lib/PandoraFMS/DataServer.pm index b3c32522c6..80e8bb4bd3 100644 --- a/pandora_server/lib/PandoraFMS/DataServer.pm +++ b/pandora_server/lib/PandoraFMS/DataServer.pm @@ -812,7 +812,7 @@ sub process_module_data ($$$$$$$$$$) { # The group name has to be translated to a group ID if (defined $module_conf->{'module_group'}) { - my $id_group_module = get_module_group_id ($dbh, $module_conf->{'module_group'}); + my $id_group_module = get_module_group_id ($dbh, $module_conf->{'module_group'}, 1); if ( $id_group_module >= 0) { $module_conf->{'id_module_group'} = $id_group_module; } diff --git a/pandora_server/lib/PandoraFMS/PluginTools.pm b/pandora_server/lib/PandoraFMS/PluginTools.pm index 09dd84336c..e6e8e211cc 100644 --- a/pandora_server/lib/PandoraFMS/PluginTools.pm +++ b/pandora_server/lib/PandoraFMS/PluginTools.pm @@ -34,7 +34,7 @@ our @ISA = qw(Exporter); # version: Defines actual version of Pandora Server for this module only my $pandora_version = "7.0NG.773.3"; -my $pandora_build = "231011"; +my $pandora_build = "231019"; our $VERSION = $pandora_version." ".$pandora_build; our %EXPORT_TAGS = ( 'all' => [ qw() ] ); diff --git a/pandora_server/pandora_server.redhat.spec b/pandora_server/pandora_server.redhat.spec index f47d0d9558..b0994b4bb5 100644 --- a/pandora_server/pandora_server.redhat.spec +++ b/pandora_server/pandora_server.redhat.spec @@ -2,9 +2,12 @@ # Pandora FMS Server # %global __os_install_post %{nil} +%global _missing_build_ids_terminate_build 0 +%define __strip /bin/true +%define debug_package %{nil} %define name pandorafms_server %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server.spec b/pandora_server/pandora_server.spec index b683278589..5e78696339 100644 --- a/pandora_server/pandora_server.spec +++ b/pandora_server/pandora_server.spec @@ -4,7 +4,7 @@ %global __os_install_post %{nil} %define name pandorafms_server %define version 7.0NG.773.3 -%define release 231011 +%define release 231019 Summary: Pandora FMS Server Name: %{name} diff --git a/pandora_server/pandora_server_installer b/pandora_server/pandora_server_installer index c6a7657f13..c65efdfb3a 100755 --- a/pandora_server/pandora_server_installer +++ b/pandora_server/pandora_server_installer @@ -9,7 +9,7 @@ # ********************************************************************** PI_VERSION="7.0NG.773.3" -PI_BUILD="231011" +PI_BUILD="231019" MODE=$1 if [ $# -gt 1 ]; then diff --git a/pandora_server/util/pandora_db.pl b/pandora_server/util/pandora_db.pl index f9ed7d40c7..b6e8e77248 100755 --- a/pandora_server/util/pandora_db.pl +++ b/pandora_server/util/pandora_db.pl @@ -35,7 +35,7 @@ use PandoraFMS::Config; use PandoraFMS::DB; # version: define current version -my $version = "7.0NG.773.3 Build 231011"; +my $version = "7.0NG.773.3 Build 231019"; # Pandora server configuration my %conf; diff --git a/pandora_server/util/pandora_manage.pl b/pandora_server/util/pandora_manage.pl index 9fe363175c..29b39101b2 100755 --- a/pandora_server/util/pandora_manage.pl +++ b/pandora_server/util/pandora_manage.pl @@ -36,7 +36,7 @@ use Encode::Locale; Encode::Locale::decode_argv; # version: define current version -my $version = "7.0NG.773.3 Build 231011"; +my $version = "7.0NG.773.3 Build 231019"; # save program name for logging my $progname = basename($0);