WIP discovery F3

Former-commit-id: 19570468cf4de9f600ab9a01468d1e59c69e6939
This commit is contained in:
fbsanchez 2019-04-03 18:13:19 +02:00
parent 11b2fbc245
commit 798a2aad16
11 changed files with 292 additions and 52 deletions

View File

@ -1,11 +1,12 @@
START TRANSACTION;
ALTER TABLE `trecon_script` ADD COLUMN `type` int NOT NULL default 0;
ALTER TABLE `trecon_task` ADD COLUMN `type` int NOT NULL default 0;
UPDATE `trecon_script` SET `type` = 1 WHERE `name`="Discovery.Application.VMware";
UPDATE `trecon_script` SET `type` = 2 WHERE `name`="Discovery.Cloud";
UPDATE `trecon_script` SET `type` = 3 WHERE `name` LIKE "IPAM%Recon";
UPDATE `trecon_script` SET `type` = 4 WHERE `name` LIKE "IPMI%Recon";
UPDATE trecon_script SET `type` = 1 WHERE `name`="Discovery.Application.VMware";
UPDATE trecon_script SET `type` = 2 WHERE `name`="Discovery.Application.MySQL";
UPDATE trecon_script SET `type` = 3 WHERE `name`="Discovery.Application.Oracle";
UPDATE trecon_script SET `type` = 100 WHERE `name`="Discovery.Cloud";
UPDATE trecon_script SET `type` = 101 WHERE `name`="Discovery.Cloud.RDS";
COMMIT;

View File

