(plugin) apps::protocols::imap - new imap library (#3924)

This commit is contained in:
qgarnier 2022-09-27 10:42:11 +02:00 committed by GitHub
parent 96cee373b6
commit f47b2b0415
6 changed files with 260 additions and 226 deletions

View File

@ -0,0 +1,237 @@
#
# Copyright 2022 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 apps::protocols::imap::custom::imapclient;
use strict;
use warnings;
use Mail::IMAPClient;
use IO::Socket::SSL;
use centreon::plugins::misc;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
if (!defined($options{output})) {
print "Class Custom: Need to specify 'output' argument.\n";
exit 3;
}
if (!defined($options{options})) {
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
$options{output}->option_exit();
}
if (!defined($options{noptions})) {
$options{options}->add_options(arguments => {
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' },
'ssl' => { name => 'use_ssl' },
'ssl-opt:s@' => { name => 'ssl_opt' },
'username:s' => { name => 'username' },
'password:s' => { name => 'password' },
'insecure' => { name => 'insecure' },
'timeout:s' => { name => 'timeout' }
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'IMAP OPTIONS', once => 1);
$self->{output} = $options{output};
return $self;
}
sub set_options {
my ($self, %options) = @_;
$self->{option_results} = $options{option_results};
}
sub set_defaults {}
sub check_options {
my ($self, %options) = @_;
$self->{hostname} = defined($self->{option_results}->{hostname}) && $self->{option_results}->{hostname} ne '' ? $self->{option_results}->{hostname} : '';
$self->{port} = defined($self->{option_results}->{port}) && $self->{option_results}->{port} =~ /(\d+)/ ? $1 : '';
$self->{username} = defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : '';
$self->{password} = defined($self->{option_results}->{password}) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : '';
$self->{timeout} = defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 30;
$self->{insecure} = defined($self->{option_results}->{insecure}) ? 1 : 0;
$self->{use_ssl} = defined($self->{option_results}->{use_ssl}) ? 1 : 0;
if ($self->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --hostname option.');
$self->{output}->option_exit();
}
if ($self->{username} ne '' && $self->{password} eq '') {
$self->{output}->add_option_msg(short_msg => 'Need to specify --password option.');
$self->{output}->option_exit();
}
$self->{ssl_context} = centreon::plugins::misc::eval_ssl_options(
output => $self->{output},
ssl_opt => $self->{option_results}->{ssl_opt}
);
if ($self->{insecure} == 1) {
$self->{ssl_context}->{SSL_verify_mode} = SSL_VERIFY_NONE;
}
return 0;
}
sub disconnect {
my ($self, %options) = @_;
$self->{imap}->disconnect();
}
sub connect {
my ($self, %options) = @_;
my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown';
$self->{imap} = Mail::IMAPClient->new();
$self->{imap}->Server($self->{hostname});
$self->{imap}->Ssl(1) if ($self->{use_ssl} == 1);
$self->{imap}->port($self->{port}) if ($self->{port} ne '');
$self->{imap}->Timeout($self->{timeout}) if ($self->{timeout} ne '');
if ($self->{output}->is_debug()) {
$self->{imap}->Debug(1);
}
my $sslargs = [];
if ($self->{use_ssl} == 1) {
foreach (keys %{$self->{ssl_context}}) {
push @$sslargs, $_, $self->{ssl_context}->{$_};
}
}
my $rv = $self->{imap}->connect(Ssl => $sslargs);
if (!defined($rv)) {
$self->{output}->output_add(
severity => $connection_exit,
short_msg => 'Unable to connect to IMAP: ' . $@
);
$self->{output}->display();
$self->{output}->exit();
}
if ($self->{username} ne '') {
$self->{imap}->User($self->{username});
$self->{imap}->Password($self->{password});
$rv = $self->{imap}->login();
if (!defined($rv)) {
$self->{output}->output_add(
severity => $connection_exit,
short_msg => "Login failed: $@"
);
$self->disconnect();
$self->{output}->display();
$self->{output}->exit();
}
}
#my $oauth_sign = encode_base64("user=". $username ."\x01auth=Bearer ". $oauth_token ."\x01\x01", '');
#$imap->authenticate('XOAUTH2', sub { return $oauth_sign }) or die("Auth error: ". $imap->LastError);
# detail: https://developers.google.com/google-apps/gmail/xoauth2_protocol
}
sub search {
my ($self, %options) = @_;
if (!defined($self->{imap}->select($options{folder}))) {
$self->{output}->output_add(
severity => 'UNKNOWN',
short_msg => "Folder select failed: $@"
);
$self->disconnect();
$self->{output}->display();
$self->{output}->exit();
}
my @ids = $self->{imap}->search($options{search});
if (defined($options{delete})) {
foreach my $msg_num (@ids) {
$self->{imap}->delete_message($msg_num);
}
$self->{imap}->expunge($options{folder});
}
return scalar(@ids);
}
1;
__END__
=head1 NAME
protocol imap.
=head1 SYNOPSIS
protocol imap.
=head1 IMAP OPTIONS
=over 8
=item B<--hostname>
IP Addr/FQDN of the imap host
=item B<--port>
Port used (Default: 143).
=item B<--ssl>
Use SSL connection.
=item B<--ssl-opt>
Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'"
=item B<--insecure>
Allow insecure TLS connection by skipping cert validation (Since redis-cli 6.2.0).
=item B<--username>
Specify username for authentification
=item B<--password>
Specify password for authentification
=item B<--timeout>
Connection timeout in seconds (Default: 30)
=back
=head1 DESCRIPTION
B<custom>.
=cut

View File

@ -1,109 +0,0 @@
#
# Copyright 2022 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 apps::protocols::imap::lib::imap;
use strict;
use warnings;
use Net::IMAP::Simple;
use IO::Socket::SSL;
my $imap_handle;
sub quit {
$imap_handle->quit;
}
sub search {
my ($self, %options) = @_;
if (!defined($imap_handle->select($self->{option_results}->{folder}))) {
my $output = $imap_handle->errstr;
$output =~ s/\r//g;
$self->{output}->output_add(
severity => 'UNKNOWN',
short_msg => 'Folder Select Error: ' . $output
);
quit();
$self->{output}->display();
$self->{output}->exit();
}
my @ids = $imap_handle->search($self->{option_results}->{search});
if (defined($self->{option_results}->{delete})) {
foreach my $msg_num (@ids) {
$imap_handle->delete($msg_num);
}
$imap_handle->expunge_mailbox();
}
return scalar(@ids);
}
sub connect {
my ($self, %options) = @_;
my %imap_options = ();
my $connection_exit = defined($options{connection_exit}) ? $options{connection_exit} : 'unknown';
$imap_options{port} = $self->{option_results}->{port} if (defined($self->{option_results}->{port}));
$imap_options{use_ssl} = 1 if (defined($self->{option_results}->{use_ssl}));
$imap_options{timeout} = $self->{option_results}->{timeout} if (defined($self->{option_results}->{timeout}));
if ($self->{ssl_options} ne '') {
$imap_options{ssl_options} = [ eval $self->{ssl_options} ];
}
if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' &&
!defined($self->{option_results}->{password})) {
$self->{output}->add_option_msg(short_msg => 'Please set --password option.');
$self->{output}->option_exit();
}
$imap_handle = Net::IMAP::Simple->new(
$self->{option_results}->{hostname},
%imap_options
);
if (!defined($imap_handle)) {
$self->{output}->output_add(
severity => $connection_exit,
short_msg => 'Unable to connect to IMAP: ' . $Net::IMAP::Simple::errstr
);
$self->{output}->display();
$self->{output}->exit();
}
if (defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '') {
if (!$imap_handle->login($self->{option_results}->{username}, $self->{option_results}->{password})) {
# Exchange put '\r'...
my $output = $imap_handle->errstr;
$output =~ s/\r//g;
$self->{output}->output_add(
severity => $connection_exit,
short_msg => 'Login failed: ' . $output
);
quit();
$self->{output}->display();
$self->{output}->exit();
}
}
}
1;

View File

@ -25,23 +25,15 @@ use base qw(centreon::plugins::mode);
use strict;
use warnings;
use Time::HiRes qw(gettimeofday tv_interval);
use apps::protocols::imap::lib::imap;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port', },
'ssl' => { name => 'use_ssl' },
'ssl-opt:s@' => { name => 'ssl_opt' },
'username:s' => { name => 'username' },
'password:s' => { name => 'password' },
'warning:s' => { name => 'warning' },
'critical:s' => { name => 'critical' },
'timeout:s' => { name => 'timeout', default => '30' }
'critical:s' => { name => 'critical' }
});
return $self;
@ -59,28 +51,14 @@ sub check_options {
$self->{output}->add_option_msg(short_msg => "Wrong critical threshold '" . $self->{option_results}->{critical} . "'.");
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{hostname})) {
$self->{output}->add_option_msg(short_msg => "Please set the hostname option");
$self->{output}->option_exit();
}
my $append = '';
$self->{ssl_options} = '';
foreach (@{$self->{option_results}->{ssl_opt}}) {
if ($_ ne '') {
$self->{ssl_options} .= $append . $_;
$append = ', ';
}
}
}
sub run {
my ($self, %options) = @_;
my $timing0 = [gettimeofday];
apps::protocols::imap::lib::imap::connect($self, connection_exit => 'critical');
apps::protocols::imap::lib::imap::quit();
$options{custom}->connect(connection_exit => 'critical');
$options{custom}->disconnect();
my $timeelapsed = tv_interval($timing0, [gettimeofday]);
@ -93,7 +71,7 @@ sub run {
short_msg => sprintf("Response time %.3f ", $timeelapsed)
);
$self->{output}->perfdata_add(
label => 'time',
nlabel => 'connection.time.seconds',
value => sprintf('%.3f', $timeelapsed),
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical')
@ -109,38 +87,10 @@ __END__
=head1 MODE
Check Connection (also login) to an IMAP Server.
Check connection (also login) to an IMAP Server.
=over 8
=item B<--hostname>
IP Addr/FQDN of the imap host
=item B<--port>
Port used
=item B<--ssl>
Use SSL connection.
=item B<--ssl-opt>
Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'"
=item B<--username>
Specify username for authentification
=item B<--password>
Specify password for authentification
=item B<--timeout>
Connection timeout in seconds (Default: 30)
=item B<--warning>
Threshold warning in seconds

View File

@ -24,23 +24,15 @@ use base qw(centreon::plugins::mode);
use strict;
use warnings;
use apps::protocols::imap::lib::imap;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port', },
'ssl' => { name => 'use_ssl' },
'ssl-opt:s@' => { name => 'ssl_opt' },
'username:s' => { name => 'username' },
'password:s' => { name => 'password' },
'warning:s' => { name => 'warning' },
'critical:s' => { name => 'critical' },
'timeout:s' => { name => 'timeout', default => '30' },
'search:s' => { name => 'search' },
'delete' => { name => 'delete' },
'folder:s' => { name => 'folder', default => 'INBOX' }
@ -62,31 +54,22 @@ sub check_options {
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{hostname})) {
$self->{output}->add_option_msg(short_msg => 'Please set the --hostname option');
$self->{output}->option_exit();
}
if (!defined($self->{option_results}->{search})) {
$self->{output}->add_option_msg(short_msg => 'Please set the --search option');
$self->{output}->option_exit();
}
my $append = '';
$self->{ssl_options} = '';
foreach (@{$self->{option_results}->{ssl_opt}}) {
if ($_ ne '') {
$self->{ssl_options} .= $append . $_;
$append = ', ';
}
}
}
sub run {
my ($self, %options) = @_;
apps::protocols::imap::lib::imap::connect($self);
my ($num) = apps::protocols::imap::lib::imap::search($self);
apps::protocols::imap::lib::imap::quit();
$options{custom}->connect(connection_exit => 'critical');
my ($num) = $options{custom}->search(
folder => $self->{option_results}->{folder},
search => $self->{option_results}->{search},
delete => $self->{option_results}->{delete}
);
$options{custom}->disconnect();
my $exit = $self->{perfdata}->threshold_check(
value => $num,
@ -97,7 +80,7 @@ sub run {
short_msg => sprintf('%d message(s) found', $num)
);
$self->{output}->perfdata_add(
label => 'numbers',
nlabel => 'messages.found.count',
value => $num,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning'),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical'),
@ -118,34 +101,6 @@ Check messages in a mailbox with IMAP filter.
=over 8
=item B<--hostname>
IP Addr/FQDN of the imap host
=item B<--port>
Port used
=item B<--ssl>
Use SSL connection.
=item B<--ssl-opt>
Set SSL options: --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE" --ssl-opt="SSL_version => 'TLSv1'"
=item B<--username>
Specify username for authentification
=item B<--password>
Specify password for authentification
=item B<--timeout>
Connection timeout in seconds (Default: 30)
=item B<--search>
Set the search string (Required)

View File

@ -22,18 +22,19 @@ package apps::protocols::imap::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_simple);
use base qw(centreon::plugins::script_custom);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
%{$self->{modes}} = (
'login' => 'apps::protocols::imap::mode::login',
'search-message' => 'apps::protocols::imap::mode::searchmessage',
);
$self->{modes} = {
'login' => 'apps::protocols::imap::mode::login',
'search-message' => 'apps::protocols::imap::mode::searchmessage'
};
$self->{custom_modes}->{imapclient} = 'apps::protocols::imap::custom::imapclient';
return $self;
}

View File

@ -76,7 +76,7 @@ sub check_options {
$self->{ssh_hostname} = defined($self->{option_results}->{ssh_hostname}) && $self->{option_results}->{ssh_hostname} ne '' ? $self->{option_results}->{ssh_hostname} : '';
$self->{server} = defined($self->{option_results}->{server}) && $self->{option_results}->{server} ne '' ? $self->{option_results}->{server} : '';
$self->{port} = defined($self->{option_results}->{port}) && $self->{option_results}->{port} ne '' ? $self->{option_results}->{port} : 26379;
$self->{username} = defined($self->{option_results}->{password}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : '';
$self->{username} = defined($self->{option_results}->{username}) && $self->{option_results}->{username} ne '' ? $self->{option_results}->{username} : '';
$self->{password} = defined($self->{option_results}->{password}) && $self->{option_results}->{password} ne '' ? $self->{option_results}->{password} : '';
$self->{timeout} = defined($self->{option_results}->{timeout}) && $self->{option_results}->{timeout} =~ /(\d+)/ ? $1 : 10;
$self->{tls} = defined($self->{option_results}->{tls}) ? 1 : 0;