zscaler-sdk-python 0.9.5__tar.gz → 0.9.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/PKG-INFO +3 -3
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/pyproject.toml +4 -5
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/__init__.py +1 -1
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/__init__.py +97 -49
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/admin_and_role_management.py +2 -1
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/labels.py +2 -1
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/locations.py +2 -1
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/security.py +17 -5
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/traffic.py +2 -1
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/users.py +7 -4
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/__init__.py +34 -34
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/policies.py +32 -44
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/LICENSE.md +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/README.md +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/cache/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/cache/cache.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/cache/no_op_cache.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/cache/zscaler_cache.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/constants.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/errors/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/errors/error.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/errors/http_error.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/errors/zscaler_api_error.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/exceptions/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/exceptions/exceptions.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/logger.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/ratelimiter/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/ratelimiter/ratelimiter.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/user_agent.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/utils.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcc/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcc/client.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcc/devices.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcc/secrets.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/activation.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/admin_and_role_management.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/client.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/ecgroups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/locations.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/provisioning.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/__init__.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/admin.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/alerts.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/apps.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/devices.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/filters.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/inventory.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/troubleshooting.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/users.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zdx/zdx_client.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/activate.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/apptotal.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/audit_logs.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/authentication_settings.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/client.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/cloud_apps.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/cloudappcontrol.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/device_management.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/dlp.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/errors.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/firewall.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/forwarding_control.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/isolation_profile.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/sandbox.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/ssl_inspection.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/url_categories.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/url_filtering.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/web_dlp.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/workload_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/zpa_gateway.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/README.md +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/app_segments.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/app_segments_inspection.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/app_segments_pra.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/authdomains.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/certificates.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/client.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/cloud_connector_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/connectors.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/emergency_access.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/errors.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/idp.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/inspection.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/isolation.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/lss.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/machine_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/microtenants.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/posture_profiles.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/privileged_remote_access.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/provisioning.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/saml_attributes.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/scim_attributes.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/scim_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/segment_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/server_groups.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/servers.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/service_edges.py +0 -0
- {zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/trusted_networks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: zscaler-sdk-python
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.7
|
|
4
4
|
Summary: Official Python SDK for the Zscaler Products (Beta)
|
|
5
5
|
Home-page: https://github.com/zscaler/zscaler-sdk-python
|
|
6
6
|
License: MIT
|
|
@@ -42,8 +42,8 @@ Requires-Dist: requests (>=2.32.3)
|
|
|
42
42
|
Requires-Dist: responses (>=0.25.3)
|
|
43
43
|
Requires-Dist: restfly (>=1.5.0)
|
|
44
44
|
Requires-Dist: six
|
|
45
|
-
Requires-Dist: xmltodict
|
|
46
|
-
Requires-Dist: yarl
|
|
45
|
+
Requires-Dist: xmltodict (>=0.14.2)
|
|
46
|
+
Requires-Dist: yarl (>=1.14.0)
|
|
47
47
|
Project-URL: Bug Tracker, https://github.com/zscaler/zscaler-sdk-python/issues
|
|
48
48
|
Project-URL: Documentation, https://zscaler-sdk-python.readthedocs.io
|
|
49
49
|
Project-URL: Repository, https://github.com/zscaler/zscaler-sdk-python
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "zscaler-sdk-python"
|
|
3
|
-
version = "0.9.
|
|
3
|
+
version = "0.9.7"
|
|
4
4
|
description = "Official Python SDK for the Zscaler Products (Beta)"
|
|
5
5
|
authors = ["Zscaler, Inc. <devrel@zscaler.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -41,15 +41,14 @@ restfly = ">=1.5.0"
|
|
|
41
41
|
six = "*"
|
|
42
42
|
flatdict = "*"
|
|
43
43
|
pyyaml = "*"
|
|
44
|
-
xmltodict = "
|
|
45
|
-
yarl = "
|
|
44
|
+
xmltodict = ">=0.14.2"
|
|
45
|
+
yarl = ">=1.14.0"
|
|
46
46
|
pycryptodomex = ">=3.20.0"
|
|
47
47
|
aenum = "*"
|
|
48
48
|
pydash = ">=8.0.3"
|
|
49
49
|
flake8 = "*"
|
|
50
50
|
pytz = ">=2024.2"
|
|
51
51
|
black = ">=24.3.0"
|
|
52
|
-
# cryptography = ">=3.4,<43.0"
|
|
53
52
|
cryptography = ">=43.0.0"
|
|
54
53
|
okta = ">=2.9.7"
|
|
55
54
|
aiohttp = ">=3.10.2"
|
|
@@ -61,7 +60,7 @@ pytest-asyncio = "^0.23.8"
|
|
|
61
60
|
pytest-mock = "*"
|
|
62
61
|
pytest-recording = "^0.13.2"
|
|
63
62
|
pytest-cov = "*"
|
|
64
|
-
pyfakefs = "
|
|
63
|
+
pyfakefs = ">=5.6.0"
|
|
65
64
|
isort = "*"
|
|
66
65
|
wheel = "*"
|
|
67
66
|
sphinx = "^7.4.7"
|
|
@@ -399,67 +399,115 @@ class ZIAClientHelper(ZIAClient):
|
|
|
399
399
|
time.sleep(delay)
|
|
400
400
|
return self.send("DELETE", path, json, params)
|
|
401
401
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
402
|
+
def get_paginated_data(
|
|
403
|
+
self,
|
|
404
|
+
path=None,
|
|
405
|
+
expected_status_code=200,
|
|
406
|
+
page=None,
|
|
407
|
+
pagesize=None,
|
|
408
|
+
search=None,
|
|
409
|
+
max_page_size=1000, # Default to 1000, can be adjusted based on endpoint constraints
|
|
410
|
+
max_items=None, # Maximum number of items to retrieve across pages
|
|
411
|
+
max_pages=None, # Maximum number of pages to retrieve
|
|
412
|
+
):
|
|
413
|
+
"""
|
|
414
|
+
Fetches paginated data from the API based on specified parameters and handles pagination.
|
|
415
|
+
|
|
416
|
+
Args:
|
|
417
|
+
path (str): The API endpoint path to send requests to.
|
|
418
|
+
expected_status_code (int): The expected HTTP status code for a successful request. Defaults to 200.
|
|
419
|
+
page (int): Specific page number to fetch. Defaults to 1 if not provided.
|
|
420
|
+
pagesize (int): Number of items per page, default is 100, with a maximum of 1000.
|
|
421
|
+
search (str): Search query to filter the results.
|
|
422
|
+
max_items (int): Maximum number of items to retrieve.
|
|
423
|
+
max_pages (int): Maximum number of pages to fetch.
|
|
412
424
|
|
|
413
425
|
Returns:
|
|
414
|
-
|
|
415
|
-
|
|
426
|
+
tuple: A tuple containing:
|
|
427
|
+
- BoxList: A list of fetched items wrapped in a BoxList for easy access.
|
|
428
|
+
- str: An error message if any occurred during the data fetching process.
|
|
416
429
|
"""
|
|
430
|
+
logger = logging.getLogger(__name__)
|
|
431
|
+
|
|
432
|
+
ERROR_MESSAGES = {
|
|
433
|
+
"UNEXPECTED_STATUS": "Unexpected status code {status_code} received for page {page}.",
|
|
434
|
+
"EMPTY_RESULTS": "No results found for page {page}.",
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
# Initialize pagination parameters
|
|
438
|
+
params = {
|
|
439
|
+
"page": page if page is not None else 1, # Start at page 1 if not specified
|
|
440
|
+
"pagesize": min(pagesize if pagesize is not None else 100, max_page_size) # Apply max_page_size limit
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if search:
|
|
444
|
+
params["search"] = search
|
|
417
445
|
|
|
418
|
-
page = 1
|
|
419
446
|
ret_data = []
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
while True:
|
|
423
|
-
required_url = f"{path}"
|
|
424
|
-
should_wait, delay = self.rate_limiter.wait("GET")
|
|
425
|
-
if should_wait:
|
|
426
|
-
time.sleep(delay)
|
|
427
|
-
|
|
428
|
-
# Now proceed with sending the request
|
|
429
|
-
response = self.send(
|
|
430
|
-
method="GET",
|
|
431
|
-
path=required_url,
|
|
432
|
-
params={"page": page, "pageSize": data_per_page},
|
|
433
|
-
)
|
|
447
|
+
total_collected = 0 # Track total items collected
|
|
434
448
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
449
|
+
try:
|
|
450
|
+
while True:
|
|
451
|
+
# Apply rate-limiting if necessary
|
|
452
|
+
should_wait, delay = self.rate_limiter.wait("GET")
|
|
453
|
+
if should_wait:
|
|
454
|
+
time.sleep(delay)
|
|
455
|
+
|
|
456
|
+
# Send the request to the API
|
|
457
|
+
response = self.send("GET", path=path, params=params)
|
|
458
|
+
|
|
459
|
+
# Check for unexpected status code
|
|
460
|
+
if response.status_code != expected_status_code:
|
|
461
|
+
error_msg = ERROR_MESSAGES["UNEXPECTED_STATUS"].format(
|
|
462
|
+
status_code=response.status_code, page=params["page"]
|
|
463
|
+
)
|
|
464
|
+
logger.error(error_msg)
|
|
465
|
+
return BoxList([]), error_msg
|
|
466
|
+
|
|
467
|
+
# Parse the response as a flat list of items
|
|
468
|
+
response_data = response.json()
|
|
469
|
+
if not isinstance(response_data, list):
|
|
470
|
+
error_msg = ERROR_MESSAGES["EMPTY_RESULTS"].format(page=params["page"])
|
|
471
|
+
logger.warn(error_msg)
|
|
472
|
+
return BoxList([]), error_msg
|
|
473
|
+
|
|
474
|
+
data = convert_keys_to_snake(response_data)
|
|
475
|
+
|
|
476
|
+
# If searching for a specific item, stop if we find a match
|
|
477
|
+
if search:
|
|
478
|
+
for item in data:
|
|
479
|
+
if item.get("name") == search:
|
|
480
|
+
ret_data.append(item)
|
|
481
|
+
return BoxList(ret_data), None
|
|
482
|
+
|
|
483
|
+
# Limit data collection based on max_items
|
|
484
|
+
if max_items is not None:
|
|
485
|
+
data = data[:max_items - total_collected] # Limit items on the current page
|
|
486
|
+
ret_data.extend(data)
|
|
487
|
+
total_collected += len(data)
|
|
488
|
+
|
|
489
|
+
# Check if we've reached max_items or max_pages limits
|
|
490
|
+
if (max_items is not None and total_collected >= max_items) or \
|
|
491
|
+
(max_pages is not None and params["page"] >= max_pages):
|
|
492
|
+
break
|
|
444
493
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
break
|
|
494
|
+
# Stop if we've processed all available pages (i.e., less than requested page size)
|
|
495
|
+
if len(data) < params["pagesize"]:
|
|
496
|
+
break
|
|
449
497
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
break
|
|
498
|
+
# Move to the next page
|
|
499
|
+
params["page"] += 1
|
|
453
500
|
|
|
454
|
-
|
|
501
|
+
finally:
|
|
502
|
+
time.sleep(2) # Ensure a delay between requests regardless of outcome
|
|
455
503
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
504
|
+
if not ret_data:
|
|
505
|
+
error_msg = ERROR_MESSAGES["EMPTY_RESULTS"].format(page=params["page"])
|
|
506
|
+
logger.warn(error_msg)
|
|
507
|
+
return BoxList([]), error_msg
|
|
459
508
|
|
|
460
|
-
|
|
509
|
+
return BoxList(ret_data), None
|
|
461
510
|
|
|
462
|
-
return BoxList(ret_data), error_message
|
|
463
511
|
|
|
464
512
|
@property
|
|
465
513
|
def admin_and_role_management(self):
|
{zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/admin_and_role_management.py
RENAMED
|
@@ -48,7 +48,8 @@ class AdminAndRoleManagementAPI:
|
|
|
48
48
|
>>> users = zia.admin_and_role_management.list_users('admin@example.com')
|
|
49
49
|
|
|
50
50
|
"""
|
|
51
|
-
|
|
51
|
+
list, _ = self.rest.get_paginated_data(path="/adminUsers", **kwargs)
|
|
52
|
+
return list
|
|
52
53
|
|
|
53
54
|
def get_user(self, user_id: str) -> Box:
|
|
54
55
|
"""
|
|
@@ -64,7 +64,8 @@ class LocationsAPI:
|
|
|
64
64
|
... print(location)
|
|
65
65
|
|
|
66
66
|
"""
|
|
67
|
-
|
|
67
|
+
list, _ = self.rest.get_paginated_data(path="/locations", **kwargs)
|
|
68
|
+
return list
|
|
68
69
|
|
|
69
70
|
def get_location(self, location_id: str = None, location_name: str = None) -> Box:
|
|
70
71
|
"""
|
|
@@ -163,11 +163,23 @@ class SecurityPolicyAPI:
|
|
|
163
163
|
|
|
164
164
|
payload = {"blacklistUrls": url_list}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
try:
|
|
167
|
+
# Send the POST request to add URLs to the blacklist
|
|
168
|
+
response = self.rest.post("security/advanced/blacklistUrls?action=ADD_TO_LIST", json=payload)
|
|
169
|
+
|
|
170
|
+
# Check if the response includes an empty 'blacklistUrls', signaling no update
|
|
171
|
+
if "blacklistUrls" in response and not response["blacklistUrls"]:
|
|
172
|
+
raise Exception("Failed to add URLs to blacklist: The API response returned an empty 'blacklistUrls' list.")
|
|
173
|
+
|
|
174
|
+
# Verify the URLs were added by checking the current blacklist
|
|
175
|
+
updated_blacklist = self.get_blacklist()
|
|
176
|
+
if all(url in updated_blacklist for url in url_list):
|
|
177
|
+
return updated_blacklist
|
|
178
|
+
else:
|
|
179
|
+
raise Exception("Failed to add URLs to blacklist: URLs were not present in the updated blacklist.")
|
|
180
|
+
|
|
181
|
+
except Exception as exc:
|
|
182
|
+
raise Exception(f"Failed to add URLs to blacklist: {exc}")
|
|
171
183
|
|
|
172
184
|
def replace_blacklist(self, url_list: list) -> BoxList:
|
|
173
185
|
"""
|
|
@@ -642,7 +642,8 @@ class TrafficForwardingAPI:
|
|
|
642
642
|
>>> for credential in zia.traffic.list_vpn_credentials(page_size=200, max_pages=2):
|
|
643
643
|
... print(credential)
|
|
644
644
|
"""
|
|
645
|
-
|
|
645
|
+
list, _ = self.rest.get_paginated_data(path="/vpnCredentials", **kwargs)
|
|
646
|
+
return list
|
|
646
647
|
|
|
647
648
|
def add_vpn_credential(self, authentication_type: str, pre_shared_key: str = None, **kwargs) -> Box:
|
|
648
649
|
"""
|
|
@@ -69,8 +69,9 @@ class UserManagementAPI:
|
|
|
69
69
|
>>> for department in zia.users.list_departments(page_size=200, max_pages=2):
|
|
70
70
|
... print(department)
|
|
71
71
|
"""
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
list, _ = self.rest.get_paginated_data(path="/departments", **kwargs)
|
|
73
|
+
return list
|
|
74
|
+
|
|
74
75
|
def get_department(self, department_id: str) -> Box:
|
|
75
76
|
"""
|
|
76
77
|
Returns the department details for a given department.
|
|
@@ -127,7 +128,8 @@ class UserManagementAPI:
|
|
|
127
128
|
... print(group)
|
|
128
129
|
|
|
129
130
|
"""
|
|
130
|
-
|
|
131
|
+
list, _ = self.rest.get_paginated_data(path="/groups", **kwargs)
|
|
132
|
+
return list
|
|
131
133
|
|
|
132
134
|
def get_group(self, group_id: str) -> Box:
|
|
133
135
|
"""
|
|
@@ -194,7 +196,8 @@ class UserManagementAPI:
|
|
|
194
196
|
... print(user)
|
|
195
197
|
|
|
196
198
|
"""
|
|
197
|
-
|
|
199
|
+
list, _ = self.rest.get_paginated_data(path="/users", **kwargs)
|
|
200
|
+
return list
|
|
198
201
|
|
|
199
202
|
def add_user(self, name: str, email: str, groups: list, department: dict, **kwargs) -> Box:
|
|
200
203
|
"""
|
|
@@ -369,27 +369,27 @@ class ZPAClientHelper(ZPAClient):
|
|
|
369
369
|
return self.send("DELETE", path, json, params, api_version=api_version)
|
|
370
370
|
|
|
371
371
|
def get_paginated_data(
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
372
|
+
self,
|
|
373
|
+
path=None,
|
|
374
|
+
params=None,
|
|
375
|
+
expected_status_code=200,
|
|
376
|
+
api_version: str = None,
|
|
377
|
+
search=None,
|
|
378
|
+
search_field="name",
|
|
379
|
+
max_pages=None,
|
|
380
|
+
max_items=None,
|
|
381
|
+
all_entries=False,
|
|
382
|
+
sort_order=None,
|
|
383
|
+
sort_by=None,
|
|
384
|
+
sort_dir=None,
|
|
385
|
+
start_time=None,
|
|
386
|
+
end_time=None,
|
|
387
|
+
idp_group_id=None,
|
|
388
|
+
scim_user_id=None,
|
|
389
|
+
scim_username=None,
|
|
390
|
+
page=None,
|
|
391
|
+
pagesize=None,
|
|
392
|
+
microtenant_id=None,
|
|
393
393
|
):
|
|
394
394
|
"""
|
|
395
395
|
Fetches paginated data from the ZPA API based on specified parameters and handles various types of API pagination.
|
|
@@ -432,15 +432,10 @@ class ZPAClientHelper(ZPAClient):
|
|
|
432
432
|
if params is None:
|
|
433
433
|
params = {}
|
|
434
434
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
)
|
|
439
|
-
|
|
440
|
-
params["page"] = page if page is not None else 1 # Default to page 1 if not specified
|
|
441
|
-
params["pagesize"] = min(pagesize if pagesize is not None else 20, 500) # Apply maximum constraint and handle default
|
|
435
|
+
# Set initial pagination params
|
|
436
|
+
params["page"] = page or 1
|
|
437
|
+
params["pagesize"] = min(pagesize, 500) if pagesize else 500
|
|
442
438
|
|
|
443
|
-
# Check for microtenantId in function arguments first, then environment variable
|
|
444
439
|
if microtenant_id:
|
|
445
440
|
params["microtenantId"] = microtenant_id
|
|
446
441
|
elif self.microtenant_id and "microtenantId" not in params:
|
|
@@ -472,7 +467,8 @@ class ZPAClientHelper(ZPAClient):
|
|
|
472
467
|
|
|
473
468
|
try:
|
|
474
469
|
while True:
|
|
475
|
-
if max_pages
|
|
470
|
+
# Stop if max_pages reached
|
|
471
|
+
if max_pages is not None and params["page"] > max_pages:
|
|
476
472
|
break
|
|
477
473
|
|
|
478
474
|
should_wait, delay = self.rate_limiter.wait("GET")
|
|
@@ -490,23 +486,27 @@ class ZPAClientHelper(ZPAClient):
|
|
|
490
486
|
|
|
491
487
|
response_data = response.json()
|
|
492
488
|
data = response_data.get("list", [])
|
|
493
|
-
if not data and
|
|
489
|
+
if not data and params["page"] == 1:
|
|
494
490
|
error_msg = ERROR_MESSAGES["EMPTY_RESULTS"]
|
|
495
491
|
logger.warn(error_msg)
|
|
496
492
|
return BoxList([]), error_msg
|
|
497
493
|
|
|
494
|
+
# Convert and extend the collected data
|
|
498
495
|
data = convert_keys_to_snake(data)
|
|
499
496
|
ret_data.extend(data[: max_items - total_collected] if max_items is not None else data)
|
|
500
497
|
total_collected += len(data)
|
|
501
498
|
|
|
499
|
+
# Check if we’ve collected the max_items
|
|
502
500
|
if max_items is not None and total_collected >= max_items:
|
|
503
501
|
break
|
|
504
502
|
|
|
505
|
-
|
|
506
|
-
|
|
503
|
+
# Determine if there is a next page based on totalPages, converting totalPages to an integer if present
|
|
504
|
+
total_pages = int(response_data.get("totalPages", 0)) # Default to 0 if not provided
|
|
505
|
+
if not total_pages or params["page"] >= total_pages:
|
|
507
506
|
break
|
|
508
507
|
|
|
509
|
-
|
|
508
|
+
# Move to the next page
|
|
509
|
+
params["page"] += 1
|
|
510
510
|
|
|
511
511
|
finally:
|
|
512
512
|
time.sleep(2) # Ensure a delay between requests regardless of outcome
|
|
@@ -56,7 +56,7 @@ class PolicySetsAPI:
|
|
|
56
56
|
conditions (list): List of condition dicts or tuples.
|
|
57
57
|
|
|
58
58
|
Returns:
|
|
59
|
-
:obj:`
|
|
59
|
+
:obj:`list`: The conditions template.
|
|
60
60
|
|
|
61
61
|
"""
|
|
62
62
|
template = []
|
|
@@ -78,63 +78,47 @@ class PolicySetsAPI:
|
|
|
78
78
|
"COUNTRY_CODE": [],
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
operators_for_types = {} # Dictionary to store specific operators for each object type
|
|
82
|
+
|
|
81
83
|
for condition in conditions:
|
|
84
|
+
# Check if the first item in a tuple is an operator, like "AND" or "OR"
|
|
85
|
+
if isinstance(condition, tuple) and isinstance(condition[0], str) and condition[0].upper() in ["AND", "OR"]:
|
|
86
|
+
operator = condition[0].upper()
|
|
87
|
+
condition = condition[1] # The second element is the actual condition
|
|
88
|
+
else:
|
|
89
|
+
operator = "OR" # Default operator if none specified
|
|
90
|
+
|
|
91
|
+
# Process each condition and categorize by object type and operator
|
|
82
92
|
if isinstance(condition, tuple) and len(condition) == 3:
|
|
83
|
-
# Handle each object type according to its pattern
|
|
84
93
|
object_type = condition[0].upper()
|
|
85
94
|
lhs = condition[1]
|
|
86
95
|
rhs = condition[2]
|
|
96
|
+
operand = {"objectType": object_type, "lhs": lhs, "rhs": rhs}
|
|
97
|
+
|
|
98
|
+
# Track the operator for the current object type
|
|
99
|
+
operators_for_types[object_type] = operator
|
|
87
100
|
|
|
88
101
|
if object_type in ["APP", "APP_GROUP"]:
|
|
89
|
-
app_and_app_group_operands.append(
|
|
102
|
+
app_and_app_group_operands.append(operand)
|
|
90
103
|
elif object_type in object_types_to_operands:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
"zpn_client_type_exporter",
|
|
94
|
-
"zpn_client_type_machine_tunnel",
|
|
95
|
-
"zpn_client_type_ip_anchoring",
|
|
96
|
-
"zpn_client_type_edge_connector",
|
|
97
|
-
"zpn_client_type_zapp",
|
|
98
|
-
"zpn_client_type_slogger",
|
|
99
|
-
}:
|
|
100
|
-
object_types_to_operands[object_type].append({"objectType": object_type, "lhs": "id", "rhs": rhs})
|
|
101
|
-
elif object_type in [
|
|
102
|
-
"PLATFORM",
|
|
103
|
-
"POSTURE",
|
|
104
|
-
"TRUSTED_NETWORK",
|
|
105
|
-
"SAML",
|
|
106
|
-
"SCIM",
|
|
107
|
-
"SCIM_GROUP",
|
|
108
|
-
"COUNTRY_CODE",
|
|
109
|
-
]:
|
|
110
|
-
object_types_to_operands[object_type].append({"objectType": object_type, "lhs": lhs, "rhs": rhs})
|
|
111
|
-
else:
|
|
112
|
-
object_types_to_operands[object_type].append({"objectType": object_type, "lhs": "id", "rhs": rhs})
|
|
104
|
+
object_types_to_operands[object_type].append(operand)
|
|
105
|
+
|
|
113
106
|
elif isinstance(condition, dict):
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
if "operator" in condition:
|
|
108
|
+
operators_for_types["default"] = condition["operator"]
|
|
109
|
+
continue # Skip to the next condition after setting the operator
|
|
116
110
|
|
|
117
|
-
|
|
111
|
+
condition_template = {}
|
|
118
112
|
for key in ["id", "negated", "operator"]:
|
|
119
113
|
if key in condition:
|
|
120
114
|
condition_template[key] = condition[key]
|
|
121
115
|
|
|
122
|
-
# Handling the operands
|
|
123
116
|
operands = condition.get("operands", [])
|
|
124
117
|
condition_template["operands"] = []
|
|
125
118
|
|
|
126
119
|
for operand in operands:
|
|
127
120
|
operand_template = {}
|
|
128
|
-
|
|
129
|
-
# Extracting keys from the operand dictionary
|
|
130
|
-
for operand_key in [
|
|
131
|
-
"id",
|
|
132
|
-
"idp_id",
|
|
133
|
-
"name",
|
|
134
|
-
"lhs",
|
|
135
|
-
"rhs",
|
|
136
|
-
"objectType",
|
|
137
|
-
]:
|
|
121
|
+
for operand_key in ["id", "idp_id", "name", "lhs", "rhs", "objectType"]:
|
|
138
122
|
if operand_key in operand:
|
|
139
123
|
operand_template[operand_key] = operand[operand_key]
|
|
140
124
|
|
|
@@ -142,14 +126,16 @@ class PolicySetsAPI:
|
|
|
142
126
|
|
|
143
127
|
template.append(condition_template)
|
|
144
128
|
|
|
145
|
-
# Combine APP and APP_GROUP operands
|
|
129
|
+
# Combine APP and APP_GROUP operands with their specific operator
|
|
146
130
|
if app_and_app_group_operands:
|
|
147
|
-
|
|
131
|
+
app_group_operator = operators_for_types.get("APP", "OR")
|
|
132
|
+
template.append({"operator": app_group_operator, "operands": app_and_app_group_operands})
|
|
148
133
|
|
|
149
|
-
# Combine other object types into their
|
|
134
|
+
# Combine other object types into their blocks with their respective operator
|
|
150
135
|
for object_type, operands in object_types_to_operands.items():
|
|
151
136
|
if operands:
|
|
152
|
-
|
|
137
|
+
operator = operators_for_types.get(object_type, "OR")
|
|
138
|
+
template.append({"operator": operator, "operands": operands})
|
|
153
139
|
|
|
154
140
|
return template
|
|
155
141
|
|
|
@@ -390,7 +376,9 @@ class PolicySetsAPI:
|
|
|
390
376
|
('app', 'id', '88888'),
|
|
391
377
|
('app_group', 'id', '77777),
|
|
392
378
|
('client_type', 'zpn_client_type_exporter', 'zpn_client_type_zapp'),
|
|
393
|
-
('trusted_network', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx', True)
|
|
379
|
+
("OR", 'trusted_network', 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx', True))
|
|
380
|
+
("OR", ("posture", "d019df8b-ec97-4087-a892-749b5abca54c", "false")),
|
|
381
|
+
]
|
|
394
382
|
custom_msg (str):
|
|
395
383
|
A custom message.
|
|
396
384
|
description (str):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zcon/admin_and_role_management.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zia/authentication_settings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/app_segments_inspection.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{zscaler_sdk_python-0.9.5 → zscaler_sdk_python-0.9.7}/zscaler/zpa/privileged_remote_access.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|