@@ -30,7 +30,7 @@ use centreon::plugins::misc qw(json_decode is_empty value_of is_excluded);
3030
3131sub new {
3232 my ($class , %options ) = @_ ;
33- my $self = {};
33+ my $self = {};
3434 bless $self , $class ;
3535
3636 if (!defined ($options {output })) {
@@ -41,23 +41,24 @@ sub new {
4141 $options {output }-> add_option_msg(short_msg => " Class Custom: Need to specify 'options' argument." );
4242 $options {output }-> option_exit();
4343 }
44-
44+
4545 if (!defined ($options {noptions })) {
4646 $options {options }-> add_options(arguments => {
47- ' key-id:s' => { name => ' key_id' , default => ' ' },
48- ' key-secret:s' => { name => ' key_secret' , default => ' ' },
49- ' api-path:s' => { name => ' api_path' , default => ' /v1' },
50- ' hostname:s' => { name => ' hostname' , default => ' api.zdxcloud.net' },
51- ' port:s' => { name => ' port' , default => 443 },
52- ' proto:s' => { name => ' proto' , default => ' https' },
53- ' timeout:s' => { name => ' timeout' , default => 10 }
47+ ' auth-url:s' => { name => ' auth_url' , default => ' ' },
48+ ' client-id:s' => { name => ' client_id' , default => ' ' },
49+ ' client-secret:s' => { name => ' client_secret' , default => ' ' },
50+ ' api-path:s' => { name => ' api_path' , default => ' /zdx/v1' },
51+ ' hostname:s' => { name => ' hostname' , default => ' api.zsapi.net' },
52+ ' port:s' => { name => ' port' , default => 443 },
53+ ' proto:s' => { name => ' proto' , default => ' https' },
54+ ' timeout:s' => { name => ' timeout' , default => 10 }
5455 });
5556 }
5657 $options {options }-> add_help(package => __PACKAGE__ , sections => ' REST API OPTIONS' , once => 1);
5758
5859 $self -> {output } = $options {output };
59- $self -> {http } = centreon::plugins::http-> new(%options , default_backend => ' curl' );
60- $self -> {cache } = centreon::plugins::statefile-> new(%options );
60+ $self -> {http } = centreon::plugins::http-> new(%options , default_backend => ' curl' );
61+ $self -> {cache } = centreon::plugins::statefile-> new(%options );
6162
6263 return $self ;
6364}
@@ -70,14 +71,13 @@ sub get_token {
7071 $self -> settings();
7172
7273 my $has_cache_file = $self -> {cache }-> read (
73- statefile => ' zdx_token_' . md5_hex(
74- $self -> {hostname }
75- . ' :' . $self -> {port }
76- . ' _' . $self -> {key_id })
74+ statefile => ' zdx_token_' . md5_hex(
75+ $self -> {auth_url }
76+ . ' _' . $self -> {client_id })
7777 );
7878 # return token stored in cache if exists after checking it is still valid
7979 if ($has_cache_file ) {
80- my $expiration = $self -> {cache }-> get(name => ' expiration' );
80+ my $expiration = $self -> {cache }-> get(name => ' expiration' );
8181 if (defined ($expiration ) && $expiration > time () + 60) {
8282 $self -> {token } = $self -> {cache }-> get(name => ' token' );
8383 $self -> {token_type } = $self -> {cache }-> get(name => ' token_type' );
@@ -89,17 +89,22 @@ sub get_token {
8989 # if we do not have a token or if it has to be renewed
9090 my $content = $self -> {http }-> request(
9191 method => ' POST' ,
92- url_path => ' /v1/oauth/token' ,
93- query_form_post => ' {"key_id": "' . $self -> {key_id } . ' ", "key_secret": "' . $self -> {key_secret } . ' "}' ,
94-
92+ full_url => $self -> {auth_url },
93+ header => [ ' Content-Type: application/x-www-form-urlencoded' ],
94+ query_form_post => " grant_type=client_credentials&client_id=" . $self -> {client_id }
95+ . " &client_secret=" . $self -> {client_secret },
9596 );
9697 my $decoded_content = json_decode($content , output => $self -> {output });
9798
98- $self -> {output }-> option_exit(short_msg => " No token found in '$content '" ) unless ($decoded_content -> {token });
99- $self -> {token } = $decoded_content -> {token };
100- $self -> {token_type } = $decoded_content -> {token_type };
99+ $self -> {output }-> option_exit(short_msg => " No token found in '$content '" )
100+ unless ($decoded_content -> {access_token } || $decoded_content -> {token });
101+ # store in $self for further requests
102+ $self -> {token } = $decoded_content -> {access_token } // $decoded_content -> {token };
103+ $self -> {token_type } = $decoded_content -> {token_type } // ' Bearer' ;
104+ # store in cache for further executions
101105 $self -> {http }-> add_header(key => ' Authorization' , value => $self -> {token_type } . ' ' . $self -> {token });
102- $self -> {cache }-> write (data => { token => $decoded_content -> {token }, token_type => $decoded_content -> {token_type }, expiration => ($decoded_content -> {expires_in } + time ()) });
106+ $self -> {cache }-> write (data => { token => $self -> {token }, token_type => $self -> {token_type }, expiration => ($decoded_content -> {expires_in } + time ()) });
107+
103108 return $self -> {token };
104109}
105110
@@ -120,7 +125,7 @@ sub build_location_filters {
120125 # if location filters are provided, get the list of location ids
121126 my $locations = $self -> get_locations(%options );
122127 # $locations points to an array of {id, name}
123- return { loc => [map { $_ -> {id }} @$locations ] };
128+ return { loc => [ map {$_ -> {id }} @$locations ] };
124129}
125130
126131sub get_unique_app {
@@ -143,10 +148,10 @@ sub get_unique_app {
143148sub get_unique_app_metrics {
144149 my ($self , %options ) = @_ ;
145150
146- my $to = time ();
147- my $get_params = { %{ $self -> {get_params }} };
151+ my $to = time ();
152+ my $get_params = { %{$self -> {get_params }} };
148153 $get_params -> {from } = $to - 60 * ($options {max_metrics_age } // 20);
149- $get_params -> {to } = $to ;
154+ $get_params -> {to } = $to ;
150155
151156 my $content = $self -> {http }-> request(
152157 method => ' GET' ,
@@ -232,8 +237,8 @@ sub get_locations {
232237
233238 # get all locations and check which ones match the filters
234239 my $locations_json = $self -> {http }-> request(
235- method => ' GET' ,
236- url_path => $self -> {option_results }-> {api_path } . ' /administration/locations/'
240+ method => ' GET' ,
241+ url_path => $self -> {option_results }-> {api_path } . ' /administration/locations/'
237242 );
238243 my $locations = json_decode($locations_json , output => $self -> {output });
239244
@@ -246,8 +251,8 @@ sub get_locations {
246251 $options {exclude_location_name });
247252
248253 push @result , {
249- id => $loc -> {id },
250- name => $loc -> {name },
254+ id => $loc -> {id },
255+ name => $loc -> {name },
251256 };
252257 }
253258
@@ -259,10 +264,11 @@ sub set_defaults {}
259264sub check_options {
260265 my ($self , %options ) = @_ ;
261266
262- $self -> {$_ } = $self -> {option_results }-> {$_ } foreach qw( hostname port proto api_path timeout key_id key_secret ) ;
267+ $self -> {$_ } = $self -> {option_results }-> {$_ } foreach qw( hostname port proto timeout auth_url api_path client_id client_secret) ;
268+ $self -> {output }-> option_exit(short_msg => " Mandatory option 'auth-url' is missing for OneAPI authentication." ) if ($self -> {auth_url } eq ' ' );
263269
264- foreach (qw( key_id key_secret ) ) {
265- $self -> {output }-> option_exit(short_msg => " Mandatory option '$_ ' is missing." ) if ($self -> {$_ } eq ' ' );
270+ foreach (qw( client_id client_secret ) ) {
271+ $self -> {output }-> option_exit(short_msg => " Mandatory option '$_ ' is missing for OneAPI authentication ." ) if ($self -> {$_ } eq ' ' );
266272 $self -> {output }-> option_exit(short_msg => " Option '$_ ' contains illegal characters." ) if ($self -> {$_ } =~ / ([\b\f\n\r\t\"\\ ]+)/ );
267273 }
268274
@@ -274,9 +280,7 @@ sub check_options {
274280sub settings {
275281 my ($self , %options ) = @_ ;
276282
277- # $self->build_options_for_httplib();
278283 $self -> {http }-> add_header(key => ' Accept' , value => ' application/json' );
279- $self -> {http }-> add_header(key => ' Content-Type' , value => ' application/json' );
280284 $self -> {http }-> set_options(%{$self -> {option_results }});
281285}
282286
@@ -298,29 +302,37 @@ Zscaler Digital Experience (ZDX) Rest API
298302
299303=over 8
300304
305+ =item B<--auth-url >
306+
307+ Authentication URL to get a token from (mandatory).
308+
309+ Depends on your Zscaler customer name.
310+
311+ Example: C<https://company-name.zslogin.net/oauth2/v1/token > .
312+
301313=item B<--hostname >
302314
303- ZDX API hostname (default: C<api.zdxcloud .net > )
315+ API URL (default: C<api.zsapi .net > ). You should not need to change it.
304316
305317=item B<--port >
306318
307- API port (default: 443)
319+ API port (default: 443).
308320
309321=item B<--proto >
310322
311- Specify http if needed (default: 'https')
323+ Specify http if needed (default: 'https').
312324
313325=item B<--api-path >
314326
315- API URL path (default: '/api ')
327+ API URL path (default: '/zdx/v1 ')
316328
317- =item B<--key -id >
329+ =item B<--client -id >
318330
319- Key ID (see L<here|https://help.zscaler.com/zdx/managing-zdx-api-keys > for more details).
331+ Client ID for OneAPI authentication (see L<here|https://help.zscaler.com/zidentity/understanding-oneapi-authentication > for more details).
320332
321- =item B<--key -secret >
333+ =item B<--client -secret >
322334
323- Key secret (see L<here|https://help.zscaler.com/zdx/managing-zdx-api-keys > for more details).
335+ Client secret for OneAPI authentication (see L<here|https://help.zscaler.com/zidentity/understanding-oneapi-authentication > for more details).
324336
325337=item B<--timeout >
326338
0 commit comments