@ -464,15 +464,30 @@ class DiscoveryTaskList extends Wizard
}
if ($task['id_recon_script'] == 0) {
// Discovery NetScan.
$data[6] = html_print_image(
'images/network.png',
true,
['title' => __('Discovery NetScan')]
).'  ';
$data[6] .= network_profiles_get_name(
$task['id_network_profile']
);
switch ($task['type']) {
case DISCOVERY_APP_MYSQL:
// Discovery Applications MySQL.
$data[6] = html_print_image(
'images/network.png',
true,
['title' => __('Discovery Applications MySQL')]
).'  ';
$data[6] .= __('Discovery.App.MySQL');
break;
case DISCOVERY_HOSTDEVICES:
default:
// Discovery NetScan.
$data[6] = html_print_image(
'images/network.png',
true,
['title' => __('Discovery NetScan')]
).'  ';
$data[6] .= network_profiles_get_name(
$task['id_network_profile']
);
break;
}
} else {
// APP recon task.
$data[6] = html_print_image(
@ -612,12 +627,14 @@ class DiscoveryTaskList extends Wizard
*/
public function getTargetWiz($task)
{
// TODO: Do not use description. Use recon_script ID instead.
switch ($task['description']) {
case 'Discovery.Application.VMware':
switch ($task['type']) {
case DISCOVERY_APP_MYSQL:
return 'wiz=app&mode=mysql&page=0';
case DISCOVERY_APP_VMWARE:
return 'wiz=app&mode=vmware&page=0';
case CLOUDWIZARD_AWS_DESCRIPTION:
case DISCOVERY_CLOUD_AWS:
return 'wiz=cloud&mode=amazonws&page=1';
case 'console_task':

View File

@ -595,12 +595,10 @@ define('DISCOVERY_CLOUD_AWS_RDS', 7);
define('DISCOVERY_SCRIPT_HOSTDEVICES_CUSTOM', 0);
// Standard applications.
define('DISCOVERY_SCRIPT_APP_VMWARE', 1);
define('DISCOVERY_SCRIPT_APP_MYSQL', 2);
define('DISCOVERY_SCRIPT_APP_ORACLE', 3);
// Cloud environments.
define('DISCOVERY_SCRIPT_CLOUD_AWS', 100);
define('DISCOVERY_SCRIPT_CLOUD_AWS_EC2', 101);
define('DISCOVERY_SCRIPT_CLOUD_AWS_RDS', 102);
define('DISCOVERY_SCRIPT_CLOUD_AWS', 2);
define('DISCOVERY_SCRIPT_IPAM_RECON', 3);
define('DISCOVERY_SCRIPT_IPMI_RECON', 4);
// Discovery task descriptions.
define('CLOUDWIZARD_AWS_DESCRIPTION', 'Discovery.Cloud.AWS.EC2');

View File

@ -16,8 +16,10 @@ ul.wizard li > label:not(.p-switch) {
}
ul.wizard li > textarea {
width: 250px;
width: 600px;
height: 15em;
display: inline-block;
font-family: monospace;
}
.hidden {

View File

@ -786,6 +786,7 @@ CREATE TABLE IF NOT EXISTS `trecon_task` (
`auth_strings` text,
`autoconfiguration_enabled` tinyint(1) unsigned default '0',
`summary` text,
`type` int NOT NULL default 0,
PRIMARY KEY (`id_rt`),
KEY `recon_task_daemon` (`id_recon_server`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -1135,9 +1135,10 @@ INSERT INTO `treport_custom_sql` (`id`, `name`, `sql`) VALUES (3, 'Monitoring&#x
INSERT INTO `treport_custom_sql` (`id`, `name`, `sql`) VALUES (4, 'Group view', 'select t1.nombre, (select count(t3.id_agente) from tagente as t3 where t1.id_grupo = t3.id_grupo) as agents, (SELECT COUNT(t4.id_agente) FROM tagente as t4 WHERE t4.id_grupo = t1.id_grupo AND t4.disabled = 0 AND t4.ultimo_contacto < NOW() - (intervalo / (1/2))) as agent_unknown, (SELECT COUNT(tagente_estado.id_agente_estado) FROM tagente_estado, tagente, tagente_modulo WHERE tagente.id_grupo = t1.id_grupo AND tagente.disabled = 0 AND tagente.id_agente = tagente_estado.id_agente AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND tagente_modulo.disabled = 0 AND utimestamp > 0 AND tagente_modulo.id_tipo_modulo NOT IN(21,22,23,24,100) AND (UNIX_TIMESTAMP(NOW()) - tagente_estado.utimestamp) >= (tagente_estado.current_interval / (1/2))) as monitor_unknow, (SELECT COUNT(tagente_estado.id_agente_estado) FROM tagente_estado, tagente, tagente_modulo WHERE tagente.id_grupo = t1.id_grupo AND tagente.disabled = 0 AND tagente.id_agente = tagente_estado.id_agente AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND tagente_modulo.disabled = 0 AND tagente_modulo.id_tipo_modulo NOT IN (21,22,23,24) AND utimestamp = 0) as monitor_no_init, (SELECT COUNT(tagente_estado.id_agente_estado) FROM tagente_estado, tagente, tagente_modulo WHERE tagente.id_grupo = t1.id_grupo AND tagente.disabled = 0 AND tagente_estado.id_agente = tagente.id_agente AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND tagente_modulo.disabled = 0 AND estado = 0 AND ((UNIX_TIMESTAMP(NOW()) - tagente_estado.utimestamp) < (tagente_estado.current_interval / (1/2)) OR (tagente_modulo.id_tipo_modulo IN(21,22,23,24,100))) AND (utimestamp > 0 OR (tagente_modulo.id_tipo_modulo IN(21,22,23,24)))) as monitor_ok, (SELECT COUNT(tagente_estado.id_agente_estado) FROM tagente_estado, tagente, tagente_modulo WHERE tagente.id_grupo = t1.id_grupo AND tagente.disabled = 0 AND tagente_estado.id_agente = tagente.id_agente AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND tagente_modulo.disabled = 0 AND estado = 1 AND ((UNIX_TIMESTAMP(NOW()) - tagente_estado.utimestamp) < (tagente_estado.current_interval / (1/2)) OR (tagente_modulo.id_tipo_modulo IN(21,22,23,24,100))) AND utimestamp > 0) as monitor_critical, (SELECT COUNT(talert_template_modules.id) FROM talert_template_modules, tagente_modulo, tagente_estado, tagente WHERE tagente.id_grupo = t1.id_grupo AND tagente_modulo.id_agente = tagente.id_agente AND tagente_estado.id_agente_modulo = tagente_modulo.id_agente_modulo AND tagente_modulo.disabled = 0 AND tagente.disabled = 0 AND talert_template_modules.id_agent_module = tagente_modulo.id_agente_modulo AND times_fired > 0) as monitor_alert_fired from tgrupo as t1 where 0 < (select count(t2.id_agente) from tagente as t2 where t1.id_grupo = t2.id_grupo)');
-- trecon scripts
INSERT INTO `trecon_script` (`type`,`name`,`description`,`script`,`macros`) VALUES (0, 'IPMI Recon','Specific Pandora FMS Intel DCM Discovery (c) Artica ST 2011 <info@artica.es>

Usage: ./ipmi-recon.pl <task_id> <group_id> <create_incident_flag> <custom_field1> <custom_field2> <custom_field3> <custom_field4>

* custom_field1 = Network i.e.: 192.168.100.0/24
* custom_field2 = Username
* custom_field3 = Password
* custom_field4 = Additional parameters i.e.: -D LAN_2_0','/usr/share/pandora_server/util/recon_scripts/ipmi-recon.pl','{\"1\":{\"macro\":\"_field1_\",\"desc\":\"Network\",\"help\":\"i.e.: 192.168.100.0/24\",\"value\":\"\",\"hide\":\"\"},\"2\":{\"macro\":\"_field2_\",\"desc\":\"Username\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"},\"3\":{\"macro\":\"_field3_\",\"desc\":\"Password\",\"help\":\"\",\"value\":\"\",\"hide\":\"1\"},\"4\":{\"macro\":\"_field4_\",\"desc\":\"Additional parameters\",\"help\":\"Optional additional parameters such as -D LAN_2_0 to use IPMI ver 2.0 instead of 1.5.  These options will also be passed to the IPMI plugin when the current values are read.\",\"value\":\"\",\"hide\":\"\"}}');
INSERT INTO `trecon_script` (`type`,`name`,`description`,`script`,`macros`) VALUES (1, 'Discovery.Application.VMware', 'Discovery Application script to monitor VMware technologies (ESXi, VCenter, VSphere)', '/usr/share/pandora_server/util/recon_scripts/vmware-plugin.pl', '{"1":{"macro":"_field1_","desc":"Configuration file","help":"","value":"","hide":""}}');
INSERT INTO `trecon_script` (`type`,`name`,`description`,`script`,`macros`) VALUES (100,'Discovery.Cloud', 'Discovery Cloud script to monitor Cloud technologies (AWS.EC2, AWS.S3, AWS.RDS,&#x20RDS,&#x20AWS.EKS)', '/usr/share/pandora_server/util/recon_scripts/pcm_client.pl', '{"1":{"macro":"_field1_","desc":"Configuration file","help":"","value":"","hide":""}}');
INSERT INTO `trecon_script` (`type`,`name`,`description`,`script`,`macros`) VALUES (2, 'Discovery.Cloud', 'Discovery Cloud script to monitor Cloud technologies (AWS.EC2, AWS.S3, AWS.RDS,&#x20RDS,&#x20AWS.EKS)', '/usr/share/pandora_server/util/recon_scripts/pcm_client.pl', '{"1":{"macro":"_field1_","desc":"Configuration file","help":"","value":"","hide":""}}');
-- IPAM is 3.
INSERT INTO `trecon_script` (`type`,`name`,`description`,`script`,`macros`) VALUES (4, 'IPMI Recon','Specific Pandora FMS Intel DCM Discovery (c) Artica ST 2011 <info@artica.es>

Usage: ./ipmi-recon.pl <task_id> <group_id> <create_incident_flag> <custom_field1> <custom_field2> <custom_field3> <custom_field4>

* custom_field1 = Network i.e.: 192.168.100.0/24
* custom_field2 = Username
* custom_field3 = Password
* custom_field4 = Additional parameters i.e.: -D LAN_2_0','/usr/share/pandora_server/util/recon_scripts/ipmi-recon.pl','{\"1\":{\"macro\":\"_field1_\",\"desc\":\"Network\",\"help\":\"i.e.: 192.168.100.0/24\",\"value\":\"\",\"hide\":\"\"},\"2\":{\"macro\":\"_field2_\",\"desc\":\"Username\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"},\"3\":{\"macro\":\"_field3_\",\"desc\":\"Password\",\"help\":\"\",\"value\":\"\",\"hide\":\"1\"},\"4\":{\"macro\":\"_field4_\",\"desc\":\"Additional parameters\",\"help\":\"Optional additional parameters such as -D LAN_2_0 to use IPMI ver 2.0 instead of 1.5.  These options will also be passed to the IPMI plugin when the current values are read.\",\"value\":\"\",\"hide\":\"\"}}');
INSERT INTO `tplugin` (`id`, `name`, `description`, `max_timeout`, `execute`, `plugin_type`, `macros`, `parameters`) VALUES (1,'IPMI Plugin','Plugin to get IPMI monitors from a IPMI Device.',0,'/usr/share/pandora_server/util/plugin/ipmi-plugin.pl',0,'{\"1\":{\"macro\":\"_field1_\",\"desc\":\"Target IP\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"},\"2\":{\"macro\":\"_field2_\",\"desc\":\"Username\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"},\"3\":{\"macro\":\"_field3_\",\"desc\":\"Password\",\"help\":\"\",\"value\":\"\",\"hide\":\"true\"},\"4\":{\"macro\":\"_field4_\",\"desc\":\"Sensor\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"},\"5\":{\"macro\":\"_field5_\",\"desc\":\"Additional Options\",\"help\":\"\",\"value\":\"\",\"hide\":\"\"}}','-h _field1_ -u _field2_ -p _field3_ -s _field4_ -- _field5_');

View File

@ -150,6 +150,9 @@ sub data_consumer ($$) {
my ($self, $task_id) = @_;
my ($pa_config, $dbh) = ($self->getConfig (), $self->getDBH ());
# Get server id.
my $server_id = get_server_id($dbh, $pa_config->{'servername'}, $self->getServerType());
# Get recon task data
my $task = get_db_single_row ($dbh, 'SELECT * FROM trecon_task WHERE id_rt = ?', $task_id);
return -1 unless defined ($task);
@ -201,7 +204,9 @@ sub data_consumer ($$) {
auth_strings_array => \@auth_strings,
autoconfiguration_enabled => $task->{'autoconfiguration_enabled'},
main_event_id => $main_event,
%{$pa_config}
server_id => $server_id,
%{$pa_config},
task_data => $task
);
$recon->scan();
@ -413,6 +418,93 @@ sub PandoraFMS::Recon::Base::connect_agents($$$$$) {
}
}
##########################################################################
# Create agents from db_scan.
# data = [
# 'agent_data' => {},
# 'module_data' => []
# ]
##########################################################################
sub PandoraFMS::Recon::Base::create_agents($$) {
my ($self, $data) = @_;
my $pa_config = $self->{'pa_config'};
my $dbh = $self->{'dbh'};
my $server_id = $self->{'server_id'};
return undef if (ref($data) ne "ARRAY");
foreach my $information (@{$data}) {
my $agent = $information->{'agent_data'};
my $modules = $information->{'module_data'};
my $force_processing = 0;
# Search agent
my $current_agent = PandoraFMS::Core::locate_agent(
$pa_config, $dbh, $agent->{'agent_name'}
);
my $parent_id;
if (defined($agent->{'parent_agent'})) {
$parent_id = PandoraFMS::Core::locate_agent(
$pa_config, $dbh, $agent->{'parent_agent'}
);
}
my $agent_id;
if (!$current_agent) {
# Create agent.
$agent_id = pandora_create_agent(
$pa_config, $pa_config->{'servername'}, $agent->{'agent_name'},
$agent->{'address'}, $agent->{'id_group'}, $parent_id,
$agent->{'os'}, $agent->{'description'}, $agent->{'interval'},
$dbh, $agent->{'timezone_offset'}
);
$current_agent = $parent_id = PandoraFMS::Core::locate_agent(
$pa_config, $dbh, $agent->{'agent_name'}
);
$force_processing = 1;
} else {
$agent_id = $current_agent->{'id_agente'};
}
if (!defined($agent_id)) {
return undef;
}
if ($agent->{'address'} ne '') {
pandora_add_agent_address(
$pa_config, $agent_id, $agent->{'agent_name'},
$agent->{'address'}, $dbh
);
}
# Update agent information
pandora_update_agent(
$pa_config, time(), $agent_id,
$agent->{'os_version'}, $agent->{'agent_version'},
$agent->{'interval'}, $dbh, undef, $parent_id
);
# Add modules.
if (ref($modules) eq "ARRAY") {
foreach my $module (@{$modules}) {
pandora_process_module(
$pa_config, {'data' => $module->{'value'}}, $current_agent, $module,
$module->{'type'}, '', time(), $server_id, $dbh
);
}
}
}
}
##########################################################################
# Create an agent for the given device. Returns the ID of the new (or
# existing) agent, undef on error.

View File

@ -0,0 +1 @@
/tmp/pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/Recon/Applications

View File

@ -20,7 +20,16 @@ use constant {
STEP_SCANNING => 1,
STEP_AFT => 2,
STEP_TRACEROUTE => 3,
STEP_GATEWAY => 4
STEP_GATEWAY => 4,
STEP_STATISTICS => 1,
STEP_DATABASE_SCAN => 2,
STEP_CUSTOM_QUERIES => 3,
DISCOVERY_HOSTDEVICES => 0,
DISCOVERY_HOSTDEVICES_CUSTOM => 1,
DISCOVERY_CLOUD_AWS => 2,
DISCOVERY_APP_VMWARE => 3,
DISCOVERY_APP_MYSQL => 4,
DISCOVERY_APP_ORACLE => 5
};
# /dev/null
@ -1417,6 +1426,83 @@ sub scan_subnet($) {
}
}
##########################################################################
# Perform a DB scan.
##########################################################################
sub db_scan($) {
my ($self) = @_;
my ($progress, $step);
my $type = '';
if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL) {
$type = 'MySQL';
} elsif ($self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
$type = 'Oracle';
} else {
# Unrecognized task type.
call('message', 'Unrecognized task type', 1);
$self->call('update_progress', -1);
return;
}
# Connect to target.
my $dbObj = PandoraFMS::Recon::Util::enterprise_new(
'PandoraFMS::Recon::Applications::'.$type,
$self->{'task_data'}
);
if (!defined($dbObj)) {
call('message', 'Cannot connect to target ' .'', 3);
$self->call('update_progress', -1);
return;
}
my @modules;
# Analyze.
$self->{'step'} = STEP_STATISTICS;
$self->{'c_network_name'} = $dbObj->get_host();
$self->call('update_progress', 10);
# Retrieve connection statistics.
# Retrieve uptime statistics
# Retrieve query stats
# Retrieve connections
# Retrieve innodb
# Retrieve cache
push @modules, $dbObj->get_statistics();
$self->call('update_progress', 50);
# Custom queries.
push @modules, $dbObj->execute_custom_queries();
$self->call('update_progress', 90);
my $data = [
{
'agent_data' => {
'agent_name' => $dbObj->get_agent_name(),
'os' => $type,
'os_version' => 'Discovery',
'interval' => $self->{'task_data'}->{'interval_sweep'},
'id_group' => $self->{'task_data'}->{'id_group'},
'address' => $dbObj->get_host(),
},
'module_data' => \@modules,
}
];
$self->call('create_agents', $data);
# Update progress.
# Done!
$self->{'step'} = '';
$self->call('update_progress', -1);
}
##########################################################################
# Perform a network scan.
##########################################################################
@ -1427,6 +1513,14 @@ sub scan($) {
# 1%
$self->call('update_progress', 1);
if (defined($self->{'task_data'})) {
if ($self->{'task_data'}->{'type'} == DISCOVERY_APP_MYSQL
|| $self->{'task_data'}->{'type'} == DISCOVERY_APP_ORACLE) {
# Database scan.
return $self->db_scan();
}
}
# Find devices.
$self->call('message', "[1/5] Scanning the network...", 3);
$self->{'step'} = STEP_SCANNING;

View File

@ -0,0 +1 @@
/tmp/pandora_enterprise/pandora_server/PandoraFMS-Enterprise/lib/PandoraFMS/Recon/Cloud

View File

@ -12,16 +12,47 @@ use lib '/usr/lib/perl5';
use Socket qw/inet_aton/;
our @ISA = ("Exporter");
our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
our %EXPORT_TAGS = ( 'all' => [qw( )] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
ip_to_long
mac_matches
mac_to_dec
parse_mac
subnet_matches
enterprise_new
ip_to_long
mac_matches
mac_to_dec
parse_mac
subnet_matches
);
########################################################################################
# Return an Enterprise Recon object.
########################################################################################
sub enterprise_new($$) {
my ($class, $arguments) = @_;
my @args;
if (ref($arguments) eq "HASH") {
@args = %{$arguments};
}
if (ref($arguments) eq "ARRAY") {
@args = @{$arguments};
}
# Try to load the module
if ($^O eq 'MSWin32') {
# If the Windows service dies the service is stopped, even inside an eval ($RUN is set to 0)!
eval 'local $SIG{__DIE__}; require '.$class.';';
}else {
eval 'require '.$class.';';
}
if ($@) {
# Not loaded.
return undef;
}
return new $class(@args);
}
########################################################################################
# Return the numeric representation of the given IP address.
########################################################################################
@ -35,13 +66,13 @@ sub ip_to_long($) {
# Returns 1 if the two given MAC addresses are the same.
########################################################################################
sub mac_matches($$) {
my ($mac_1, $mac_2) = @_;
my ($mac_1, $mac_2) = @_;
if (parse_mac($mac_1) eq parse_mac($mac_2)) {
return 1;
}
if (parse_mac($mac_1) eq parse_mac($mac_2)) {
return 1;
}
return 0;
return 0;
}
########################################################################################
@ -53,7 +84,7 @@ sub mac_to_dec($) {
my $dec_mac = '';
my @elements = split(/:/, $mac);
foreach my $element (@elements) {
$dec_mac .= unpack('s', pack 's', hex($element)) . '.'
$dec_mac .= unpack('s', pack 's', hex($element)) . '.';
}
chop($dec_mac);
@ -64,23 +95,23 @@ sub mac_to_dec($) {
# Make sure all MAC addresses are in the same format (00 11 22 33 44 55 66).
########################################################################################
sub parse_mac($) {
my ($mac) = @_;
my ($mac) = @_;
# Remove leading and trailing whitespaces.
$mac =~ s/(^\s+)|(\s+$)//g;
# Remove leading and trailing whitespaces.
$mac =~ s/(^\s+)|(\s+$)//g;
# Replace whitespaces and dots with colons.
$mac =~ s/\s+|\./:/g;
# Replace whitespaces and dots with colons.
$mac =~ s/\s+|\./:/g;
# Convert hex digits to uppercase.
$mac =~ s/([a-f])/\U$1/g;
# Convert hex digits to uppercase.
$mac =~ s/([a-f])/\U$1/g;
# Add a leading 0 to single digits.
$mac =~ s/^([0-9A-F]):/0$1:/g;
$mac =~ s/:([0-9A-F]):/:0$1:/g;
$mac =~ s/:([0-9A-F])$/:0$1/g;
# Add a leading 0 to single digits.
$mac =~ s/^([0-9A-F]):/0$1:/g;
$mac =~ s/:([0-9A-F]):/:0$1:/g;
$mac =~ s/:([0-9A-F])$/:0$1/g;
return $mac;
return $mac;
}
########################################################################################
@ -95,6 +126,7 @@ sub subnet_matches($$;$) {
$netaddr = $subnet;
$netmask = ip_to_long($mask);
}
# CIDR notation.
else {
($netaddr, $netmask) = split('/', $subnet);