diff --git a/centreon-plugins/centreon/plugins/passwordmgr/teampass.pm b/centreon-plugins/centreon/plugins/passwordmgr/teampass.pm new file mode 100644 index 000000000..147026913 --- /dev/null +++ b/centreon-plugins/centreon/plugins/passwordmgr/teampass.pm @@ -0,0 +1,237 @@ +# +# Copyright 2019 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::passwordmgr::teampass; + +use strict; +use warnings; +use JSON::Path; +use JSON::XS; +use Data::Dumper; +use centreon::plugins::http; + +use vars qw($teampass_connections); + +sub new { + my ($class, %options) = @_; + my $self = {}; + bless $self, $class; + + if (!defined($options{output})) { + print "Class PasswordMgr: Need to specify 'output' argument.\n"; + exit 3; + } + if (!defined($options{options})) { + $options{output}->add_option_msg(short_msg => "Class PasswordMgr: Need to specify 'options' argument."); + $options{output}->option_exit(); + } + + $options{options}->add_options(arguments => { + "teampass-endpoint:s" => { name => 'teampass_endpoint' }, + "teampass-endpoint-file:s" => { name => 'teampass_endpoint_file' }, + "teampass-api-key:s" => { name => 'teampass_api_key' }, + "teampass-api-address:s" => { name => 'teampass_api_address' }, + "teampass-api-request:s" => { name => 'teampass_api_request' }, + "teampass-search-value:s@" => { name => 'teampass_search_value' }, + "teampass-map-option:s@" => { name => 'teampass_map_option' }, + "teampass-timeout:s" => { name => 'teampass_timeout' }, + }); + $options{options}->add_help(package => __PACKAGE__, sections => 'TEAMPASS OPTIONS'); + + $self->{output} = $options{output}; + $self->{http} = centreon::plugins::http->new(output => $self->{output}); + $JSON::Path::Safe = 0; + + return $self; +} + +sub build_api_args { + my ($self, %options) = @_; + + $self->{connection_info} = { address => undef, key => undef, request => undef }; + if (defined($options{option_results}->{teampass_endpoint_file}) && $options{option_results}->{teampass_endpoint_file} ne '') { + if (! -f $options{option_results}->{teampass_endpoint_file} or ! -r $options{option_results}->{teampass_endpoint_file}) { + $self->{output}->add_option_msg(short_msg => "Cannot read teampass file: $!"); + $self->{output}->option_exit(); + } + + require $options{option_results}->{teampass_endpoint_file}; + if (defined($teampass_connections) && defined($options{option_results}->{teampass_endpoint}) && $options{option_results}->{teampass_endpoint} ne '') { + if (!defined($teampass_connections->{$options{option_results}->{teampass_endpoint}})) { + $self->{output}->add_option_msg(short_msg => "Endpoint $options{option_results}->{teampass_endpoint} doesn't exist in teampass file"); + $self->{output}->option_exit(); + } + + $self->{connection_info} = $teampass_connections->{$options{option_results}->{teampass_endpoint}}; + } + } + + foreach (['teampass_api_address', 'address'], ['teampass_api_key', 'key'], ['teampass_api_request', 'request']) { + if (defined($options{option_results}->{$_->[0]}) && $options{option_results}->{$_->[0]} ne '') { + $self->{connection_info}->{$_->[1]} = $options{option_results}->{$_->[0]}; + } + } + + if (defined($self->{connection_info}->{address}) && $self->{connection_info}->{address} ne '') { + foreach ('key', 'request') { + if (!defined($self->{connection_info}->{$_}) || $self->{connection_info}->{$_} eq '') { + $self->{output}->add_option_msg(short_msg => "Please set teampass-api-$_ option"); + $self->{output}->option_exit(); + } + } + } +} + +sub do_lookup { + my ($self, %options) = @_; + + $self->{lookup_values} = {}; + return if (!defined($options{option_results}->{teampass_search_value})); + + foreach (@{$options{option_results}->{teampass_search_value}}) { + next if (! /^(.+?)=(.+)$/); + my ($map, $lookup) = ($1, $2); + + # Change %{xxx} options usage + while ($lookup =~ /\%\{(.*?)\}/g) { + my $sub = ''; + $sub = $options{option_results}->{$1} if (defined($options{option_results}->{$1})); + $lookup =~ s/\%\{$1\}/$sub/g + } + + my $jpath = JSON::Path->new($lookup); + my $result = $jpath->value($options{json}); + $self->{output}->output_add(long_msg => 'lookup = ' . $lookup. ' - response = ' . Data::Dumper::Dumper($result), debug => 1); + $self->{lookup_values}->{$map} = $result; + } +} + +sub do_map { + my ($self, %options) = @_; + + return if (!defined($options{option_results}->{teampass_map_option})); + foreach (@{$options{option_results}->{teampass_map_option}}) { + next if (! /^(.+?)=(.+)$/); + my ($option, $map) = ($1, $2); + + # Change %{xxx} options usage + while ($map =~ /\%\{(.*?)\}/g) { + my $sub = ''; + $sub = $self->{lookup_values}->{$1} if (defined($self->{lookup_values}->{$1})); + $map =~ s/\%\{$1\}/$sub/g + } + + $option =~ s/-/_/g; + $options{option_results}->{$option} = $map; + } +} + +sub manage_options { + my ($self, %options) = @_; + + $self->build_api_args(%options); + return if (!defined($self->{connection_info}->{address})); + + $self->{http}->set_options( + timeout => $options{option_results}->{teampass_timeout}, + unknown_status => '%{http_code} < 200 or %{http_code} >= 300', + ); + my $response = $self->{http}->request(method => 'GET', + full_url => $self->{connection_info}->{address} . $self->{connection_info}->{request}, + hostname => '', + get_param => ['apikey=' . $self->{connection_info}->{key}], + ); + $self->{output}->output_add(long_msg => $response, debug => 1); + + my $json; + eval { + $json = JSON::XS->new->utf8->decode($response); + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "Cannot decode teampass json response: $@"); + $self->{output}->option_exit(); + } + + $self->do_lookup(%options, json => $json); + $self->do_map(%options); +} + +1; + +__END__ + +=head1 NAME + +Teampass global + +=head1 SYNOPSIS + +teampass class + +=head1 TEAMPASS OPTIONS + +=over 8 + +=item B<--teampass-endpoint> + +Connection information to be used in teampass file. + +=item B<--teampass-endpoint-file> + +File with teampass connection informations. + +=item B<--teampass-timeout> + +Set HTTP Rest API timeout (Default: 5). + +=item B<--teampass-api-key> + +Teampass API Key. + +=item B<--teampass-api-address> + +Teampass URL (example: http://10.0.0.1/teampass). + +=item B<--teampass-api-request> + +Teampass request (example: /api/index.php/folder/3). + +=item B<--teampass-search-value> + +Looking for a value in the JSON teampass response. Can use JSON Path and other option values. +Example: +--teampass-search-value='password=$.[?($_->{label} =~ /serveur1/i)].pw' +--teampass-search-value='login=$.[?($_->{label} =~ /serveur1/i)].login' +--teampass-search-value='password=$.[?($_->{label} =~ /%{hostname}/i)].pw' + +=item B<--teampass-map-option> + +Overload plugin option. +Example: +--teampass-map-option="password=%{password}" +--teampass-map-option="username=%{login}" + +=back + +=head1 DESCRIPTION + +B. + +=cut diff --git a/centreon-plugins/centreon/plugins/script_custom.pm b/centreon-plugins/centreon/plugins/script_custom.pm index 383e73577..9bc01b669 100644 --- a/centreon-plugins/centreon/plugins/script_custom.pm +++ b/centreon-plugins/centreon/plugins/script_custom.pm @@ -97,6 +97,8 @@ sub init { # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); + + $self->load_password_mgr(); if (defined($self->{custommode_name}) && $self->{custommode_name} ne '') { $self->load_custom_mode(); @@ -139,6 +141,7 @@ sub init { $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); + $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); push @{$self->{custommode_stored}}, $self->{custommode_current}; $self->{custommode_current}->set_options(option_results => $self->{option_results}); @@ -152,6 +155,18 @@ sub init { $self->{mode}->check_options(option_results => $self->{option_results}, default => $self->{default}); } +sub load_password_mgr { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); + + (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( + output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, + error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" + ); + $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); +} + sub run { my $self = shift; diff --git a/centreon-plugins/centreon/plugins/script_simple.pm b/centreon-plugins/centreon/plugins/script_simple.pm index cf53a1f59..5f2e1f749 100644 --- a/centreon-plugins/centreon/plugins/script_simple.pm +++ b/centreon-plugins/centreon/plugins/script_simple.pm @@ -79,6 +79,8 @@ sub init { # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); + $self->load_password_mgr(); + # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { $self->is_mode(mode => $self->{mode_name}); @@ -115,9 +117,22 @@ sub init { $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); + $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{mode}->check_options(option_results => $self->{option_results}, default => $self->{default}); } +sub load_password_mgr { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); + + (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( + output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, + error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" + ); + $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); +} + sub run { my $self = shift; diff --git a/centreon-plugins/centreon/plugins/script_snmp.pm b/centreon-plugins/centreon/plugins/script_snmp.pm index 7afce9dfd..08b1cb0ba 100644 --- a/centreon-plugins/centreon/plugins/script_snmp.pm +++ b/centreon-plugins/centreon/plugins/script_snmp.pm @@ -42,6 +42,7 @@ sub new { 'list-mode' => { name => 'list_mode' }, 'mode-version:s' => { name => 'mode_version' }, 'sanity-options' => { name => 'sanity_options' }, # keep it for 6 month before remove it + 'pass-manager:s' => { name => 'pass_manager' }, } ); $self->{version} = '1.0'; @@ -81,8 +82,11 @@ sub init { # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); + $self->load_password_mgr(); + # SNMP $self->{snmp} = centreon::plugins::snmp->new(options => $self->{options}, output => $self->{output}); + # Load mode if (defined($self->{mode_name}) && $self->{mode_name} ne '') { @@ -120,10 +124,23 @@ sub init { $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); + $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{snmp}->check_options(option_results => $self->{option_results}); $self->{mode}->check_options(option_results => $self->{option_results}, default => $self->{default}); } +sub load_password_mgr { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); + + (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( + output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, + error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" + ); + $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); +} + sub run { my ($self) = @_; @@ -206,6 +223,10 @@ Check minimal version of mode. If not, unknown error. Display plugin version. +=item B<--pass-manager> + +Use a password manager. + =back =head1 DESCRIPTION diff --git a/centreon-plugins/centreon/plugins/script_sql.pm b/centreon-plugins/centreon/plugins/script_sql.pm index fd0fa3372..1caf73052 100644 --- a/centreon-plugins/centreon/plugins/script_sql.pm +++ b/centreon-plugins/centreon/plugins/script_sql.pm @@ -89,6 +89,8 @@ sub init { # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); + + $self->load_password_mgr(); if (defined($self->{sqlmode_name}) && $self->{sqlmode_name} ne '') { $self->is_sqlmode(sqlmode => $self->{sqlmode_name}); @@ -135,6 +137,7 @@ sub init { $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); + $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); push @{$self->{sqlmode_stored}}, $self->{sqlmode_current}; $self->{sqlmode_current}->set_options(option_results => $self->{option_results}); @@ -148,6 +151,18 @@ sub init { $self->{mode}->check_options(option_results => $self->{option_results}, default => $self->{default}); } +sub load_password_mgr { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); + + (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( + output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, + error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" + ); + $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); +} + sub run { my $self = shift; diff --git a/centreon-plugins/centreon/plugins/script_wsman.pm b/centreon-plugins/centreon/plugins/script_wsman.pm index deda54aea..7f8e672ec 100644 --- a/centreon-plugins/centreon/plugins/script_wsman.pm +++ b/centreon-plugins/centreon/plugins/script_wsman.pm @@ -80,6 +80,8 @@ sub init { # Output HELP $self->{options}->add_help(package => 'centreon::plugins::output', sections => 'OUTPUT OPTIONS'); + + $self->load_password_mgr(); # WSMAN $self->{wsman} = centreon::plugins::wsman->new(options => $self->{options}, output => $self->{output}); @@ -115,11 +117,24 @@ sub init { $self->{options}->parse_options(); $self->{option_results} = $self->{options}->get_options(); + $self->{pass_mgr}->manage_options(option_results => $self->{option_results}) if (defined($self->{pass_mgr})); $self->{wsman}->check_options(option_results => $self->{option_results}); $self->{mode}->check_options(option_results => $self->{option_results}, default => $self->{default}); } +sub load_password_mgr { + my ($self, %options) = @_; + + return if (!defined($self->{option_results}->{pass_manager}) || $self->{option_results}->{pass_manager} eq ''); + + (undef, my $pass_mgr_name) = centreon::plugins::misc::mymodule_load( + output => $self->{output}, module => "centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager}, + error_msg => "Cannot load module 'centreon::plugins::passwordmgr::" . $self->{option_results}->{pass_manager} . "'" + ); + $self->{pass_mgr} = $pass_mgr_name->new(options => $self->{options}, output => $self->{output}); +} + sub run { my $self = shift;