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
zscaler/zia/web_dlp.py ADDED
@@ -0,0 +1,295 @@
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(
197
+ f"API call failed with status {status_code}: {response.json()}"
198
+ )
199
+ return response
200
+
201
+ def update_rule(self, rule_id: str, **kwargs) -> Box:
202
+ """
203
+ Updates an existing DLP policy rule. Not applicable to SaaS Security API DLP policy rules.
204
+
205
+ Args:
206
+ rule_id (str): ID of the rule.
207
+ **kwargs: Optional keyword args.
208
+
209
+ Keyword Args:
210
+ order (str): Rule order, defaults to bottom of list.
211
+ rank (str): Admin rank of the rule.
212
+ state (str): Rule state ('ENABLED' or 'DISABLED').
213
+ auditor (list): IDs for auditors this rule applies to.
214
+ cloud_applications (list): IDs for cloud applications rule applies to.
215
+ description (str): Additional information about the rule.
216
+ departments (list): IDs for departments rule applies to.
217
+ dlp_engines (list): IDs for DLP engines rule applies to.
218
+ excluded_groups (list): IDs for excluded groups.
219
+ excluded_departments (list): IDs for excluded departments.
220
+ excluded_users (list): IDs for excluded users.
221
+ file_types (list): List of file types the rule applies to.
222
+ groups (list): IDs for groups rule applies to.
223
+ icap_server (list): IDs for the ICAP server rule applies to.
224
+ labels (list): IDs for labels rule applies to.
225
+ locations (list): IDs for locations rule applies to.
226
+ location_groups (list): IDs for location groups rule applies to.
227
+ notification_template (list): IDs for the notification template.
228
+ time_windows (list): IDs for time windows rule applies to.
229
+ users (list): IDs for users rule applies to.
230
+ url_categories (list): IDs for URL categories rule applies to.
231
+ external_auditor_email (str): Email of external auditor for DLP notifications.
232
+ dlp_download_scan_enabled (bool): True enables DLP scan for file downloads.
233
+ min_size (str): Minimum file size (in KB) for rule evaluation.
234
+ match_only (bool): If true, uses min_size for rule evaluation.
235
+ ocr_enabled (bool): True allows OCR scanning of image files.
236
+ without_content_inspection (bool): True for DLP rule without content inspection.
237
+ zcc_notifications_enabled (bool): True enables ZCC notification for block action.
238
+
239
+ Returns:
240
+ :obj:`Box`: The updated web dlp rule resource record.
241
+
242
+ Examples:
243
+ Update a Web DLP Policy Rule:
244
+
245
+ >>> zia.web_dlp.get_rule('9999')
246
+ ... name="updated name."
247
+ ... description="updated name."
248
+
249
+ Update a web dlp policy rule to update description:
250
+
251
+ >>> zia.web_dlp.update_rule('976597', description="TT#1965232866")
252
+ """
253
+ # Set payload to value of existing record and convert nested dict keys.
254
+ payload = convert_keys(self.get_rule(rule_id))
255
+
256
+ # Convert enabled to API format if present in kwargs
257
+ if "enabled" in kwargs:
258
+ kwargs["state"] = "ENABLED" if kwargs.pop("enabled") else "DISABLED"
259
+
260
+ # Transform ID fields in kwargs
261
+ transform_common_id_fields(self.reformat_params, kwargs, payload)
262
+
263
+ # Add remaining optional parameters to payload
264
+ for key, value in kwargs.items():
265
+ payload[snake_to_camel(key)] = value
266
+
267
+ response = self.rest.put(f"webDlpRules/{rule_id}", json=payload)
268
+ if isinstance(response, Response) and not response.ok:
269
+ # Handle error response
270
+ raise Exception(
271
+ f"API call failed with status {response.status_code}: {response.json()}"
272
+ )
273
+
274
+ # Return the updated object
275
+ return self.get_rule(rule_id)
276
+
277
+ def delete_rule(self, rule_id: str) -> Box:
278
+ """
279
+ Deletes a DLP policy rule. This endpoint is not applicable to SaaS Security API DLP policy rules.
280
+
281
+ Args:
282
+ rule_id (str): Unique id of the Web DLP Policy Rule that will be deleted.
283
+
284
+ Returns:
285
+ :obj:`Box`: Response message from the ZIA API endpoint.
286
+
287
+ Examples:
288
+ Delete a rule with an id of 9999.
289
+
290
+ >>> results = zia.web_dlp.delete_rule(rule_id=9999)
291
+ ... print(results)
292
+
293
+
294
+ """
295
+ 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,187 @@
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")}
107
+ for segment in zpa_app_segments
108
+ ]
109
+
110
+ # Add other optional parameters to payload
111
+ for key, value in kwargs.items():
112
+ payload[snake_to_camel(key)] = value
113
+
114
+ response = self.rest.post("zpaGateways", json=payload)
115
+ if isinstance(response, Response):
116
+ # Handle error response
117
+ status_code = response.status_code
118
+ raise Exception(
119
+ f"API call failed with status {status_code}: {response.json()}"
120
+ )
121
+ return response
122
+
123
+ def update_gateway(self, gateway_id: str, **kwargs):
124
+ """
125
+ Updates information for the specified ZPA Gateway.
126
+
127
+ Args:
128
+ gateway_id (str): The unique id for the ZPA Gateway to be updated.
129
+
130
+ Keyword Args:
131
+ name (str): The name of the ZPA gateway.
132
+ description (str): Additional details about the ZPA gateway.
133
+ type (str): Indicates whether the ZPA gateway is configured for
134
+ Zscaler Internet Access (using option ZPA) or Zscaler Cloud
135
+ Connector (using option ECZPA). Accepted values are 'ZPA' or 'ECZPA'.
136
+ zpa_server_group (dict, optional): The ZPA Server Group configured for
137
+ Source IP Anchoring.
138
+ zpa_app_segments (list, optional): All the Application Segments associated
139
+ with the selected ZPA Server Group for which Source IP Anchoring is
140
+ enabled.
141
+ zpa_tenant_id (int): The ID of the ZPA tenant where Source IP Anchoring
142
+ is configured
143
+
144
+ Returns:
145
+ :obj:`Box`: The updated ZPA Gateway resource record.
146
+ """
147
+ payload = convert_keys(self.get_gateway(gateway_id))
148
+
149
+ # Update payload with provided arguments
150
+ for key, value in kwargs.items():
151
+ if key == "zpa_server_group" and isinstance(value, dict):
152
+ # Convert nested keys in zpa_server_group to camelCase
153
+ value = {snake_to_camel(k): v for k, v in value.items()}
154
+ elif key == "zpa_app_segments" and isinstance(value, list):
155
+ # Convert nested keys in zpa_app_segments to camelCase
156
+ value = [
157
+ {snake_to_camel(k): v for k, v in item.items()} for item in value
158
+ ]
159
+
160
+ payload[snake_to_camel(key)] = value
161
+
162
+ response = self.rest.put(f"zpaGateways/{gateway_id}", json=payload)
163
+ if isinstance(response, Response) and not response.ok:
164
+ # Handle error response
165
+ raise Exception(
166
+ f"API call failed with status {response.status_code}: "
167
+ f"{response.json()}"
168
+ )
169
+
170
+ # Return the updated object
171
+ return self.get_gateway(gateway_id)
172
+
173
+ def delete_gateway(self, gateway_id):
174
+ """
175
+ Deletes the specified ZPA Gateway.
176
+
177
+ Args:
178
+ gateway_id (str): The unique identifier of the ZPA Gateway that will be deleted.
179
+
180
+ Returns:
181
+ :obj:`int`: The response code for the request.
182
+
183
+ Examples
184
+ >>> gateway = zia.zpa_gateway.delete_gateway('99999')
185
+
186
+ """
187
+ return self.rest.delete(f"zpaGateways/{gateway_id}").status_code