File Coverage

blib/lib/Net/Fortinet/FortiManager.pm
Criterion Covered Total %
statement 23 435 5.2
branch 0 40 0.0
condition 0 27 0.0
subroutine 8 71 11.2
pod 56 56 100.0
total 87 629 13.8


line stmt bran cond sub pod time code
1             package Net::Fortinet::FortiManager;
2             $Net::Fortinet::FortiManager::VERSION = '0.003001';
3             # ABSTRACT: Fortinet FortiManager REST API client library
4              
5 1     1   211572 use 5.024;
  1         6  
6 1     1   474 use Moo;
  1         6127  
  1         4  
7 1     1   1245 use feature 'signatures';
  1         2  
  1         134  
8 1     1   515 use Types::Standard qw( ArrayRef HashRef InstanceOf Str );
  1         86160  
  1         12  
9 1     1   1508 use Types::Common::Numeric qw( PositiveInt );
  1         17964  
  1         6  
10 1     1   407 use Carp qw( croak );
  1         2  
  1         55  
11 1     1   5 use List::Util qw( all any none );
  1         2  
  1         58  
12              
13 1     1   5 no warnings "experimental::signatures";
  1         1  
  1         3617  
14              
15              
16             has 'user' => (
17             isa => Str,
18             is => 'rw',
19             predicate => 1,
20             );
21              
22             has 'passwd' => (
23             isa => Str,
24             is => 'rw',
25             predicate => 1,
26             );
27              
28             has '_sessionid' => (
29             isa => Str,
30             is => 'rw',
31             predicate => 1,
32             clearer => 1,
33             );
34              
35             has '_last_transaction_id' => (
36             isa => PositiveInt,
37             is => 'rw',
38             predicate => 1,
39             clearer => 1,
40             );
41              
42 0     0     sub _get_transaction_id ($self) {
  0            
  0            
43 0           my $id;
44 0 0         if ($self->_has_last_transaction_id) {
45 0           $id = $self->_last_transaction_id;
46 0           $id++;
47             }
48             else {
49 0           $id = 1;
50             }
51              
52 0           $self->_last_transaction_id($id);
53 0           return $id;
54             }
55              
56              
57             has 'adoms' => (
58             is => 'rwp',
59             isa => ArrayRef[Str],
60             );
61              
62              
63             has 'adom' => (
64             is => 'rw',
65             isa => Str,
66             default => sub { 'root' },
67             );
68              
69             with 'Role::REST::Client';
70              
71             # around 'do_request' => sub($orig, $self, $method, $uri, $opts) {
72             # warn 'request: ' . np($method, $uri, $opts);
73             # my $response = $orig->($self, $method, $uri, $opts);
74             # warn 'response: ' . np($response);
75             # return $response;
76             # };
77              
78 0     0     sub _http_error_handler ($self, $res) {
  0            
  0            
  0            
79 0 0         croak('http error (' . $res->code . '): ' . $res->response->decoded_content)
80             unless $res->code == 200;
81             }
82              
83 0     0     sub _rpc_error_handler ($self, $res, $number_of_expected_results) {
  0            
  0            
  0            
  0            
84 0 0 0       if (ref $res->data eq 'HASH'
      0        
      0        
      0        
85             && exists $res->data->{result}
86             && ref $res->data->{result} eq 'ARRAY'
87             && scalar $res->data->{result}->@* == $number_of_expected_results
88 0     0     && all { ref $_ eq 'HASH' } $res->data->{result}->@* ) {
89 0 0         if ($number_of_expected_results == 1) {
90 0           my $code = $res->data->{result}->[0]->{status}->{code};
91 0           my $message = $res->data->{result}->[0]->{status}->{message};
92 0 0         if ($code != 0) {
93 0           croak("jsonrpc error ($code): $message");
94             }
95             }
96             else {
97             my @failed_calls = grep {
98 0           $_->{status}->{code} != 0
99 0           } $res->data->{result}->@*;
100              
101 0 0         if (@failed_calls) {
102             croak("jsonrpc errors: " . join(', ', map {
103 0           $_->{url} . ': (' . $_->{status}->{code} . ') ' .
104             $_->{status}->{message}
105 0           } @failed_calls));
106             }
107             }
108             }
109             else {
110 0           croak "jsonrpc error: response not in expected format: " .
111             $res->response->decoded_content;
112             }
113             }
114              
115 0     0     sub _exec_method ($self, $method, $params = undef) {
  0            
  0            
  0            
  0            
116 0 0 0       croak 'params needs to be an arrayref'
117             if defined $params && ref $params ne 'ARRAY';
118              
119 0           my $body = {
120             id => $self->_get_transaction_id,
121             method => $method,
122             params => $params,
123             verbose => 1,
124             };
125 0 0         $body->{session} = $self->_sessionid
126             if $self->_has_sessionid;
127              
128             # p $body;
129 0           my $res = $self->post('/jsonrpc', $body);
130             # p $res;
131              
132 0           $self->_http_error_handler($res);
133              
134 0 0         $self->_rpc_error_handler($res, defined $params ? scalar $params->@* : 1);
135              
136 0           return $res;
137             }
138              
139              
140 0     0 1   sub exec_method ($self, $method, $url, $params = undef) {
  0            
  0            
  0            
  0            
  0            
141 0 0 0       croak 'params needs to be a hashref'
142             if defined $params && ref $params ne 'HASH';
143              
144 0 0         my %full_params = defined $params
145             ? $params->%*
146             : ();
147 0           $full_params{url} = $url;
148 0           my $rv = $self->_exec_method($method, [\%full_params])->data;
149              
150             # the existance of {result}[0] is already verified by _rpc_error_handler
151             # called in _exec_method
152 0 0         if (exists $rv->{result}[0]->{data}) {
153 0           return $rv->{result}[0]->{data};
154             }
155 0           return 1;
156             }
157              
158              
159 0     0 1   sub exec_method_multi ($self, $method, $params) {
  0            
  0            
  0            
  0            
160 0 0         croak 'params needs to be an arrayref'
161             unless ref $params eq 'ARRAY';
162              
163             croak 'each parameter needs to be a hashref'
164 0 0   0     unless any { ref $_ eq 'HASH' } $params->@*;
  0            
165              
166 0           my $rv = $self->_exec_method($method, $params)->data;
167              
168 0 0         if (exists $rv->{result}) {
169 0           return $rv->{result};
170             }
171 0           return 1;
172             }
173              
174              
175 0     0 1   sub login ($self) {
  0            
  0            
176 0 0 0       die "user and password required\n"
177             unless $self->has_user && $self->has_passwd;
178              
179 0           my $res = $self->_exec_method('exec', [{
180             url => "/sys/login/user",
181             data => {
182             user => $self->user,
183             passwd => $self->passwd,
184             },
185             }]);
186              
187 0           $self->_sessionid($res->data->{session});
188              
189 0           $self->_set_adoms($self->list_adoms_by_name);
190              
191             # switch to first ADOM if the currently set ADOM isn't available
192 0 0   0     if (none { $_ eq $self->adom } $self->adoms->@*) {
  0            
193 0           $self->adom($self->adoms->[0]);
194             }
195              
196 0           return 1;
197             }
198              
199              
200 0     0 1   sub logout ($self) {
  0            
  0            
201 0           $self->exec_method('exec', '/sys/logout');
202 0           $self->_clear_sessionid;
203 0           $self->_clear_last_transaction_id;
204              
205 0           return 1;
206             }
207              
208              
209 0     0 1   sub get_sys_status ($self) {
  0            
  0            
210 0           return $self->exec_method('get', '/sys/status');
211             }
212              
213              
214 0     0 1   sub list_adoms ($self, $params = {}) {
  0            
  0            
  0            
215 0           $self->exec_method('get', '/dvmdb/adom', $params);
216             }
217              
218              
219 0     0 1   sub list_adoms_by_name ($self) {
  0            
  0            
220             my @adoms =
221             sort
222             map {
223 0           $_->{name}
224 0           } $self->list_adoms({
225             fields => [qw( name )],
226             })->@*;
227 0           return \@adoms;
228             }
229              
230              
231 0     0 1   sub list_firewall_addresses ($self, $params = {}) {
  0            
  0            
  0            
232 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
233             '/obj/firewall/address', $params);
234             }
235              
236              
237 0     0 1   sub get_firewall_address ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
238 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
239             '/obj/firewall/address/'. $name, $params);
240             }
241              
242              
243 0     0 1   sub create_firewall_address ($self, $name, $data) {
  0            
  0            
  0            
  0            
244 0           my $params = {
245             data => [{
246             $data->%*,
247             name => $name,
248             }],
249             };
250 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
251             '/obj/firewall/address', $params);
252             }
253              
254              
255 0     0 1   sub update_firewall_address ($self, $name, $data) {
  0            
  0            
  0            
  0            
256 0           my $params = {
257             data => {
258             $data->%*,
259             },
260             };
261 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
262             '/obj/firewall/address/' . $name, $params);
263             }
264              
265              
266 0     0 1   sub delete_firewall_address ($self, $name) {
  0            
  0            
  0            
267 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
268             '/obj/firewall/address/' . $name);
269             }
270              
271              
272 0     0 1   sub list_firewall_address_groups ($self, $params = {}) {
  0            
  0            
  0            
273 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
274             '/obj/firewall/addrgrp', $params);
275             }
276              
277              
278 0     0 1   sub get_firewall_address_group ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
279 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
280             '/obj/firewall/addrgrp/'. $name, $params);
281             }
282              
283              
284 0     0 1   sub create_firewall_address_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
285 0           my $params = {
286             data => [{
287             $data->%*,
288             name => $name,
289             }],
290             };
291 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
292             '/obj/firewall/addrgrp', $params);
293             }
294              
295              
296 0     0 1   sub update_firewall_address_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
297 0           my $params = {
298             data => {
299             $data->%*,
300             },
301             };
302 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
303             '/obj/firewall/addrgrp/' . $name, $params);
304             }
305              
306              
307 0     0 1   sub delete_firewall_address_group ($self, $name) {
  0            
  0            
  0            
308 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
309             '/obj/firewall/addrgrp/' . $name);
310             }
311              
312              
313 0     0 1   sub list_firewall_ipv6_addresses ($self, $params = {}) {
  0            
  0            
  0            
314 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
315             '/obj/firewall/address6', $params);
316             }
317              
318              
319 0     0 1   sub get_firewall_ipv6_address ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
320 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
321             '/obj/firewall/address6/'. $name, $params);
322             }
323              
324              
325 0     0 1   sub create_firewall_ipv6_address ($self, $name, $data) {
  0            
  0            
  0            
  0            
326 0           my $params = {
327             data => [{
328             $data->%*,
329             name => $name,
330             }],
331             };
332 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
333             '/obj/firewall/address6', $params);
334             }
335              
336              
337 0     0 1   sub update_firewall_ipv6_address ($self, $name, $data) {
  0            
  0            
  0            
  0            
338 0           my $params = {
339             data => {
340             $data->%*,
341             },
342             };
343 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
344             '/obj/firewall/address6/' . $name, $params);
345             }
346              
347              
348 0     0 1   sub delete_firewall_ipv6_address ($self, $name) {
  0            
  0            
  0            
349 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
350             '/obj/firewall/address6/' . $name);
351             }
352              
353              
354 0     0 1   sub list_firewall_ipv6_address_groups ($self, $params = {}) {
  0            
  0            
  0            
355 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
356             '/obj/firewall/addrgrp6', $params);
357             }
358              
359              
360 0     0 1   sub get_firewall_ipv6_address_group ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
361 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
362             '/obj/firewall/addrgrp6/'. $name, $params);
363             }
364              
365              
366 0     0 1   sub create_firewall_ipv6_address_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
367 0           my $params = {
368             data => [{
369             $data->%*,
370             name => $name,
371             }],
372             };
373 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
374             '/obj/firewall/addrgrp6', $params);
375             }
376              
377              
378 0     0 1   sub update_firewall_ipv6_address_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
379 0           my $params = {
380             data => {
381             $data->%*,
382             },
383             };
384 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
385             '/obj/firewall/addrgrp6/' . $name, $params);
386             }
387              
388              
389 0     0 1   sub delete_firewall_ipv6_address_group ($self, $name) {
  0            
  0            
  0            
390 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
391             '/obj/firewall/addrgrp6/' . $name);
392             }
393              
394              
395 0     0 1   sub list_firewall_services ($self, $params = {}) {
  0            
  0            
  0            
396 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
397             '/obj/firewall/service/custom', $params);
398             }
399              
400              
401 0     0 1   sub get_firewall_service ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
402 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
403             '/obj/firewall/service/custom/'. $name, $params);
404             }
405              
406              
407 0     0 1   sub create_firewall_service ($self, $name, $data) {
  0            
  0            
  0            
  0            
408 0           my $params = {
409             data => [{
410             $data->%*,
411             name => $name,
412             }],
413             };
414 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
415             '/obj/firewall/service/custom', $params);
416             }
417              
418              
419 0     0 1   sub update_firewall_service ($self, $name, $data) {
  0            
  0            
  0            
  0            
420 0           my $params = {
421             data => {
422             $data->%*,
423             },
424             };
425 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
426             '/obj/firewall/service/custom/' . $name, $params);
427             }
428              
429              
430 0     0 1   sub delete_firewall_service ($self, $name) {
  0            
  0            
  0            
431 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
432             '/obj/firewall/service/custom/' . $name);
433             }
434              
435              
436 0     0 1   sub list_firewall_service_groups ($self, $params = {}) {
  0            
  0            
  0            
437 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
438             '/obj/firewall/service/group', $params);
439             }
440              
441              
442 0     0 1   sub get_firewall_service_group ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
443 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
444             '/obj/firewall/service/group/'. $name, $params);
445             }
446              
447              
448 0     0 1   sub create_firewall_service_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
449 0           my $params = {
450             data => [{
451             $data->%*,
452             name => $name,
453             }],
454             };
455 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
456             '/obj/firewall/service/group', $params);
457             }
458              
459              
460 0     0 1   sub update_firewall_service_group ($self, $name, $data) {
  0            
  0            
  0            
  0            
461 0           my $params = {
462             data => {
463             $data->%*,
464             },
465             };
466 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
467             '/obj/firewall/service/group/' . $name, $params);
468             }
469              
470              
471 0     0 1   sub delete_firewall_service_group ($self, $name) {
  0            
  0            
  0            
472 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
473             '/obj/firewall/service/group/' . $name);
474             }
475              
476              
477 0     0 1   sub list_policy_packages ($self, $params = {}) {
  0            
  0            
  0            
478 0           $self->exec_method('get', '/pm/pkg/adom/' . $self->adom, $params);
479             }
480              
481              
482 0     0 1   sub get_policy_package ($self, $name, $params = {}) {
  0            
  0            
  0            
  0            
483 0           $self->exec_method('get', '/pm/pkg/adom/' . $self->adom . '/'. $name,
484             $params);
485             }
486              
487              
488 0     0 1   sub create_policy_package ($self, $name, $data) {
  0            
  0            
  0            
  0            
489 0           my $params = {
490             data => [{
491             $data->%*,
492             name => $name,
493             }],
494             };
495 0           $self->exec_method('add', '/pm/pkg/adom/' . $self->adom, $params);
496             }
497              
498              
499 0     0 1   sub update_policy_package ($self, $name, $data) {
  0            
  0            
  0            
  0            
500 0           my $params = {
501             data => {
502             $data->%*,
503             },
504             };
505 0           $self->exec_method('update', '/pm/pkg/adom/' . $self->adom . '/' . $name,
506             $params);
507             }
508              
509              
510 0     0 1   sub delete_policy_package ($self, $name) {
  0            
  0            
  0            
511 0           $self->exec_method('delete', '/pm/pkg/adom/' . $self->adom . '/' . $name);
512             }
513              
514              
515 0     0 1   sub install_policy_package ($self, $name, $data = {}) {
  0            
  0            
  0            
  0            
516 0           my $params = {
517             data => {
518             $data->%*,
519             adom => $self->adom,
520             pkg => $name,
521             },
522             };
523 0           my $res = $self->exec_method('exec', '/securityconsole/install/package',
524             $params);
525              
526 0           return $res->{task};
527             }
528              
529              
530 0     0 1   sub list_tasks ($self, $params = {}) {
  0            
  0            
  0            
531 0           $self->exec_method('get', '/task/task', $params);
532             }
533              
534              
535 0     0 1   sub get_task ($self, $id, $params = {}) {
  0            
  0            
  0            
  0            
536 0           $self->exec_method('get', '/task/task/' . $id, $params);
537             }
538              
539              
540 0     0 1   sub wait_for_task($self, $taskid, $callback = undef) {
  0            
  0            
  0            
  0            
541 0 0         croak "task-id missing"
542             unless defined $taskid;
543 0 0 0       croak "callback must be a coderef"
544             if defined $callback && ref $callback ne 'CODE';
545              
546 0           my $task;
547 0   0       while (($task = $self->get_task($taskid))
548             && $task->{percent} != 100) {
549 0 0         &$callback($task)
550             if defined $callback;
551 0           sleep 1;
552             }
553 0           return $task;
554             }
555              
556              
557 0     0 1   sub list_firewall_policies ($self, $pkg, $params = {}) {
  0            
  0            
  0            
  0            
558 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
559             '/pkg/' . $pkg . '/firewall/policy', $params);
560             }
561              
562              
563 0     0 1   sub get_firewall_policy ($self, $pkg, $id, $params = {}) {
  0            
  0            
  0            
  0            
  0            
564 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
565             '/pkg/' . $pkg . '/firewall/policy/' . $id, $params);
566             }
567              
568              
569 0     0 1   sub create_firewall_policy ($self, $pkg, $data) {
  0            
  0            
  0            
  0            
570 0           my $params = {
571             data => [{
572             $data->%*,
573             }],
574             };
575 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
576             '/pkg/' . $pkg . '/firewall/policy', $params);
577             }
578              
579              
580 0     0 1   sub update_firewall_policy ($self, $pkg, $id, $data) {
  0            
  0            
  0            
  0            
  0            
581 0           my $params = {
582             data => {
583             $data->%*,
584             },
585             };
586 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
587             '/pkg/' . $pkg . '/firewall/policy/' . $id , $params);
588             }
589              
590              
591 0     0 1   sub delete_firewall_policy ($self, $pkg, $id) {
  0            
  0            
  0            
  0            
592 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
593             '/pkg/' . $pkg . '/firewall/policy/' . $id);
594             }
595              
596              
597 0     0 1   sub list_firewall_security_policies ($self, $pkg, $params = {}) {
  0            
  0            
  0            
  0            
598 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
599             '/pkg/' . $pkg . '/firewall/security-policy', $params);
600             }
601              
602              
603 0     0 1   sub get_firewall_security_policy ($self, $pkg, $id, $params = {}) {
  0            
  0            
  0            
  0            
  0            
604 0           $self->exec_method('get', '/pm/config/adom/' . $self->adom .
605             '/pkg/' . $pkg . '/firewall/security-policy/' . $id, $params);
606             }
607              
608              
609              
610 0     0 1   sub create_firewall_security_policy ($self, $pkg, $data) {
  0            
  0            
  0            
  0            
611 0           my $params = {
612             data => [{
613             $data->%*,
614             }],
615             };
616 0           $self->exec_method('add', '/pm/config/adom/' . $self->adom .
617             '/pkg/' . $pkg . '/firewall/security-policy', $params);
618             }
619              
620              
621 0     0 1   sub update_firewall_security_policy ($self, $pkg, $id, $data) {
  0            
  0            
  0            
  0            
  0            
622 0           my $params = {
623             data => {
624             $data->%*,
625             },
626             };
627 0           $self->exec_method('update', '/pm/config/adom/' . $self->adom .
628             '/pkg/' . $pkg . '/firewall/security-policy/' . $id , $params);
629             }
630              
631              
632 0     0 1   sub delete_firewall_security_policy ($self, $pkg, $id) {
  0            
  0            
  0            
  0            
633 0           $self->exec_method('delete', '/pm/config/adom/' . $self->adom .
634             '/pkg/' . $pkg . '/firewall/security-policy/' . $id);
635             }
636              
637              
638             1;
639              
640             __END__
641              
642             =pod
643              
644             =encoding UTF-8
645              
646             =head1 NAME
647              
648             Net::Fortinet::FortiManager - Fortinet FortiManager REST API client library
649              
650             =head1 VERSION
651              
652             version 0.003001
653              
654             =head1 SYNOPSIS
655              
656             use strict;
657             use warnings;
658             use Net::Fortinet::FortiManager;
659              
660             my $fortimanager = Net::Fortinet::FortiManager->new(
661             server => 'https://fortimanager.example.com',
662             user => 'username',
663             passwd => '$password',
664             clientattrs => {
665             timeout => 10,
666             },
667             );
668              
669             $fortimanager->login;
670              
671             $fortimanager->adom('adomname');
672              
673             =head1 DESCRIPTION
674              
675             This module is a client library for the Fortigate FortiManager JSONRPC-like
676             API.
677             Currently it is developed and tested against version 6.4.6.
678             All requests have the verbose parameter set to 1 to ensure that enums return
679             their strings instead of undocumented ids.
680              
681             =head1 ATTRIBUTES
682              
683             =head2 adoms
684              
685             Returns a list of hashrefs containing name and uuid of all ADOMs which gets
686             populated by L</login>.
687              
688             =head2 adom
689              
690             The name of the ADOM which is used by all methods.
691             Defaults to 'root'.
692              
693             =head1 METHODS
694              
695             =head2 exec_method
696              
697             Executes a method with the specified parameters.
698              
699             Returns its response.
700              
701             This is the lowest level method which can be used to execute every API action
702             that's available.
703             It does the http and JSONRPC error handling and extraction of the result
704             from the JSONRPC response.
705              
706             =head2 exec_method_multi
707              
708             Executes a method with multiple specified parameters.
709              
710             Returns its responses.
711              
712             This is also a low level method which can be used to execute multiple API
713             actions in a single JSONRPC call.
714             The only restriction of the JSONRPC API is that all actions need to use the
715             same method.
716             It does the http and JSONRPC error handling and extraction of the results
717             from the JSONRPC response.
718              
719             =head2 login
720              
721             Logs into the Fortinet FortiManager and switches to the first available ADOM
722             if the currently set L<adom> isn't available, for example because the user
723             is limited to one or more ADOMs.
724              
725             =head2 logout
726              
727             Logs out of the Fortinet FortiManager.
728              
729             =head2 get_sys_status
730              
731             Returns /sys/status.
732              
733             =head2 list_adoms
734              
735             Takes an optional parameter hashref.
736              
737             Returns an arrayref of ADOMs.
738              
739             =head2 list_adoms_by_name
740              
741             Returns an arrayref of ADOMs sorted by name.
742              
743             =head2 list_firewall_addresses
744              
745             Returns an arrayref of firewall addresses.
746              
747             =head2 get_firewall_address
748              
749             Takes a firewall address name and an optional parameter hashref.
750              
751             Returns its data as a hashref.
752              
753             =head2 create_firewall_address
754              
755             Takes a firewall address name and a hashref of address config.
756              
757             Returns true on success.
758              
759             Throws an exception on error.
760              
761             =head2 update_firewall_address
762              
763             Takes a firewall address name and a hashref of address config.
764              
765             Returns true on success.
766              
767             Throws an exception on error.
768              
769             =head2 delete_firewall_address
770              
771             Takes a firewall address name.
772              
773             Returns true on success.
774              
775             Throws an exception on error.
776              
777             =head2 list_firewall_address_groups
778              
779             Returns an arrayref of firewall address groups.
780              
781             =head2 get_firewall_address_group
782              
783             Takes a firewall address group name and an optional parameter hashref.
784              
785             Returns its data as a hashref.
786              
787             =head2 create_firewall_address_group
788              
789             Takes a firewall address group name and a hashref of address group config.
790              
791             Returns true on success.
792              
793             Throws an exception on error.
794              
795             =head2 update_firewall_address_group
796              
797             Takes a firewall address group name and a hashref of address group config.
798              
799             Returns true on success.
800              
801             Throws an exception on error.
802              
803             =head2 delete_firewall_address_group
804              
805             Takes a firewall address group name.
806              
807             Returns true on success.
808              
809             Throws an exception on error.
810              
811             =head2 list_firewall_ipv6_addresses
812              
813             Returns an arrayref of firewall IPv6 addresses.
814              
815             =head2 get_firewall_ipv6_address
816              
817             Takes a firewall IPv6 address name and an optional parameter hashref.
818              
819             Returns its data as a hashref.
820              
821             =head2 create_firewall_ipv6_address
822              
823             Takes a firewall IPv6 address name and a hashref of address config.
824              
825             Returns true on success.
826              
827             Throws an exception on error.
828              
829             =head2 update_firewall_ipv6_address
830              
831             Takes a firewall IPv6 address name and a hashref of address config.
832              
833             Returns true on success.
834              
835             Throws an exception on error.
836              
837             =head2 delete_firewall_ipv6_address
838              
839             Takes a firewall IPv6 address name.
840              
841             Returns true on success.
842              
843             Throws an exception on error.
844              
845             =head2 list_firewall_ipv6_address_groups
846              
847             Returns an arrayref of firewall IPv6 address groups.
848              
849             =head2 get_firewall_ipv6_address_group
850              
851             Takes a firewall IPv6 address group name and an optional parameter hashref.
852              
853             Returns its data as a hashref.
854              
855             =head2 create_firewall_ipv6_address_group
856              
857             Takes a firewall IPv6 address group name and a hashref of address group config.
858              
859             Returns true on success.
860              
861             Throws an exception on error.
862              
863             =head2 update_firewall_ipv6_address_group
864              
865             Takes a firewall IPv6 address group name and a hashref of address group config.
866              
867             Returns true on success.
868              
869             Throws an exception on error.
870              
871             =head2 delete_firewall_ipv6_address_group
872              
873             Takes a firewall IPv6 address group name.
874              
875             Returns true on success.
876              
877             Throws an exception on error.
878              
879             =head2 list_firewall_services
880              
881             Returns an arrayref of firewall services.
882              
883             =head2 get_firewall_service
884              
885             Takes a firewall service name and an optional parameter hashref.
886              
887             Returns its data as a hashref.
888              
889             =head2 create_firewall_service
890              
891             Takes a firewall service name and a hashref of service config.
892              
893             Returns true on success.
894              
895             Throws an exception on error.
896              
897             =head2 update_firewall_service
898              
899             Takes a firewall service name and a hashref of service config.
900              
901             Returns true on success.
902              
903             Throws an exception on error.
904              
905             =head2 delete_firewall_service
906              
907             Takes a firewall service name.
908              
909             Returns true on success.
910              
911             Throws an exception on error.
912              
913             =head2 list_firewall_service_groups
914              
915             Returns an arrayref of firewall service groups.
916              
917             =head2 get_firewall_service_group
918              
919             Takes a firewall service group name and an optional parameter hashref.
920              
921             Returns its data as a hashref.
922              
923             =head2 create_firewall_service_group
924              
925             Takes a firewall service group name and a hashref of service group config.
926              
927             Returns true on success.
928              
929             Throws an exception on error.
930              
931             =head2 update_firewall_service_group
932              
933             Takes a firewall service group name and a hashref of service group config.
934              
935             Returns true on success.
936              
937             Throws an exception on error.
938              
939             =head2 delete_firewall_service_group
940              
941             Takes a firewall service group name.
942              
943             Returns true on success.
944              
945             Throws an exception on error.
946              
947             =head2 list_policy_packages
948              
949             Takes optional parameters.
950              
951             Returns an arrayref of policy packages.
952              
953             =head2 get_policy_package
954              
955             Takes a policy package name and an optional parameter hashref.
956              
957             Returns its data as a hashref.
958              
959             =head2 create_policy_package
960              
961             Takes a policy package name and a hashref of attributes.
962              
963             Returns true on success.
964              
965             Throws an exception on error.
966              
967             The firewall policies are configured depending on the 'ngfw-mode'.
968             For profile-based policy packages you have to use the 'policy' methods,
969             for policy-based the 'security_policy' methods.
970              
971             =head2 update_policy_package
972              
973             Takes a policy package name and a hashref of attributes.
974              
975             Returns true on success.
976              
977             Throws an exception on error.
978              
979             =head2 delete_policy_package
980              
981             Takes a policy package name.
982              
983             Returns true on success.
984              
985             Throws an exception on error.
986              
987             =head2 install_policy_package
988              
989             Takes a policy package name and a hashref of parameters.
990              
991             Returns the task id on success.
992              
993             Throws an exception on error.
994              
995             =head2 list_tasks
996              
997             Takes optional parameters.
998              
999             Returns an arrayref of tasks.
1000              
1001             =head2 get_task
1002              
1003             Takes a task id and an optional parameter hashref.
1004              
1005             Returns its data as a hashref.
1006              
1007             =head2 wait_for_task
1008              
1009             Takes a task id and checks its status every second until its percent
1010             have reached 100 and return the status.
1011             Takes an optional callback coderef which is called for every check with the
1012             task as argument.
1013              
1014             =head2 list_firewall_policies
1015              
1016             Takes a package name and optional parameters.
1017              
1018             Returns an arrayref of firewall policies.
1019              
1020             =head2 get_firewall_policy
1021              
1022             Takes a policy package name, a firewall policy id and an optional parameter
1023             hashref.
1024              
1025             Returns its data as a hashref.
1026              
1027             =head2 create_firewall_policy
1028              
1029             Takes a policy package name and a hashref of firewall policy attributes.
1030              
1031             Returns the response data from the API on success which is a hashref
1032             containing only the policyid.
1033              
1034             Throws an exception on error.
1035              
1036             =head2 update_firewall_policy
1037              
1038             Takes a policy package name, a firewall policy id and a hashref of firewall
1039             policy attributes.
1040              
1041             Returns the response data from the API on success which is a hashref
1042             containing only the policyid.
1043              
1044             Throws an exception on error.
1045              
1046             =head2 delete_firewall_policy
1047              
1048             Takes a policy package name and a firewall policy id.
1049              
1050             Returns true on success.
1051              
1052             Throws an exception on error.
1053              
1054             =head2 list_firewall_security_policies
1055              
1056             Takes a package name and optional parameters.
1057              
1058             Returns an arrayref of firewall security policies.
1059              
1060             =head2 get_firewall_security_policy
1061              
1062             Takes a policy package name, a firewall security policy id and an optional
1063             parameter hashref.
1064              
1065             Returns its data as a hashref.
1066              
1067             =head2 create_firewall_security_policy
1068              
1069             Takes a policy package name and a hashref of firewall security policy
1070             attributes.
1071              
1072             Returns the response data from the API on success which is a hashref
1073             containing only the policyid.
1074              
1075             Throws an exception on error.
1076              
1077             =head2 update_firewall_security_policy
1078              
1079             Takes a policy package name, a firewall security policy id and a hashref of
1080             firewall security policy attributes.
1081              
1082             Returns the response data from the API on success which is a hashref
1083             containing only the policyid.
1084              
1085             Throws an exception on error.
1086              
1087             =head2 delete_firewall_security_policy
1088              
1089             Takes a policy package name and a firewall security policy id.
1090              
1091             Returns true on success.
1092              
1093             Throws an exception on error.
1094              
1095             =for Pod::Coverage has_user has_passwd has_api_key
1096              
1097             =head1 TESTS
1098              
1099             To run the live API tests the following environment variables need to be set:
1100              
1101             =over
1102              
1103             =item NET_FORTINET_FORTIMANAGER_HOSTNAME
1104              
1105             =item NET_FORTINET_FORTIMANAGER_USERNAME
1106              
1107             =item NET_FORTINET_FORTIMANAGER_PASSWORD
1108              
1109             =item NET_FORTINET_FORTIMANAGER_POLICY
1110              
1111             =back
1112              
1113             Several network objects are created as well as a policy package named by the
1114             NET_FORTINET_FORTIMANAGER_POLICY environment variable.
1115              
1116             The test aborts if any of the objects can't be created, most likely if it
1117             already exists.
1118             All objects are deleted at the end of the test run, even when it aborts.
1119              
1120             =head1 AUTHOR
1121              
1122             Alexander Hartmaier <abraxxa@cpan.org>
1123              
1124             =head1 COPYRIGHT AND LICENSE
1125              
1126             This software is copyright (c) 2022 by Alexander Hartmaier.
1127              
1128             This is free software; you can redistribute it and/or modify it under
1129             the same terms as the Perl 5 programming language system itself.
1130              
1131             =cut