File Coverage

blib/lib/Net/Checkpoint/Management/v1.pm
Criterion Covered Total %
statement 26 194 13.4
branch 0 60 0.0
condition 0 45 0.0
subroutine 9 25 36.0
pod 8 8 100.0
total 43 332 12.9


line stmt bran cond sub pod time code
1             package Net::Checkpoint::Management::v1;
2             $Net::Checkpoint::Management::v1::VERSION = '0.003000';
3             # ABSTRACT: Checkpoint Management API version 1.x client library
4              
5 1     1   249032 use 5.024;
  1         10  
6 1     1   659 use Moo;
  1         7835  
  1         4  
7 1     1   1616 use feature 'signatures';
  1         3  
  1         169  
8 1     1   735 use Types::Standard qw( ArrayRef Str );
  1         119899  
  1         14  
9 1     1   3495 use Carp::Clan qw(^Net::Checkpoint::Management::v1);
  1         1964  
  1         8  
10 1     1   552 use Clone qw( clone );
  1         2506  
  1         89  
11 1     1   7 use List::Util qw( first );
  1         2  
  1         69  
12 1     1   521 use Net::Checkpoint::Management::v1::Role::ObjectMethods;
  1         3  
  1         38  
13              
14 1     1   7 no warnings "experimental::signatures";
  1         2  
  1         2509  
