enh(custommode): add support of 3CX v18 and higher (#5093)
This commit is contained in:
parent
d635b1c04e
commit
0e252334d8
|
@ -48,6 +48,7 @@ sub new {
|
|||
'hostname:s' => { name => 'hostname' },
|
||||
'port:s' => { name => 'port'},
|
||||
'proto:s' => { name => 'proto' },
|
||||
'3cx-version:s' => { name => 'version_3cx' },
|
||||
'api-username:s' => { name => 'api_username' },
|
||||
'api-password:s' => { name => 'api_password' },
|
||||
'timeout:s' => { name => 'timeout', default => 30 },
|
||||
|
@ -80,6 +81,7 @@ sub check_options {
|
|||
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : '';
|
||||
$self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443;
|
||||
$self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https';
|
||||
$self->{version_3cx} = (defined($self->{option_results}->{version_3cx})) ? $self->{option_results}->{version_3cx} : '';
|
||||
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 30;
|
||||
$self->{ssl_opt} = (defined($self->{option_results}->{ssl_opt})) ? $self->{option_results}->{ssl_opt} : undef;
|
||||
$self->{api_username} = (defined($self->{option_results}->{api_username})) ? $self->{option_results}->{api_username} : '';
|
||||
|
@ -100,7 +102,7 @@ sub check_options {
|
|||
$self->{output}->add_option_msg(short_msg => 'Need to specify --api-password option.');
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
$self->{option_results}->{api_version} = $self->get_api_version(version_3cx => $self->{option_results}->{version_3cx});
|
||||
$self->{cache}->check_options(option_results => $self->{option_results});
|
||||
|
||||
return 0;
|
||||
|
@ -123,8 +125,12 @@ sub settings {
|
|||
$self->{http}->add_header(key => 'Content-Type', value => 'application/json;charset=UTF-8');
|
||||
if (defined($self->{cookie})) {
|
||||
$self->{http}->add_header(key => 'Cookie', value => $self->{cookie});
|
||||
if (defined($self->{xsrf})) {
|
||||
$self->{http}->add_header(key => 'X-XSRF-TOKEN', value => $self->{xsrf});
|
||||
|
||||
if (defined($self->{auth_header})) {
|
||||
my $auth_header_key = ( $self->{option_results}->{api_version} == 1 )
|
||||
? 'X-XSRF-TOKEN'
|
||||
: 'Authorization';
|
||||
$self->{http}->add_header(key => $auth_header_key, value => $self->{auth_header});
|
||||
}
|
||||
}
|
||||
$self->{http}->set_options(%{$self->{option_results}});
|
||||
|
@ -135,10 +141,10 @@ sub authenticate {
|
|||
|
||||
my $has_cache_file = $options{statefile}->read(statefile => '3cx_api_' . md5_hex($self->{option_results}->{hostname}) . '_' . md5_hex($self->{option_results}->{api_username}));
|
||||
my $cookie = $options{statefile}->get(name => 'cookie');
|
||||
my $xsrf = $options{statefile}->get(name => 'xsrf');
|
||||
my $auth_header = $options{statefile}->get(name => 'auth_header');
|
||||
my $expires_on = $options{statefile}->get(name => 'expires_on');
|
||||
|
||||
if ($has_cache_file == 0 || !defined($cookie) || !defined($xsrf) || (($expires_on - time()) < 10)) {
|
||||
if ($has_cache_file == 0 || !defined($cookie) || !defined($auth_header) || (($expires_on - time()) < 10)) {
|
||||
my $post_data = '{"Username":"' . $self->{api_username} . '",' .
|
||||
'"Password":"' . $self->{api_password} . '"}';
|
||||
|
||||
|
@ -161,17 +167,49 @@ sub authenticate {
|
|||
$self->{output}->add_option_msg(short_msg => "Error retrieving cookie");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
|
||||
my $data;
|
||||
if ($self->{option_results}->{api_version} == 1)
|
||||
{
|
||||
# for 3CX versions prior to 18.0.5
|
||||
# 3CX 16.0.5.611 does not use XSRF-TOKEN anymore
|
||||
if (defined ($header) && $header =~ /(?:^| )XSRF-TOKEN=([^;]+);.*/) {
|
||||
$xsrf = $1;
|
||||
$auth_header = $1;
|
||||
}
|
||||
$data = { last_timestamp => time(), cookie => $cookie, xsrf => $auth_header, expires_on => time() + (3600 * 24) };
|
||||
} else {
|
||||
# for 3CX versions higher or equal to 18.0.5
|
||||
$self->{http}->add_header(key => 'Cookie', value => $cookie);
|
||||
$content = $self->{http}->request(
|
||||
method => 'GET',
|
||||
url_path => '/api/Token',
|
||||
unknown_status => $self->{unknown_http_status},
|
||||
warning_status => $self->{warning_http_status},
|
||||
critical_status => $self->{critical_http_status}
|
||||
);
|
||||
my $decoded;
|
||||
eval {
|
||||
$decoded = JSON::XS->new->decode($content);
|
||||
};
|
||||
if ($@) {
|
||||
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
if (!defined($decoded)) {
|
||||
$self->{output}->add_option_msg(short_msg => "Error while retrieving data (add --debug option for detailed message)");
|
||||
$self->{output}->option_exit();
|
||||
}
|
||||
$auth_header = $decoded->{token_type} . " " . $decoded->{access_token};
|
||||
$expires_on = time() + ($decoded->{expires_in} * 60);
|
||||
|
||||
$data = { last_timestamp => time(), cookie => $cookie, bearer => $auth_header, expires_on => $expires_on };
|
||||
}
|
||||
|
||||
my $datas = { last_timestamp => time(), cookie => $cookie, xsrf => $xsrf, expires_on => time() + (3600 * 24) };
|
||||
$options{statefile}->write(data => $datas);
|
||||
$options{statefile}->write(data => $data);
|
||||
}
|
||||
|
||||
$self->{cookie} = $cookie;
|
||||
$self->{xsrf} = $xsrf;
|
||||
$self->{auth_header} = $auth_header;
|
||||
}
|
||||
|
||||
sub request_api {
|
||||
|
@ -271,7 +309,7 @@ sub api_system_status {
|
|||
return $status;
|
||||
}
|
||||
|
||||
sub internal_update_checker {
|
||||
sub internal_update_checker_v1 {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $status = $self->request_api(method => 'GET', url_path =>'/api/UpdateChecker/GetFromParams', eval_content => 1);
|
||||
|
@ -285,11 +323,65 @@ sub internal_update_checker {
|
|||
return $status;
|
||||
}
|
||||
|
||||
sub internal_update_checker_v2 {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $status = $self->request_api(method => 'GET', url_path =>'/xapi/v1/GetUpdatesStats()');
|
||||
if (ref($status) eq 'HASH') {
|
||||
$status = $status->{TcxUpdate};
|
||||
if (ref($status) ne 'ARRAY') {
|
||||
# See above note about strange content
|
||||
$status = JSON::XS->new->decode($status);
|
||||
}
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
|
||||
|
||||
sub api_update_checker {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
my $status = $self->internal_update_checker();
|
||||
return $status;
|
||||
if ($self->{option_results}->{api_version} == 1){
|
||||
return $self->internal_update_checker_v1();
|
||||
}
|
||||
return $self->internal_update_checker_v2();
|
||||
}
|
||||
|
||||
sub get_api_version {
|
||||
my ($self, %options) = @_;
|
||||
|
||||
# Given the provided (or not) 3cx version, determine once and for all the API version
|
||||
# This API version is an internal reference in centreon-plugins
|
||||
# Version 1 corresponds to versions prior to v18 update 5 (<= 18.0.4.x)
|
||||
# Version 2 corresponds to versions greater or equal to v18 update 5 (> 18.0.5.0)
|
||||
|
||||
# assuming the lastest API version if not provided
|
||||
return 2 if ( !defined($options{version_3cx}) );
|
||||
|
||||
my @version_decomposition = $options{version_3cx} =~ /^([0-9]+)\.?([0-9]*)\.?([0-9]*)\.?([0-9]*)$/;
|
||||
|
||||
if (scalar(@version_decomposition) == 0){
|
||||
$self->{output}->add_option_msg(
|
||||
debug => 1,
|
||||
long_msg => "Version '" . $options{version_3cx} . "' not formatted properly. Switching to latest supported version.");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if ($version_decomposition[0] < 18
|
||||
or $version_decomposition[0] == 18
|
||||
and defined($version_decomposition[1]) and $version_decomposition[1] == 0
|
||||
and defined($version_decomposition[2]) and $version_decomposition[2] < 5) {
|
||||
|
||||
$self->{output}->add_option_msg(
|
||||
debug => 1,
|
||||
long_msg => "Version '" . $options{version_3cx} . "' identified as prior to 18 update 5. Using old API.");
|
||||
return 1;
|
||||
} else {
|
||||
$self->{output}->add_option_msg(
|
||||
debug => 1,
|
||||
long_msg => "Version '" . $options{version_3cx} . "' identified as higher or equal to 18 update 5. Using new API.");
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -298,7 +390,7 @@ __END__
|
|||
|
||||
=head1 NAME
|
||||
|
||||
3CX Rest API
|
||||
3CX Rest API module
|
||||
|
||||
=head1 REST API OPTIONS
|
||||
|
||||
|
@ -306,37 +398,48 @@ __END__
|
|||
|
||||
=item B<--hostname>
|
||||
|
||||
Set hostname or IP of 3CX server.
|
||||
Define the name or the address of the 3CX server.
|
||||
|
||||
=item B<--port>
|
||||
|
||||
Set 3CX Port (default: '443').
|
||||
Define the port to connect to (default: '443').
|
||||
|
||||
=item B<--proto>
|
||||
|
||||
Specify http if needed (default: 'https').
|
||||
Define the protocol to reach the API (default: 'https').
|
||||
|
||||
=item B<--3cx-version>
|
||||
|
||||
Define the version of 3CX to monitor for the plugin to adapt to the API version. If this option is omitted, the plugin will assume the API is in the latest supported version.
|
||||
Example: 18.0.9.20 for version 18 update 9.
|
||||
|
||||
|
||||
=item B<--api-username>
|
||||
|
||||
Set 3CX Username.
|
||||
Define the username for authentication.
|
||||
|
||||
=item B<--api-password>
|
||||
|
||||
Set 3CX Password.
|
||||
Define the password associated with the username.
|
||||
|
||||
=item B<--timeout>
|
||||
|
||||
Threshold for HTTP timeout (default: '30').
|
||||
Define the timeout in seconds (default: 30).
|
||||
|
||||
=item B<--unknown-http-status>
|
||||
Threshold unknown for http response code.
|
||||
(default: '%{http_code} < 200 or %{http_code} >= 300')
|
||||
|
||||
Define the conditions to match on the HTTP Status for the returned status to be UNKNOWN.
|
||||
Default: '%{http_code} < 200 or %{http_code} >= 300'
|
||||
|
||||
=item B<--warning-http-status>
|
||||
Warning threshold for http response code.
|
||||
|
||||
Define the conditions to match on the HTTP Status for the returned status to be WARNING.
|
||||
Example: '%{http_code} == 500'
|
||||
|
||||
=item B<--critical-http-status>
|
||||
Critical threshold for http response code.
|
||||
|
||||
Define the conditions to match on the HTTP Status for the returned status to be CRITICAL.
|
||||
Example: '%{http_code} == 500'
|
||||
|
||||
=back
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ __END__
|
|||
|
||||
=head1 PLUGIN DESCRIPTION
|
||||
|
||||
Check 3CX ressources through its HTTPS remote API.
|
||||
Monitor 3CX resources through its HTTPS API.
|
||||
|
||||
Requirements: at least 3CX 15.5.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
--3cx-version
|
||||
--add-sysdesc
|
||||
--api-filter-orgs
|
||||
--api-password
|
||||
|
@ -49,6 +50,7 @@
|
|||
-InputFormat
|
||||
-NoLogo
|
||||
2c
|
||||
3CX
|
||||
ADSL
|
||||
ASAM
|
||||
Alcatel
|
||||
|
|
Loading…
Reference in New Issue