#11206 Resolve conflicts

This commit is contained in:
miguel angel rasteu 2023-08-22 11:21:10 +02:00
commit 384fb8d115
74 changed files with 3457 additions and 80 deletions

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, AIX version # Version 7.0NG.773.1, AIX version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, FreeBSD Version # Version 7.0NG.773.1, FreeBSD Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, HP-UX Version # Version 7.0NG.773.1, HP-UX Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, GNU/Linux # Version 7.0NG.773.1, GNU/Linux
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, GNU/Linux # Version 7.0NG.773.1, GNU/Linux
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, Solaris Version # Version 7.0NG.773.1, Solaris Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,6 +1,6 @@
# Base config file for Pandora FMS Windows Agent # Base config file for Pandora FMS Windows Agent
# (c) 2006-2023 Pandora FMS # (c) 2006-2023 Pandora FMS
# Version 7.0NG.773 # Version 7.0NG.773.1
# This program is Free Software, you can redistribute it and/or modify it # This program is Free Software, you can redistribute it and/or modify it
# under the terms of the GNU General Public Licence as published by the Free Software # under the terms of the GNU General Public Licence as published by the Free Software
# Foundation; either version 2 of the Licence or any later version # Foundation; either version 2 of the Licence or any later version

View File

@ -1,6 +1,6 @@
# Fichero de configuracion base de agentes de Pandora # Fichero de configuracion base de agentes de Pandora
# Base config file for Pandora agents # Base config file for Pandora agents
# Version 7.0NG.773, AIX version # Version 7.0NG.773.1, AIX version
# General Parameters # General Parameters
# ================== # ==================

View File

@ -1,6 +1,6 @@
# Fichero de configuracion base de agentes de Pandora # Fichero de configuracion base de agentes de Pandora
# Base config file for Pandora agents # Base config file for Pandora agents
# Version 7.0NG.773 # Version 7.0NG.773.1
# FreeBSD/IPSO version # FreeBSD/IPSO version
# Licenced under GPL licence, 2003-2007 Sancho Lerena # Licenced under GPL licence, 2003-2007 Sancho Lerena

View File

@ -1,6 +1,6 @@
# Fichero de configuracion base de agentes de Pandora # Fichero de configuracion base de agentes de Pandora
# Base config file for Pandora agents # Base config file for Pandora agents
# Version 7.0NG.773, HPUX Version # Version 7.0NG.773.1, HPUX Version
# General Parameters # General Parameters
# ================== # ==================

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773 # Version 7.0NG.773.1
# Licensed under GPL license v2, # Licensed under GPL license v2,
# (c) 2003-2023 Pandora FMS # (c) 2003-2023 Pandora FMS
# please visit http://pandora.sourceforge.net # please visit http://pandora.sourceforge.net

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773 # Version 7.0NG.773.1
# Licensed under GPL license v2, # Licensed under GPL license v2,
# (c) 2003-2023 Pandora FMS # (c) 2003-2023 Pandora FMS
# please visit http://pandora.sourceforge.net # please visit http://pandora.sourceforge.net

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773 # Version 7.0NG.773.1
# Licensed under GPL license v2, # Licensed under GPL license v2,
# please visit http://pandora.sourceforge.net # please visit http://pandora.sourceforge.net

View File

@ -1,6 +1,6 @@
# Fichero de configuracion base de agentes de Pandora # Fichero de configuracion base de agentes de Pandora
# Base config file for Pandora agents # Base config file for Pandora agents
# Version 7.0NG.773, Solaris version # Version 7.0NG.773.1, Solaris version
# General Parameters # General Parameters
# ================== # ==================

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, AIX version # Version 7.0NG.773.1, AIX version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
package: pandorafms-agent-unix package: pandorafms-agent-unix
Version: 7.0NG.773-230821 Version: 7.0NG.773.1-230822
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.773-230821" pandora_version="7.0NG.773.1-230822"
echo "Test if you has the tools for to make the packages." echo "Test if you has the tools for to make the packages."
whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null whereis dpkg-deb | cut -d":" -f2 | grep dpkg-deb > /dev/null

View File

@ -31,7 +31,7 @@ fi
if [ "$#" -ge 2 ]; then if [ "$#" -ge 2 ]; then
VERSION="$2" VERSION="$2"
else else
VERSION="7.0NG.773" VERSION="7.0NG.773.1"
fi fi
# Path for the generated DMG file # Path for the generated DMG file

View File

@ -19,11 +19,11 @@
<choice id="com.pandorafms.pandorafms_src" visible="false"> <choice id="com.pandorafms.pandorafms_src" visible="false">
<pkg-ref id="com.pandorafms.pandorafms_src"/> <pkg-ref id="com.pandorafms.pandorafms_src"/>
</choice> </choice>
<pkg-ref id="com.pandorafms.pandorafms_src" version="7.0NG.773" onConclusion="none">pandorafms_src.pdk</pkg-ref> <pkg-ref id="com.pandorafms.pandorafms_src" version="7.0NG.773.1" onConclusion="none">pandorafms_src.pdk</pkg-ref>
<choice id="com.pandorafms.pandorafms_uninstall" visible="true" customLocation="/Applications"> <choice id="com.pandorafms.pandorafms_uninstall" visible="true" customLocation="/Applications">
<pkg-ref id="com.pandorafms.pandorafms_uninstall"/> <pkg-ref id="com.pandorafms.pandorafms_uninstall"/>
</choice> </choice>
<pkg-ref id="com.pandorafms.pandorafms_uninstall" version="7.0NG.773" onConclusion="none">pandorafms_uninstall.pdk</pkg-ref> <pkg-ref id="com.pandorafms.pandorafms_uninstall" version="7.0NG.773.1" onConclusion="none">pandorafms_uninstall.pdk</pkg-ref>
<!-- <installation-check script="check()" /> <!-- <installation-check script="check()" />
<script> <script>
<![CDATA[ <![CDATA[

View File

@ -5,9 +5,9 @@
<key>CFBundleIconFile</key> <string>pandorafms.icns</string> <key>CFBundleIconFile</key> <string>pandorafms.icns</string>
<key>CFBundleIdentifier</key> <string>com.pandorafms.pandorafms_uninstall</string> <key>CFBundleIdentifier</key> <string>com.pandorafms.pandorafms_uninstall</string>
<key>CFBundleVersion</key> <string>7.0NG.773</string> <key>CFBundleVersion</key> <string>7.0NG.773.1</string>
<key>CFBundleGetInfoString</key> <string>7.0NG.773 Pandora FMS on Aug 2020</string> <key>CFBundleGetInfoString</key> <string>7.0NG.773.1 Pandora FMS on Aug 2020</string>
<key>CFBundleShortVersionString</key> <string>7.0NG.773</string> <key>CFBundleShortVersionString</key> <string>7.0NG.773.1</string>
<key>NSPrincipalClass</key><string>NSApplication</string> <key>NSPrincipalClass</key><string>NSApplication</string>
<key>NSMainNibFile</key><string>MainMenu</string> <key>NSMainNibFile</key><string>MainMenu</string>

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, GNU/Linux # Version 7.0NG.773.1, GNU/Linux
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, FreeBSD Version # Version 7.0NG.773.1, FreeBSD Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, HP-UX Version # Version 7.0NG.773.1, HP-UX Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773 # Version 7.0NG.773.1
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2004-2023 Pandora FMS # Copyright (c) 2004-2023 Pandora FMS
# https://pandorafms.com # https://pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, GNU/Linux # Version 7.0NG.773.1, GNU/Linux
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, NetBSD Version # Version 7.0NG.773.1, NetBSD Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1,5 +1,5 @@
# Base config file for Pandora FMS agents # Base config file for Pandora FMS agents
# Version 7.0NG.773, Solaris Version # Version 7.0NG.773.1, Solaris Version
# Licensed under GPL license v2, # Licensed under GPL license v2,
# Copyright (c) 2003-2023 Pandora FMS # Copyright (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -1030,8 +1030,8 @@ my $Sem = undef;
# Semaphore used to control the number of threads # Semaphore used to control the number of threads
my $ThreadSem = undef; my $ThreadSem = undef;
use constant AGENT_VERSION => '7.0NG.773'; use constant AGENT_VERSION => '7.0NG.773.1';
use constant AGENT_BUILD => '230821'; use constant AGENT_BUILD => '230822';
# Agent log default file size maximum and instances # Agent log default file size maximum and instances
use constant DEFAULT_MAX_LOG_SIZE => 600000; use constant DEFAULT_MAX_LOG_SIZE => 600000;

View File

@ -3,8 +3,8 @@
# #
%global __os_install_post %{nil} %global __os_install_post %{nil}
%define name pandorafms_agent_linux %define name pandorafms_agent_linux
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
Summary: Pandora FMS Linux agent, PERL version Summary: Pandora FMS Linux agent, PERL version
Name: %{name} Name: %{name}

View File

@ -3,8 +3,8 @@
# #
%global __os_install_post %{nil} %global __os_install_post %{nil}
%define name pandorafms_agent_linux %define name pandorafms_agent_linux
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
Summary: Pandora FMS Linux agent, PERL version Summary: Pandora FMS Linux agent, PERL version
Name: %{name} Name: %{name}

View File

@ -9,8 +9,8 @@
# Please see http://www.pandorafms.org. This code is licensed under GPL 2.0 license. # Please see http://www.pandorafms.org. This code is licensed under GPL 2.0 license.
# ********************************************************************** # **********************************************************************
PI_VERSION="7.0NG.773" PI_VERSION="7.0NG.773.1"
PI_BUILD="230821" PI_BUILD="230822"
OS_NAME=`uname -s` OS_NAME=`uname -s`
FORCE=0 FORCE=0

View File

@ -1,6 +1,6 @@
# Base config file for Pandora FMS Windows Agent # Base config file for Pandora FMS Windows Agent
# (c) 2006-2023 Pandora FMS # (c) 2006-2023 Pandora FMS
# Version 7.0NG.773 # Version 7.0NG.773.1
# This program is Free Software, you can redistribute it and/or modify it # This program is Free Software, you can redistribute it and/or modify it
# under the terms of the GNU General Public Licence as published by the Free Software # under the terms of the GNU General Public Licence as published by the Free Software
# Foundation; either version 2 of the Licence or any later version # Foundation; either version 2 of the Licence or any later version

View File

@ -3,7 +3,7 @@ AllowLanguageSelection
{Yes} {Yes}
AppName AppName
{Pandora FMS Windows Agent v7.0NG.773} {Pandora FMS Windows Agent v7.0NG.773.1}
ApplicationID ApplicationID
{17E3D2CF-CA02-406B-8A80-9D31C17BD08F} {17E3D2CF-CA02-406B-8A80-9D31C17BD08F}
@ -186,7 +186,7 @@ UpgradeApplicationID
{} {}
Version Version
{230821} {230822}
ViewReadme ViewReadme
{Yes} {Yes}

View File

@ -30,7 +30,7 @@ using namespace Pandora;
using namespace Pandora_Strutils; using namespace Pandora_Strutils;
#define PATH_SIZE _MAX_PATH+1 #define PATH_SIZE _MAX_PATH+1
#define PANDORA_VERSION ("7.0NG.773 Build 230821") #define PANDORA_VERSION ("7.0NG.773.1 Build 230822")
string pandora_path; string pandora_path;
string pandora_dir; string pandora_dir;

View File

@ -11,7 +11,7 @@ BEGIN
VALUE "LegalCopyright", "Pandora FMS" VALUE "LegalCopyright", "Pandora FMS"
VALUE "OriginalFilename", "PandoraAgent.exe" VALUE "OriginalFilename", "PandoraAgent.exe"
VALUE "ProductName", "Pandora FMS Windows Agent" VALUE "ProductName", "Pandora FMS Windows Agent"
VALUE "ProductVersion", "(7.0NG.773(Build 230821))" VALUE "ProductVersion", "(7.0NG.773.1(Build 230822))"
VALUE "FileVersion", "1.0.0.0" VALUE "FileVersion", "1.0.0.0"
END END
END END

View File

@ -1,5 +1,5 @@
package: pandorafms-console package: pandorafms-console
Version: 7.0NG.773-230821 Version: 7.0NG.773.1-230822
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.773-230821" pandora_version="7.0NG.773.1-230822"
package_pear=0 package_pear=0
package_pandora=1 package_pandora=1

View File

@ -261,12 +261,27 @@ function agents_modules_load_js()
} }
function select_selected () { function select_selected () {
// $('#id_agents2 option').each(function(){ var f = document.forms.filter_form;
// if($(this).attr('selected') === 'selected'){ f.action = "index.php?sec=view&sec2=extensions/agents_modules";
// $(this).prop('selected', true); $('#filter_form').submit();
// }
// });
} }
/* <![CDATA[ */
function export_csv() {
let group_id = $('#group_id option:selected').val();
let module_group_id = $('#modulegroup option:selected').val();
let agent_id = $('#id_agents2 option:selected').map((_, e) => e.value).get();
let module_id = $('#module option:selected').map((_, e) => e.value).get();
let filters_array = {group_id: group_id, module_group_id:module_group_id, agent_id:agent_id, module_id:module_id}
let jsonFilters = JSON.stringify(filters_array)
let filters = window.btoa(jsonFilters)
var f = document.forms.filter_form;
blockResubmit($(this));
f.action = "extensions/agents_modules_csv.php?get_agents_module_csv=1&filters="+filters;
$("#filter_form").submit();
}
/* ]]> */
</script> </script>
<?php <?php
} }
@ -653,7 +668,7 @@ function mainAgentsModules()
} }
if ($config['pure'] != 1) { if ($config['pure'] != 1) {
$show_filters = '<form method="post" action="index.php?sec=view&sec2=extensions/agents_modules" class="w100p">'; $show_filters = '<form id="filter_form" method="post" action="index.php?sec=view&sec2=extensions/agents_modules" class="w100p">';
$show_filters .= '<table class="filter-table-adv w100p no-border" cellpadding="4" cellspacing="4">'; $show_filters .= '<table class="filter-table-adv w100p no-border" cellpadding="4" cellspacing="4">';
$show_filters .= '<tr>'; $show_filters .= '<tr>';
$show_filters .= '<td width="33%">'.$filter_type.'</td>'; $show_filters .= '<td width="33%">'.$filter_type.'</td>';
@ -679,6 +694,13 @@ function mainAgentsModules()
'onclick' => 'select_selected()', 'onclick' => 'select_selected()',
], ],
true true
).html_print_button(
__('Export to CSV'),
'srcbutton_csv',
false,
'export_csv()',
['class' => 'secondary mini'],
true,
), ),
], ],
true true