15              
16              
17             has 'user' => (
18             isa => Str,
19             is => 'rw',
20             );
21             has 'passwd' => (
22             isa => Str,
23             is => 'rw',
24             );
25              
26              
27             has 'api_versions' => (
28             is => 'lazy',
29             isa => ArrayRef[Str],
30             );
31              
32 0     0     sub _build_api_versions ($self) {
  0            
  0            
33 0           my $res_versions = $self->post('/web_api/v1.1/show-api-versions', {});
34 0           return $res_versions->data->{'supported-versions'};
35             }
36              
37              
38             has 'api_version' => (
39             is => 'rw',
40             isa => Str,
41             );
42              
43             with 'Net::Checkpoint::Management::v1::Role::REST::Client';
44              
45 0     0     sub _error_handler ($self, $data) {
  0            
  0            
  0            
46 0           my $error_message;
47              
48 0 0         if (ref $data eq 'HASH' ) {
49 0 0 0       if (exists $data->{'blocking-errors'}
    0 0        
    0 0        
      0        
      0        
      0        
      0        
      0        
      0        
50             && ref $data->{'blocking-errors'} eq 'ARRAY'
51             && exists $data->{'blocking-errors'}->[0]
52             && exists $data->{'blocking-errors'}->[0]->{message}) {
53 0           $error_message = $data->{'blocking-errors'}->[0]->{message};
54             }
55             elsif (exists $data->{errors}
56             && ref $data->{errors} eq 'ARRAY'
57             && exists $data->{errors}->[0]
58             && exists $data->{errors}->[0]->{message}) {
59 0           $error_message = $data->{errors}->[0]->{message};
60             }
61             # when ignore-warnings isn't passed to the API call, a response with only
62             # warnings is also considered an error because its changes aren't saved
63             # when passing ignore-warnings the error handler isn't called because the
64             # http response code is 200
65             elsif (exists $data->{warnings}
66             && ref $data->{warnings} eq 'ARRAY'
67             && exists $data->{warnings}->[0]
68             && exists $data->{warnings}->[0]->{message}) {
69 0           $error_message = $data->{warnings}->[0]->{message};
70             }
71             else {
72 0           $error_message = $data->{message};
73             }
74             }
75             # underlying exception like Could not connect to 'cpmanager.example.org'
76             else {
77 0           $error_message = $data;
78             }
79 0           croak($error_message);
80             }
81              
82 0     0     sub _create ($self, $url, $object_data, $query_params = {}) {
  0            
  0            
  0            
  0            
  0            
83 0           my $params = $self->user_agent->www_form_urlencode( $query_params );
84 0           my $res = $self->post("$url?$params", $object_data);
85 0           my $code = $res->code;
86 0           my $data = $res->data;
87              
88 0 0         $self->_error_handler($data)
89             unless $code == 200;
90 0           return $data;
91             }
92              
93 0     0     sub _list ($self, $url, $list_key, $query_params = {}) {
  0            
  0            
  0            
  0            
  0            
94             # the API only allows 500 objects at a time
95             # work around that by making multiple API calls
96 0           my $offset = 0;
97             my $limit = exists $query_params->{limit}
98             ? $query_params->{limit}
99 0 0         : 500;
100 0           my $more_data_available = 1;
101 0           my $response;
102 0           while ($more_data_available) {
103 0           my $res = $self->post($url, {
104             offset => $offset,
105             limit => $limit,
106             %$query_params,
107             });
108 0           my $code = $res->code;
109 0           my $data = $res->data;
110 0 0         $self->_error_handler($data)
111             unless $code == 200;
112              
113             # use first response for base structure of response
114 0 0         if ($offset == 0) {
115 0           $response = clone($data);
116 0           delete $response->{from};
117 0           delete $response->{to};
118             }
119             else {
120             push $response->{$list_key}->@*, $data->{$list_key}->@*
121 0 0 0       if exists $data->{$list_key} && ref $data->{$list_key} eq 'ARRAY';
122             }
123              
124             # check if more data is available
125 0 0         if ($offset + $limit < $data->{total}) {
126 0           $more_data_available = 1;
127 0           $offset += $limit;
128             }
129             else {
130 0           $more_data_available = 0;
131             }
132             }
133              
134             # return response similar to Checkpoint API
135 0           return $response;
136             }
137              
138 0     0     sub _get ($self, $url, $query_params = {}) {
  0            
  0            
  0            
  0            
139 0           my $res = $self->post($url, $query_params);
140 0           my $code = $res->code;
141 0           my $data = $res->data;
142              
143 0 0         $self->_error_handler($data)
144             unless $code == 200;
145              
146 0           return $data;
147             }
148              
149 0     0     sub _update ($self, $url, $object_data) {
  0            
  0            
  0            
  0            
150 0           my $res = $self->post($url, $object_data);
151 0           my $code = $res->code;
152 0           my $data = $res->data;
153 0 0         $self->_error_handler($data)
154             unless $code == 200;
155              
156 0           return $data;
157             }
158              
159 0     0     sub _delete ($self, $url, $object) {
  0            
  0            
  0            
  0            
160 0           my $res = $self->post($url, $object);
161 0           my $code = $res->code;
162 0           my $data = $res->data;
163 0 0         $self->_error_handler($data)
164             unless $code == 200;
165              
166 0           return 1;
167             }
168              
169             Net::Checkpoint::Management::v1::Role::ObjectMethods->apply([
170             {
171             object => 'packages',
172             singular => 'package',
173             create => 'add-package',
174             list => 'show-packages',
175             get => 'show-package',
176             update => 'set-package',
177             delete => 'delete-package',
178             list_key => 'packages',
179             id_keys => [qw( uid name )],
180             },
181             {
182             object => 'accessrules',
183             singular => 'accessrule',
184             create => 'add-access-rule',
185             list => 'show-access-rulebase',
186             get => 'show-access-rule',
187             update => 'set-access-rule',
188             delete => 'delete-access-rule',
189             list_key => 'rulebase',
190             id_keys => ['uid', 'name', 'rule-number'],
191             },
192             {
193             object => 'networks',
194             singular => 'network',
195             create => 'add-network',
196             list => 'show-networks',
197             get => 'show-network',
198             update => 'set-network',
199             delete => 'delete-network',
200             list_key => 'objects',
201             id_keys => [qw( uid name )],
202             },
203             {
204             object => 'hosts',
205             singular => 'host',
206             create => 'add-host',
207             list => 'show-hosts',
208             get => 'show-host',
209             update => 'set-host',
210             delete => 'delete-host',
211             list_key => 'objects',
212             id_keys => [qw( uid name )],
213             },
214             {
215             object => 'address_ranges',
216             singular => 'address_range',
217             create => 'add-address-range',
218             list => 'show-address-ranges',
219             get => 'show-address-range',
220             update => 'set-address-range',
221             delete => 'delete-address-range',
222             list_key => 'objects',
223             id_keys => [qw( uid name )],
224             },
225             {
226             object => 'dns_domains',
227             singular => 'dns_domain',
228             create => 'add-dns-domain',
229             list => 'show-dns-domains',
230             get => 'show-dns-domain',
231             update => 'set-dns-domain',
232             delete => 'delete-dns-domain',
233             list_key => 'objects',
234             id_keys => [qw( uid name )],
235             },
236             {
237             object => 'groups',
238             singular => 'group',
239             create => 'add-group',
240             list => 'show-groups',
241             get => 'show-group',
242             update => 'set-group',
243             delete => 'delete-group',
244             list_key => 'objects',
245             id_keys => [qw( uid name )],
246             },
247             {
248             object => 'access_roles',
249             singular => 'access_role',
250             create => 'add-access-role',
251             list => 'show-access-roles',
252             get => 'show-access-role',
253             update => 'set-access-role',
254             delete => 'delete-access-role',
255             list_key => 'objects',
256             id_keys => [qw( uid name )],
257             },
258             {
259             object => 'services_tcp',
260             singular => 'service_tcp',
261             create => 'add-service-tcp',
262             list => 'show-services-tcp',
263             get => 'show-service-tcp',
264             update => 'set-service-tcp',
265             delete => 'delete-service-tcp',
266             list_key => 'objects',
267             id_keys => [qw( uid name )],
268             },
269             {
270             object => 'services_udp',
271             singular => 'service_udp',
272             create => 'add-service-udp',
273             list => 'show-services-udp',
274             get => 'show-service-udp',
275             update => 'set-service-udp',
276             delete => 'delete-service-udp',
277             list_key => 'objects',
278             id_keys => [qw( uid name )],
279             },
280             {
281             object => 'services_icmp',
282             singular => 'service_icmp',
283             create => 'add-service-icmp',
284             list => 'show-services-icmp',
285             get => 'show-service-icmp',
286             update => 'set-service-icmp',
287             delete => 'delete-service-icmp',
288             list_key => 'objects',
289             id_keys => [qw( uid name )],
290             },
291             {
292             object => 'services_icmpv6',
293             singular => 'service_icmpv6',
294             create => 'add-service-icmp6',
295             list => 'show-services-icmp6',
296             get => 'show-service-icmp6',
297             update => 'set-service-icmp6',
298             delete => 'delete-service-icmp6',
299             list_key => 'objects',
300             id_keys => [qw( uid name )],
301             },
302             {
303             object => 'services_other',
304             singular => 'service_other',
305             create => 'add-service-other',
306             list => 'show-services-other',
307             get => 'show-service-other',
308             update => 'set-service-other',
309             delete => 'delete-service-other',
310             list_key => 'objects',
311             id_keys => [qw( uid name )],
312             },
313             {
314             object => 'service_groups',
315             singular => 'service_group',
316             create => 'add-service-group',
317             list => 'show-service-groups',
318             get => 'show-service-group',
319             update => 'set-service-group',
320             delete => 'delete-service-group',
321             list_key => 'objects',
322             id_keys => [qw( uid name )],
323             },
324             {
325             object => 'sessions',
326             singular => 'session',
327             list => 'show-sessions',
328             get => 'show-session',
329             update => 'set-session',
330             list_key => 'objects',
331             },
332             {
333             object => 'tasks',
334             singular => 'task',
335             list => 'show-tasks',
336             get => 'show-task',
337             list_key => 'tasks',
338             },
339             ]);
340              
341              
342 0     0 1   sub login($self) {
  0            
  0            
343 0           my $res = $self->post('/web_api/v1/login', {
344             user => $self->user,
345             password => $self->passwd,
346             });
347 0 0         if ($res->code == 200) {
348 0           my $api_version = $res->data->{'api-server-version'};
349 0           $self->api_version($api_version);
350             $self->set_persistent_header('X-chkp-sid',
351 0           $res->data->{sid});
352             }
353             else {
354 0           $self->_error_handler($res->data);
355             }
356             }
357              
358              
359 0     0 1   sub logout($self) {
  0            
  0            
360 0           my $res = $self->post('/web_api/v1/logout', {});
361 0           my $code = $res->code;
362 0           my $data = $res->data;
363 0 0         $self->_error_handler($data)
364             unless $code == 200;
365             }
366              
367              
368 0     0 1   sub publish($self) {
  0            
  0            
369 0           my $res = $self->post('/web_api/v' . $self->api_version . '/publish', {});
370 0           my $code = $res->code;
371 0           my $data = $res->data;
372 0 0         $self->_error_handler($data)
373             unless $code == 200;
374              
375 0           return $data->{'task-id'};
376             }
377              
378              
379 0     0 1   sub discard($self) {
  0            
  0            
380 0           my $res = $self->post('/web_api/v' . $self->api_version . '/discard', {});
381 0           my $code = $res->code;
382 0           my $data = $res->data;
383 0 0         $self->_error_handler($data)
384             unless $code == 200;
385              
386 0           return $data;
387             }
388              
389              
390 0     0 1   sub verify_policy($self, $policyname) {
  0            
  0            
  0            
391 0 0         croak "policy name missing"
392             unless defined $policyname;
393              
394 0           my $res = $self->post('/web_api/v' . $self->api_version .
395             '/verify-policy', {
396             'policy-package' => $policyname,
397             });
398 0           my $code = $res->code;
399 0           my $data = $res->data;
400 0 0         $self->_error_handler($data)
401             unless $code == 200;
402              
403 0           return $data->{'task-id'};
404             }
405              
406              
407 0     0 1   sub install_policy($self, $policyname, $targets, $params={}) {
  0            
  0            
  0            
  0            
  0            
408 0 0         croak "policy name missing"
409             unless defined $policyname;
410 0 0         croak "target(s) missing"
411             unless defined $targets;
412 0 0 0       croak "target(s) must be a single name or uid or a list of names or uids"
413             unless ref $targets eq ''
414             || ref $targets eq 'ARRAY';
415 0 0 0       croak "parameters needs to be a hashref"
416             if defined $params && ref $params ne 'HASH';
417              
418 0           my $res = $self->post('/web_api/v' . $self->api_version .
419             '/install-policy', {
420             $params->%*,
421             'policy-package' => $policyname,
422             targets => $targets,
423             });
424 0           my $code = $res->code;
425 0           my $data = $res->data;
426 0 0         $self->_error_handler($data)
427             unless $code == 200;
428              
429 0           return $data->{'task-id'};
430             }
431              
432              
433 0     0 1   sub wait_for_task($self, $taskid, $callback) {
  0            
  0            
  0            
  0            
434 0 0         croak "task-id missing"
435             unless defined $taskid;
436 0 0 0       croak "callback must be a coderef"
437             if defined $callback && ref $callback ne 'CODE';
438              
439 0           my $task;
440 0   0       while (($task = $self->get_task({'task-id' => $taskid})->{tasks}[0])
441             && $task->{status} eq 'in progress') {
442 0 0         &$callback($task)
443             if defined $callback;
444 0           sleep 1;
445             }
446 0           return $task;
447             }
448              
449              
450 0     0 1   sub where_used ($self, $object, $query_params = {}) {
  0            
  0            
  0            
  0            
451 0 0         croak "object must be a hashref"
452             unless ref $object eq 'HASH';
453             croak "object needs a name or uid attribute"
454 0 0 0       unless exists $object->{name} || exists $object->{uid};
455              
456             my $res = $self->post('/web_api/v' . $self->api_version .
457             '/where-used', {
458 0     0     (map { $_ => $object->{$_} } first { exists $object->{$_} } (qw( uid name ))),
  0            
  0            
459             %$query_params,
460             });
461 0           my $code = $res->code;
462 0           my $data = $res->data;
463 0 0         $self->_error_handler($data)
464             unless $code == 200;
465              
466 0           return $data;
467             }
468              
469             1;
470              
471             __END__
472              
473             =pod
474              
475             =encoding UTF-8
476              
477             =head1 NAME
478              
479             Net::Checkpoint::Management::v1 - Checkpoint Management API version 1.x client library
480              
481             =head1 VERSION
482              
483             version 0.003000
484              
485             =head1 SYNOPSIS
486              
487             use strict;
488             use warnings;
489             use Net::Checkpoint::Management::v1;
490              
491             my $cpmgmt = Net::Checkpoint::Management::v1->new(
492             server => 'https://cpmgmt.example.com',
493             user => 'username',
494             passwd => '$password',
495             clientattrs => { timeout => 30 },
496             );
497              
498             $cpmgmt->login;
499              
500             =head1 DESCRIPTION
501              
502             This module is a client library for the Checkpoint Management API version 1.x.
503             Currently it is developed and tested against version R80.40.
504              
505             =head1 ATTRIBUTES
506              
507             =head2 api_versions
508              
509             Returns a list of all available API versions which gets populated on the first
510             call.
511             Only works on API version 1.1 and higher.
512              
513             =head2 api_version
514              
515             The API version used by all methods. Is automatically set to the highest
516             version available by the L</login> method.
517              
518             =head1 METHODS
519              
520             =head2 login
521              
522             Logs into the Checkpoint Manager API using version 1.
523              
524             =head2 logout
525              
526             Logs out of the Checkpoint Manager API using version 1.
527              
528             =head2 publish
529              
530             Publishes all previously submitted changes.
531             Returns the task id on success.
532              
533             =head2 discard
534              
535             Discards all previously submitted changes.
536             Returns a hashref containing the operation status message and the number of
537             discarded changes.
538              
539             =head2 verify_policy
540              
541             Verifies the policy of the given package.
542              
543             Takes a policy name.
544              
545             Returns the task id on success.
546              
547             =head2 install_policy
548              
549             Installs the policy of the given package onto the given target(s).
550              
551             Takes a policy name, target(s) and an optional hashref of additional
552             parameters.
553             The target(s) can be a single name or uid or a list of names or uids.
554              
555             Returns the task id on success.
556              
557             =head2 wait_for_task
558              
559             Takes a task id and checks its status every second until it isn't
560             'in progress' any more and return the status.
561             Takes an optional callback coderef which is called for every check with the
562             task as argument.
563              
564             =head2 where_used
565              
566             Takes a Checkpoint object in form of a hashref as returned by the various APIs
567             and optional query parameters.
568              
569             Prefers the object uid over its name for the query.
570              
571             Returns the unmodified response on success.
572              
573             =head1 AUTHOR
574              
575             Alexander Hartmaier <abraxxa@cpan.org>
576              
577             =head1 COPYRIGHT AND LICENSE
578              
579             This software is copyright (c) 2023 by Alexander Hartmaier.
580              
581             This is free software; you can redistribute it and/or modify it under
582             the same terms as the Perl 5 programming language system itself.
583              
584             =cut