zscaler-sdk-python 1.0.0__py2.py3-none-any.whl

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.
Files changed (75) hide show
  1. zscaler/__init__.py +34 -0
  2. zscaler/cache/__init__.py +0 -0
  3. zscaler/cache/cache.py +105 -0
  4. zscaler/cache/no_op_cache.py +68 -0
  5. zscaler/cache/zscaler_cache.py +161 -0
  6. zscaler/constants.py +26 -0
  7. zscaler/errors/__init__.py +0 -0
  8. zscaler/errors/error.py +10 -0
  9. zscaler/errors/http_error.py +20 -0
  10. zscaler/errors/zscaler_api_error.py +24 -0
  11. zscaler/exceptions/__init__.py +1 -0
  12. zscaler/exceptions/exceptions.py +101 -0
  13. zscaler/logger.py +57 -0
  14. zscaler/ratelimiter/__init__.py +0 -0
  15. zscaler/ratelimiter/ratelimiter.py +39 -0
  16. zscaler/user_agent.py +23 -0
  17. zscaler/utils.py +577 -0
  18. zscaler/zia/__init__.py +657 -0
  19. zscaler/zia/activate.py +52 -0
  20. zscaler/zia/admin_and_role_management.py +344 -0
  21. zscaler/zia/apptotal.py +71 -0
  22. zscaler/zia/audit_logs.py +95 -0
  23. zscaler/zia/authentication_settings.py +98 -0
  24. zscaler/zia/client.py +88 -0
  25. zscaler/zia/cloud_apps.py +406 -0
  26. zscaler/zia/device_management.py +90 -0
  27. zscaler/zia/dlp.py +784 -0
  28. zscaler/zia/errors.py +37 -0
  29. zscaler/zia/firewall.py +1104 -0
  30. zscaler/zia/forwarding_control.py +271 -0
  31. zscaler/zia/isolation_profile.py +83 -0
  32. zscaler/zia/labels.py +180 -0
  33. zscaler/zia/locations.py +661 -0
  34. zscaler/zia/sandbox.py +180 -0
  35. zscaler/zia/security.py +236 -0
  36. zscaler/zia/ssl_inspection.py +175 -0
  37. zscaler/zia/traffic.py +853 -0
  38. zscaler/zia/url_categories.py +442 -0
  39. zscaler/zia/url_filtering.py +310 -0
  40. zscaler/zia/users.py +386 -0
  41. zscaler/zia/web_dlp.py +295 -0
  42. zscaler/zia/workload_groups.py +58 -0
  43. zscaler/zia/zpa_gateway.py +187 -0
  44. zscaler/zpa/__init__.py +683 -0
  45. zscaler/zpa/app_segments.py +331 -0
  46. zscaler/zpa/app_segments_inspection.py +311 -0
  47. zscaler/zpa/app_segments_pra.py +310 -0
  48. zscaler/zpa/certificates.py +234 -0
  49. zscaler/zpa/client.py +113 -0
  50. zscaler/zpa/cloud_connector_groups.py +75 -0
  51. zscaler/zpa/connectors.py +518 -0
  52. zscaler/zpa/emergency_access.py +178 -0
  53. zscaler/zpa/errors.py +37 -0
  54. zscaler/zpa/idp.py +83 -0
  55. zscaler/zpa/inspection.py +1012 -0
  56. zscaler/zpa/isolation_profile.py +85 -0
  57. zscaler/zpa/lss.py +568 -0
  58. zscaler/zpa/machine_groups.py +79 -0
  59. zscaler/zpa/policies.py +848 -0
  60. zscaler/zpa/posture_profiles.py +122 -0
  61. zscaler/zpa/privileged_remote_access.py +862 -0
  62. zscaler/zpa/provisioning.py +271 -0
  63. zscaler/zpa/saml_attributes.py +100 -0
  64. zscaler/zpa/scim_attributes.py +117 -0
  65. zscaler/zpa/scim_groups.py +146 -0
  66. zscaler/zpa/segment_groups.py +191 -0
  67. zscaler/zpa/server_groups.py +217 -0
  68. zscaler/zpa/servers.py +202 -0
  69. zscaler/zpa/service_edges.py +404 -0
  70. zscaler/zpa/trusted_networks.py +127 -0
  71. zscaler_sdk_python-1.0.0.dist-info/LICENSE.md +21 -0
  72. zscaler_sdk_python-1.0.0.dist-info/METADATA +59 -0
  73. zscaler_sdk_python-1.0.0.dist-info/RECORD +75 -0
  74. zscaler_sdk_python-1.0.0.dist-info/WHEEL +6 -0
  75. zscaler_sdk_python-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,683 @@