View File

@ -0,0 +1,117 @@
<?php
/**
* Export data.
*
* @category Tools
* @package Pandora FMS
* @subpackage Operation
* @version 1.0.0
* @license See below
*
* ______ ___ _______ _______ ________
* | __ \.-----.--.--.--| |.-----.----.-----. | ___| | | __|
* | __/| _ | | _ || _ | _| _ | | ___| |__ |
* |___| |___._|__|__|_____||_____|__| |___._| |___| |__|_|__|_______|
*
* ============================================================================
* Copyright (c) 2005-2023 Pandora FMS
* Please see https://pandorafms.com/community/ for full contribution list
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation for version 2.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ============================================================================
*/
/*
require_once $config['homedir'].'/include/config.php';
require_once $config['homedir'].'/include/functions_reporting.php';
require_once $config['homedir'].'/include/functions_modules.php';
*/
require_once '../include/config.php';
require_once '../include/functions_agents.php';
require_once '../include/functions_reporting.php';
require_once '../include/functions_modules.php';
require_once '../include/functions_users.php';
global $config;
check_login();
// ACL Check.
if (! check_acl($config['id_user'], 0, 'AR')) {
db_pandora_audit(
AUDIT_LOG_ACL_VIOLATION,
'Trying to access Agent view (Grouped)'
);
include 'general/noaccess.php';
exit;
}
$get_agents_module_csv = get_parameter('get_agents_module_csv', 0);
if ($get_agents_module_csv === '1') {
// ***************************************************
// Header output
// ***************************************************
$config['ignore_callback'] = true;
while (@ob_end_clean()) {
}
$filename = 'agents_module_view_'.date('Ymd').'-'.date('His');
// Set cookie for download control.
setDownloadCookieToken();
header('Content-Type: text/csv');
header('Content-Disposition: attachment; filename="'.$filename.'.csv"');
// ***************************************************
// Data processing
// ***************************************************
echo pack('C*', 0xEF, 0xBB, 0xBF);
$json_filters = get_parameter('filters', '');
$filters = json_decode(
base64_decode(
get_parameter('filters', '')
),
true
);
$results = export_agents_module_csv($filters);
$divider = $config['csv_divider'];
$dataend = PHP_EOL;
$header_fields = [
__('Agent'),
__('Module'),
__('Data'),
];
$out_csv = '';
foreach ($header_fields as $key => $value) {
$out_csv .= $value.$divider;
}
$out_csv .= "\n";
foreach ($results as $result) {
foreach ($result as $key => $value) {
$out_csv .= io_safe_output($value).$divider;
}
$out_csv .= "\n";
}
echo io_safe_output($out_csv);
exit;
}

View File

@ -532,6 +532,54 @@ echo sprintf('<div id="header_table" class="header_table_%s">', $menuTypeClass);
element.style.display = "none" element.style.display = "none"
} }
function notifications_clean_all() {
let wrapper_inner = document.getElementById('notification-wrapper-inner');
while (wrapper_inner.firstChild) {
wrapper_inner.removeChild(wrapper_inner.firstChild);
}
}
function mark_all_notification_as_read() {
jQuery.post ("ajax.php",
{
"page" : "godmode/setup/setup_notifications",
"mark_all_notification_as_read" : 1
},
function (data, status) {
notifications_clean_all();
location.reload();
},
"json"
)
.fail(function(xhr, textStatus, errorThrown){
console.error(
"Failed to mark al notification as read. Error: ",
xhr.responseText
);
});
}
function filter_notification() {
let notification_type = '';
$('.notification-item').hide();
$(".checkbox_filter_notifications:checkbox:checked").each(function() {
notification_type = $(this).val();
console.log(notification_type);
$('.notification-item[value='+notification_type+']').show();
if (notification_type == 'All'){
$('.notification-item').show();
}
});
if (notification_type == 'All'){
$('.notification-item').show();
}
if (notification_type == ''){
$('.notification-item').hide();
}
}
function click_on_notification_toast(event) { function click_on_notification_toast(event) {
var match = /notification-(.*)-id-([0-9]+)/.exec(event.target.id); var match = /notification-(.*)-id-([0-9]+)/.exec(event.target.id);
if (!match) { if (!match) {

View File

@ -187,6 +187,27 @@ if (get_parameter('mark_notification_as_read', 0)) {
return; return;
} }
if (get_parameter('mark_all_notification_as_read', 0)) {
$unread_messages = db_get_all_rows_sql('SELECT id_mensaje FROM tnotification_user WHERE utimestamp_read is NULL');
if ($unread_messages !== false) {
foreach ($unread_messages as $messages) {
messages_process_read($messages['id_mensaje']);
}
$result = true;
} else {
$result = false;
}
// If there is new messages, get the info.
echo json_encode(
['result' => $result]
);
return;
}
if (get_parameter('get_notifications_dropdown', 0)) { if (get_parameter('get_notifications_dropdown', 0)) {
echo notifications_print_dropdown(); echo notifications_print_dropdown();
return; return;

View File

@ -169,6 +169,7 @@ class ConsoleSupervisor
* NOTIF.PHP.DISABLE_FUNCTIONS * NOTIF.PHP.DISABLE_FUNCTIONS
* NOTIF.PHP.CHROMIUM * NOTIF.PHP.CHROMIUM
* NOTIF.PHP.VERSION * NOTIF.PHP.VERSION
* NOTIF.PHP.VERSION.SUPPORT
*/ */
$this->checkPHPSettings(); $this->checkPHPSettings();
@ -383,6 +384,7 @@ class ConsoleSupervisor
* NOTIF.PHP.DISABLE_FUNCTIONS * NOTIF.PHP.DISABLE_FUNCTIONS
* NOTIF.PHP.CHROMIUM * NOTIF.PHP.CHROMIUM
* NOTIF.PHP.VERSION * NOTIF.PHP.VERSION
* NOTIF.PHP.VERSION.SUPPORT
*/ */
$this->checkPHPSettings(); $this->checkPHPSettings();
@ -874,6 +876,7 @@ class ConsoleSupervisor
case 'NOTIF.PHP.DISABLE_FUNCTIONS': case 'NOTIF.PHP.DISABLE_FUNCTIONS':
case 'NOTIF.PHP.CHROMIUM': case 'NOTIF.PHP.CHROMIUM':
case 'NOTIF.PHP.VERSION': case 'NOTIF.PHP.VERSION':
case 'NOTIF.PHP.VERSION.SUPPORT':
case 'NOTIF.HISTORYDB': case 'NOTIF.HISTORYDB':
case 'NOTIF.PANDORADB': case 'NOTIF.PANDORADB':
case 'NOTIF.PANDORADB.HISTORICAL': case 'NOTIF.PANDORADB.HISTORICAL':
@ -1830,14 +1833,14 @@ class ConsoleSupervisor
$url = 'https://www.php.net/supported-versions.php'; $url = 'https://www.php.net/supported-versions.php';
$this->notify( $this->notify(
[ [
'type' => 'NOTIF.PHP.VERSION', 'type' => 'NOTIF.PHP.VERSION.SUPPORT',
'title' => __('PHP UPDATE REQUIRED'), 'title' => __('PHP UPDATE REQUIRED'),
'message' => __('You should update your PHP version because it will be out of official support').'<br>'.__('Current PHP version: ').PHP_VERSION, 'message' => __('You should update your PHP version because it will be out of official support').'<br>'.__('Current PHP version: ').PHP_VERSION,
'url' => $url, 'url' => $url,
] ]
); );
} else { } else {
$this->cleanNotifications('NOTIF.PHP.VERSION'); $this->cleanNotifications('NOTIF.PHP.VERSION.SUPPORT');
} }
} }

View File

@ -20,8 +20,8 @@
/** /**
* Pandora build version and version * Pandora build version and version
*/ */
$build_version = 'PC230821'; $build_version = 'PC230822';
$pandora_version = 'v7.0NG.773'; $pandora_version = 'v7.0NG.773.1';
// Do not overwrite default timezone set if defined. // Do not overwrite default timezone set if defined.
$script_tz = @date_default_timezone_get(); $script_tz = @date_default_timezone_get();

View File

@ -2904,6 +2904,8 @@ function html_print_anchor(
$output .= '>'; $output .= '>';
$output .= (isset($options['text']) === true) ? $options['text'] : '';
$output .= (isset($options['content']) === true) ? io_safe_input_html($options['content']) : ''; $output .= (isset($options['content']) === true) ? io_safe_input_html($options['content']) : '';
$output .= '</a>'; $output .= '</a>';
@ -7118,6 +7120,7 @@ function html_print_menu_button(array $options, bool $return=false)
'class' => ($options['class'] ?? ''), 'class' => ($options['class'] ?? ''),
'style' => ($options['style'] ?? ''), 'style' => ($options['style'] ?? ''),
'onClick' => ($options['onClick'] ?? ''), 'onClick' => ($options['onClick'] ?? ''),
'text' => ($options['text'] ?? ''),
'content' => $content, 'content' => $content,
], ],
$return $return

View File

@ -4687,3 +4687,75 @@ function get_agent_module_childs(
} }
} }
} }
/**
* Function for export a csv file from Agents/Module view
*
* @param array $filters Data from agents/module filter.
*
* @return array Returns the data that will be saved in the csv file
*/
function export_agents_module_csv($filters)
{
$query_filter = '';
foreach ($filters as $key => $filter) {
switch ($key) {
case 'group_id':
if ($filter != 0) {
$query_filter .= ' AND ta.id_grupo = '.$filter.' ';
}
break;
case 'module_group_id':
if ($filter != 0) {
$query_filter .= ' AND tam.id_module_group = '.$filter.' ';
;
}
break;
case 'agent_id':
if (count($filter) > 0) {
$agent_filter = '('.implode(', ', $filter).')';
$query_filter .= ' AND ta.id_agente IN '.$agent_filter.' ';
}
break;
case 'module_id':
if (count($filter) > 0) {
if (is_numeric($filter[0]) === false) {
foreach ($filter as $key => $module) {
$filter[$key] = io_safe_input($module);
}
$module_filter = '(\''.implode("', '", $filter).'\')';
$query_filter .= ' AND tam.nombre IN '.$module_filter.' ';
} else {
$module_filter = '('.implode(', ', $filter).')';
$query_filter .= ' AND tam.id_tipo_modulo IN '.$module_filter.' ';
}
}
break;
default:
// Nothing to do
break;
}
}
// Query fields result.
$query = sprintf(
'SELECT ta.alias as agent, tam.nombre as module, tae.datos as data
FROM tagente_modulo as tam
INNER JOIN tagente as ta ON tam.id_agente = ta.id_agente
INNER JOIN tagente_estado as tae ON tam.id_agente_modulo = tae.id_agente_modulo
WHERE ta.disabled = 0
%s
',
$query_filter
);
$result = db_get_all_rows_sql($query);
return $result;
}

View File

