Skip to content

Commit e901bba

Browse files
committed
feat: add the possibility to fetch all nat objects at once
1 parent 7e28d37 commit e901bba

File tree

1 file changed

+270
-19
lines changed
  • pycheckpoint_api/management/access_control_nat

1 file changed

+270
-19
lines changed

pycheckpoint_api/management/access_control_nat/nat_rule.py

Lines changed: 270 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import logging
2+
import time
13
from typing import List, Union
24

35
from box import Box
@@ -7,6 +9,8 @@
79

810
from ..exception import MandatoryFieldMissing
911

12+
logger = logging.getLogger(__name__)
13+
1014

1115
class NATRule(APIEndpoint):
1216
def add(
@@ -332,16 +336,19 @@ def delete(
332336
def show_nat_rulebase(
333337
self,
334338
package: str,
339+
show_all: bool = False,
335340
filter_results: str = None,
336341
filter_settings: dict = None,
337342
limit: int = 50,
338343
offset: int = 0,
339344
order: List[dict] = None,
345+
show_as_ranges: bool = False,
346+
show_hits: bool = None,
340347
use_object_dictionnary: bool = None,
348+
hits_settings: dict = None,
341349
**kw,
342350
) -> Box:
343-
"""
344-
Shows the entire NAT Rules layer. This layer is divided into sections. A NAT Rule may be within a section,
351+
"""Shows the entire NAT Rules layer. This layer is divided into sections. A NAT Rule may be within a section,
345352
or independent of a section (in which case it is said to be under the "global" section).
346353
There are two types of sections: auto generated
347354
read only sections and general sections which are created manually. The reply features a list of objects.
@@ -351,8 +358,8 @@ def show_nat_rulebase(
351358
352359
Args:
353360
package (str): Name of the package
354-
name (str, optional): Object name. Must be unique in the domain.
355-
uid (str, optional): Object unique identifier.
361+
show_all (bool, optional): Indicates if you want to shown all objects or not. If yes, `offset` will be ignored.\
362+
Defaults to False
356363
filter_results (str, optional): Search expression to filter objects by.\
357364
The provided text should be exactly the same as it would be given in SmartConsole Object Explorer.\
358365
The logical operators in the expression ('AND', 'OR') should be provided in capital letters.\
@@ -362,33 +369,116 @@ def show_nat_rulebase(
362369
offset (int, optional): Number of the results to initially skip. Defaults to 0
363370
order (List[dict], optional): Sorts results by the given field. By default the results are sorted in the \
364371
descending order by the session publish time.
365-
package (str, optional): Name of the package.
372+
show_as_ranges (bool, optional): When true, the source, destination and services & applications parameters are\
373+
displayed as ranges of IP addresses and port numbers rather than network objects. Objects that are not represented\
374+
using IP addresses or port numbers are presented as objects. In addition, the response of each rule does not\
375+
contain the parameters: source, source-negate, destination, destination-negate, service and service-negate,\
376+
but instead it contains the parameters: source-ranges, destination-ranges and service-ranges.\
377+
Note: Requesting to show rules as ranges is limited up to 20 rules per request, otherwise an error is returned.\
378+
If you wish to request more rules, use the offset and limit parameters to limit your request.
379+
show_hits (bool, optional): N/A
366380
use_object_dictionnary (bool, optional): N/A
381+
hits_settings (dict, optional): N/A
367382
368383
Keyword Args:
369384
**details_level (str, optional):
370385
The level of detail for some of the fields in the response can vary from showing only the UID value\
371386
of the object to a fully detailed representation of the object.
372-
**domains_to_process (List[str], optional):
373-
Indicates which domains to process the commands on. It cannot be used with the details_level full,\
374-
must be run from the System Domain only and with ignore_warnings true.\
375-
Valid values are: CURRENT_DOMAIN, ALL_DOMAINS_ON_THIS_SERVER.
387+
**show_membership (bool, optional):
388+
Indicates whether to calculate and show "groups" field for every object in reply.
376389
**dereference_group_members (bool, optional):
377390
Indicates whether to dereference "members" field by details level for every object in reply.
378391
379392
Returns:
380393
:obj:`Box`: The response from the server
381394
382395
Examples:
383-
>>> management.access_control_nat.nat_rule.show_nat_rulebase(
384-
... package="standard",
385-
... offset=0,
386-
... limit=20,
387-
... order={"ASC": "name"},
388-
... details_level="standard",
389-
... use_object_dictionnary=True,
390-
... filter_results="",
391-
... filter_settings={},)
396+
>>> firewall.access_control_nat.nat_rule.show_nat_rulebase(package="MyPackage")
397+
398+
"""
399+
400+
if show_all:
401+
return self._show_all_nat_rulebase(
402+
package=package,
403+
filter_results=filter_results,
404+
filter_settings=filter_settings,
405+
limit=limit,
406+
order=order,
407+
package=package,
408+
show_as_ranges=show_as_ranges,
409+
show_hits=show_hits,
410+
use_object_dictionnary=use_object_dictionnary,
411+
hits_settings=hits_settings,
412+
**kw,
413+
)
414+
else:
415+
return self._show_partial_nat_rulebase(
416+
package=package,
417+
filter_results=filter_results,
418+
filter_settings=filter_settings,
419+
limit=limit,
420+
offset=offset,
421+
order=order,
422+
package=package,
423+
show_as_ranges=show_as_ranges,
424+
show_hits=show_hits,
425+
use_object_dictionnary=use_object_dictionnary,
426+
hits_settings=hits_settings,
427+
**kw,
428+
)
429+
430+
def _show_partial_nat_rulebase(
431+
self,
432+
package: str = None,
433+
filter_results: str = None,
434+
filter_settings: dict = None,
435+
limit: int = 50,
436+
offset: int = 0,
437+
order: List[dict] = None,
438+
show_as_ranges: bool = False,
439+
show_hits: bool = None,
440+
use_object_dictionnary: bool = None,
441+
hits_settings: dict = None,
442+
**kw,
443+
) -> Box:
444+
"""Retrieve partially objects
445+
446+
Args:
447+
package (str): Name of the package
448+
filter_results (str, optional): Search expression to filter objects by.\
449+
The provided text should be exactly the same as it would be given in SmartConsole Object Explorer.\
450+
The logical operators in the expression ('AND', 'OR') should be provided in capital letters.\
451+
he search involves both a IP search and a textual search in name, comment, tags etc.
452+
filter_settings (str, optional): Sets filter preferences.
453+
limit (int, optional): The maximal number of returned results. Defaults to 50 (between 1 and 500)
454+
offset (int, optional): Number of the results to initially skip. Defaults to 0
455+
order (List[dict], optional): Sorts results by the given field. By default the results are sorted in the \
456+
descending order by the session publish time.
457+
show_as_ranges (bool, optional): When true, the source, destination and services & applications parameters are\
458+
displayed as ranges of IP addresses and port numbers rather than network objects. Objects that are not represented\
459+
using IP addresses or port numbers are presented as objects. In addition, the response of each rule does not\
460+
contain the parameters: source, source-negate, destination, destination-negate, service and service-negate,\
461+
but instead it contains the parameters: source-ranges, destination-ranges and service-ranges.\
462+
Note: Requesting to show rules as ranges is limited up to 20 rules per request, otherwise an error is returned.\
463+
If you wish to request more rules, use the offset and limit parameters to limit your request.
464+
show_hits (bool, optional): N/A
465+
use_object_dictionnary (bool, optional): N/A
466+
hits_settings (dict, optional): N/A
467+
468+
Keyword Args:
469+
**details_level (str, optional):
470+
The level of detail for some of the fields in the response can vary from showing only the UID value\
471+
of the object to a fully detailed representation of the object.
472+
**show_membership (bool, optional):
473+
Indicates whether to calculate and show "groups" field for every object in reply.
474+
**dereference_group_members (bool, optional):
475+
Indicates whether to dereference "members" field by details level for every object in reply.
476+
477+
Returns:
478+
:obj:`Box`: The response from the server
479+
480+
Examples:
481+
>>> firewall.access_control_nat.nat_rule._show_partial_nat_rulebase(package="MyPackage")
392482
"""
393483
# Main request parameters
394484
payload = {"package": package}
@@ -403,16 +493,177 @@ def show_nat_rulebase(
403493
payload["offset"] = offset
404494
if order is not None:
405495
payload["order"] = order
496+
if package is not None:
497+
payload["package"] = package
498+
if show_as_ranges is not None:
499+
payload["show-as-ranges"] = show_as_ranges
500+
if show_hits is not None:
501+
payload["show-hits"] = show_hits
406502
if use_object_dictionnary is not None:
407503
payload["use-object-dictionnary"] = use_object_dictionnary
504+
if hits_settings is not None:
505+
payload["hits-settings"] = hits_settings
408506

409507
# Secondary parameters
410508
secondary_parameters = {
411509
"dereference_group_members": bool,
412510
"details_level": str,
413-
"domains_to_process": List[str],
511+
"show_membership": bool,
414512
}
415513

416514
payload.update(sanitize_secondary_parameters(secondary_parameters, **kw))
417515

418516
return self._post("show-nat-rulebase", json=payload)
517+
518+
def _show_all_nat_rulebase(
519+
self,
520+
package: str,
521+
filter_results: str = None,
522+
filter_settings: dict = None,
523+
limit: int = 50,
524+
order: List[dict] = None,
525+
show_as_ranges: bool = False,
526+
show_hits: bool = None,
527+
use_object_dictionnary: bool = None,
528+
hits_settings: dict = None,
529+
**kw,
530+
) -> Box:
531+
"""Retrieve all objects
532+
533+
Args:
534+
name (str, optional): Object name. Must be unique in the domain.
535+
uid (str, optional): Object unique identifier.
536+
filter_results (str, optional): Search expression to filter objects by.\
537+
The provided text should be exactly the same as it would be given in SmartConsole Object Explorer.\
538+
The logical operators in the expression ('AND', 'OR') should be provided in capital letters.\
539+
he search involves both a IP search and a textual search in name, comment, tags etc.
540+
filter_settings (str, optional): Sets filter preferences.
541+
limit (int, optional): The maximal number of returned results. Defaults to 50 (between 1 and 500)
542+
offset (int, optional): Number of the results to initially skip. Defaults to 0
543+
order (List[dict], optional): Sorts results by the given field. By default the results are sorted in the \
544+
descending order by the session publish time.
545+
show_as_ranges (bool, optional): When true, the source, destination and services & applications parameters are\
546+
displayed as ranges of IP addresses and port numbers rather than network objects. Objects that are not represented\
547+
using IP addresses or port numbers are presented as objects. In addition, the response of each rule does not\
548+
contain the parameters: source, source-negate, destination, destination-negate, service and service-negate,\
549+
but instead it contains the parameters: source-ranges, destination-ranges and service-ranges.\
550+
Note: Requesting to show rules as ranges is limited up to 20 rules per request, otherwise an error is returned.\
551+
If you wish to request more rules, use the offset and limit parameters to limit your request.
552+
show_hits (bool, optional): N/A
553+
use_object_dictionnary (bool, optional): N/A
554+
hits_settings (dict, optional): N/A
555+
556+
Keyword Args:
557+
**details_level (str, optional):
558+
The level of detail for some of the fields in the response can vary from showing only the UID value\
559+
of the object to a fully detailed representation of the object.
560+
**show_membership (bool, optional):
561+
Indicates whether to calculate and show "groups" field for every object in reply.
562+
**dereference_group_members (bool, optional):
563+
Indicates whether to dereference "members" field by details level for every object in reply.
564+
565+
Returns:
566+
:obj:`Box`: The response from the server
567+
568+
Examples:
569+
>>> firewall.access_control_nat.nat_rule._show_all_nat_rulebase(package="MyPackage")
570+
"""
571+
all_rules = None
572+
573+
# Get a timer
574+
timer_start = time.time()
575+
576+
# Made a first request to determine the total number of objects
577+
resp = self._show_partial_nat_rulebase(
578+
package=package,
579+
filter_results=filter_results,
580+
filter_settings=filter_settings,
581+
limit=limit,
582+
offset=0,
583+
order=order,
584+
show_as_ranges=show_as_ranges,
585+
show_hits=show_hits,
586+
use_object_dictionnary=use_object_dictionnary,
587+
hits_settings=hits_settings,
588+
**kw,
589+
)
590+
591+
# Add the first results
592+
all_rules = resp
593+
594+
# Evaluate the number of requests to be done
595+
number_requests = int(resp.total / limit) + 1
596+
597+
logger.info(
598+
"access-rules - Total: "
599+
+ str(resp.total)
600+
+ " - Number of requests to do: "
601+
+ str(number_requests)
602+
+ " (limit set to "
603+
+ str(limit)
604+
+ "/request) - In progress..."
605+
)
606+
logger.debug(
607+
"access-rules - 1/"
608+
+ str(number_requests)
609+
+ " (limit set to "
610+
+ str(limit)
611+
+ "/request) exported... (offset:0)"
612+
)
613+
614+
for i in range(1, number_requests):
615+
resp = self._show_partial_nat_rulebase(
616+
package=package,
617+
filter_results=filter_results,
618+
filter_settings=filter_settings,
619+
limit=limit,
620+
offset=i * limit,
621+
order=order,
622+
show_as_ranges=show_as_ranges,
623+
show_hits=show_hits,
624+
use_object_dictionnary=use_object_dictionnary,
625+
hits_settings=hits_settings,
626+
**kw,
627+
)
628+
629+
logger.debug(
630+
"access-rules - "
631+
+ str(i + 1)
632+
+ "/"
633+
+ str(number_requests)
634+
+ " (limit set to "
635+
+ str(limit)
636+
+ "/request) exported... (offset:"
637+
+ str(i)
638+
+ ")"
639+
)
640+
641+
all_rules.rulebase += resp.rulebase
642+
643+
# Finalize the output
644+
all_rules.to = all_rules.total
645+
646+
# End timer
647+
timer_diff = time.time() - timer_start
648+
649+
timer_text = ""
650+
651+
if round(timer_diff % 60) != 0:
652+
timer_text = (
653+
str(int(timer_diff / 60)) + "min " + str(round(timer_diff % 60)) + "s"
654+
) # pragma: no cover
655+
else:
656+
timer_text = "<1s"
657+
658+
logger.info(
659+
"access-rules - Total: "
660+
+ str(resp.total)
661+
+ " - Number of requests done: "
662+
+ str(number_requests)
663+
+ " (limit set to "
664+
+ str(limit)
665+
+ "/request) - Done in "
666+
+ timer_text
667+
)
668+
669+
return all_rules

0 commit comments

Comments
 (0)