1
+ import logging
2
+ import os
3
+ import time
4
+ import urllib.parse
5
+ import uuid
6
+ from time import sleep
7
+
8
+ import requests
9
+ from box import BoxList
10
+
11
+ from zscaler import __version__
12
+ from zscaler.cache.no_op_cache import NoOpCache
13
+ from zscaler.cache.zscaler_cache import ZscalerCache
14
+ from zscaler.constants import ZPA_BASE_URLS
15
+ from zscaler.errors.http_error import HTTPError, ZscalerAPIError
16
+ from zscaler.exceptions.exceptions import HTTPException, ZscalerAPIException
17
+ from zscaler.logger import setup_logging
18
+ from zscaler.ratelimiter.ratelimiter import RateLimiter
19
+ from zscaler.user_agent import UserAgent
20
+ from zscaler.utils import (
21
+ convert_keys_to_snake,
22
+ dump_request,
23
+ dump_response,
24
+ format_json_response,
25
+ is_token_expired,
26
+ retry_with_backoff,
27
+ snake_to_camel,
28
+ )
29
+ from zscaler.zpa.app_segments import ApplicationSegmentAPI
30
+ from zscaler.zpa.app_segments_inspection import AppSegmentsInspectionAPI
31
+ from zscaler.zpa.app_segments_pra import AppSegmentsPRAAPI
32
+ from zscaler.zpa.certificates import CertificatesAPI
33
+ from zscaler.zpa.client import ZPAClient
34
+ from zscaler.zpa.cloud_connector_groups import CloudConnectorGroupsAPI
35
+ from zscaler.zpa.connectors import AppConnectorControllerAPI
36
+ from zscaler.zpa.emergency_access import EmergencyAccessAPI
37
+ from zscaler.zpa.idp import IDPControllerAPI
38
+ from zscaler.zpa.inspection import InspectionControllerAPI
39
+ from zscaler.zpa.isolation_profile import IsolationProfileAPI
40
+ from zscaler.zpa.lss import LSSConfigControllerAPI
41
+ from zscaler.zpa.machine_groups import MachineGroupsAPI
42
+ from zscaler.zpa.policies import PolicySetsAPI
43
+ from zscaler.zpa.posture_profiles import PostureProfilesAPI
44
+ from zscaler.zpa.privileged_remote_access import PrivilegedRemoteAccessAPI
45
+ from zscaler.zpa.provisioning import ProvisioningKeyAPI
46
+ from zscaler.zpa.saml_attributes import SAMLAttributesAPI
47
+ from zscaler.zpa.scim_attributes import ScimAttributeHeaderAPI
48
+ from zscaler.zpa.scim_groups import SCIMGroupsAPI
49
+ from zscaler.zpa.segment_groups import SegmentGroupsAPI
50
+ from zscaler.zpa.server_groups import ServerGroupsAPI
51
+ from zscaler.zpa.servers import AppServersAPI
52
+ from zscaler.zpa.service_edges import ServiceEdgesAPI
53
+ from zscaler.zpa.trusted_networks import TrustedNetworksAPI
54
+
55
+ # Setup the logger
56
+ setup_logging(logger_name="zscaler-sdk-python")
57
+ logger = logging.getLogger("zscaler-sdk-python")
58
+
59
+
60
+ class ZPAClientHelper(ZPAClient):
61
+ """A Controller to access Endpoints in the Zscaler Private Access (ZPA) API.
62
+
63
+ The ZPA object stores the session token and simplifies access to API interfaces within ZPA.
64
+
65
+ Attributes:
66
+ client_id (str): The ZPA API client ID generated from the ZPA console.
67
+ client_secret (str): The ZPA API client secret generated from the ZPA console.
68
+ customer_id (str): The ZPA tenant ID found in the Administration > Company menu in the ZPA console.
69
+ cloud (str): The Zscaler cloud for your tenancy, accepted values are:
70
+
71
+ * ``production``
72
+ * ``beta``
73
+ * ``gov``
74
+ * ``govus``
75
+ * ``zpatwo``
76
+ """
77
+
78
+ def __init__(
79
+ self,
80
+ client_id,
81
+ client_secret,
82
+ customer_id,
83
+ cloud,
84
+ timeout=240,
85
+ cache=None,
86
+ fail_safe=False,
87
+ ):
88
+ # Initialize rate limiter
89
+ # You may want to adjust these parameters as per your rate limit configuration
90
+ self.rate_limiter = RateLimiter(
91
+ get_limit=20, # Adjusted to allow 20 GET requests per 10 seconds
92
+ post_put_delete_limit=10, # Adjusted to allow 10 POST/PUT/DELETE requests per 10 seconds
93
+ get_freq=10, # Adjust frequency to 10 seconds
94
+ post_put_delete_freq=10, # Adjust frequency to 10 seconds
95
+ )
96
+
97
+ # Validate cloud value
98
+ if cloud not in ZPA_BASE_URLS:
99
+ valid_clouds = ", ".join(ZPA_BASE_URLS.keys())
100
+ raise ValueError(
101
+ f"The provided ZPA_CLOUD value '{cloud}' is not supported. "
102
+ f"Please use one of the following supported values: {valid_clouds}"
103
+ )
104
+
105
+ # Continue with existing initialization...
106
+ # Select the appropriate URL
107
+ self.baseurl = ZPA_BASE_URLS.get(cloud, ZPA_BASE_URLS["PRODUCTION"])
108
+
109
+ self.timeout = timeout
110
+ self.client_id = client_id
111
+ self.client_secret = client_secret
112
+ self.customer_id = customer_id
113
+ self.cloud = cloud
114
+ self.url = f"{self.baseurl}/mgmtconfig/v1/admin/customers/{customer_id}"
115
+ self.user_config_url = f"{self.baseurl}/userconfig/v1/customers/{customer_id}"
116
+ self.v2_url = f"{self.baseurl}/mgmtconfig/v2/admin/customers/{customer_id}"
117
+ self.cbi_url = f"{self.baseurl}/cbiconfig/cbi/api/customers/{customer_id}"
118
+ self.fail_safe = fail_safe
119
+ # Cache setup
120
+ cache_enabled = (
121
+ os.environ.get("ZSCALER_CLIENT_CACHE_ENABLED", "true").lower() == "true"
122
+ )
123
+ if cache is None:
124
+ if cache_enabled:
125
+ ttl = int(os.environ.get("ZSCALER_CLIENT_CACHE_DEFAULT_TTL", 3600))
126
+ tti = int(os.environ.get("ZSCALER_CLIENT_CACHE_DEFAULT_TTI", 1800))
127
+ self.cache = ZscalerCache(ttl=ttl, tti=tti)
128
+ else:
129
+ self.cache = NoOpCache()
130
+ else:
131
+ self.cache = cache
132
+
133
+ # Initialize user-agent
134
+ ua = UserAgent()
135
+ self.user_agent = ua.get_user_agent_string()
136
+ self.refreshToken()
137
+
138
+ def refreshToken(self):
139
+ # login
140
+ response = self.login()
141
+ if response is None or response.status_code > 299 or not response.json():
142
+ logger.error(
143
+ "Failed to login using provided credentials, response: %s", response
144
+ )
145
+ raise Exception("Failed to login using provided credentials.")
146
+ self.access_token = response.json().get("access_token")
147
+ self.headers = {
148
+ "Content-Type": "application/json",
149
+ "Accept": "application/json",
150
+ "Authorization": f"Bearer {self.access_token}",
151
+ "User-Agent": self.user_agent,
152
+ }
153
+
154
+ @retry_with_backoff(retries=5)
155
+ def login(self):
156
+ """Log in to the ZPA API and set the access token for subsequent requests."""
157
+ data = urllib.parse.urlencode(
158
+ {"client_id": self.client_id, "client_secret": self.client_secret}
159
+ )
160
+ headers = {
161
+ "Content-Type": "application/x-www-form-urlencoded",
162
+ "Accept": "application/json",
163
+ "User-Agent": self.user_agent,
164
+ }
165
+ try:
166
+ url = f"{self.baseurl}/signin"
167
+ resp = requests.post(url, data=data, headers=headers, timeout=self.timeout)
168
+ # Avoid logging all data from the response, focus on the status and a summary instead
169
+ logger.info("Login attempt with status: %d", resp.status_code)
170
+ return resp
171
+ except Exception as e:
172
+ logger.error("Login failed due to an exception: %s", str(e))
173
+ return None
174
+
175
+ def send(self, method, path, json=None, params=None, api_version: str = None):
176
+ """
177
+ Send a request to the ZPA API.
178
+
179
+ Parameters:
180
+ - method (str): The HTTP method.
181
+ - path (str): API endpoint path.
182
+ - json (dict, optional): Request payload. Defaults to None.
183
+ Returns:
184
+ - Response: Response object from the request.
185
+ """
186
+ api = self.url
187
+ if api_version is None:
188
+ api = self.url
189
+ elif api_version == "v2":
190
+ api = self.v2_url
191
+ elif api_version == "userconfig_v1":
192
+ api = self.user_config_url
193
+
194
+ url = f"{api}/{path.lstrip('/')}"
195
+ start_time = time.time()
196
+ # Update headers to include the user agent
197
+ headers_with_user_agent = self.headers.copy()
198
+ headers_with_user_agent["User-Agent"] = self.user_agent
199
+ # Generate a unique UUID for this request
200
+ request_uuid = uuid.uuid4()
201
+ dump_request(
202
+ logger, url, method, json, params, headers_with_user_agent, request_uuid
203
+ )
204
+ # Check cache before sending request
205
+ cache_key = self.cache.create_key(url, params)
206
+ if method == "GET" and self.cache.contains(cache_key):
207
+ resp = self.cache.get(cache_key)
208
+ dump_response(
209
+ logger=logger,
210
+ url=url,
211
+ method=method,
212
+ params=params,
213
+ resp=resp,
214
+ request_uuid=request_uuid,
215
+ start_time=start_time,
216
+ from_cache=True,
217
+ )
218
+ return resp
219
+
220
+ attempts = 0
221
+ while attempts < 5: # Trying a maximum of 5 times
222
+ try:
223
+ # If the token is None or expired, fetch a new token
224
+ if is_token_expired(self.access_token):
225
+ logger.warning(
226
+ "The provided or fetched token was already expired. Refreshing..."
227
+ )
228
+ self.refreshToken()
229
+ resp = requests.request(
230
+ method,
231
+ url,
232
+ json=json,
233
+ headers=headers_with_user_agent,
234
+ timeout=self.timeout,
235
+ )
236
+ dump_response(
237
+ logger=logger,
238
+ url=url,
239
+ params=params,
240
+ method=method,
241
+ resp=resp,
242
+ request_uuid=request_uuid,
243
+ start_time=start_time,
244
+ )
245
+ if (
246
+ resp.status_code == 429
247
+ ): # HTTP Status code 429 indicates "Too Many Requests"
248
+ sleep_time = int(
249
+ resp.headers.get("Retry-After", 2)
250
+ ) # Default to 60 seconds if 'Retry-After' header is missing
251
+ logger.warning(
252
+ f"Rate limit exceeded. Retrying in {sleep_time} seconds."
253
+ )
254
+ sleep(sleep_time)
255
+ attempts += 1
256
+ continue
257
+ else:
258
+ break
259
+ except requests.RequestException as e:
260
+ if attempts == 4: # If it's the last attempt, raise the exception
261
+ logger.error(
262
+ f"Failed to send {method} request to {url} after 5 attempts. Error: {str(e)}"
263
+ )
264
+ raise e
265
+ else:
266
+ logger.warning(
267
+ f"Failed to send {method} request to {url}. Retrying... Error: {str(e)}"
268
+ )
269
+ attempts += 1
270
+ sleep(5) # Sleep for 5 seconds before retrying
271
+
272
+ # If Non-GET call, clear the
273
+ if method != "GET":
274
+ self.cache.delete(cache_key)
275
+
276
+ # Detailed logging for request and response
277
+ try:
278
+ response_data = resp.json()
279
+ except ValueError: # Using ValueError for JSON decoding errors
280
+ response_data = resp.text
281
+ # check if call was succesful
282
+ if 200 > resp.status_code or resp.status_code > 299:
283
+ # create errors
284
+ try:
285
+ error = ZscalerAPIError(url, resp, response_data)
286
+ if self.fail_safe:
287
+ raise ZscalerAPIException(response_data)
288
+ except ZscalerAPIException:
289
+ raise
290
+ except Exception:
291
+ error = HTTPError(url, resp, response_data)
292
+ if self.fail_safe:
293
+ logger.error(response_data)
294
+ raise HTTPException(response_data)
295
+ logger.error(error)
296
+ # Cache the response if it's a successful GET request
297
+ if method == "GET" and resp.status_code == 200:
298
+ self.cache.add(cache_key, resp)
299
+ return resp
300
+
301
+ def get(self, path, json=None, params=None, api_version: str = None):
302
+ """
303
+ Send a GET request to the ZPA API.
304
+
305
+ Parameters:
306
+ - path (str): API endpoint path.
307
+ - data (dict, optional): Request payload. Defaults to None.
308
+ Returns:
309
+ - Response: Response object from the request.
310
+ """
311
+
312
+ # Use rate limiter before making a request
313
+ should_wait, delay = self.rate_limiter.wait("GET")
314
+ if should_wait:
315
+ time.sleep(delay)
316
+
317
+ # Now proceed with sending the request
318
+ resp = self.send("GET", path, json, params, api_version=api_version)
319
+ formatted_resp = format_json_response(resp, box_attrs=dict())
320
+ return formatted_resp
321
+
322
+ def put(self, path, json=None, params=None, api_version: str = None):
323
+ should_wait, delay = self.rate_limiter.wait("PUT")
324
+ if should_wait:
325
+ time.sleep(delay)
326
+ resp = self.send("PUT", path, json, params, api_version=api_version)
327
+ formatted_resp = format_json_response(resp, box_attrs=dict())
328
+ return formatted_resp
329
+
330
+ def post(self, path, json=None, params=None, api_version: str = None):
331
+ should_wait, delay = self.rate_limiter.wait("POST")
332
+ if should_wait:
333
+ time.sleep(delay)
334
+ resp = self.send("POST", path, json, params, api_version=api_version)
335
+ formatted_resp = format_json_response(resp, box_attrs=dict())
336
+ return formatted_resp
337
+
338
+ def delete(self, path, json=None, params=None, api_version: str = None):
339
+ should_wait, delay = self.rate_limiter.wait("DELETE")
340
+ if should_wait:
341
+ time.sleep(delay)
342
+ return self.send("DELETE", path, json, params, api_version=api_version)
343
+
344
+ def get_paginated_data(
345
+ self,
346
+ path=None,
347
+ params=None,
348
+ expected_status_code=200,
349
+ api_version: str = None,
350
+ search=None,
351
+ search_field="name",
352
+ max_pages=None,
353
+ max_items=None,
354
+ sort_order=None,
355
+ sort_by=None,
356
+ sort_dir=None,
357
+ start_time=None,
358
+ end_time=None,
359
+ idp_group_id=None,
360
+ scim_user_id=None,
361
+ page=None,
362
+ pagesize=20,
363
+ ):
364
+ """
365
+ Fetches paginated data from the ZPA API based on specified parameters and handles various types of API pagination.
366
+
367
+ Args:
368
+ path (str): The API endpoint path to send requests to.
369
+ params (dict): Initial set of query parameters for the API request.
370
+ expected_status_code (int): The expected HTTP status code for a successful request. Defaults to 200.
371
+ api_version (str): Specifies the version of the API to be used. Helps in routing within the API service.
372
+ search (str): Search query to filter the results based on specific conditions.
373
+ search_field (str): The field name against which to search the query. Default is "name".
374
+ max_pages (int): The maximum number of pages to fetch. If None, fetches all available pages.
375
+ max_items (int): The maximum number of items to fetch across all pages. Stops fetching once reached.
376
+ sort_order (str): Specifies the order of sorting (e.g., 'ASC' or 'DSC').
377
+ sort_by (str): Specifies the field name by which the results should be sorted.
378
+ sort_dir (str): Specifies the direction of sorting. This is similar to `sort_order` and can be used interchangeably.
379
+ start_time (str): The start of a time range for filtering data based on modification time.
380
+ end_time (str): The end of a time range for filtering data based on modification time.
381
+ idp_group_id (str): Identifier for a specific IDP group, used for fetching data related to that group.
382
+ scim_user_id (str): Identifier for a specific SCIM user, used for fetching data related to that user.
383
+ page (int): Specific page number to fetch. Overrides automatic pagination.
384
+ pagesize (int): Number of items per page, default is 20 as per API specification, maximum is 500.
385
+
386
+ Returns:
387
+ tuple: A tuple containing:
388
+ - BoxList: A list of fetched items wrapped in a BoxList for easy access.
389
+ - str: An error message if any occurred during the data fetching process.
390
+
391
+ Raises:
392
+ Logs errors and warnings through the configured logger when requests fail or if no data is found.
393
+ """
394
+ logger = logging.getLogger(__name__)
395
+
396
+ ERROR_MESSAGES = {
397
+ "UNEXPECTED_STATUS": "Unexpected status code {status_code} received for page {page}.",
398
+ "MISSING_DATA_KEY": "The key 'list' was not found in the response for page {page}.",
399
+ "EMPTY_RESULTS": "No results found for all requested pages.",
400
+ }
401
+
402
+ if params is None:
403
+ params = {}
404
+
405
+ if (page is not None or pagesize != 20) and (
406
+ max_pages is not None or max_items is not None
407
+ ):
408
+ raise ValueError(
409
+ "Do not mix 'page' or 'pagesize' with 'max_pages' or 'max_items'. Choose either set of parameters."
410
+ )
411
+
412
+ params["pagesize"] = min(
413
+ pagesize, 500
414
+ ) # Apply maximum constraint and handle default
415
+
416
+ if page:
417
+ params["page"] = page
418
+
419
+ if search:
420
+ api_search_field = snake_to_camel(search_field)
421
+ params["search"] = f"{api_search_field} EQ {search}"
422
+ if sort_order:
423
+ params["sortOrder"] = sort_order
424
+ if sort_by:
425
+ params["sortBy"] = sort_by
426
+ if sort_dir:
427
+ params["sortdir"] = sort_dir
428
+ if start_time and end_time:
429
+ params["startTime"] = start_time
430
+ params["endTime"] = end_time
431
+ if idp_group_id:
432
+ params["idpGroupId"] = idp_group_id
433
+ if scim_user_id:
434
+ params["scimUserId"] = scim_user_id
435
+
436
+ total_collected = 0
437
+ ret_data = []
438
+
439
+ try:
440
+ while True:
441
+ if max_pages is not None and (page is not None and page > max_pages):
442
+ break
443
+
444
+ should_wait, delay = self.rate_limiter.wait("GET")
445
+ if should_wait:
446
+ time.sleep(delay)
447
+
448
+ url = f"{path}?{urllib.parse.urlencode(params)}"
449
+ response = self.send("GET", url, api_version=api_version)
450
+
451
+ if response.status_code != expected_status_code:
452
+ error_msg = ERROR_MESSAGES["UNEXPECTED_STATUS"].format(
453
+ status_code=response.status_code, page=page
454
+ )
455
+ logger.error(error_msg)
456
+ return BoxList([]), error_msg
457
+
458
+ response_data = response.json()
459
+ data = response_data.get("list", [])
460
+ if not data and (page is None or page == 1):
461
+ error_msg = ERROR_MESSAGES["EMPTY_RESULTS"]
462
+ logger.warn(error_msg)
463
+ return BoxList([]), error_msg
464
+
465
+ data = convert_keys_to_snake(data)
466
+ ret_data.extend(
467
+ data[: max_items - total_collected]
468
+ if max_items is not None
469
+ else data
470
+ )
471
+ total_collected += len(data)
472
+
473
+ if max_items is not None and total_collected >= max_items:
474
+ break
475
+
476
+ nextPage = response_data.get("nextPage")
477
+ if not nextPage or (max_pages is not None and page >= max_pages):
478
+ break
479
+
480
+ page = nextPage if page is None else page + 1
481
+ params["page"] = page
482
+
483
+ finally:
484
+ time.sleep(1) # Ensure a delay between requests regardless of outcome
485
+
486
+ if not ret_data:
487
+ error_msg = ERROR_MESSAGES["EMPTY_RESULTS"]
488
+ logger.warn(error_msg)
489
+ return BoxList([]), error_msg
490
+
491
+ return BoxList(ret_data), None
492
+
493
+ @property
494
+ def app_segments(self):
495
+ """
496
+ The interface object for the :ref:`ZPA Application Segments interface <zpa-app_segments>`.
497
+
498
+ """
499
+ return ApplicationSegmentAPI(self)
500
+
501
+ @property
502
+ def app_segments_pra(self):
503
+ """
504
+ The interface object for the :ref:`ZPA Application Segments PRA interface <zpa-app_segments_pra>`.
505
+
506
+ """
507
+ return AppSegmentsPRAAPI(self)
508
+
509
+ @property
510
+ def app_segments_inspection(self):
511
+ """
512
+ The interface object for the :ref:`ZPA Application Segments PRA interface <zpa-app_segments_inspection>`.
513
+
514
+ """
515
+ return AppSegmentsInspectionAPI(self)
516
+
517
+ @property
518
+ def certificates(self):
519
+ """
520
+ The interface object for the :ref:`ZPA Browser Access Certificates interface <zpa-certificates>`.
521
+
522
+ """
523
+ return CertificatesAPI(self)
524
+
525
+ @property
526
+ def isolation_profile(self):
527
+ """
528
+ The interface object for the :ref:`ZPA Isolation Profiles <zpa-isolation_profile>`.
529
+
530
+ """
531
+ return IsolationProfileAPI(self)
532
+
533
+ @property
534
+ def cloud_connector_groups(self):
535
+ """
536
+ The interface object for the :ref:`ZPA Cloud Connector Groups interface <zpa-cloud_connector_groups>`.
537
+
538
+ """
539
+ return CloudConnectorGroupsAPI(self)
540
+
541
+ @property
542
+ def connectors(self):
543
+ """
544
+ The interface object for the :ref:`ZPA Connectors interface <zpa-connectors>`.
545
+
546
+ """
547
+ return AppConnectorControllerAPI(self)
548
+
549
+ @property
550
+ def emergency_access(self):
551
+ """
552
+ The interface object for the :ref:`ZPA Emergency Access interface <zpa-emergency_access>`.
553
+
554
+ """
555
+ return EmergencyAccessAPI(self)
556
+
557
+ @property
558
+ def idp(self):
559
+ """
560
+ The interface object for the :ref:`ZPA IDP interface <zpa-idp>`.
561
+
562
+ """
563
+ return IDPControllerAPI(self)
564
+
565
+ @property
566
+ def inspection(self):
567
+ """
568
+ The interface object for the :ref:`ZPA Inspection interface <zpa-inspection>`.
569
+
570
+ """
571
+ return InspectionControllerAPI(self)
572
+
573
+ @property
574
+ def lss(self):
575
+ """
576
+ The interface object for the :ref:`ZIA Log Streaming Service Config interface <zpa-lss>`.
577
+
578
+ """
579
+ return LSSConfigControllerAPI(self)
580
+
581
+ @property
582
+ def machine_groups(self):
583
+ """
584
+ The interface object for the :ref:`ZPA Machine Groups interface <zpa-machine_groups>`.
585
+
586
+ """
587
+ return MachineGroupsAPI(self)
588
+
589
+ @property
590
+ def policies(self):
591
+ """
592
+ The interface object for the :ref:`ZPA Policy Sets interface <zpa-policies>`.
593
+
594
+ """
595
+ return PolicySetsAPI(self)
596
+
597
+ @property
598
+ def posture_profiles(self):
599
+ """
600
+ The interface object for the :ref:`ZPA Posture Profiles interface <zpa-posture_profiles>`.
601
+
602
+ """
603
+ return PostureProfilesAPI(self)
604
+
605
+ @property
606
+ def privileged_remote_access(self):
607
+ """
608
+ The interface object for the :ref:`ZPA Privileged Remote Access interface <zpa-privileged_remote_access>`.
609
+
610
+ """
611
+ return PrivilegedRemoteAccessAPI(self)
612
+
613
+ @property
614
+ def provisioning(self):
615
+ """
616
+ The interface object for the :ref:`ZPA Provisioning interface <zpa-provisioning>`.
617
+
618
+ """
619
+ return ProvisioningKeyAPI(self)
620
+
621
+ @property
622
+ def saml_attributes(self):
623
+ """
624
+ The interface object for the :ref:`ZPA SAML Attributes interface <zpa-saml_attributes>`.
625
+
626
+ """
627
+ return SAMLAttributesAPI(self)
628
+
629
+ @property
630
+ def scim_attributes(self):
631
+ """
632
+ The interface object for the :ref:`ZPA SCIM Attributes interface <zpa-scim_attributes>`.
633
+
634
+ """
635
+ return ScimAttributeHeaderAPI(self)
636
+
637
+ @property
638
+ def scim_groups(self):
639
+ """
640
+ The interface object for the :ref:`ZPA SCIM Groups interface <zpa-scim_groups>`.
641
+
642
+ """
643
+ return SCIMGroupsAPI(self)
644
+
645
+ @property
646
+ def segment_groups(self):
647
+ """
648
+ The interface object for the :ref:`ZPA Segment Groups interface <zpa-segment_groups>`.
649
+
650
+ """
651
+ return SegmentGroupsAPI(self)
652
+
653
+ @property
654
+ def server_groups(self):
655
+ """
656
+ The interface object for the :ref:`ZPA Server Groups interface <zpa-server_groups>`.
657
+
658
+ """
659
+ return ServerGroupsAPI(self)
660
+
661
+ @property
662
+ def servers(self):
663
+ """
664
+ The interface object for the :ref:`ZPA Application Servers interface <zpa-app_servers>`.
665
+
666
+ """
667
+ return AppServersAPI(self)
668
+
669
+ @property
670
+ def service_edges(self):
671
+ """
672
+ The interface object for the :ref:`ZPA Service Edges interface <zpa-service_edges>`.
673
+
674
+ """
675
+ return ServiceEdgesAPI(self)
676
+
677
+ @property
678
+ def trusted_networks(self):
679
+ """
680
+ The interface object for the :ref:`ZPA Trusted Networks interface <zpa-trusted_networks>`.
681
+
682
+ """
683
+ return TrustedNetworksAPI(self)