@ -136,6 +136,7 @@ function notifications_get_subtypes(?string $source=null)
'NOTIF.PHP.DISABLE_FUNCTIONS', 'NOTIF.PHP.DISABLE_FUNCTIONS',
'NOTIF.PHP.CHROMIUM', 'NOTIF.PHP.CHROMIUM',
'NOTIF.PHP.VERSION', 'NOTIF.PHP.VERSION',
'NOTIF.PHP.VERSION.SUPPORT',
'NOTIF.HISTORYDB', 'NOTIF.HISTORYDB',
'NOTIF.PANDORADB', 'NOTIF.PANDORADB',
'NOTIF.PANDORADB.HISTORICAL', 'NOTIF.PANDORADB.HISTORICAL',
@ -1010,6 +1011,106 @@ function notifications_print_user_switch($source, $user, $label)
} }
/**
* Generates an HTML of notification filter types.
*
* @return string HTML filter notification.
*/
function notification_filter()
{
$types_list[] = 'All';
$notification_types = db_get_all_rows_sql('SELECT DISTINCT tm.subtype FROM tmensajes as tm INNER JOIN tnotification_user as tnu ON tm.id_mensaje = tnu.id_mensaje WHERE tnu.utimestamp_read IS NULL');
if ($notification_types !== false) {
foreach ($notification_types as $notification_type) {
$type = explode('.', $notification_type['subtype'])[1];
$types_list[] = $type;
}
}
$types_list = array_unique($types_list);
$notification_filter = "<ul id='menu-filter_notification'>";
$notification_filter .= "<li>
<input type='checkbox' name='filter_menu' id='filter_menu'>
<label for='filter_menu' id='filter_menu_label'>".__('Filter').'</label>';
$notification_filter .= "<ul class='sublevel-filter_notification'>";
foreach ($types_list as $type) {
if ($type === 'All') {
$checked = 'checked';
} else {
$checked = '';
}
switch ($type) {
case 'HISTORYDB':
$type_name = 'HISTORY DB';
break;
case 'PANDORADB':
$type_name = 'PANDORA DB';
break;
case 'UPDATEMANAGER':
$type_name = 'UPDATE MANAGER';
break;
case 'ALLOWOVERRIDE':
$type_name = 'ALLOW OVERRIDE';
break;
case 'DISCOVERYTASK':
$type_name = 'DISCOVERY TASK';
break;
default:
$type_name = $type;
break;
}
$notification_filter .= "<li><div class='item-filter'>
<input type='checkbox'
class='checkbox_filter_notifications'
value=".$type."
name='filter_".$type."'
".$checked."
id='filter_".$type."'>
<label for='filter_".$type."'>".$type_name.'</label>
</div>
</li>';
}
$notification_filter .= "<li><div class='item-filter'>";
$notification_filter .= html_print_div(
[
'class' => 'action-buttons w100p',
'content' => html_print_submit_button(
__('Filter'),
'btn_submit',
false,
[
'class' => 'mini sub filter',
'icon' => 'search mini',
'onClick' => 'filter_notification()',
],
true
),
],
true
);
$notification_filter .= '</div>
</li>';
$notification_filter .= '</ul>';
$notification_filter .= '</li>';
$notification_filter .= '</ul>';
return $notification_filter;
}
/** /**
* Generates the dropdown notifications menu. * Generates the dropdown notifications menu.
* *
@ -1022,9 +1123,24 @@ function notifications_print_dropdown()
$mess = []; $mess = [];
} }
$notification_menu = html_print_menu_button(
[
'href' => 'javascript:',
'class' => 'notification_menu_actions',
'text' => __('Mark all as read'),
'onClick' => 'mark_all_notification_as_read()',
],
true
);
$notification_filter = notification_filter();
return sprintf( return sprintf(
"<div id='notification-wrapper'> "<div id='notification-wrapper'>
<div id='notification-wrapper-inner'> <div id='notification-wrapper-inner'>
<div class='notificaion_menu_container'>
<div class='menu_tab filter_notification'>%s</div>
<div class='menu_tab notification_menu'>%s</div>
</div>
%s %s
</div> </div>
</div> </div>
@ -1034,6 +1150,8 @@ function notifications_print_dropdown()
> >
</div> </div>
", ",
$notification_filter,
$notification_menu,
array_reduce( array_reduce(
$mess, $mess,
function ($carry, $message) { function ($carry, $message) {
@ -1093,6 +1211,8 @@ function notifications_print_dropdown_element($message_info)
$message_info['subject'] = io_safe_input($img); $message_info['subject'] = io_safe_input($img);
} }
$type = explode('.', $message_info['subtype'])[1];
if (strlen($body_preview) >= 170) { if (strlen($body_preview) >= 170) {
$body_preview = substr($body_preview, 0, 150); $body_preview = substr($body_preview, 0, 150);
$body_preview .= __('. Read More...'); $body_preview .= __('. Read More...');
@ -1103,6 +1223,7 @@ function notifications_print_dropdown_element($message_info)
class='notification-item' class='notification-item'
onclick='%s' onclick='%s'
id='notification-item-id-%s' id='notification-item-id-%s'
value='%s'
href='%s' href='%s'
target='%s' target='%s'
> >
@ -1116,8 +1237,9 @@ function notifications_print_dropdown_element($message_info)
</p> </p>
</div> </div>
</a>", </a>",
$action.';click_on_notification_toast(event)', $action.'; click_on_notification_toast(event)',
$message_info['id_mensaje'], $message_info['id_mensaje'],
$type,
messages_get_url($message_info['id_mensaje']), messages_get_url($message_info['id_mensaje']),
$target, $target,
html_print_image('images/info.svg', true, ['style' => 'height: 40px;margin-left: -20px;margin-top: -40px;']), html_print_image('images/info.svg', true, ['style' => 'height: 40px;margin-left: -20px;margin-top: -40px;']),

View File

@ -12395,6 +12395,59 @@ form.cfv_status_agent input:checked + label:before {
content: "✓ "; content: "✓ ";
} }
.notificaion_menu_container {
display: flex;
padding-top: 10px;
padding-left: 15px;
}
.notification_menu {
width: 100px;
}
.filter_notification {
width: auto;
min-width: 50px;
}
#menu-filter_notification * {
list-style: none;
}
#menu-filter_notification li {
line-height: 180%;
}
#menu-filter_notification input[name="filter_menu"] {
position: absolute;
left: -1000em;
}
#menu-filter_notification label[id="filter_menu_label"]:before {
content: "\025b8";
margin-right: 4px;
}
#menu-filter_notification
input[name="filter_menu"]:checked
~ label[id="filter_menu_label"]:before {
content: "\025be";
}
#menu-filter_notification .sublevel-filter_notification {
display: none;
}
#menu-filter_notification input[name="filter_menu"]:checked ~ ul {
display: block;
}
.item-filter > label {
display: inline-block;
width: auto;
vertical-align: middle;
}
.item-filter > input[type="checkbox"] {
display: inline-block;
width: 40px;
height: 100%;
vertical-align: middle;
}
/* --- Custom fields view --- */ /* --- Custom fields view --- */
.custom_fields_view_layout { .custom_fields_view_layout {
margin-top: 15px; margin-top: 15px;

View File

@ -130,8 +130,8 @@
</div> </div>
<div style='padding-bottom: 50px'> <div style='padding-bottom: 50px'>
<?php <?php
$version = '7.0NG.773'; $version = '7.0NG.773.1';
$build = '230821'; $build = '230822';
$banner = "v$version Build $build"; $banner = "v$version Build $build";
error_reporting(0); error_reporting(0);

View File

@ -2,8 +2,8 @@
# Pandora FMS Console # Pandora FMS Console
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name httpd %define httpd_name httpd

View File

@ -2,8 +2,8 @@
# Pandora FMS Console # Pandora FMS Console
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name httpd %define httpd_name httpd

View File

@ -2,8 +2,8 @@
# Pandora FMS Console # Pandora FMS Console
# #
%define name pandorafms_console %define name pandorafms_console
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
%define httpd_name httpd %define httpd_name httpd
# User and Group under which Apache is running # User and Group under which Apache is running
%define httpd_name apache2 %define httpd_name apache2

View File

@ -9,7 +9,7 @@
# This code is licensed under GPL 2.0 license. # This code is licensed under GPL 2.0 license.
# ********************************************************************** # **********************************************************************
PI_VERSION="7.0NG.773" PI_VERSION="7.0NG.773.1"
FORCE=0 FORCE=0
DESTDIR="" DESTDIR=""
LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"` LOG_TIMESTAMP=`date +"%Y/%m/%d %H:%M:%S"`

View File

@ -1,5 +1,5 @@
package: pandorafms-server package: pandorafms-server
Version: 7.0NG.773-230821 Version: 7.0NG.773.1-230822
Architecture: all Architecture: all
Priority: optional Priority: optional
Section: admin Section: admin

View File

@ -14,7 +14,7 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
pandora_version="7.0NG.773-230821" pandora_version="7.0NG.773.1-230822"
package_cpan=0 package_cpan=0
package_pandora=1 package_pandora=1

View File

@ -1,7 +1,7 @@
############################################################################# #############################################################################
# Pandora FMS Server Parameters # Pandora FMS Server Parameters
# Pandora FMS, the Flexible Monitoring System. # Pandora FMS, the Flexible Monitoring System.
# Version 7.0NG.773 # Version 7.0NG.773.1
# Licensed under GPL license v2, # Licensed under GPL license v2,
# (c) 2003-2023 Pandora FMS # (c) 2003-2023 Pandora FMS
# http://www.pandorafms.com # http://www.pandorafms.com

View File

@ -0,0 +1,85 @@
# Python: module plugintools for PandoraFMS Developers
pandoraPluginTools is a library that aims to help the creation of scripts and their integration in Pandora FMS.
[PluginTools Reference Documentation](https://pandorafms.com/guides/public/books/plugintools)
The package includes the following modules. Each one has different functions that facilitate and automate the data integration in Pandora FMS:
**general**
Module containing general purpose functions, useful in the creation of plugins for PandoraFMS.
**threads**
Module containing threading purpose functions, useful to run parallel functions.
**agents**
Module that contains functions oriented to the creation of Pandora FMS agents
**modules**
Module that contains functions oriented to the creation of Pandora FMS modules.
**transfer**
Module containing functions oriented to file transfer and data sending to Pandora FMS server.
**discovery**
Module containing functions oriented to the creation of Pandora FMS discovery plugins.
**http**
Module containing functions oriented to HTTP API calls.
## Example
```python
import pandoraPluginTools as ppt
## Define agent
server_name = "WIN-SERV"
agent=ppt.init_agent({
"agent_name" : ppt.generate_md5(server_name),
"agent_alias" : server_name,
"description" : "Default Windows server"
})
## Define modules
modules=[]
data = 10
modules.append({
"name" : "CPU usage",
"type" : "generic_data",
"value": data,
"desc" : "Percentage of CPU utilization",
"unit" : "%"
})
## Generate and transfer XML
xml_content = ppt.print_agent(agent, modules)
xml_file = ppt.write_xml(xml_content, agent["agent_name"])
ppt.transfer_xml(
xml_file,
transfer_mode="tentacle",
tentacle_ip="192.168.1.20",
tentacle_port="41121",
)
```
The package has the following dependencies:
- Hashlib
- datetime.datetime
- hashlib
- json
- os
- print_agent
- print_log_module
- print_module
- queue.Queue
- requests.auth.HTTPBasicAuth
- requests.auth.HTTPDigestAuth
- requests.sessions.Session
- requests_ntlm.HttpNtlmAuth
- shutil
- subprocess.Popen
- sys
- threading.Thread

View File

@ -0,0 +1,10 @@
from .general import *
from .output import *
from .encryption import *
from .threads import *
from .agents import *
from .modules import *
from .transfer import *
from .discovery import *
from .http import *
from .snmp import *

View File

@ -0,0 +1,409 @@
import sys
import os
####
# Define global variables dict, used in functions as default values.
# Its values can be changed.
#########################################################################################
_GLOBAL_VARIABLES = {
'agents_group_name' : '',
'interval' : 300
}
####
# Define some global variables
#########################################################################################
_WINDOWS = os.name == "nt" or os.name == "ce"
_LINUX = sys.platform.startswith("linux")
_MACOS = sys.platform.startswith("darwin")
_OSX = _MACOS # deprecated alias
_FREEBSD = sys.platform.startswith("freebsd")
_OPENBSD = sys.platform.startswith("openbsd")
_NETBSD = sys.platform.startswith("netbsd")
_BSD = _FREEBSD or _OPENBSD or _NETBSD
_SUNOS = sys.platform.startswith(("sunos", "solaris"))
_AIX = sys.platform.startswith("aix")
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Prints any list, dict, string, float or integer as a json
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Set a global variable with the specified name and assigns a value to it.
#########################################################################################
def set_global_variable(
variable_name: str = "",
value = None
)-> None:
"""
Sets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
value (any): Value to assign to the variable.
Returns:
None
"""
from .general import set_dict_key_value
set_dict_key_value(_GLOBAL_VARIABLES, variable_name, value)
####
# Get a global variable with the specified name.
#########################################################################################
def get_global_variable(
variable_name: str = ""
)-> None:
"""
Gets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
Returns:
None
"""
from .general import get_dict_key_value
get_dict_key_value(_GLOBAL_VARIABLES, variable_name)
####
# Agent class
#########################################################################################
class Agent:
"""
Basic agent class. Requires agent parameters (config {dictionary})
and module definition (modules_def [list of dictionaries])
"""
def __init__(
self,
config: dict = {},
modules_def: list = [],
log_modules_def: list = []
):
self.modules_def = []
self.added_modules = []
self.log_modules_def = []
self.config = init_agent(config)
for module in modules_def:
self.add_module(module)
for log_module in log_modules_def:
self.add_log_module(log_module)
def update_config(
self,
config: dict = {}
)-> None:
'''
Update the configuration settings with new values.
Args:
config (dict): A dictionary containing configuration keys and their new values.
Returns:
None
'''
for key, value in config.items():
if key in self.config:
self.config[key] = value
def get_config(
self
) -> dict:
'''
Retrieve the current configuration settings.
Returns:
dict: A dictionary containing the current configuration settings.
'''
return self.config
def add_module(
self,
module: dict = {}
)-> None:
'''
Add a new module to the list of modules.
Args:
module (dict): A dictionary containing module information.
Returns:
None
'''
from .general import generate_md5
from .modules import init_module
if "name" in module and type(module["name"]) == str and len(module["name"].strip()) > 0:
self.modules_def.append(init_module(module))
self.added_modules.append(generate_md5(module["name"]))
def del_module(
self,
module_name: str = ""
)-> None:
'''
Delete a module based on its name.
Args:
module_name (str): The name of the module to be deleted.
Returns:
None
'''
from .general import generate_md5
if len(module_name.strip()) > 0:
try:
module_id = self.added_modules.index(generate_md5(module_name))
except:
module_id = None
if module_id is not None:
self.added_modules.pop(module_id)
self.modules_def.pop(module_id)
def update_module(
self,
module_name: str = "",
module: dict = {}
)-> None:
'''
Update a module based on its name.
Args:
module_name (str): The name of the module to be updated.
module (dict): A dictionary containing updated module information.
Returns:
None
'''
module_def = self.get_module(module_name)
if module_def:
if "name" not in module:
module["name"] = module_name
module_def.update(module)
self.del_module(module_name)
self.add_module(module_def)
def get_module(
self,
module_name: str = ""
) -> dict:
'''
Retrieve module information based on its name.
Args:
module_name (str): The name of the module to retrieve.
Returns:
dict: A dictionary containing module information if found, otherwise an empty dictionary.
'''
from .general import generate_md5
if len(module_name.strip()) > 0:
try:
module_id = self.added_modules.index(generate_md5(module_name))
except:
module_id = None
if module_id is not None:
return self.modules_def[module_id]
else:
return {}
def get_modules_def(
self
) -> dict:
'''
Retrieve the definitions of all added modules.
Returns:
dict: A dictionary containing the definitions of all added modules.
'''
return self.modules_def
def add_log_module(
self,
log_module: dict = {}
)-> None:
'''
Add a new log module to the list of log modules.
Args:
log_module (dict): A dictionary containing log module information.
Returns:
None
'''
from .modules import init_log_module
if "source" in log_module and type(log_module["source"]) == str and len(log_module["source"].strip()) > 0:
self.log_modules_def.append(init_log_module(log_module))
def get_log_modules_def(
self
) -> dict:
'''
Retrieve the definitions of all added log modules.
Returns:
dict: A dictionary containing the definitions of all added log modules.
'''
return self.log_modules_def
def print_xml(
self,
print_flag: bool = False
) -> str:
'''
Generate and optionally print the XML representation of the agent.
Args:
print_flag (bool): A flag indicating whether to print the XML representation.
Returns:
str: The XML representation of the agent.
'''
return print_agent(self.get_config(), self.get_modules_def(), self.get_log_modules_def(), print_flag)
####
# Gets system OS name
#########################################################################################
def get_os() -> str:
"""
Gets system OS name
Returns:
str: OS name.
"""
os = "Other"
if _WINDOWS:
os = "Windows"
if _LINUX:
os = "Linux"
if _MACOS or _OSX:
os = "MacOS"
if _FREEBSD or _OPENBSD or _NETBSD or _BSD:
os = "BSD"
if _SUNOS:
os = "Solaris"
if _AIX:
os = "AIX"
return os
####
# Init agent template
#########################################################################################
def init_agent(
default_values: dict = {}
) -> dict:
"""
Initialize an agent template with default values.
Args:
default_values (dict): A dictionary containing custom default values for the agent template.
Returns:
dict: A dictionary representing the agent template with default and custom values.
"""
from .general import now
agent = {
"agent_name" : "",
"agent_alias" : "",
"parent_agent_name" : "",
"description" : "",
"version" : "",
"os_name" : "",
"os_version" : "",
"timestamp" : now(),
"address" : "",
"group" : _GLOBAL_VARIABLES['agents_group_name'],
"interval" : _GLOBAL_VARIABLES['interval'],
"agent_mode" : "1"
}
for key, value in default_values.items():
if key in agent:
agent[key] = value
return agent
####
# Prints agent XML. Requires agent conf (dict) and modules (list) as arguments.
#########################################################################################
def print_agent(
agent: dict = None,
modules: list = [],
log_modules: list = [],
print_flag: bool = False
) -> str:
"""
Print the XML representation of an agent.
Args:
agent (dict): A dictionary containing agent configuration.
modules (list): A list of dictionaries representing modules.
log_modules (list): A list of dictionaries representing log modules.
print_flag (bool): A flag indicating whether to print the XML representation.
Returns:
str: The XML representation of the agent.
"""
from .output import print_stdout
from .modules import print_module,print_log_module
xml = ""
data_file = None
if agent is not None:
header = "<?xml version='1.0' encoding='UTF-8'?>\n"
header += "<agent_data"
for dato in agent:
header += " " + str(dato) + "='" + str(agent[dato]) + "'"
header += ">\n"
xml = header
for module in modules:
modules_xml = print_module(module)
xml += str(modules_xml)
for log_module in log_modules:
modules_xml = print_log_module(log_module)
xml += str(modules_xml)
xml += "</agent_data>"
if print_flag:
print_stdout(xml)
return xml

View File

@ -0,0 +1,225 @@
import sys
import json
####
# Define some global variables
#########################################################################################
_ERROR_LEVEL = 0
_SUMMARY = {}
_INFO = ""
_MONITORING_DATA = []
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Print the variable as a JSON-like representation for debugging purposes.
Args:
var (any): The variable to be printed.
print_errors (bool): A flag indicating whether to print errors during debugging.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Set error level to value
#########################################################################################
def set_disco_error_level(
value: int = 0
)-> None:
"""
Sets the error level to the specified value.
Args:
value (int, optional): The error level value. Default is 0.
"""
global _ERROR_LEVEL
_ERROR_LEVEL = value
####
# Set fixed value to summary dict
#########################################################################################
def set_disco_summary(
data: dict = {}
)-> None:
"""
Sets the disk summary data in the internal summary dictionary.
This function updates the summary dictionary with the provided disk summary data.
Args:
data (dict): A dictionary containing disk summary data.
Returns:
None
"""
global _SUMMARY
_SUMMARY = {}
####
# Set fixed value to summary key
#########################################################################################
def set_disco_summary_value(
key: str = "",
value = None
)-> None:
"""
Sets a fixed value for a key in the '_SUMMARY' dictionary.
Args:
key (str): Key to set the value for.
value (any): Value to assign to the key.
Returns:
None
"""
global _SUMMARY
_SUMMARY[key] = value
####
# Add value to summary key
#########################################################################################
def add_disco_summary_value(
key: str = "",
value = None
)-> None:
"""
Adds a value to a key in the 'SUMMARY' dictionary.
If the key already exists, the value will be incremented. Otherwise, a new key will be created.
Args:
key (str): Key to add the value to.
value (any): Value to add to the key.
Returns:
None
"""
global _SUMMARY
if key in _SUMMARY:
_SUMMARY[key] += value
else:
set_disco_summary_value(key, value)
####
# Set fixed value to info
#########################################################################################
def set_disco_info_value(
value: str = ""
)-> None:
"""
Sets a fixed value to the '_INFO' variable.
Args:
data (str, optional): The value to set in the '_INFO' variable. Default is an empty string.
Returns:
None
"""
global _INFO
_INFO = value
####
# Add data to info
#########################################################################################
def add_disco_info_value(
value: str = ""
)-> None:
"""
Adds data to the '_INFO' variable.
Args:
data (str, optional): The data to add to the '_INFO' variable. Default is an empty string.
Returns:
None
"""
global _INFO
_INFO += value
####
# Set fixed value to monitoring data
#########################################################################################
def set_disco_monitoring_data(
data: list = []
)-> None:
"""
Set the monitoring data for disk usage.
Args:
data (list): A list containing disk monitoring data.
Returns:
None
"""
global _MONITORING_DATA
_MONITORING_DATA = data
####
# Add value to monitoring data
#########################################################################################
def add_disco_monitoring_data(
data: dict = {}
)-> None:
"""
Add disk monitoring data to the global monitoring dataset.
Args:
data (dict): A dictionary containing disk monitoring data.
Returns:
None
"""
global _MONITORING_DATA
_MONITORING_DATA.append(data)
####
# Print JSON output and exit script
#########################################################################################
def disco_output()-> None:
"""
Prints the JSON output and exits the script.
The function uses the global variables '_ERROR_LEVEL', '_SUMMARY', '_INFO' and '_MONITORING_DATA'
to create the JSON output. It then prints the JSON string and exits the script with
the '_ERROR_LEVEL' as the exit code.
Returns:
None
"""
from .output import print_stdout
global _ERROR_LEVEL
global _SUMMARY
global _INFO
global _MONITORING_DATA
output={}
if _SUMMARY:
output["summary"] = _SUMMARY
if _INFO:
output["info"] = _INFO
if _MONITORING_DATA:
output["monitoring_data"] = _MONITORING_DATA
json_string = json.dumps(output)
print_stdout(json_string)
sys.exit(_ERROR_LEVEL)

View File

@ -0,0 +1,116 @@
try:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
except ImportError as e:
import sys
from .output import print_stderr
print_stderr("ModuleNotFoundError: No module named 'pycryptodome'")
sys.exit(1)
import hashlib
import base64
import hmac
from binascii import unhexlify
####
# Define encription internal global variables.
#########################################################################################
_PASSWORD = "default_salt"
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Print the variable as a JSON-like representation for debugging purposes.
Args:
var (any): The variable to be printed.
print_errors (bool): A flag indicating whether to print errors during debugging.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Internal use only: Get AES cipher
#########################################################################################
def _get_cipher(
password: str = _PASSWORD
) -> AES:
'''
Internal use only: Get AES cipher for encryption and decryption.
Args:
password (str): The password used to derive the encryption key.
Returns:
AES: An AES cipher instance for encryption and decryption.
'''
key = b''
msg = password.encode('utf-8')
hash_obj = hmac.new(key, msg, hashlib.sha256)
hash_result = hash_obj.digest()
hash_base64 = base64.b64encode(hash_result)[:16].decode()
iv = b'0000000000000000'
return AES.new(hash_base64.encode(), AES.MODE_CBC, iv)
####
# Return encrypted string
#########################################################################################
def encrypt_AES(
str_to_encrypt: str = "",
password: str = _PASSWORD
) -> str:
'''
Encrypt a string using AES encryption.
Args:
str_to_encrypt (str): The string to be encrypted.
password (str): The password used to derive the encryption key.
Returns:
str: The encrypted string in base64 encoding.
'''
cipher = _get_cipher(password)
try:
msg_padded = pad(str_to_encrypt.encode(), AES.block_size, style='pkcs7')
cipher_text = cipher.encrypt(msg_padded)
b64str = base64.b64encode(cipher_text).decode()
except:
b64str = ''
return b64str
####
# Return decrypted string
#########################################################################################
def decrypt_AES(
str_to_decrypt: str = "",
password: str = _PASSWORD
) -> str:
'''
Decrypt an encrypted string using AES decryption.
Args:
str_to_decrypt (str): The encrypted string to be decrypted.
password (str): The password used to derive the encryption key.
Returns:
str: The decrypted string.
'''
cipher = _get_cipher(password)
try:
decrypted_str = unpad(cipher.decrypt(base64.b64decode(str_to_decrypt)), AES.block_size, style='pkcs7').decode().strip()
except:
decrypted_str = ''
return decrypted_str

View File

@ -0,0 +1,652 @@
import sys
from datetime import datetime
import hashlib
####
# Define some global variables
#########################################################################################
# Entity to character mapping. Contains a few tweaks to make it backward compatible with the previous safe_input implementation.
_ENT2CHR = {
'#x00': chr(0),
'#x01': chr(1),
'#x02': chr(2),
'#x03': chr(3),
'#x04': chr(4),
'#x05': chr(5),
'#x06': chr(6),
'#x07': chr(7),
'#x08': chr(8),
'#x09': chr(9),
'#x0a': chr(10),
'#x0b': chr(11),
'#x0c': chr(12),
'#x0d': chr(13),
'#x0e': chr(14),
'#x0f': chr(15),
'#x10': chr(16),
'#x11': chr(17),
'#x12': chr(18),
'#x13': chr(19),
'#x14': chr(20),
'#x15': chr(21),
'#x16': chr(22),
'#x17': chr(23),
'#x18': chr(24),
'#x19': chr(25),
'#x1a': chr(26),
'#x1b': chr(27),
'#x1c': chr(28),
'#x1d': chr(29),
'#x1e': chr(30),
'#x1f': chr(31),
'#x20': chr(32),
'quot': chr(34),
'amp': chr(38),
'#039': chr(39),
'#40': chr(40),
'#41': chr(41),
'lt': chr(60),
'gt': chr(62),
'#92': chr(92),
'#x80': chr(128),
'#x81': chr(129),
'#x82': chr(130),
'#x83': chr(131),
'#x84': chr(132),
'#x85': chr(133),
'#x86': chr(134),
'#x87': chr(135),
'#x88': chr(136),
'#x89': chr(137),
'#x8a': chr(138),
'#x8b': chr(139),
'#x8c': chr(140),
'#x8d': chr(141),
'#x8e': chr(142),
'#x8f': chr(143),
'#x90': chr(144),
'#x91': chr(145),
'#x92': chr(146),
'#x93': chr(147),
'#x94': chr(148),
'#x95': chr(149),
'#x96': chr(150),
'#x97': chr(151),
'#x98': chr(152),
'#x99': chr(153),
'#x9a': chr(154),
'#x9b': chr(155),
'#x9c': chr(156),
'#x9d': chr(157),
'#x9e': chr(158),
'#x9f': chr(159),
'#xa0': chr(160),
'#xa1': chr(161),
'#xa2': chr(162),
'#xa3': chr(163),
'#xa4': chr(164),
'#xa5': chr(165),
'#xa6': chr(166),
'#xa7': chr(167),
'#xa8': chr(168),
'#xa9': chr(169),
'#xaa': chr(170),
'#xab': chr(171),
'#xac': chr(172),
'#xad': chr(173),
'#xae': chr(174),
'#xaf': chr(175),
'#xb0': chr(176),
'#xb1': chr(177),
'#xb2': chr(178),
'#xb3': chr(179),
'#xb4': chr(180),
'#xb5': chr(181),
'#xb6': chr(182),
'#xb7': chr(183),
'#xb8': chr(184),
'#xb9': chr(185),
'#xba': chr(186),
'#xbb': chr(187),
'#xbc': chr(188),
'#xbd': chr(189),
'#xbe': chr(190),
'Aacute': chr(193),
'Auml': chr(196),
'Eacute': chr(201),
'Euml': chr(203),
'Iacute': chr(205),
'Iuml': chr(207),
'Ntilde': chr(209),
'Oacute': chr(211),
'Ouml': chr(214),
'Uacute': chr(218),
'Uuml': chr(220),
'aacute': chr(225),
'auml': chr(228),
'eacute': chr(233),
'euml': chr(235),
'iacute': chr(237),
'iuml': chr(239),
'ntilde': chr(241),
'oacute': chr(243),
'ouml': chr(246),
'uacute': chr(250),
'uuml': chr(252),
'OElig': chr(338),
'oelig': chr(339),
'Scaron': chr(352),
'scaron': chr(353),
'Yuml': chr(376),
'fnof': chr(402),
'circ': chr(710),
'tilde': chr(732),
'Alpha': chr(913),
'Beta': chr(914),
'Gamma': chr(915),
'Delta': chr(916),
'Epsilon': chr(917),
'Zeta': chr(918),
'Eta': chr(919),
'Theta': chr(920),
'Iota': chr(921),
'Kappa': chr(922),
'Lambda': chr(923),
'Mu': chr(924),
'Nu': chr(925),
'Xi': chr(926),
'Omicron': chr(927),
'Pi': chr(928),
'Rho': chr(929),
'Sigma': chr(931),
'Tau': chr(932),
'Upsilon': chr(933),
'Phi': chr(934),
'Chi': chr(935),
'Psi': chr(936),
'Omega': chr(937),
'alpha': chr(945),
'beta': chr(946),
'gamma': chr(947),
'delta': chr(948),
'epsilon': chr(949),
'zeta': chr(950),
'eta': chr(951),
'theta': chr(952),
'iota': chr(953),
'kappa': chr(954),
'lambda': chr(955),
'mu': chr(956),
'nu': chr(957),
'xi': chr(958),
'omicron': chr(959),
'pi': chr(960),
'rho': chr(961),
'sigmaf': chr(962),
'sigma': chr(963),
'tau': chr(964),
'upsilon': chr(965),
'phi': chr(966),
'chi': chr(967),
'psi': chr(968),
'omega': chr(969),
'thetasym': chr(977),
'upsih': chr(978),
'piv': chr(982),
'ensp': chr(8194),
'emsp': chr(8195),
'thinsp': chr(8201),
'zwnj': chr(8204),
'zwj': chr(8205),
'lrm': chr(8206),
'rlm': chr(8207),
'ndash': chr(8211),
'mdash': chr(8212),
'lsquo': chr(8216),
'rsquo': chr(8217),
'sbquo': chr(8218),
'ldquo': chr(8220),
'rdquo': chr(8221),
'bdquo': chr(8222),
'dagger': chr(8224),
'Dagger': chr(8225),
'bull': chr(8226),
'hellip': chr(8230),
'permil': chr(8240),
'prime': chr(8242),
'Prime': chr(8243),
'lsaquo': chr(8249),
'rsaquo': chr(8250),
'oline': chr(8254),
'frasl': chr(8260),
'euro': chr(8364),
'image': chr(8465),
'weierp': chr(8472),
'real': chr(8476),
'trade': chr(8482),
'alefsym': chr(8501),
'larr': chr(8592),
'uarr': chr(8593),
'rarr': chr(8594),
'darr': chr(8595),
'harr': chr(8596),
'crarr': chr(8629),
'lArr': chr(8656),
'uArr': chr(8657),
'rArr': chr(8658),
'dArr': chr(8659),
'hArr': chr(8660),
'forall': chr(8704),
'part': chr(8706),
'exist': chr(8707),
'empty': chr(8709),
'nabla': chr(8711),
'isin': chr(8712),
'notin': chr(8713),
'ni': chr(8715),
'prod': chr(8719),
'sum': chr(8721),
'minus': chr(8722),
'lowast': chr(8727),
'radic': chr(8730),
'prop': chr(8733),
'infin': chr(8734),
'ang': chr(8736),
'and': chr(8743),
'or': chr(8744),
'cap': chr(8745),
'cup': chr(8746),
'int': chr(8747),
'there4': chr(8756),
'sim': chr(8764),
'cong': chr(8773),
'asymp': chr(8776),
'ne': chr(8800),
'equiv': chr(8801),
'le': chr(8804),
'ge': chr(8805),
'sub': chr(8834),
'sup': chr(8835),
'nsub': chr(8836),
'sube': chr(8838),
'supe': chr(8839),
'oplus': chr(8853),
'otimes': chr(8855),
'perp': chr(8869),
'sdot': chr(8901),
'lceil': chr(8968),
'rceil': chr(8969),
'lfloor': chr(8970),
'rfloor': chr(8971),
'lang': chr(9001),
'rang': chr(9002),
'loz': chr(9674),
'spades': chr(9824),
'clubs': chr(9827),
'hearts': chr(9829),
'diams': chr(9830),
}
# Construct the character to entity mapping.
_CHR2ENT = {v: "&" + k + ";" for k, v in _ENT2CHR.items()}
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Print the variable as a JSON-like representation for debugging purposes.
Args:
var (any): The variable to be printed.
print_errors (bool): A flag indicating whether to print errors during debugging.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Convert the input_string encoded in html entity to clear char string.
#########################################################################################
def safe_input(
input_string: str = ""
) -> str:
'''
Convert an input string encoded in HTML entities to a clear character string.
Args:
input_string (str): The input string encoded in HTML entities.
Returns:
str: The decoded clear character string.
'''
if not input_string:
return ""
return "".join(_CHR2ENT.get(char, char) for char in input_string)
####
# Convert the html entities to input_string encoded to rebuild char string.
#########################################################################################
def safe_output(
input_string: str = ""
) -> str:
'''
Convert HTML entities back to their corresponding characters in the input string.
Args:
input_string (str): The input string containing HTML entities.
Returns:
str: The decoded clear character string.
'''
if not input_string:
return ""
for char, entity in _CHR2ENT.items():
input_string = input_string.replace(entity, char)
return input_string
####
# Assign to a key in a dict a given value.
#########################################################################################
def set_dict_key_value(
input_dict: dict = {},
input_key: str = "",
input_value = None
)-> None:
"""
Assign a given value to a specified key in a dictionary.
Args:
input_dict (dict): The dictionary to which the value will be assigned.
input_key (str): The key in the dictionary to which the value will be assigned.
input_value (any): The value to be assigned to the specified key.
Returns:
None
"""
key = input_key.strip()
if len(key) > 0:
input_dict[key] = input_value
####
# Return the value of a key in a given dict.
#########################################################################################
def get_dict_key_value(
input_dict: dict = {},
input_key: str = ""
)-> None:
"""
Return the value associated with a given key in a provided dictionary.
Args:
input_dict (dict): The dictionary to search for the key-value pair.
input_key (str): The key to look up in the dictionary.
Returns:
The value associated with the specified key, or None if the key is not found.
"""
key = input_key.strip()
if key in input_dict:
return input_dict[key]
else:
return None
####
# Return MD5 hash string.
#########################################################################################
def generate_md5(
input_string: str = ""
) -> str:
"""
Generates an MD5 hash for the given input string.
Args:
input_string (str): The string for which the MD5 hash will be generated.
Returns:
str: The MD5 hash of the input string as a hexadecimal string.
"""
try:
md5_hash = hashlib.md5(input_string.encode()).hexdigest()
except:
md5_hash = ""
return md5_hash
####
# Returns or print current time in date format or utimestamp.
#########################################################################################
def now(
utimestamp: bool = False,
print_flag: bool = False
) -> str:
"""
Get the current time in the specified format or as a Unix timestamp.
Args:
utimestamp (bool): Set to True to get the Unix timestamp (epoch time).
print_flag (bool): Set to True to print the time to standard output.
Returns:
str: The current time in the desired format or as a Unix timestamp.
"""
from .output import print_stdout
today = datetime.today()
if utimestamp:
time = datetime.timestamp(today)
else:
time = today.strftime('%Y/%m/%d %H:%M:%S')
if print_flag:
print_stdout(time)
return time
####
# Translate macros in string from a dict.
#########################################################################################
def translate_macros(
macro_dic: dict = {},
data: str = ""
) -> str:
"""
Replace macros in the input string with their corresponding values.
Args:
macro_dic (dict): A dictionary containing macro names and their corresponding values.
data (str): The input string in which macros should be replaced.
Returns:
str: The input string with macros replaced by their values.
"""
for macro_name, macro_value in macro_dic.items():
data = data.replace(macro_name, macro_value)
return data
####
# Parse configuration file line by line based on separator and return dict.
#########################################################################################
def parse_configuration(
file: str = "/etc/pandora/pandora_server.conf",
separator: str = " ",
default_values: dict = {}
) -> dict:
"""
Parse a configuration file and return its data as a dictionary.
Args:
file (str): The path to the configuration file. Defaults to "/etc/pandora/pandora_server.conf".
separator (str, optional): The separator between option and value. Defaults to " ".
default_values (dict, optional): A dictionary of default values. Defaults to an empty dictionary.
Returns:
dict: A dictionary containing all keys and values from the configuration file.
"""
from .output import print_stderr
config = {}
try:
with open (file, "r") as conf:
lines = conf.read().splitlines()
for line in lines:
if line.strip().startswith("#") or len(line.strip()) < 1 :
continue
else:
option, value = line.strip().split(separator, maxsplit=1)
config[option.strip()] = value.strip()
except Exception as e:
print_stderr(f"{type(e).__name__}: {e}")
for option, value in default_values.items():
if option.strip() not in config:
config[option.strip()] = value.strip()
return config
####
# Parse csv file line by line and return list.
#########################################################################################
def parse_csv_file(
file: str = "",
separator: str = ';',
count_parameters: int = 0,
print_errors: bool = False
) -> list:
"""
Parse a CSV configuration file and return its data in a list.
Args:
file (str): The path to the CSV configuration file.
separator (str, optional): The separator between values in the CSV. Defaults to ";".
count_parameters (int, optional): The minimum number of parameters each line should have. Defaults to 0.
print_errors (bool, optional): Set to True to print errors for lines with insufficient parameters. Defaults to False.
Returns:
list: A list containing lists of values for each line in the CSV.
"""
from .output import print_stderr
csv_arr = []
try:
with open (file, "r") as csv:
lines = csv.read().splitlines()
for line in lines:
if line.strip().startswith("#") or len(line.strip()) < 1 :
continue
else:
value = line.strip().split(separator)
if len(value) >= count_parameters:
csv_arr.append(value)
elif print_errors==True:
print_stderr(f'Csv line: {line} does not match minimun parameter defined: {count_parameters}')
except Exception as e:
print_stderr(f"{type(e).__name__}: {e}")
return csv_arr
####
# Parse given variable to integer.
#########################################################################################
def parse_int(
var = None
) -> int:
"""
Parse given variable to integer.
Args:
var (any): The variable to be parsed as an integer.
Returns:
int: The parsed integer value. If parsing fails, returns 0.
"""
try:
return int(var)
except:
return 0
####
# Parse given variable to float.
#########################################################################################
def parse_float(
var = None
) -> float:
"""
Parse given variable to float.
Args:
var (any): The variable to be parsed as an float.
Returns:
float: The parsed float value. If parsing fails, returns 0.
"""
try:
return float(var)
except:
return 0
####
# Parse given variable to string.
#########################################################################################
def parse_str(
var = None
) -> str:
"""
Parse given variable to string.
Args:
var (any): The variable to be parsed as an string.
Returns:
str: The parsed string value. If parsing fails, returns "".
"""
try:
return str(var)
except:
return ""
####
# Parse given variable to bool.
#########################################################################################
def parse_bool(
var = None
) -> bool:
"""
Parse given variable to bool.
Args:
var (any): The variable to be parsed as an bool.
Returns:
bool: The parsed bool value. If parsing fails, returns False.
"""
try:
return bool(var)
except:
return False

View File

@ -0,0 +1,113 @@
import urllib3
import warnings
from requests.sessions import Session
from requests_ntlm import HttpNtlmAuth
from requests.auth import HTTPBasicAuth
from requests.auth import HTTPDigestAuth
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Print the provided variable as JSON, supporting various data types.
Args:
var (any): The variable to be printed as JSON.
print_errors (bool): Set to True to print errors encountered during printing.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Internal: Auth URL session
#########################################################################################
def _auth_call(
session = None,
authtype: str = "basic",
user: str = "",
passw: str = ""
)-> None:
"""
Perform authentication for URL requests using various authentication types.
Args:
session (object, optional): The request Session() object. Defaults to None.
authtype (str, optional): The authentication type. Supported values: 'ntlm', 'basic', or 'digest'. Defaults to 'basic'.
user (str, optional): The authentication user. Defaults to an empty string.
passw (str, optional): The authentication password. Defaults to an empty string.
Returns:
None
"""
if session is not None:
if authtype == 'ntlm':
session.auth = HttpNtlmAuth(user, passw)
elif authtype == 'basic':
session.auth = HTTPBasicAuth(user, passw)
elif authtype == 'digest':
session.auth = HTTPDigestAuth(user, passw)
####
# Call URL and return output
#########################################################################################
def call_url(
url: str = "",
authtype: str = "basic",
user: str = "",
passw: str = "",
timeout: int = 1,
verify: bool = True,
print_errors: bool = False
) -> str:
"""
Call a URL and return its contents.
Args:
url (str): The URL to call.
authtype (str, optional): The authentication type. Supported values: 'ntlm', 'basic', 'digest'. Defaults to 'basic'.
user (str, optional): The authentication user. Defaults to an empty string.
passw (str, optional): The authentication password. Defaults to an empty string.
timeout (int, optional): The session timeout in seconds. Defaults to 1.
print_errors (bool, optional): Set to True to print errors encountered during the call. Defaults to False.
Returns:
str: The output from the URL call.
"""
from .output import print_stderr
if url == "":
if print_errors:
print_stderr("Error: URL not provided")
return None
else:
# using with so we make sure the session is closed even when exceptions are encountered
with Session() as session:
if authtype is not None:
_auth_call(session, authtype, user, passw)
output = ""
try:
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=urllib3.exceptions.InsecureRequestWarning)
response = session.get(url, timeout=timeout, verify=verify)
response.raise_for_status() # Raise an exception for non-2xx responses
return response.content
except requests.exceptions.Timeout:
if print_errors:
print_stderr("Error: Request timed out")
except requests.exceptions.RequestException as e:
if print_errors:
print_stderr(f"RequestException:\t{e}")
except ValueError:
if print_errors:
print_stderr("Error: URL format not valid (example http://myserver/page.php)")
return None

View File

@ -0,0 +1,330 @@
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Print the provided variable as JSON format, supporting various data types.
Args:
var (any, optional): The variable to be printed as JSON. Defaults to an empty string.
print_errors (bool, optional): Set to True to print errors encountered during printing. Defaults to False.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Init module template
#########################################################################################
def init_module(
default_values: dict = {}
) -> dict:
"""
Initializes a module template with default values.
Args:
default_values (dict, optional): Dictionary containing default values to override template values. Defaults to an empty dictionary.
Returns:
dict: Dictionary representing the module template with default values.
"""
module = {
"name" : None,
"type" : "generic_data_string",
"value" : "0",
"desc" : "",
"unit" : "",
"interval" : "",
"tags" : "",
"module_group" : "",
"module_parent" : "",
"min_warning" : "",
"min_warning_forced" : "",
"max_warning" : "",
"max_warning_forced" : "",
"min_critical" : "",
"min_critical_forced" : "",
"max_critical" : "",
"max_critical_forced" : "",
"str_warning" : "",
"str_warning_forced" : "",
"str_critical" : "",
"str_critical_forced" : "",
"critical_inverse" : "",
"warning_inverse" : "",
"max" : "",
"min" : "",
"post_process" : "",
"disabled" : "",
"min_ff_event" : "",
"status" : "",
"timestamp" : "",
"custom_id" : "",
"critical_instructions" : "",
"warning_instructions" : "",
"unknown_instructions" : "",
"quiet" : "",
"module_ff_interval" : "",
"crontab" : "",
"min_ff_event_normal" : "",
"min_ff_event_warning" : "",
"min_ff_event_critical" : "",
"ff_type" : "",
"ff_timeout" : "",
"each_ff" : "",
"module_parent_unlink" : "",
"alert" : []
}
for key, value in default_values.items():
if key in module:
module[key] = value
return module
####
# Returns module in XML format. Accepts only {dict}
#########################################################################################
def print_module(
module: dict = None,
print_flag: bool = False
) -> str:
"""
Returns module in XML format. Accepts only {dict}.
Args:
module (dict, optional): Dictionary containing module data. Defaults to None.
print_flag (bool, optional): Flag to print the module XML to STDOUT. Defaults to False.
Returns:
str: Module data in XML format.
"""
from .output import print_stdout
module_xml = ""
if module is not None:
data = dict(module)
module_xml = ("<module>\n"
"\t<name><![CDATA[" + str(data["name"]) + "]]></name>\n"
"\t<type>" + str(data["type"]) + "</type>\n"
)
if type(data["type"]) is not str and "string" not in data["type"]: #### Strip spaces if module not generic_data_string
data["value"] = data["value"].strip()
if isinstance(data["value"], list): # Checks if value is a list
module_xml += "\t<datalist>\n"
for value in data["value"]:
if type(value) is dict and "value" in value:
module_xml += "\t<data>\n"
module_xml += "\t\t<value><![CDATA[" + str(value["value"]) + "]]></value>\n"
if "timestamp" in value:
module_xml += "\t\t<timestamp><![CDATA[" + str(value["timestamp"]) + "]]></timestamp>\n"
module_xml += "\t</data>\n"
module_xml += "\t</datalist>\n"
else:
module_xml += "\t<data><![CDATA[" + str(data["value"]) + "]]></data>\n"
if "desc" in data and len(str(data["desc"]).strip()) > 0:
module_xml += "\t<description><![CDATA[" + str(data["desc"]) + "]]></description>\n"
if "unit" in data and len(str(data["unit"]).strip()) > 0:
module_xml += "\t<unit><![CDATA[" + str(data["unit"]) + "]]></unit>\n"
if "interval" in data and len(str(data["interval"]).strip()) > 0:
module_xml += "\t<module_interval><![CDATA[" + str(data["interval"]) + "]]></module_interval>\n"
if "tags" in data and len(str(data["tags"]).strip()) > 0:
module_xml += "\t<tags>" + str(data["tags"]) + "</tags>\n"
if "module_group" in data and len(str(data["module_group"]).strip()) > 0:
module_xml += "\t<module_group>" + str(data["module_group"]) + "</module_group>\n"
if "module_parent" in data and len(str(data["module_parent"]).strip()) > 0:
module_xml += "\t<module_parent>" + str(data["module_parent"]) + "</module_parent>\n"
if "min_warning" in data and len(str(data["min_warning"]).strip()) > 0:
module_xml += "\t<min_warning><![CDATA[" + str(data["min_warning"]) + "]]></min_warning>\n"
if "min_warning_forced" in data and len(str(data["min_warning_forced"]).strip()) > 0:
module_xml += "\t<min_warning_forced><![CDATA[" + str(data["min_warning_forced"]) + "]]></min_warning_forced>\n"
if "max_warning" in data and len(str(data["max_warning"]).strip()) > 0:
module_xml += "\t<max_warning><![CDATA[" + str(data["max_warning"]) + "]]></max_warning>\n"
if "max_warning_forced" in data and len(str(data["max_warning_forced"]).strip()) > 0:
module_xml += "\t<max_warning_forced><![CDATA[" + str(data["max_warning_forced"]) + "]]></max_warning_forced>\n"
if "min_critical" in data and len(str(data["min_critical"]).strip()) > 0:
module_xml += "\t<min_critical><![CDATA[" + str(data["min_critical"]) + "]]></min_critical>\n"
if "min_critical_forced" in data and len(str(data["min_critical_forced"]).strip()) > 0:
module_xml += "\t<min_critical_forced><![CDATA[" + str(data["min_critical_forced"]) + "]]></min_critical_forced>\n"
if "max_critical" in data and len(str(data["max_critical"]).strip()) > 0:
module_xml += "\t<max_critical><![CDATA[" + str(data["max_critical"]) + "]]></max_critical>\n"
if "max_critical_forced" in data and len(str(data["max_critical_forced"]).strip()) > 0:
module_xml += "\t<max_critical_forced><![CDATA[" + str(data["max_critical_forced"]) + "]]></max_critical_forced>\n"
if "str_warning" in data and len(str(data["str_warning"]).strip()) > 0:
module_xml += "\t<str_warning><![CDATA[" + str(data["str_warning"]) + "]]></str_warning>\n"
if "str_warning_forced" in data and len(str(data["str_warning_forced"]).strip()) > 0:
module_xml += "\t<str_warning_forced><![CDATA[" + str(data["str_warning_forced"]) + "]]></str_warning_forced>\n"
if "str_critical" in data and len(str(data["str_critical"]).strip()) > 0:
module_xml += "\t<str_critical><![CDATA[" + str(data["str_critical"]) + "]]></str_critical>\n"
if "str_critical_forced" in data and len(str(data["str_critical_forced"]).strip()) > 0:
module_xml += "\t<str_critical_forced><![CDATA[" + str(data["str_critical_forced"]) + "]]></str_critical_forced>\n"
if "critical_inverse" in data and len(str(data["critical_inverse"]).strip()) > 0:
module_xml += "\t<critical_inverse><![CDATA[" + str(data["critical_inverse"]) + "]]></critical_inverse>\n"
if "warning_inverse" in data and len(str(data["warning_inverse"]).strip()) > 0:
module_xml += "\t<warning_inverse><![CDATA[" + str(data["warning_inverse"]) + "]]></warning_inverse>\n"
if "max" in data and len(str(data["max"]).strip()) > 0:
module_xml += "\t<max><![CDATA[" + str(data["max"]) + "]]></max>\n"
if "min" in data and len(str(data["min"]).strip()) > 0:
module_xml += "\t<min><![CDATA[" + str(data["min"]) + "]]></min>\n"
if "post_process" in data and len(str(data["post_process"]).strip()) > 0:
module_xml += "\t<post_process><![CDATA[" + str(data["post_process"]) + "]]></post_process>\n"
if "disabled" in data and len(str(data["disabled"]).strip()) > 0:
module_xml += "\t<disabled><![CDATA[" + str(data["disabled"]) + "]]></disabled>\n"
if "min_ff_event" in data and len(str(data["min_ff_event"]).strip()) > 0:
module_xml += "\t<min_ff_event><![CDATA[" + str(data["min_ff_event"]) + "]]></min_ff_event>\n"
if "status" in data and len(str(data["status"]).strip()) > 0:
module_xml += "\t<status><![CDATA[" + str(data["status"]) + "]]></status>\n"
if "timestamp" in data and len(str(data["timestamp"]).strip()) > 0:
module_xml += "\t<timestamp><![CDATA[" + str(data["timestamp"]) + "]]></timestamp>\n"
if "custom_id" in data and len(str(data["custom_id"]).strip()) > 0:
module_xml += "\t<custom_id><![CDATA[" + str(data["custom_id"]) + "]]></custom_id>\n"
if "critical_instructions" in data and len(str(data["critical_instructions"]).strip()) > 0:
module_xml += "\t<critical_instructions><![CDATA[" + str(data["critical_instructions"]) + "]]></critical_instructions>\n"
if "warning_instructions" in data and len(str(data["warning_instructions"]).strip()) > 0:
module_xml += "\t<warning_instructions><![CDATA[" + str(data["warning_instructions"]) + "]]></warning_instructions>\n"
if "unknown_instructions" in data and len(str(data["unknown_instructions"]).strip()) > 0:
module_xml += "\t<unknown_instructions><![CDATA[" + str(data["unknown_instructions"]) + "]]></unknown_instructions>\n"
if "quiet" in data and len(str(data["quiet"]).strip()) > 0:
module_xml += "\t<quiet><![CDATA[" + str(data["quiet"]) + "]]></quiet>\n"
if "module_ff_interval" in data and len(str(data["module_ff_interval"]).strip()) > 0:
module_xml += "\t<module_ff_interval><![CDATA[" + str(data["module_ff_interval"]) + "]]></module_ff_interval>\n"
if "crontab" in data and len(str(data["crontab"]).strip()) > 0:
module_xml += "\t<crontab><![CDATA[" + str(data["crontab"]) + "]]></crontab>\n"
if "min_ff_event_normal" in data and len(str(data["min_ff_event_normal"]).strip()) > 0:
module_xml += "\t<min_ff_event_normal><![CDATA[" + str(data["min_ff_event_normal"]) + "]]></min_ff_event_normal>\n"
if "min_ff_event_warning" in data and len(str(data["min_ff_event_warning"]).strip()) > 0:
module_xml += "\t<min_ff_event_warning><![CDATA[" + str(data["min_ff_event_warning"]) + "]]></min_ff_event_warning>\n"
if "min_ff_event_critical" in data and len(str(data["min_ff_event_critical"]).strip()) > 0:
module_xml += "\t<min_ff_event_critical><![CDATA[" + str(data["min_ff_event_critical"]) + "]]></min_ff_event_critical>\n"
if "ff_type" in data and len(str(data["ff_type"]).strip()) > 0:
module_xml += "\t<ff_type><![CDATA[" + str(data["ff_type"]) + "]]></ff_type>\n"
if "ff_timeout" in data and len(str(data["ff_timeout"]).strip()) > 0:
module_xml += "\t<ff_timeout><![CDATA[" + str(data["ff_timeout"]) + "]]></ff_timeout>\n"
if "each_ff" in data and len(str(data["each_ff"]).strip()) > 0:
module_xml += "\t<each_ff><![CDATA[" + str(data["each_ff"]) + "]]></each_ff>\n"
if "module_parent_unlink" in data and len(str(data["module_parent_unlink"]).strip()) > 0:
module_xml += "\t<module_parent_unlink><![CDATA[" + str(data["module_parent_unlink"]) + "]]></module_parent_unlink>\n"
if "alert" in data:
for alert in data["alert"]:
if len(str(alert).strip()) > 0:
module_xml += "\t<alert_template><![CDATA[" + str(alert) + "]]></alert_template>\n"
module_xml += "</module>\n"
if print_flag:
print_stdout(module_xml)
return module_xml
####
# Init log module template
#########################################################################################
def init_log_module(
default_values: dict = {}
) -> dict:
"""
Initializes a log module template with default values.
Args:
default_values (dict, optional): Default values to initialize the log module with. Defaults to an empty dictionary.
Returns:
dict: Dictionary representing the log module template with default values.
"""
module = {
"source" : None,
"value" : ""
}
for key, value in default_values.items():
if key in module:
module[key] = value
return module
####
# Returns log module in XML format. Accepts only {dict}
#########################################################################################
def print_log_module(
module: dict = None,
print_flag: bool = False
) -> str:
"""
Returns log module in XML format. Accepts only {dict}.
- Only works with one module at a time: otherwise iteration is needed.
- Module "value" field accepts str type.
- Use not_print_flag to avoid printing the XML (only populates variables).
Args:
module (dict, optional): Dictionary representing the log module. Defaults to None.
print_flag (bool, optional): Flag to indicate whether to print the XML. Defaults to False.
Returns:
str: XML representation of the log module.
"""
from .output import print_stdout
module_xml = ""
if module is not None:
data = dict(module)
module_xml = ("<log_module>\n"
"\t<source><![CDATA[" + str(data["source"]) + "]]></source>\n"
"\t<data>\"" + str(data["value"]) + "\"</data>\n"
)
module_xml += "</log_module>\n"
if print_flag:
print_stdout(module_xml)
return module_xml

View File

@ -0,0 +1,137 @@
import sys
import os
import json
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Prints any list, dict, string, float or integer as a json
Args:
var (any, optional): Variable to be printed. Defaults to "".
print_errors (bool, optional): Flag to indicate whether to print errors. Defaults to False.
"""
print_debug(var, print_errors)
####
# Prints message in stdout
#########################################################################################
def print_stdout(
message: str = ""
)-> None:
"""
Prints message in stdout
Args:
message (str, optional): Message to be printed. Defaults to "".
Returns:
None
"""
print(message)
####
# Prints message in stderr
#########################################################################################
def print_stderr(
message: str = ""
)-> None:
"""
Prints message in stderr
Args:
message (str, optional): Message to be printed. Defaults to "".
Returns:
None
"""
print(message, file=sys.stderr)
####
# Prints dictionary in formatted json string.
#########################################################################################
def print_debug(
var = "",
print_errors: bool = False
)-> None:
"""
Prints any list, dict, string, float or integer as a json
Args:
var: Variable to be printed.
print_errors (bool, optional): Whether to print errors. Defaults to False.
Returns:
None
"""
try:
debug_json = json.dumps(var, indent=4)
print_stdout(debug_json)
except json.JSONDecodeError as e:
if print_errors:
print_stderr(f"debug_dict: Failed to dump. Error: {e}")
except Exception as e:
if print_errors:
print_stderr(f"debug_dict: Unexpected error: {e}")
####
# Add new line to log file
#########################################################################################
def logger(
log_file: str = "",
message: str = "",
log_level: str = "",
add_date: bool = True,
print_errors: bool = False
) -> bool:
'''
Add new line to log file
Args:
log_file (str): Path to the log file.
message (str): Message to be added to the log.
log_level (str): Log level, if applicable. Defaults to an empty string.
add_date (bool): Whether to add the current date and time to the log entry. Defaults to True.
print_errors (bool): Whether to print errors. Defaults to False.
Returns:
bool: True if the log entry was successfully added, False otherwise.
'''
from .general import now
try:
if not os.path.exists(log_file):
with open(log_file, 'w') as file:
pass # Creates an empty file
elif not os.access(log_file, os.W_OK):
if print_errors:
print_stderr(f"Log file '{log_file}' is not writable.")
return False
with open(log_file, 'a') as file:
final_message = ""
if add_date:
final_message += now() + " "
if log_level != "":
final_message += "[" + log_level + "] "
final_message += message + "\n"
file.write(final_message)
return True
except Exception as e:
if print_errors:
print_stderr(f"An error occurred while appending to the log: {e}")
return False

View File

@ -0,0 +1,330 @@
from easysnmp import Session
from pysnmp.hlapi import *
####
# Define global variables dict, used in functions as default values.
# Its values can be changed.
#########################################################################################
_GLOBAL_VARIABLES = {
'hostname' : "",
'version' : 1,
'community' : "public",
'user' : "",
'auth_protocol' : "",
'auth_password' : "",
'privacy_protocol' : "",
'privacy_password' : "",
'security_level' : "noAuthNoPriv",
'timeout' : 2,
'retries' : 1,
'remote_port' : 161,
}
####
# Set a global variable with the specified name and assigns a value to it.
#########################################################################################
def set_global_variable(
variable_name: str = "",
value = None
)-> None:
"""
Sets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
value (any): Value to assign to the variable.
Returns:
None
"""
from .general import set_dict_key_value
set_dict_key_value(_GLOBAL_VARIABLES, variable_name, value)
####
# Get a global variable with the specified name.
#########################################################################################
def get_global_variable(
variable_name: str = ""
)-> None:
"""
Gets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
Returns:
None
"""
from .general import get_dict_key_value
get_dict_key_value(_GLOBAL_VARIABLES, variable_name)
####
# A class that represents an SNMP target, providing methods for setting up SNMP configuration and performing SNMP operations like GET and WALK.
#########################################################################################
class SNMPTarget:
"""
A class that represents an SNMP target, providing methods for setting up SNMP configuration
and performing SNMP operations like GET and WALK.
"""
def __init__(
self,
host: str = _GLOBAL_VARIABLES['hostname'],
version: int = _GLOBAL_VARIABLES['version'],
community: str = _GLOBAL_VARIABLES['community'],
user: str = _GLOBAL_VARIABLES['user'],
auth_protocol: str = _GLOBAL_VARIABLES['auth_protocol'],
auth_password: str = _GLOBAL_VARIABLES['auth_password'],
privacy_protocol: str = _GLOBAL_VARIABLES['privacy_protocol'],
privacy_password: str = _GLOBAL_VARIABLES['privacy_password'],
security_level: str = _GLOBAL_VARIABLES['security_level'],
timeout: int = _GLOBAL_VARIABLES['timeout'],
retries: int = _GLOBAL_VARIABLES['retries'],
remote_port: int = _GLOBAL_VARIABLES['remote_port']):
self.session = create_snmp_session(
host,
version,
community,
user,
auth_protocol,
auth_password,
privacy_protocol,
privacy_password,
security_level,
timeout,
retries,
remote_port
)
####
# Performs an SNMP GET operation to retrieve the value of a specified OID.
#########################################################################################
def snmp_get(self, oid):
"""
Performs an SNMP GET operation to retrieve the value of a specified OID.
Args:
oid (str): The OID (Object Identifier) for the SNMP GET operation.
Returns:
str: The value retrieved from the specified OID.
"""
return self.session.get(oid).value
####
# Performs an SNMP WALK operation to retrieve a list of values from a subtree of the MIB.
#########################################################################################
def snmp_walk(self, oid):
"""
Performs an SNMP WALK operation to retrieve a list of values from a subtree of the MIB.
Args:
oid (str): The OID (Object Identifier) representing the root of the subtree.
Returns:
list: A list of values retrieved from the specified subtree.
"""
oid_items = self.session.walk(oid)
oid_value_dict = {} # Initialize an empty dictionary
for item in oid_items:
oid_with_index = f"{item.oid}.{item.oid_index}"
oid_value_dict[oid_with_index] = item.value
return oid_value_dict
####
# Creates an SNMP session based on the global configuration variables.
#########################################################################################
def create_snmp_session(
host: str = _GLOBAL_VARIABLES['hostname'],
version: int = _GLOBAL_VARIABLES['version'],
community: str = _GLOBAL_VARIABLES['community'],
user: str = _GLOBAL_VARIABLES['user'],
auth_protocol: str = _GLOBAL_VARIABLES['auth_protocol'],
auth_password: str = _GLOBAL_VARIABLES['auth_password'],
privacy_protocol: str = _GLOBAL_VARIABLES['privacy_protocol'],
privacy_password: str = _GLOBAL_VARIABLES['privacy_password'],
security_level: str = _GLOBAL_VARIABLES['security_level'],
timeout: int = _GLOBAL_VARIABLES['timeout'],
retries: int = _GLOBAL_VARIABLES['retries'],
remote_port: int = _GLOBAL_VARIABLES['remote_port']
) -> Session:
"""
Creates an SNMP session based on the provided configuration or global variables.
Args:
hostname (str): Hostname or IP address of the SNMP agent.
version (int): SNMP version (1, 2, or 3).
community (str): SNMP community string (for version 1 or 2).
user (str): SNMPv3 username (for version 3).
auth_protocol (str): SNMPv3 authentication protocol (e.g., 'MD5' or 'SHA').
auth_password (str): SNMPv3 authentication password.
privacy_protocol (str): SNMPv3 privacy protocol (e.g., 'AES' or 'DES').
privacy_password (str): SNMPv3 privacy password.
security_level (str): SNMPv3 security level ('noAuthNoPriv', 'authNoPriv', 'authPriv').
timeout (int): SNMP request timeout in seconds.
retries (int): Number of SNMP request retries.
remote_port (int): SNMP agent port.
Returns:
Session: An SNMP session configured based on the provided or global variables.
"""
session_kwargs = {
"hostname": host,
"version": version,
"use_numeric": True,
"timeout": timeout,
"retries": retries,
"remote_port": remote_port
}
if version == 1 or version == 2:
session_kwargs["community"] = community
elif version == 3:
session_kwargs["security_username"] = user
if security_level == "authPriv":
session_kwargs.update({
"auth_protocol": auth_protocol,
"auth_password": auth_password,
"privacy_protocol": privacy_protocol,
"privacy_password": privacy_password,
"security_level": "auth_with_privacy"
})
elif security_level == "authNoPriv":
session_kwargs.update({
"auth_protocol": auth_protocol,
"auth_password": auth_password,
"security_level": "auth_without_privacy"
})
elif security_level == "noAuthNoPriv":
session_kwargs["security_level"] = "no_auth_or_privacy"
return Session(**session_kwargs)
####
# Performs an SNMP GET operation to retrieve the value of a specified OID.
#########################################################################################
def snmp_get(
oid: str,
host: str = _GLOBAL_VARIABLES['hostname'],
version: int = _GLOBAL_VARIABLES['version'],
community: str = _GLOBAL_VARIABLES['community'],
user: str = _GLOBAL_VARIABLES['user'],
auth_protocol: str = _GLOBAL_VARIABLES['auth_protocol'],
auth_password: str = _GLOBAL_VARIABLES['auth_password'],
privacy_protocol: str = _GLOBAL_VARIABLES['privacy_protocol'],
privacy_password: str = _GLOBAL_VARIABLES['privacy_password'],
security_level: str = _GLOBAL_VARIABLES['security_level'],
timeout: int = _GLOBAL_VARIABLES['timeout'],
retries: int = _GLOBAL_VARIABLES['retries'],
remote_port: int = _GLOBAL_VARIABLES['remote_port']
) -> str:
"""
Performs an SNMP GET operation to retrieve the value of a specified OID.
Args:
oid (str): The OID (Object Identifier) for the SNMP GET operation.
Returns:
str: The value retrieved from the specified OID.
"""
session = create_snmp_session(host,version,community,user,auth_protocol,auth_password,privacy_protocol,privacy_password,security_level,timeout,retries,remote_port)
return session.get(oid).value
####
# Performs an SNMP WALK operation to retrieve a list of values from a subtree of the MIB.
#########################################################################################
def snmp_walk(
oid: str,
host: str = _GLOBAL_VARIABLES['hostname'],
version: int = _GLOBAL_VARIABLES['version'],
community: str = _GLOBAL_VARIABLES['community'],
user: str = _GLOBAL_VARIABLES['user'],
auth_protocol: str = _GLOBAL_VARIABLES['auth_protocol'],
auth_password: str = _GLOBAL_VARIABLES['auth_password'],
privacy_protocol: str = _GLOBAL_VARIABLES['privacy_protocol'],
privacy_password: str = _GLOBAL_VARIABLES['privacy_password'],
security_level: str = _GLOBAL_VARIABLES['security_level'],
timeout: int = _GLOBAL_VARIABLES['timeout'],
retries: int = _GLOBAL_VARIABLES['retries'],
remote_port: int = _GLOBAL_VARIABLES['remote_port']
) -> dict:
"""
Performs an SNMP WALK operation to retrieve a list of values from a subtree of the MIB.
Args:
oid (str): The OID (Object Identifier) representing the root of the subtree.
Returns:
list: A list of values retrieved from the specified subtree.
"""
session = create_snmp_session(host,version,community,user,auth_protocol,auth_password,privacy_protocol,privacy_password,security_level,timeout,retries,remote_port)
oid_items = session.walk(oid)
oid_value_dict = {}
for item in oid_items:
oid_with_index = f"{item.oid}.{item.oid_index}"
oid_value_dict[oid_with_index] = item.value
return oid_value_dict
####
# Sends an SNMP trap to the specified destination IP using the given OID, value, and community.
#########################################################################################
def snmp_trap(
trap_oid: str,
trap_value: str,
destination_ip: str,
community: str) -> None:
"""
Sends an SNMP trap to the specified destination IP using the given OID, value, and community.
Args:
trap_oid (str): The OID (Object Identifier) for the SNMP trap.
trap_value (str): The value associated with the trap.
destination_ip (str): The IP address of the trap's destination.
community (str): The SNMP community string for authentication.
Returns:
None
"""
trap_object = ObjectIdentity(trap_oid)
trap_value = OctetString(trap_value)
errorIndication, errorStatus, errorIndex, varBinds = next(
sendNotification(
SnmpEngine(),
CommunityData(community),
UdpTransportTarget((destination_ip, 162)),
ContextData(),
'trap',
NotificationType(
ObjectIdentity('SNMPv2-MIB', 'coldStart')
).addVarBinds(
(trap_object, trap_value)
)
)
)
if errorIndication:
print('Error:', errorIndication)
elif errorStatus:
print(
'%s at %s' %
(
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex) - 1][0] or '?'
)
)
else:
print('SNMP trap sent successfully.')

View File

@ -0,0 +1,249 @@
import sys
from queue import Queue
from threading import Thread
from multiprocessing import Pool, Manager
####
# Define multi-processing internal global variables.
#########################################################################################
_MANAGER = Manager()
_SHARED_DICT = _MANAGER.dict()
_SHARED_DICT_LOCK = _MANAGER.Lock()
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Prints the provided variable in a JSON-like format.
Args:
var: The variable (list, dict, string, float, integer) to be printed.
print_errors (bool): If True, prints any errors that occur during formatting.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Internal use only: Run a given function in a thread
#########################################################################################
def _single_thread(
q = None,
function: callable = None,
errors: list = []
):
"""
Internal use only: Runs a given function in a thread.
Args:
q: A queue from which to get parameters for the function.
function (callable): The function to be executed in the thread.
errors (list): A list to store any errors encountered during execution.
"""
params=q.get()
q.task_done()
try:
function(params)
except Exception as e:
errors.append("Error while runing single thread: "+str(e))
####
# Run a given function for given items list in a given number of threads
#########################################################################################
def run_threads(
max_threads: int = 1,
function: callable = None,
items: list = [],
print_errors: bool = False
) -> bool:
"""
Run a given function for a list of items in multiple threads.
Args:
max_threads (int): Maximum number of threads to use.
function (callable): The function to be executed in each thread.
items (list): List of items to process.
print_errors (bool): Whether to print errors encountered during execution.
Returns:
bool: True if all threads executed successfully, False otherwise.
"""
from .output import print_stderr
# Assign threads
threads = max_threads
if threads > len(items):
threads = len(items)
if threads < 1:
threads = 1
# Distribute items per thread
items_per_thread = []
thread = 0
for item in items:
if not 0 <= thread < len(items_per_thread):
items_per_thread.append([])
items_per_thread[thread].append(item)
thread += 1
if thread >= threads:
thread=0
# Run threads
try:
q=Queue()
for n_thread in range(threads) :
q.put(items_per_thread[n_thread])
run_threads = []
errors = []
for n_thread in range(threads):
t = Thread(target=_single_thread, args=(q, function, errors))
t.daemon=True
t.start()
run_threads.append(t)
for t in run_threads:
t.join()
q.join()
if print_errors:
for error in errors:
print_stderr(str(error))
if len(errors) > 0:
return False
else:
return True
except Exception as e:
if print_errors:
print_stderr("Error while running threads: "+str(e))
return False
####
# Set a given value to a key in the internal shared dict.
# Used by all parallel processes.
#########################################################################################
def set_shared_dict_value(
key: str = None,
value = None
)-> None:
"""
Set a value for a key in the internal shared dictionary.
This function is used by all parallel processes.
Args:
key (str): The key in the shared dictionary.
value: The value to be assigned to the key.
"""
global _SHARED_DICT
if key is not None:
with _SHARED_DICT_LOCK:
_SHARED_DICT[key] = value
####
# Add a given value to a key in the internal shared dict.
# Used by all parallel processes.
#########################################################################################
def add_shared_dict_value(
key: str = None,
value = None
)-> None:
"""
Add a value to a key in the internal shared dictionary.
This function is used by all parallel processes.
Args:
key (str): The key in the shared dictionary.
value: The value to be added to the key.
"""
global _SHARED_DICT
if key is not None:
with _SHARED_DICT_LOCK:
if key in _SHARED_DICT:
_SHARED_DICT[key] += value
else:
set_shared_dict_value(key, value)
####
# Get the value of a key in the internal shared dict.
# Used by all parallel processes.
#########################################################################################
def get_shared_dict_value(
key: str = None
):
"""
Get the value of a key in the internal shared dictionary.
This function is used by all parallel processes.
Args:
key (str): The key in the shared dictionary.
Returns:
The value associated with the key, or None if the key does not exist.
"""
global _SHARED_DICT
with _SHARED_DICT_LOCK:
if key in _SHARED_DICT and key is not None:
return _SHARED_DICT[key]
else:
return None
####
# Run a given function for given items list in a given number of processes
# Given function receives each item as first parameter
#########################################################################################
def run_processes(
max_processes: int = 1,
function: callable = None,
items: list = [],
print_errors: bool = False
) -> bool:
"""
Run a given function for given items list in a given number of processes
Args:
max_processes (int): The maximum number of processes to run in parallel.
function (callable): The function to be executed for each item.
items (list): List of items to be processed.
print_errors (bool): Whether to print errors.
Returns:
bool: True if all processes completed successfully, False otherwise.
"""
from .output import print_stderr
# Assign processes
processes = max_processes
if processes > len(items):
processes = len(items)
if processes < 1:
processes = 1
# Run processes
with Pool(processes) as pool:
try:
pool.map(function, items)
result = True
except Exception as error:
if print_errors:
print_stderr(str(error))
result = False
return result

View File

@ -0,0 +1,258 @@
from datetime import datetime
from subprocess import *
import shutil
import subprocess
import os
import sys
####
# Define global variables dict, used in functions as default values.
# Its values can be changed.
#########################################################################################
_GLOBAL_VARIABLES = {
'transfer_mode' : 'tentacle',
'temporal' : '/tmp',
'data_dir' : '/var/spool/pandora/data_in/',
'tentacle_client' : 'tentacle_client',
'tentacle_ip' : '127.0.0.1',
'tentacle_port' : 41121,
'tentacle_extra_opts' : '',
'tentacle_retries' : 1
}
####
# Internal: Alias for output.print_debug function
#########################################################################################
def _print_debug(
var = "",
print_errors: bool = False
):
"""
Prints any list, dict, string, float or integer as a json
Args:
var: The variable to be printed.
print_errors (bool): Whether to print errors.
"""
from .output import print_debug
print_debug(var, print_errors)
####
# Set a global variable with the specified name and assigns a value to it.
#########################################################################################
def set_global_variable(
variable_name: str = "",
value = None
)-> None:
"""
Sets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
value (any): Value to assign to the variable.
Returns:
None
"""
from .general import set_dict_key_value
set_dict_key_value(_GLOBAL_VARIABLES, variable_name, value)
####
# Get a global variable with the specified name.
#########################################################################################
def get_global_variable(
variable_name: str = ""
)-> None:
"""
Gets the value of a global variable in the '_GLOBAL_VARIABLES' dictionary.
Args:
variable_name (str): Name of the variable to set.
Returns:
None
"""
from .general import get_dict_key_value
get_dict_key_value(_GLOBAL_VARIABLES, variable_name)
####
# Sends file using tentacle protocol
#########################################################################################
def tentacle_xml(
data_file: str = "",
tentacle_ops: dict = {},
tentacle_path: str = _GLOBAL_VARIABLES['tentacle_client'],
retry: bool = False,
debug: int = 0,
print_errors: bool = True
) -> bool:
"""
Sends file using tentacle protocol
Args:
data_file (str): Path to the data file to be sent.
tentacle_ops (dict): Tentacle options as a dictionary (address [password] [port]).
tentacle_path (str): Custom path for the tentacle client executable.
retry (bool): Whether to retry sending the file if it fails.
debug (int): Debug mode flag. If enabled (1), the data file will not be removed after sending.
print_errors (bool): Whether to print error messages.
Returns:
bool: True for success, False for errors.
"""
from .output import print_stderr
if data_file is not None :
if not 'address' in tentacle_ops:
tentacle_ops['address'] = _GLOBAL_VARIABLES['tentacle_ip']
if not 'port' in tentacle_ops:
tentacle_ops['port'] = _GLOBAL_VARIABLES['tentacle_port']
if not 'extra_opts' in tentacle_ops:
tentacle_ops['extra_opts'] = _GLOBAL_VARIABLES['tentacle_extra_opts']
if tentacle_ops['address'] is None :
if print_errors:
print_stderr("Tentacle error: No address defined")
return False
try :
with open(data_file.strip(), 'r') as data:
data.read()
data.close()
except Exception as e :
if print_errors:
print_stderr(f"Tentacle error: {type(e).__name__} {e}")
return False
tentacle_cmd = f"{tentacle_path} -v -a {tentacle_ops['address']} -p {tentacle_ops['port']} {tentacle_ops['extra_opts']} {data_file.strip()}"
tentacle_exe=subprocess.Popen(tentacle_cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
rc=tentacle_exe.wait()
result = True
if rc != 0 :
if retry:
tentacle_retries = _GLOBAL_VARIABLES['tentacle_retries']
if tentacle_retries < 1:
tentacle_retries = 1
retry_count = 0
while retry_count < tentacle_retries :
tentacle_exe=subprocess.Popen(tentacle_cmd, stdout=subprocess.PIPE,stderr=subprocess.PIPE, shell=True)
rc=tentacle_exe.wait()
if rc == 0:
break
if print_errors:
stderr = tentacle_exe.stderr.read().decode()
msg = f"Tentacle error (Retry {retry_count + 1}/{tentacle_retries}): {stderr}"
print_stderr(str(datetime.today().strftime('%Y-%m-%d %H:%M')) + msg)
retry_count += 1
if retry_count >= tentacle_retries:
result = False
else:
if print_errors:
stderr = tentacle_exe.stderr.read().decode()
msg="Tentacle error:" + str(stderr)
print_stderr(str(datetime.today().strftime('%Y-%m-%d %H:%M')) + msg)
result = False
if debug == 0 :
os.remove(data_file.strip())
return result
else:
if print_errors:
print_stderr("Tentacle error: file path is required.")
return False
####
# Detect transfer mode and send XML.
#########################################################################################
def transfer_xml(
file: str = "",
transfer_mode: str = _GLOBAL_VARIABLES['transfer_mode'],
tentacle_ip: str = _GLOBAL_VARIABLES['tentacle_ip'],
tentacle_port: int = _GLOBAL_VARIABLES['tentacle_port'],
tentacle_extra_opts: str = _GLOBAL_VARIABLES['tentacle_extra_opts'],
data_dir: str = _GLOBAL_VARIABLES['data_dir']
)-> None:
"""
Detects the transfer mode and calls the agentplugin() function to perform the transfer.
Args:
file (str): Path to file to send.
transfer_mode (str, optional): Transfer mode. Default is _GLOBAL_VARIABLES['transfer_mode'].
tentacle_ip (str, optional): IP address for Tentacle. Default is _GLOBAL_VARIABLES['tentacle_ip'].
tentacle_port (str, optional): Port for Tentacle. Default is _GLOBAL_VARIABLES['tentacle_port'].
data_dir (str, optional): Path to data dir with local transfer mode. Default is _GLOBAL_VARIABLES['data_dir'].
Returns:
None
"""
if file is not None:
if transfer_mode != "local":
tentacle_conf = {
'address' : tentacle_ip,
'port' : tentacle_port,
'extra_opts' : tentacle_extra_opts
}
tentacle_xml(file, tentacle_conf)
else:
shutil.move(file, data_dir)
####
# Creates a agent .data file in the specified data_dir folder
#########################################################################################
def write_xml(
xml: str = "",
agent_name: str = "",
data_dir: str = _GLOBAL_VARIABLES['temporal'],
print_errors: bool = False
) -> str:
"""
Creates an agent .data file in the specified data_dir folder
Args:
xml (str): XML string to be written in the file.
agent_name (str): Agent name for the XML and file name.
data_dir (str): Folder in which the file will be created.
print_errors (bool): Whether to print error messages.
Returns:
str: Path to the created .data file.
"""
from .general import generate_md5
from .output import print_stderr
Utime = datetime.now().strftime('%s')
agent_name_md5 = generate_md5(agent_name)
data_file = "%s/%s.%s.data" %(str(data_dir),agent_name_md5,str(Utime))
try:
with open(data_file, 'x') as data:
data.write(xml)
except OSError as o:
if print_errors:
print_stderr(f"ERROR - Could not write file: {o}, please check directory permissions")
except Exception as e:
if print_errors:
print_stderr(f"{type(e).__name__}: {e}")
return data_file

View File

@ -45,8 +45,8 @@ our @EXPORT = qw(
); );
# version: Defines actual version of Pandora Server for this module only # version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.773"; my $pandora_version = "7.0NG.773.1";
my $pandora_build = "230821"; my $pandora_build = "230822";
our $VERSION = $pandora_version." ".$pandora_build; our $VERSION = $pandora_version." ".$pandora_build;
# Setup hash # Setup hash

View File

@ -2058,6 +2058,8 @@ sub PandoraFMS::Recon::Base::report_scanned_agents($;$) {
'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist#' 'index.php?sec=gservers&sec2=godmode/servers/discovery&wiz=tasklist#'
); );
$notification->{'subtype'} .= safe_input('NOTIF.DISCOVERYTASK.REVIEW');
$notification->{'mensaje'} = safe_input( $notification->{'mensaje'} = safe_input(
'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'}) 'Discovery task (host&devices) \''.safe_output($self->{'task_data'}{'name'})
.'\' has been completed. Please review the results.' .'\' has been completed. Please review the results.'

View File

@ -33,8 +33,8 @@ use base 'Exporter';
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
# version: Defines actual version of Pandora Server for this module only # version: Defines actual version of Pandora Server for this module only
my $pandora_version = "7.0NG.773"; my $pandora_version = "7.0NG.773.1";
my $pandora_build = "230821"; my $pandora_build = "230822";
our $VERSION = $pandora_version." ".$pandora_build; our $VERSION = $pandora_version." ".$pandora_build;
our %EXPORT_TAGS = ( 'all' => [ qw() ] ); our %EXPORT_TAGS = ( 'all' => [ qw() ] );

View File

@ -3,8 +3,8 @@
# #
%global __os_install_post %{nil} %global __os_install_post %{nil}
%define name pandorafms_server %define name pandorafms_server
%define version 7.0NG.773 %define version 7.0NG.773.1
%define release 230821 %define release 230822
Summary: Pandora FMS Server Summary: Pandora FMS Server
Name: %{name} Name: %{name}

View File

@ -8,8 +8,8 @@
# This code is licensed under GPL 2.0 license. # This code is licensed under GPL 2.0 license.
# ********************************************************************** # **********************************************************************
PI_VERSION="7.0NG.773" PI_VERSION="7.0NG.773.1"
PI_BUILD="230821" PI_BUILD="230822"
MODE=$1 MODE=$1
if [ $# -gt 1 ]; then if [ $# -gt 1 ]; then

View File

@ -35,7 +35,7 @@ use PandoraFMS::Config;
use PandoraFMS::DB; use PandoraFMS::DB;
# version: define current version # version: define current version
my $version = "7.0NG.773 Build 230821"; my $version = "7.0NG.773.1 Build 230822";
# Pandora server configuration # Pandora server configuration
my %conf; my %conf;
@ -769,8 +769,8 @@ sub pandora_checkdb_integrity {
# Delete orphan data from visual console. # Delete orphan data from visual console.
log_message ('INTEGRITY', "Deleting orphan visual console items."); log_message ('INTEGRITY', "Deleting orphan visual console items.");
db_do ($dbh, 'DELETE FROM tlayout_data WHERE id_agent NOT IN (SELECT id_agente FROM tagente)'); db_do ($dbh, 'DELETE FROM tlayout_data WHERE id_agent <> 0 AND id_agent NOT IN (SELECT id_agente FROM tagente)');
db_do ($dbh, 'DELETE FROM tlayout_data WHERE id_agente_modulo NOT IN (SELECT id_agente_modulo FROM tagente_modulo)'); db_do ($dbh, 'DELETE FROM tlayout_data WHERE id_agente_modulo <> 0 AND id_agente_modulo NOT IN (SELECT id_agente_modulo FROM tagente_modulo)');
# Delete orphan data form deleted agents. # Delete orphan data form deleted agents.
# Clearl orphan data from dashboards # Clearl orphan data from dashboards

View File

@ -36,7 +36,7 @@ use Encode::Locale;
Encode::Locale::decode_argv; Encode::Locale::decode_argv;
# version: define current version # version: define current version
my $version = "7.0NG.773 Build 230821"; my $version = "7.0NG.773.1 Build 230822";
# save program name for logging # save program name for logging
my $progname = basename($0); my $progname = basename($0);