zscaler-sdk-python 0.1.3__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 +35 -0
  2. zscaler/cache/__init__.py +0 -0
  3. zscaler/cache/cache.py +105 -0
  4. zscaler/cache/no_op_cache.py +66 -0
  5. zscaler/cache/zscaler_cache.py +159 -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 +21 -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 +37 -0
  16. zscaler/user_agent.py +21 -0
  17. zscaler/utils.py +546 -0
  18. zscaler/zia/__init__.py +629 -0
  19. zscaler/zia/activate.py +51 -0
  20. zscaler/zia/admin_and_role_management.py +336 -0
  21. zscaler/zia/apptotal.py +71 -0
  22. zscaler/zia/audit_logs.py +93 -0
  23. zscaler/zia/authentication_settings.py +94 -0
  24. zscaler/zia/client.py +88 -0
  25. zscaler/zia/cloud_apps.py +402 -0
  26. zscaler/zia/device_management.py +90 -0
  27. zscaler/zia/dlp.py +772 -0
  28. zscaler/zia/errors.py +37 -0
  29. zscaler/zia/firewall.py +1064 -0
  30. zscaler/zia/forwarding_control.py +267 -0
  31. zscaler/zia/isolation_profile.py +83 -0
  32. zscaler/zia/labels.py +178 -0
  33. zscaler/zia/locations.py +645 -0
  34. zscaler/zia/sandbox.py +201 -0
  35. zscaler/zia/security.py +232 -0
  36. zscaler/zia/ssl_inspection.py +169 -0
  37. zscaler/zia/traffic.py +819 -0
  38. zscaler/zia/url_categories.py +422 -0
  39. zscaler/zia/url_filtering.py +306 -0
  40. zscaler/zia/users.py +378 -0
  41. zscaler/zia/web_dlp.py +291 -0
  42. zscaler/zia/workload_groups.py +58 -0
  43. zscaler/zia/zpa_gateway.py +179 -0
  44. zscaler/zpa/README.md +40 -0
  45. zscaler/zpa/__init__.py +655 -0
  46. zscaler/zpa/app_segments.py +317 -0
  47. zscaler/zpa/app_segments_inspection.py +295 -0
  48. zscaler/zpa/app_segments_pra.py +296 -0
  49. zscaler/zpa/certificates.py +230 -0
  50. zscaler/zpa/client.py +113 -0
  51. zscaler/zpa/cloud_connector_groups.py +75 -0
  52. zscaler/zpa/connectors.py +500 -0
  53. zscaler/zpa/emergency_access.py +170 -0
  54. zscaler/zpa/errors.py +37 -0
  55. zscaler/zpa/idp.py +83 -0
  56. zscaler/zpa/inspection.py +968 -0
  57. zscaler/zpa/isolation_profile.py +85 -0
  58. zscaler/zpa/lss.py +544 -0
  59. zscaler/zpa/machine_groups.py +79 -0
  60. zscaler/zpa/policies.py +824 -0
  61. zscaler/zpa/posture_profiles.py +120 -0
  62. zscaler/zpa/privileged_remote_access.py +827 -0
  63. zscaler/zpa/provisioning.py +262 -0
  64. zscaler/zpa/saml_attributes.py +96 -0
  65. zscaler/zpa/scim_attributes.py +115 -0
  66. zscaler/zpa/scim_groups.py +133 -0
  67. zscaler/zpa/segment_groups.py +183 -0
  68. zscaler/zpa/server_groups.py +211 -0
  69. zscaler/zpa/servers.py +198 -0
  70. zscaler/zpa/service_edges.py +388 -0
  71. zscaler/zpa/trusted_networks.py +125 -0
  72. zscaler_sdk_python-0.1.3.dist-info/LICENSE.md +21 -0
  73. zscaler_sdk_python-0.1.3.dist-info/METADATA +362 -0
  74. zscaler_sdk_python-0.1.3.dist-info/RECORD +75 -0
  75. zscaler_sdk_python-0.1.3.dist-info/WHEEL +4 -0
