diff --git a/centreon/plugins/backend/ssh/libssh.pm b/centreon/plugins/backend/ssh/libssh.pm new file mode 100644 index 000000000..d0cfc8aeb --- /dev/null +++ b/centreon/plugins/backend/ssh/libssh.pm @@ -0,0 +1,181 @@ +# +# Copyright 2020 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::plugins::backend::ssh::libssh; + +use strict; +use warnings; + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{noptions}) || $options{noptions} != 1) { + $options{options}->add_options(arguments => { + 'libssh-strict-connect' => { name => 'libssh_strict_connect' } + }); + $options{options}->add_help(package => __PACKAGE__, sections => 'BACKEND LIBSSH OPTIONS', once => 1); + } + + $self->{connected} = 0; + $self->{output} = $options{output}; + return $self; +} + +sub check_options { + my ($self, %options) = @_; + + centreon::plugins::misc::mymodule_load( + output => $self->{output}, + module => 'Libssh::Session', + error_msg => "Cannot load module 'Libssh::Session'." + ); + centreon::plugins::misc::mymodule_load( + output => $self->{output}, + module => 'centreon::plugins::backend::ssh::libsshconstants', + error_msg => "Cannot load module 'centreon::plugins::backend::ssh::libsshconstants'." + ); + $self->{constant_cb} = \¢reon::plugins::backend::ssh::libsshconstants::get_constant_value; + + if (!defined($self->{ssh})) { + $self->{ssh} = Libssh::Session->new(); + } + + $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; + $self->{ssh}->options(port => $self->{ssh_port}); + $self->{ssh_username} = $options{option_results}->{ssh_username}; + $self->{ssh_password} = $options{option_results}->{ssh_password}; + + $self->{ssh}->options(identity => $options{option_results}->{ssh_priv_key}) + if (defined($options{option_results}->{ssh_priv_key}) && $options{option_results}->{ssh_priv_key} ne ''); + $self->{ssh}->options(user => $options{option_results}->{ssh_username}) + if (defined($options{option_results}->{ssh_username}) && $options{option_results}->{ssh_username} ne ''); + $self->{ssh_strict_connect} = defined($options{option_results}->{libssh_strict_connect}) ? 1 : 0; +} + +sub connect { + my ($self, %options) = @_; + + return if ($self->{connected} == 1); + + if ($self->{ssh}->connect(SkipKeyProblem => $self->{ssh_strict_connect}) != $self->{constant_cb}->(name => 'SSH_OK')) { + $self->{output}->add_option_msg(short_msg => 'connect issue: ' . $self->{ssh}->error()); + $self->{output}->option_exit(); + } + + if ($self->{ssh}->auth_publickey_auto() != $self->{constant_cb}->(name => 'SSH_AUTH_SUCCESS')) { + if (defined($self->{ssh_username}) && $self->{ssh_username} ne '' && + defined($self->{ssh_password}) && $self->{ssh_password} ne '' && + $self->{ssh}->auth_password(password => $self->{ssh_password}) != $self->{constant_cb}->(name => 'SSH_AUTH_SUCCESS')) { + my $msg_error = $self->{ssh}->error(GetErrorSession => 1); + $self->{output}->add_option_msg(short_msg => sprintf("auth issue: %s", defined($msg_error) && $msg_error ne '' ? $msg_error : 'pubkey issue')); + $self->{output}->option_exit(); + } + } + + $self->{connected} = 1; +} + +sub execute { + my ($self, %options) = @_; + + if (defined($options{timeout}) && $options{timeout} =~ /(\d+)/) { + $self->{ssh}->options(timeout => $options{timeout}); + } + $self->connect(); + + my $cmd = ''; + $cmd = 'sudo ' if (defined($options{sudo})); + $cmd .= $options{command_path} . '/' if (defined($options{command_path})); + $cmd .= $options{command} . ' ' if (defined($options{command})); + $cmd .= $options{command_options} if (defined($options{command_options})); + + my $ret; + if (defined($options{ssh_pipe})) { + $ret = $self->{ssh}->execute_simple( + input_data => $cmd, + timeout => $options{timeout}, + timeout_nodata => $options{timeout} + ); + } else { + $ret = $self->{ssh}->execute_simple( + cmd => $cmd, + timeout => $options{timeout}, + timeout_nodata => $options{timeout} + ); + } + + my ($content, $exit_code); + if ($ret->{exit} == $self->{constant_cb}->(name => 'SSH_OK')) { + $content = $ret->{stdout}; + $exit_code = $ret->{exit_code}; + } elsif ($ret->{exit} == $self->{constant_cb}->(name => 'SSH_AGAIN')) { # AGAIN means timeout + $self->{output}->output_add(long_msg => $ret->{stdout}, debug => 1); + $self->{output}->output_add(long_msg => $ret->{stderr}, debug => 1); + $self->{output}->add_option_msg(short_msg => sprintf('command execution timeout')); + $self->{output}->option_exit(); + } else { + $self->{output}->add_option_msg(short_msg => + sprintf( + 'command execution error: %s', + $ret->{session}->error(GetErrorSession => 1) + ) + ); + $self->{output}->option_exit(); + } + + if ($exit_code != 0) { + $self->{output}->output_add(long_msg => $ret->{stdout}, debug => 1); + $self->{output}->output_add(long_msg => $ret->{stderr}, debug => 1); + $self->{output}->add_option_msg(short_msg => sprintf('command execution error [exit code: %s]', $exit_code)); + $self->{output}->option_exit(); + } + + return ($content, $exit_code); +} + +1; + +__END__ + +=head1 NAME + +libssh backend. + +=head1 SYNOPSIS + +libssh backend. + +=head1 BACKEND LIBSSH OPTIONS + +=over 8 + +=item B<--libssh-strict-connect> + +Connection won't be OK even if there is a problem (server known changed or server found other) with the ssh server. + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon/plugins/backend/ssh/libsshconstants.pm b/centreon/plugins/backend/ssh/libsshconstants.pm new file mode 100644 index 000000000..0ed5a691d --- /dev/null +++ b/centreon/plugins/backend/ssh/libsshconstants.pm @@ -0,0 +1,33 @@ +# +# Copyright 2020 Centreon (http://www.centreon.com/) +# +# Centreon is a full-fledged industry-strength solution that meets +# the needs in IT infrastructure and application monitoring for +# service performance. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +package centreon::plugins::backend::ssh::libsshconstants; + +use strict; +use warnings; +use Libssh::Session qw(:constants); + +sub get_constant_value { + my (%options) = @_; + + return eval $options{name}; +} + +1; diff --git a/centreon/plugins/backend/ssh/plink.pm b/centreon/plugins/backend/ssh/plink.pm index b409d36d5..c8009b804 100644 --- a/centreon/plugins/backend/ssh/plink.pm +++ b/centreon/plugins/backend/ssh/plink.pm @@ -47,7 +47,7 @@ sub check_options { $self->{ssh_command} = defined($options{option_results}->{plink_command}) && $options{option_results}->{plink_command} ne '' ? $options{option_results}->{plink_command} : 'plink'; - $self->{ssh_path} = $options{option_results}->{sshcli_path}; + $self->{ssh_path} = $options{option_results}->{plink_path}; $self->{ssh_option} = defined($options{option_results}->{plink_option}) ? $options{option_results}->{plink_option} : []; $self->{ssh_port} = defined($options{option_results}->{ssh_port}) && $options{option_results}->{ssh_port} =~ /(\d+)/ ? $1 : 22; $self->{ssh_priv_key} = $options{option_results}->{ssh_priv_key}; @@ -122,6 +122,6 @@ Specify plink options (example: --plink-option='-T'). =head1 DESCRIPTION -B. +B. =cut diff --git a/centreon/plugins/ssh.pm b/centreon/plugins/ssh.pm index 0780e7d07..ad5408064 100644 --- a/centreon/plugins/ssh.pm +++ b/centreon/plugins/ssh.pm @@ -53,6 +53,13 @@ sub new { ); $self->{backend_plink} = centreon::plugins::backend::ssh::plink->new(%options); + centreon::plugins::misc::mymodule_load( + output => $options{output}, + module => 'centreon::plugins::backend::ssh::libssh', + error_msg => "Cannot load module 'centreon::plugins::backend::ssh::libssh'." + ); + $self->{backend_libssh} = centreon::plugins::backend::ssh::libssh->new(%options); + $self->{output} = $options{output}; return $self; }