zscaler/zia/web_dlp.py ADDED
@@ -0,0 +1,291 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2023, Zscaler Inc.
4
+ #
5
+ # Permission to use, copy, modify, and/or distribute this software for any
6
+ # purpose with or without fee is hereby granted, provided that the above
7
+ # copyright notice and this permission notice appear in all copies.
8
+ #
9
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
17
+ from box import Box, BoxList
18
+ from requests import Response
19
+
20
+ from zscaler.utils import (
21
+ convert_keys,
22
+ recursive_snake_to_camel,
23
+ snake_to_camel,
24
+ transform_common_id_fields,
25
+ )
26
+ from zscaler.zia import ZIAClient
27
+
28
+
29
+ class WebDLPAPI:
30
+ # Web DLP rule keys that only require an ID to be provided.
31
+ reformat_params = [
32
+ ("auditor", "auditor"),
33
+ ("dlp_engines", "dlpEngines"),
34
+ ("departments", "departments"),
35
+ ("excluded_departments", "excludedDepartments"),
36
+ ("excluded_groups", "excludedGroups"),
37
+ ("excluded_users", "excludedUsers"),
38
+ ("groups", "groups"),
39
+ ("labels", "labels"),
40
+ ("locations", "locations"),
41
+ ("location_groups", "locationGroups"),
42
+ ("notification_template", "notificationTemplate"),
43
+ ("time_windows", "timeWindows"),
44
+ ("users", "users"),
45
+ ("url_categories", "urlCategories"),
46
+ ]
47
+
48
+ def __init__(self, client: ZIAClient):
49
+ self.rest = client
50
+
51
+ def list_rules(self) -> BoxList:
52
+ """
53
+ Returns a list of DLP policy rules, excluding SaaS Security API DLP policy rules.
54
+
55
+ Returns:
56
+ :obj:`BoxList`: List of Web DLP items.
57
+
58
+ Examples:
59
+ Get a list of all Web DLP Items
60
+
61
+ >>> results = zia.web_dlp.list_rules()
62
+ ... for item in results:
63
+ ... print(item)
64
+
65
+ """
66
+ response = self.rest.get("/webDlpRules")
67
+ if isinstance(response, Response):
68
+ return None
69
+ return response
70
+
71
+ def get_rule(self, rule_id: str) -> Box:
72
+ """
73
+ Returns a DLP policy rule, excluding SaaS Security API DLP policy rules.
74
+
75
+ Args:
76
+ rule_id (str): The unique id for the Web DLP rule.
77
+
78
+ Returns:
79
+ :obj:`Box`: The Web DLP Rule resource record.
80
+
81
+ Examples:
82
+ Get information on a Web DLP item by ID
83
+
84
+ >>> results = zia.web_dlp.get_rule(rule_id='9999')
85
+ ... print(results)
86
+
87
+ """
88
+ return self.rest.get(f"webDlpRules/{rule_id}")
89
+
90
+ def list_rules_lite(self) -> BoxList:
91
+ """
92
+ Returns the name and ID for all DLP policy rules, excluding SaaS Security API DLP policy rules.
93
+
94
+ Returns:
95
+ :obj:`BoxList`: List of Web DLP name/ids.
96
+
97
+ Examples:
98
+ Get Web DLP Lite results
99
+
100
+ >>> results = zia.web_dlp.list_rules_lite()
101
+ ... for item in results:
102
+ ... print(item)
103
+
104
+ """
105
+ response = self.rest.get("webDlpRules/lite")
106
+ if isinstance(response, Response):
107
+ return None
108
+ return response
109
+
110
+ def add_rule(self, name: str, action: str, **kwargs) -> Box:
111
+ """
112
+ Adds a new DLP policy rule.
113
+
114
+ Args:
115
+ name (str): The name of the filter rule. 31 char limit.
116
+ action (str): The action for the filter rule.
117
+
118
+ Keyword Args:
119
+ order (str): The order of the rule, defaults to adding rule to bottom of list.
120
+ rank (str): The admin rank of the rule.
121
+ state (str): The rule state. Accepted values are 'ENABLED' or 'DISABLED'.
122
+ auditor (:obj:`list` of :obj:`int`): IDs for the auditors this rule applies to.
123
+ cloud_applications (list): IDs for cloud applications this rule applies to.
124
+ description (str): Additional information about the rule
125
+ departments (:obj:`list` of :obj:`int`): IDs for departments this rule applies to.
126
+ dlp_engines (:obj:`list` of :obj:`int`): IDs for DLP engines this rule applies to.
127
+ excluded_groups (:obj:`list` of :obj:`int`): IDs for excluded groups.
128
+ excluded_departments (:obj:`list` of :obj:`int`): IDs for excluded departments.
129
+ excluded_users (:obj:`list` of :obj:`int`): IDs for excluded users.
130
+ file_types (list): List of file types the DLP policy rule applies to.
131
+ groups (:obj:`list` of :obj:`int`): IDs for groups this rule applies to.
132
+ icap_server (:obj:`list` of :obj:`int`): IDs for the icap server this rule applies to.
133
+ labels (:obj:`list` of :obj:`int`): IDs for labels this rule applies to.
134
+ locations (:obj:`list` of :obj:`int`): IDs for locations this rule applies to.
135
+ location_groups (:obj:`list` of :obj:`int`): IDs for location groups this rule applies to.
136
+ notification_template (:obj:`list` of :obj:`int`): IDs for the notification template.
137
+ time_windows (:obj:`list` of :obj:`int`): IDs for time windows this rule applies to.
138
+ users (:obj:`list` of :obj:`int`): IDs for users this rule applies to.
139
+ url_categories (list): IDs for URL categories the rule applies to.
140
+ external_auditor_email (str): Email of an external auditor for DLP notifications.
141
+ dlp_download_scan_enabled (bool): True enables DLP scan for file downloads.
142
+ min_size (str): Minimum file size (in KB) for DLP policy rule evaluation.
143
+ match_only (bool): If true, matches file size for DLP policy rule evaluation.
144
+ ocr_enabled (bool): True allows OCR scanning of image files.
145
+ without_content_inspection (bool): True indicates a DLP rule without content inspection.
146
+ zcc_notifications_enabled (bool): True enables Zscaler Client Connector notification.
147
+
148
+ Returns:
149
+ :obj:`Box`: The new dlp web rule resource record.
150
+
151
+ Examples:
152
+ Add a rule to allow all traffic to Google DNS (admin ranking is enabled):
153
+
154
+ >>> zia.web_dlp.add_rule(rank='7',
155
+ ... file_types=['BITMAP', 'JPEG', 'PNG'],
156
+ ... name='ALLOW_ANY_TO_GOOG-DNS',
157
+ ... action='ALLOW',
158
+ ... description='TT#1965432122')
159
+
160
+ Add a rule to block all traffic to Quad9 DNS for Finance Group:
161
+
162
+ >>> zia.web_dlp.add_rule(rank='7',
163
+ ... file_types=['BITMAP', 'JPEG', 'PNG'],
164
+ ... name='BLOCK_GROUP-FIN_TO_Q9-DNS',
165
+ ... action='BLOCK_ICMP',
166
+ ... groups=['95016183'],
167
+ ... description='TT#1965432122')
168
+ """
169
+ # Convert enabled to API format if present
170
+ if "enabled" in kwargs:
171
+ kwargs["state"] = "ENABLED" if kwargs.pop("enabled") else "DISABLED"
172
+
173
+ payload = {
174
+ "name": name,
175
+ "action": action,
176
+ "order": kwargs.pop("order", len(self.list_rules())),
177
+ }
178
+
179
+ # Transform ID fields in kwargs
180
+ transform_common_id_fields(self.reformat_params, kwargs, payload)
181
+ for key, value in kwargs.items():
182
+ if value is not None:
183
+ payload[snake_to_camel(key)] = value
184
+
185
+ # Convert the entire payload's keys to camelCase before sending
186
+ camel_payload = recursive_snake_to_camel(payload)
187
+ for key, value in kwargs.items():
188
+ if value is not None:
189
+ camel_payload[snake_to_camel(key)] = value
190
+
191
+ # Send POST request to create the rule
192
+ response = self.rest.post("webDlpRules", json=payload)
193
+ if isinstance(response, Response):
194
+ status_code = response.status_code
195
+ # Handle error response
196
+ raise Exception(f"API call failed with status {status_code}: {response.json()}")
197
+ return response
198
+
199
+ def update_rule(self, rule_id: str, **kwargs) -> Box:
200
+ """
201
+ Updates an existing DLP policy rule. Not applicable to SaaS Security API DLP policy rules.
202
+
203
+ Args:
204
+ rule_id (str): ID of the rule.
205
+ **kwargs: Optional keyword args.
206
+
207
+ Keyword Args:
208
+ order (str): Rule order, defaults to bottom of list.
209
+ rank (str): Admin rank of the rule.
210
+ state (str): Rule state ('ENABLED' or 'DISABLED').
211
+ auditor (list): IDs for auditors this rule applies to.
212
+ cloud_applications (list): IDs for cloud applications rule applies to.
213
+ description (str): Additional information about the rule.
214
+ departments (list): IDs for departments rule applies to.
215
+ dlp_engines (list): IDs for DLP engines rule applies to.
216
+ excluded_groups (list): IDs for excluded groups.
217
+ excluded_departments (list): IDs for excluded departments.
218
+ excluded_users (list): IDs for excluded users.
219
+ file_types (list): List of file types the rule applies to.
220
+ groups (list): IDs for groups rule applies to.
221
+ icap_server (list): IDs for the ICAP server rule applies to.
222
+ labels (list): IDs for labels rule applies to.
223
+ locations (list): IDs for locations rule applies to.
224
+ location_groups (list): IDs for location groups rule applies to.
225
+ notification_template (list): IDs for the notification template.
226
+ time_windows (list): IDs for time windows rule applies to.
227
+ users (list): IDs for users rule applies to.
228
+ url_categories (list): IDs for URL categories rule applies to.
229
+ external_auditor_email (str): Email of external auditor for DLP notifications.
230
+ dlp_download_scan_enabled (bool): True enables DLP scan for file downloads.
231
+ min_size (str): Minimum file size (in KB) for rule evaluation.
232
+ match_only (bool): If true, uses min_size for rule evaluation.
233
+ ocr_enabled (bool): True allows OCR scanning of image files.
234
+ without_content_inspection (bool): True for DLP rule without content inspection.
235
+ zcc_notifications_enabled (bool): True enables ZCC notification for block action.
236
+
237
+ Returns:
238
+ :obj:`Box`: The updated web dlp rule resource record.
239
+
240
+ Examples:
241
+ Update a Web DLP Policy Rule:
242
+
243
+ >>> zia.web_dlp.get_rule('9999')
244
+ ... name="updated name."
245
+ ... description="updated name."
246
+
247
+ Update a web dlp policy rule to update description:
248
+
249
+ >>> zia.web_dlp.update_rule('976597', description="TT#1965232866")
250
+ """
251
+ # Set payload to value of existing record and convert nested dict keys.
252
+ payload = convert_keys(self.get_rule(rule_id))
253
+
254
+ # Convert enabled to API format if present in kwargs
255
+ if "enabled" in kwargs:
256
+ kwargs["state"] = "ENABLED" if kwargs.pop("enabled") else "DISABLED"
257
+
258
+ # Transform ID fields in kwargs
259
+ transform_common_id_fields(self.reformat_params, kwargs, payload)
260
+
261
+ # Add remaining optional parameters to payload
262
+ for key, value in kwargs.items():
263
+ payload[snake_to_camel(key)] = value
264
+
265
+ response = self.rest.put(f"webDlpRules/{rule_id}", json=payload)
266
+ if isinstance(response, Response) and not response.ok:
267
+ # Handle error response
268
+ raise Exception(f"API call failed with status {response.status_code}: {response.json()}")
269
+
270
+ # Return the updated object
271
+ return self.get_rule(rule_id)
272
+
273
+ def delete_rule(self, rule_id: str) -> Box:
274
+ """
275
+ Deletes a DLP policy rule. This endpoint is not applicable to SaaS Security API DLP policy rules.
276
+
277
+ Args:
278
+ rule_id (str): Unique id of the Web DLP Policy Rule that will be deleted.
279
+
280
+ Returns:
281
+ :obj:`Box`: Response message from the ZIA API endpoint.
282
+
283
+ Examples:
284
+ Delete a rule with an id of 9999.
285
+
286
+ >>> results = zia.web_dlp.delete_rule(rule_id=9999)
287
+ ... print(results)
288
+
289
+
290
+ """
291
+ return self.rest.delete(f"webDlpRules/{rule_id}").status_code
@@ -0,0 +1,58 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2023, Zscaler Inc.
4
+ #
5
+ # Permission to use, copy, modify, and/or distribute this software for any
6
+ # purpose with or without fee is hereby granted, provided that the above
7
+ # copyright notice and this permission notice appear in all copies.
8
+ #
9
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
17
+ from box import BoxList
18
+ from requests import Response
19
+
20
+ from zscaler.zia import ZIAClient
21
+
22
+
23
+ class WorkloadGroupsAPI:
24
+ def __init__(self, client: ZIAClient):
25
+ self.rest = client
26
+
27
+ def list_groups(self, **kwargs) -> BoxList:
28
+ """
29
+ Returns a list of all firewall filter rules.
30
+
31
+ Returns:
32
+ :obj:`BoxList`: The list of firewall filter rules
33
+
34
+ Examples:
35
+ >>> for rule in zia.workload_groups.list_groups():
36
+ ... pprint(rule)
37
+
38
+ """
39
+ response = self.rest.get("/workloadGroups")
40
+ if isinstance(response, Response):
41
+ return None
42
+ return response
43
+
44
+ # Search Workload Group By Name
45
+ def get_group_by_name(self, name):
46
+ groups = self.list_groups()
47
+ for group in groups:
48
+ if group.get("name") == name:
49
+ return group
50
+ return None
51
+
52
+ # Search Workload Group By ID
53
+ def get_group_by_id(self, group_id):
54
+ groups = self.list_groups()
55
+ for group in groups:
56
+ if group.get("id") == group_id:
57
+ return group
58
+ return None
@@ -0,0 +1,179 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # Copyright (c) 2023, Zscaler Inc.
4
+ #
5
+ # Permission to use, copy, modify, and/or distribute this software for any
6
+ # purpose with or without fee is hereby granted, provided that the above
7
+ # copyright notice and this permission notice appear in all copies.
8
+ #
9
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+
17
+ from box import Box, BoxList
18
+ from requests import Response
19
+
20
+ from zscaler.utils import convert_keys, snake_to_camel
21
+ from zscaler.zia import ZIAClient
22
+
23
+
24
+ class ZPAGatewayAPI:
25
+ def __init__(self, client: ZIAClient):
26
+ self.rest = client
27
+
28
+ def list_gateways(self, **kwargs) -> BoxList:
29
+ """
30
+ Returns a list of all ZPA Gateways.
31
+
32
+ Returns:
33
+ :obj:`BoxList`: The list of all ZPA Gateways Items
34
+
35
+ Returns:
36
+ :obj:`BoxList`: The list of all ZPA Gateways Items
37
+
38
+ Examples:
39
+ Get a list of all ZPA Gateways Items
40
+
41
+ >>> results = zia.zpa_gateway.list_gateways()
42
+ ... for item in results:
43
+ ... print(item)
44
+ """
45
+ return self.rest.get("zpaGateways")
46
+
47
+ def get_gateway(self, gateway_id: str) -> Box:
48
+ """
49
+ Returns the zpa gateway details for a given ZPA Gateway.
50
+
51
+ Args:
52
+ gatewayId (str): The unique identifier for the ZPA Gateway.
53
+
54
+ Returns:
55
+ :obj:`Box`: The ZPA Gateway resource record.
56
+
57
+ Examples:
58
+ >>> gw = zia.zpa_gateway.get_gateway('99999')
59
+ """
60
+ response = self.rest.get("/zpaGateways/%s" % (gateway_id))
61
+ if isinstance(response, Response):
62
+ status_code = response.status_code
63
+ if status_code != 200:
64
+ return None
65
+ return response
66
+
67
+ def add_gateway(
68
+ self,
69
+ name: str,
70
+ zpa_server_group: dict = None,
71
+ zpa_app_segments: list = None,
72
+ **kwargs,
73
+ ) -> Box:
74
+ """
75
+ Creates a new ZPA Gateway.
76
+
77
+ Args:
78
+ name (str): The name of the ZPA Gateway.
79
+ zpa_server_group (dict, required): The ZPA Server Group that is
80
+ configured for Source IP Anchoring.
81
+ zpa_app_segments (list, optional): All the Application Segments that are
82
+ associated with the selected ZPA Server Group for which Source IP
83
+ Anchoring is enabled.
84
+
85
+ Keyword Args:
86
+ description (str): Additional details about the ZPA gateway.
87
+ type (str): Indicates whether the ZPA gateway is configured for Zscaler
88
+ Internet Access (using option ZPA) or Zscaler Cloud Connector (using
89
+ option ECZPA). Accepted values are 'ZPA' or 'ECZPA'.
90
+ zpa_tenant_id (int): The ID of the ZPA tenant where Source IP Anchoring
91
+ is configured
92
+
93
+ Returns:
94
+ :obj:`Box`: The newly added ZPA Gateway resource record.
95
+ """
96
+ payload = {"name": name, "type": "ZPA"}
97
+
98
+ if zpa_server_group:
99
+ payload["zpaServerGroup"] = {
100
+ "externalId": zpa_server_group.get("external_id"),
101
+ "name": zpa_server_group.get("name"),
102
+ }
103
+
104
+ if zpa_app_segments:
105
+ payload["zpaAppSegments"] = [
106
+ {"externalId": segment.get("external_id"), "name": segment.get("name")} for segment in zpa_app_segments
107
+ ]
108
+
109
+ # Add other optional parameters to payload
110
+ for key, value in kwargs.items():
111
+ payload[snake_to_camel(key)] = value
112
+
113
+ response = self.rest.post("zpaGateways", json=payload)
114
+ if isinstance(response, Response):
115
+ # Handle error response
116
+ status_code = response.status_code
117
+ raise Exception(f"API call failed with status {status_code}: {response.json()}")
118
+ return response
119
+
120
+ def update_gateway(self, gateway_id: str, **kwargs):
121
+ """
122
+ Updates information for the specified ZPA Gateway.
123
+
124
+ Args:
125
+ gateway_id (str): The unique id for the ZPA Gateway to be updated.
126
+
127
+ Keyword Args:
128
+ name (str): The name of the ZPA gateway.
129
+ description (str): Additional details about the ZPA gateway.
130
+ type (str): Indicates whether the ZPA gateway is configured for
131
+ Zscaler Internet Access (using option ZPA) or Zscaler Cloud
132
+ Connector (using option ECZPA). Accepted values are 'ZPA' or 'ECZPA'.
133
+ zpa_server_group (dict, optional): The ZPA Server Group configured for
134
+ Source IP Anchoring.
135
+ zpa_app_segments (list, optional): All the Application Segments associated
136
+ with the selected ZPA Server Group for which Source IP Anchoring is
137
+ enabled.
138
+ zpa_tenant_id (int): The ID of the ZPA tenant where Source IP Anchoring
139
+ is configured
140
+
141
+ Returns:
142
+ :obj:`Box`: The updated ZPA Gateway resource record.
143
+ """
144
+ payload = convert_keys(self.get_gateway(gateway_id))
145
+
146
+ # Update payload with provided arguments
147
+ for key, value in kwargs.items():
148
+ if key == "zpa_server_group" and isinstance(value, dict):
149
+ # Convert nested keys in zpa_server_group to camelCase
150
+ value = {snake_to_camel(k): v for k, v in value.items()}
151
+ elif key == "zpa_app_segments" and isinstance(value, list):
152
+ # Convert nested keys in zpa_app_segments to camelCase
153
+ value = [{snake_to_camel(k): v for k, v in item.items()} for item in value]
154
+
155
+ payload[snake_to_camel(key)] = value
156
+
157
+ response = self.rest.put(f"zpaGateways/{gateway_id}", json=payload)
158
+ if isinstance(response, Response) and not response.ok:
159
+ # Handle error response
160
+ raise Exception(f"API call failed with status {response.status_code}: " f"{response.json()}")
161
+
162
+ # Return the updated object
163
+ return self.get_gateway(gateway_id)
164
+
165
+ def delete_gateway(self, gateway_id):
166
+ """
167
+ Deletes the specified ZPA Gateway.
168
+
169
+ Args:
170
+ gateway_id (str): The unique identifier of the ZPA Gateway that will be deleted.
171
+
172
+ Returns:
173
+ :obj:`int`: The response code for the request.
174
+
175
+ Examples
176
+ >>> gateway = zia.zpa_gateway.delete_gateway('99999')
177
+
178
+ """
179
+ return self.rest.delete(f"zpaGateways/{gateway_id}").status_code
zscaler/zpa/README.md ADDED
@@ -0,0 +1,40 @@
1
+ ## ZPA Pagination
2
+
3
+ This SDK offers several pagination controls that help manage data retrieval efficiently from the API. Understanding and using these controls properly ensures effective data handling and optimal usage of network resources.
4
+
5
+ ### Available Pagination Controls
6
+
7
+ 1. **`page`**
8
+ - **Purpose:** Specifies the starting page number for the API request.
9
+ - **Use Case:** Ideal for resuming data fetching from a specific point, especially useful if the operations were previously interrupted.
10
+
11
+ 2. **`pagesize`**
12
+ - **Purpose:** Defines the number of items to be returned per page.
13
+ - **Use Case:** Designed to control the volume of data per API call, which is crucial for managing memory overhead and coping with current rate-limits.
14
+
15
+ 3. **`max_pages`**
16
+ - **Purpose:** Sets a limit on the number of pages that can be retrieved.
17
+ - **Use Case:** Great for to cap the extent of data fetched, especially when only a sample or a finite number of API calls is desired.
18
+
19
+ 4. **`max_items`**
20
+ - **Purpose:** Caps the total number of items retrieved across all pages.
21
+ - **Use Case:** Ensures that the fetching process stops once a specific number of items is reached, perfect when a precise dataset size is needed.
22
+
23
+ ### Guidelines and Best Practices
24
+
25
+ - **Combining Controls:**
26
+ - Combining `page` and `pagesize` provides a straightforward control over the start point and volume of data for each fetch.
27
+ - Using `max_pages` and `max_items` provides limits on the fetching operations but from different perspectives: `max_pages` limits the number of fetch operations, whereas `max_items` limits the total number of items fetched.
28
+
29
+ - **Preventing Parameter Conflicts:**
30
+ - Mixing `page` or `pagesize` with `max_pages` or `max_items` can lead to conflicts in the data fetching logic. To prevent these issues and ensure clarity:
31
+ - A `ValueError` exception is thrown if both sets of parameters are used simultaneously. This alert helps avoid misconfigurations that can lead to inefficient data fetching and potential performance issues.
32
+
33
+ - **Error Handling:**
34
+ - **`ValueError`:** This is raised to alert about the improper use of incompatible pagination controls. It ensures developers are aware to not mix direct pagination controls (`page`, `pagesize`) with overarching limits (`max_pages`, `max_items`).
35
+
36
+ - **Recommendations:**
37
+ - Use `page` and `pagesize` for straightforward pagination without intrinsic limits on the number or volume of data.
38
+ - Choose either `max_pages` or `max_items` based on the specific requirements of the operation to avoid unnecessary complexity and potential conflicts.
39
+ - Always set sensible defaults for `pagesize` to prevent excessive data fetches.
40
+