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,310 @@
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
+
18
+ from box import Box, BoxList
19
+ from requests import Response
20
+
21
+ from zscaler.utils import (
22
+ convert_keys,
23
+ recursive_snake_to_camel,
24
+ snake_to_camel,
25
+ transform_common_id_fields,
26
+ )
27
+ from zscaler.zia import ZIAClient
28
+
29
+
30
+ class URLFilteringAPI:
31
+ # URL Filtering Policy rule keys that only require an ID to be provided.
32
+ reformat_params = [
33
+ ("departments", "departments"),
34
+ ("devices", "devices"),
35
+ ("device_groups", "deviceGroups"),
36
+ ("groups", "groups"),
37
+ ("labels", "labels"),
38
+ ("locations", "locations"),
39
+ ("location_groups", "locationGroups"),
40
+ ("override_users", "overrideUsers"),
41
+ ("override_groups", "overrideGroups"),
42
+ ("time_windows", "timeWindows"),
43
+ ("users", "users"),
44
+ ]
45
+
46
+ def __init__(self, client: ZIAClient):
47
+ self.rest = client
48
+
49
+ def list_rules(self) -> BoxList:
50
+ """
51
+ Returns the list of URL Filtering Policy rules
52
+
53
+ Returns:
54
+ :obj:`BoxList`: The list of URL Filtering Policy rules.
55
+
56
+ Examples:
57
+ >>> for rule in zia.url_filters.list_rules():
58
+ ... pprint(rule)
59
+
60
+ """
61
+ response = self.rest.get("urlFilteringRules")
62
+ if isinstance(response, Response):
63
+ return None
64
+ return response
65
+
66
+ def get_rule(self, rule_id: str) -> Box:
67
+ """
68
+ Returns information on the specified URL Filtering Policy rule.
69
+
70
+ Args:
71
+ rule_id (str): The unique ID for the URL Filtering Policy rule.
72
+
73
+ Returns:
74
+ :obj:`Box`: The URL Filtering Policy rule.
75
+
76
+ Examples:
77
+ >>> pprint(zia.url_filters.get_rule('977469'))
78
+
79
+ """
80
+
81
+ return self.rest.get(f"urlFilteringRules/{rule_id}")
82
+
83
+ def add_rule(
84
+ self,
85
+ rank: str,
86
+ name: str,
87
+ action: str,
88
+ protocols: list,
89
+ # override_users: list,
90
+ # override_groups: list,
91
+ **kwargs,
92
+ ) -> Box:
93
+ """
94
+ Adds a new URL Filtering Policy rule.
95
+
96
+ Args:
97
+ rank (str): The admin rank of the user who creates the rule.
98
+ name (str): The name of the rule.
99
+ action (str): Action taken when traffic matches rule criteria. Accepted values are:
100
+
101
+ `ANY`, `NONE`, `BLOCK`, `CAUTION`, `ALLOW` and `ICAP_RESPONSE`
102
+
103
+ device_trust_levels (list): List of device trust levels for which the rule must be applied. Accepted values are:
104
+ `ANY`, `UNKNOWN_DEVICETRUSTLEVEL`, `LOW_TRUST`, `MEDIUM_TRUST`, and `HIGH_TRUST`
105
+
106
+ protocols (list): The protocol criteria for the rule.
107
+ **kwargs: Optional keyword args.
108
+
109
+ Keyword Args:
110
+ block_override (bool): When set to true, a 'BLOCK' action triggered by the rule could be overridden.
111
+ Defaults to `False`.
112
+ ciparule (bool): The CIPA compliance rule is enabled if this is set to `True`. Defaults to `False`.
113
+ departments (list): The IDs for the departments that this rule applies to.
114
+ devices (list): The IDs for the devices that this rule applies to.
115
+ device_groups (list): The IDs for the device groups that this rule applies to.
116
+ labels (list): The IDs for the labels that this rule applies to.
117
+ description (str): Additional information about the URL Filtering rule.
118
+ end_user_notification_url (str): URL of end user notification page to be displayed when the rule is matched.
119
+ Not applicable if either ``override_users`` or ``override_groups`` is specified.
120
+ enforce_time_validity (bool): Enforce a set validity time period for the URL Filtering rule.
121
+ groups (list): The IDs for the groups that this rule applies to.
122
+ locations (list): The IDs for the locations that this rule applies to.
123
+ location_groups (list): The IDs for the location groups that this rule applies to.
124
+ order (str): Order of execution of rule with respect to other URL Filtering rules. Defaults to placing rule
125
+ at the bottom of the list.
126
+ override_users (:obj:`list` of :obj:`int`): The IDs of users that this rule can be overridden for.
127
+ Only applies if ``block_override`` is True, ``action`` is `BLOCK` and ``override_groups`` is not set.
128
+ override_groups (:obj:`list` of :obj:`int`): The IDs of groups that this rule can be overridden for.
129
+ Only applies if ``block_override`` is True and ``action`` is `BLOCK`.
130
+ request_methods (list): The request methods that this rule will apply to. If not specified, the rule will
131
+ apply to all methods.
132
+ size_quota (str): Size quota in KB for applying the URL Filtering rule.
133
+ time_quota (str): Time quota in minutes elapsed after the URL Filtering rule is applied.
134
+ time_windows (list): The IDs for the time windows that this rule applies to.
135
+ url_categories (list): The names of URL categories that this rule applies to.
136
+ users (list): The IDs for the users that this rule applies to.
137
+ validity_start_time (str): Date and time the rule's effects will be valid from. ``enforce_time_validity``
138
+ must be set to `True` for this to take effect.
139
+ validity_end_time (str): Date and time the rule's effects will end. ``enforce_time_validity`` must be set to
140
+ `True` for this to take effect.
141
+ validity_time_zone_id (str): The URL Filter rule validity date and time will be based on the TZ provided.
142
+ ``enforce_time_validity`` must be set to `True` for this to take effect.
143
+
144
+ Returns:
145
+ :obj:`Box`: The newly created URL Filtering Policy rule.
146
+
147
+ Examples:
148
+ Add a rule with the minimum required parameters:
149
+
150
+ >>> zia.url_filters.add_rule(rank='7',
151
+ ... name="Empty URL Filter",
152
+ ... action="ALLOW",
153
+ ... protocols=['ANY_RULE']
154
+
155
+ Add a rule to block HTTP POST to Social Media sites for the Finance department.
156
+
157
+ >>> zia.url_filters.add_rule(rank='7',
158
+ ... name="Block POST to Social Media",
159
+ ... action="BLOCK",
160
+ ... protocols=["HTTP_PROXY", "HTTP_RULE", "HTTPS_RULE"],
161
+ ... request_methods=['POST'],
162
+ ... departments=["95022175"],
163
+ ... url_categories=["SOCIAL_NETWORKING"])
164
+
165
+ """
166
+ # Convert enabled to API format if present
167
+ if "enabled" in kwargs:
168
+ kwargs["state"] = "ENABLED" if kwargs.pop("enabled") else "DISABLED"
169
+
170
+ # Initialize the payload with required parameters
171
+ payload = {
172
+ "rank": rank,
173
+ "name": name,
174
+ "action": action,
175
+ "protocols": protocols,
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("urlFilteringRules", json=payload)
193
+ if isinstance(response, Response):
194
+ # Handle error response
195
+ status_code = response.status_code
196
+ if status_code != 200:
197
+ raise Exception(
198
+ f"API call failed with status {status_code}: {response.json()}"
199
+ )
200
+ return response
201
+
202
+ def update_rule(self, rule_id: str, **kwargs) -> Box:
203
+ """
204
+ Updates the specified URL Filtering Policy rule.
205
+
206
+ Args:
207
+ rule_id: The unique ID of the URL Filtering Policy rule to be updated.
208
+ **kwargs: Optional keyword args.
209
+
210
+ Keyword Args:
211
+ name (str): The name of the rule.
212
+ action (str): Action taken when traffic matches rule criteria. Accepted values are:
213
+
214
+ `ANY`, `NONE`, `BLOCK`, `CAUTION`, `ALLOW` and `ICAP_RESPONSE`
215
+
216
+ device_trust_levels (list): List of device trust levels for which the rule must be applied. Accepted values are:
217
+ `ANY`, `UNKNOWN_DEVICETRUSTLEVEL`, `LOW_TRUST`, `MEDIUM_TRUST`, and `HIGH_TRUST`
218
+
219
+ protocols (list): The protocol criteria for the rule.
220
+ block_override (bool): When set to true, a 'BLOCK' action triggered by the rule could be overridden.
221
+ Defaults to `False`.
222
+ ciparule (bool): The CIPA compliance rule is enabled if this is set to `True`. Defaults to `False`.
223
+ departments (list): The IDs for the departments that this rule applies to.
224
+ devices (list): The IDs for the devices that this rule applies to.
225
+ device_groups (list): The IDs for the device groups that this rule applies to.
226
+ labels (list): The IDs for the labels that this rule applies to.
227
+ description (str): Additional information about the URL Filtering rule.
228
+ end_user_notification_url (str): URL of end user notification page to be displayed when the rule is matched.
229
+ Not applicable if either ``override_users`` or ``override_groups`` is specified.
230
+ enforce_time_validity (bool): Enforce a set validity time period for the URL Filtering rule.
231
+ groups (list): The IDs for the groups that this rule applies to.
232
+ locations (list): The IDs for the locations that this rule applies to.
233
+ location_groups (list): The IDs for the location groups that this rule applies to.
234
+ order (str): Order of execution of rule with respect to other URL Filtering rules. Defaults to placing rule
235
+ at the bottom of the list.
236
+ override_users (:obj:`list` of :obj:`int`):
237
+ The IDs of users that this rule can be overridden for.
238
+ Only applies if ``block_override`` is True, ``action`` is `BLOCK` and ``override_groups`` is not set.
239
+ override_groups (:obj:`list` of :obj:`int`):
240
+ The IDs of groups that this rule can be overridden for.
241
+ Only applies if ``block_override`` is True and ``action`` is `BLOCK`.
242
+ request_methods (list): The request methods that this rule will apply to. If not specified, the rule will
243
+ apply to all methods.
244
+ size_quota (str): Size quota in KB for applying the URL Filtering rule.
245
+ time_quota (str): Time quota in minutes elapsed after the URL Filtering rule is applied.
246
+ time_windows (list): The IDs for the time windows that this rule applies to.
247
+ url_categories (list): The names of URL categories that this rule applies to.
248
+ users (list): The IDs for the users that this rule applies to.
249
+ validity_start_time (str): Date and time the rule's effects will be valid from. ``enforce_time_validity``
250
+ must be set to `True` for this to take effect.
251
+ validity_end_time (str): Date and time the rule's effects will end. ``enforce_time_validity`` must be set to
252
+ `True` for this to take effect.
253
+ validity_time_zone_id (str): The URL Filter rule validity date and time will be based on the TZ provided.
254
+ ``enforce_time_validity`` must be set to `True` for this to take effect.
255
+
256
+ Returns:
257
+ :obj:`Box`: The updated URL Filtering Policy rule.
258
+
259
+ Examples:
260
+ Update the name of a URL Filtering Policy rule:
261
+
262
+ >>> zia.url_filters.update_rule('977467',
263
+ ... name="Updated Name")
264
+
265
+ Add GET to request methods and change action to ALLOW:
266
+
267
+ >>> zia.url_filters.update_rule('977468',
268
+ ... request_methods=['POST', 'GET'],
269
+ ... action="ALLOW")
270
+
271
+ """
272
+ # Set payload to value of existing record and convert nested dict keys.
273
+ payload = convert_keys(self.get_rule(rule_id))
274
+
275
+ # Convert enabled to API format if present in kwargs
276
+ if "enabled" in kwargs:
277
+ kwargs["state"] = "ENABLED" if kwargs.pop("enabled") else "DISABLED"
278
+
279
+ # Transform ID fields in kwargs
280
+ transform_common_id_fields(self.reformat_params, kwargs, payload)
281
+
282
+ # Add remaining optional parameters to payload
283
+ for key, value in kwargs.items():
284
+ payload[snake_to_camel(key)] = value
285
+
286
+ response = self.rest.put(f"urlFilteringRules/{rule_id}", json=payload)
287
+ if isinstance(response, Response) and not response.ok:
288
+ # Handle error response
289
+ raise Exception(
290
+ f"API call failed with status {response.status_code}: {response.json()}"
291
+ )
292
+
293
+ # Return the updated object
294
+ return self.get_rule(rule_id)
295
+
296
+ def delete_rule(self, rule_id: str) -> int:
297
+ """
298
+ Deletes the specified URL Filtering Policy rule.
299
+
300
+ Args:
301
+ rule_id (str): The unique ID for the URL Filtering Policy rule.
302
+
303
+ Returns:
304
+ :obj:`int`: The status code for the operation.
305
+
306
+ Examples:
307
+ >>> zia.url_filters.delete_rule('977463')
308
+
309
+ """
310
+ return self.rest.delete(f"urlFilteringRules/{rule_id}").status_code
zscaler/zia/users.py ADDED
@@ -0,0 +1,386 @@
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
+
18
+ from box import Box, BoxList
19
+
20
+ from zscaler.utils import Iterator, convert_keys, snake_to_camel
21
+ from zscaler.zia import ZIAClient
22
+
23
+
24
+ class UserManagementAPI:
25
+ """
26
+ The methods within this section use the ZIA User Management API and are accessed via ``ZIA.users``.
27
+
28
+ """
29
+
30
+ def __init__(self, client: ZIAClient):
31
+ self.rest = client
32
+
33
+ def list_departments(self, **kwargs) -> BoxList:
34
+ """
35
+ Returns the list of departments.
36
+
37
+ Keyword Args:
38
+ **limit_search (bool, optional):
39
+ Limits the search to match against the department name only.
40
+ **max_items (int, optional):
41
+ The maximum number of items to request before stopping iteration.
42
+ **max_pages (int, optional):
43
+ The maximum number of pages to request before stopping iteration.
44
+ **page_size (int, optional):
45
+ Specifies the page size. The default size is 100, but the maximum size is 1000.
46
+ **search (str, optional):
47
+ The search string used to match against a department's name or comments attributes.
48
+ **sort_by (str):
49
+ The field name to sort by, supported values: id, name, creationTime or modifiedTime (default to name)
50
+ **sort_order (str):
51
+ The sort order, values: ASC or DESC (default DESC)
52
+
53
+ Returns:
54
+ :obj:`BoxList`: The list of departments configured in ZIA.
55
+
56
+ Examples:
57
+ List departments using default settings:
58
+
59
+ >>> for department in zia.users.list_departments():
60
+ ... print(department)
61
+
62
+ List departments, limiting to a maximum of 10 items:
63
+
64
+ >>> for department in zia.users.list_departments(max_items=10):
65
+ ... print(department)
66
+
67
+ List departments, returning 200 items per page for a maximum of 2 pages:
68
+
69
+ >>> for department in zia.users.list_departments(page_size=200, max_pages=2):
70
+ ... print(department)
71
+ """
72
+ return BoxList(Iterator(self.rest, "departments", **kwargs))
73
+
74
+ def get_department(self, department_id: str) -> Box:
75
+ """
76
+ Returns the department details for a given department.
77
+
78
+ Args:
79
+ department_id (str): The unique identifier for the department.
80
+
81
+ Returns:
82
+ :obj:`Box`: The department resource record.
83
+
84
+ Examples:
85
+ >>> department = zia.users.get_department('99999')
86
+
87
+ """
88
+ return self.rest.get(f"departments/{department_id}")
89
+
90
+ def get_dept_by_name(self, name):
91
+ depts = self.list_departments()
92
+ for dept in depts:
93
+ if dept.get("name") == name:
94
+ return dept
95
+ return None
96
+
97
+ def list_groups(self, **kwargs) -> BoxList:
98
+ """
99
+ Returns the list of user groups.
100
+
101
+ Keyword Args:
102
+ **max_items (int, optional):
103
+ The maximum number of items to request before stopping iteration.
104
+ **max_pages (int, optional):
105
+ The maximum number of pages to request before stopping iteration.
106
+ **page_size (int, optional):
107
+ Specifies the page size. The default size is 100, but the maximum size is 1000.
108
+ **search (str, optional):
109
+ The search string used to match against a group's name or comments attributes.
110
+ Returns:
111
+ :obj:`BoxList`: The list of user groups configured in ZIA.
112
+
113
+ Examples:
114
+ List groups using default settings:
115
+
116
+ >>> for group in zia.users.list_groups():
117
+ ... print(group)
118
+
119
+ List groups, limiting to a maximum of 10 items:
120
+
121
+ >>> for group in zia.users.list_groups(max_items=10):
122
+ ... print(group)
123
+
124
+ List groups, returning 200 items per page for a maximum of 2 pages:
125
+
126
+ >>> for group in zia.users.list_groups(page_size=200, max_pages=2):
127
+ ... print(group)
128
+
129
+ """
130
+ return BoxList(Iterator(self.rest, "groups", **kwargs))
131
+
132
+ def get_group(self, group_id: str) -> Box:
133
+ """
134
+ Returns the user group details for a given user group.
135
+
136
+ Args:
137
+ group_id (str): The unique identifier for the user group.
138
+
139
+ Returns:
140
+ :obj:`Box`: The user group resource record.
141
+
142
+ Examples:
143
+ >>> user_group = zia.users.get_group('99999')
144
+
145
+ """
146
+ return self.rest.get(f"groups/{group_id}")
147
+
148
+ def get_group_by_name(self, name):
149
+ groups = self.list_groups()
150
+ for group in groups:
151
+ if group.get("name") == name:
152
+ return group
153
+ return None
154
+
155
+ def list_users(self, **kwargs) -> BoxList:
156
+ """
157
+ Returns the list of users.
158
+
159
+ Keyword Args:
160
+ **dept (str, optional):
161
+ Filters by department name. This is a `starts with` match.
162
+ **group (str, optional):
163
+ Filters by group name. This is a `starts with` match.
164
+ **max_items (int, optional):
165
+ The maximum number of items to request before stopping iteration.
166
+ **max_pages (int, optional):
167
+ The maximum number of pages to request before stopping iteration.
168
+ **name (str, optional):
169
+ Filters by user name. This is a `partial` match.
170
+ **page_size (int, optional):
171
+ Specifies the page size. The default size is 100, but the maximum size is 1000.
172
+ **sort_by (str):
173
+ The field name to sort by, supported values: id, name, creationTime or modifiedTime (default to name)
174
+ **sort_order (str):
175
+ The sort order, values: ASC or DESC (default DESC)
176
+
177
+ Returns:
178
+ :obj:`BoxList`: The list of users configured in ZIA.
179
+
180
+ Examples:
181
+ List users using default settings:
182
+
183
+ >>> for user in zia.users.list_users():
184
+ ... print(user)
185
+
186
+ List users, limiting to a maximum of 10 items:
187
+
188
+ >>> for user in zia.users.list_users(max_items=10):
189
+ ... print(user)
190
+
191
+ List users, returning 200 items per page for a maximum of 2 pages:
192
+
193
+ >>> for user in zia.users.list_users(page_size=200, max_pages=2):
194
+ ... print(user)
195
+
196
+ """
197
+ return BoxList(Iterator(self.rest, "users", **kwargs))
198
+
199
+ def add_user(
200
+ self, name: str, email: str, groups: list, department: dict, **kwargs
201
+ ) -> Box:
202
+ """
203
+ Creates a new ZIA user.
204
+
205
+ Args:
206
+ name (str):
207
+ User name.
208
+ email (str):
209
+ User email consists of a user name and domain name. It does not have to be a valid email address,
210
+ but it must be unique and its domain must belong to the organisation.
211
+ groups (list):
212
+ List of Groups a user belongs to.
213
+ department (dict):
214
+ The department the user belongs to.
215
+
216
+ Keyword Args:
217
+ **comments (str):
218
+ Additional information about this user.
219
+ **tempAuthEmail (str):
220
+ Temporary Authentication Email. If you enabled one-time tokens or links, enter the email address to
221
+ which the Zscaler service sends the tokens or links. If this is empty, the service will send the
222
+ email to the User email.
223
+ **adminUser (bool):
224
+ True if this user is an Admin user.
225
+ **password (str):
226
+ User's password. Applicable only when authentication type is Hosted DB. Password strength must follow
227
+ what is defined in the auth settings.
228
+ **type (str):
229
+ User type. Provided only if this user is not an end user. Accepted values are SUPERADMIN, ADMIN,
230
+ AUDITOR, GUEST, REPORT_USER and UNAUTH_TRAFFIC_DEFAULT.
231
+
232
+ Returns:
233
+ :obj:`Box`: The resource record for the new user.
234
+
235
+ Examples:
236
+ Add a user with the minimum required params:
237
+
238
+ >>> zia.users.add_user(name='Jane Doe',
239
+ ... email='jane.doe@example.com',
240
+ ... groups=[{
241
+ ... 'id': '49916183'}]
242
+ ... department={
243
+ ... 'id': '49814321'})
244
+
245
+ """
246
+ payload = {
247
+ "name": name,
248
+ "email": email,
249
+ "groups": groups,
250
+ "department": department,
251
+ }
252
+
253
+ # Add optional parameters to payload
254
+ for key, value in kwargs.items():
255
+ payload[key] = value
256
+ return self.rest.post("users", json=payload)
257
+
258
+ def bulk_delete_users(self, user_ids: list) -> Box:
259
+ """
260
+ Bulk delete ZIA users.
261
+
262
+ Args:
263
+ user_ids (list): List containing id int of each user that will be deleted.
264
+
265
+ Returns:
266
+ :obj:`Box`: Object containing list of users that were deleted.
267
+
268
+ Examples:
269
+ >>> bulk_delete_users = zia.users.bulk_delete_users(['99999', '88888', '77777'])
270
+
271
+ """
272
+
273
+ payload = {"ids": user_ids}
274
+
275
+ return self.rest.post("users/bulkDelete", json=payload)
276
+
277
+ def get_user(self, user_id: str = None, email: str = None) -> Box:
278
+ """
279
+ Returns the user information for the specified ID or email.
280
+
281
+ Args:
282
+ user_id (optional, str): The unique identifier for the requested user.
283
+ email (optional, str): The unique email for the requested user.
284
+
285
+ Returns:
286
+ :obj:`Box`: The resource record for the requested user.
287
+
288
+ Examples
289
+ >>> user = zia.users.get_user('99999')
290
+
291
+ >>> user = zia.users.get_user(email='jane.doe@example.com')
292
+
293
+ """
294
+
295
+ if user_id and email:
296
+ raise ValueError(
297
+ "TOO MANY ARGUMENTS: Expected either a user_id or an email. Both were provided."
298
+ )
299
+
300
+ elif email:
301
+ user = (
302
+ record
303
+ for record in self.list_users(search=email)
304
+ if record.email == email
305
+ )
306
+ return next(user, None)
307
+
308
+ return self.rest.get(f"users/{user_id}")
309
+
310
+ def update_user(
311
+ self,
312
+ user_id: str,
313
+ **kwargs,
314
+ ) -> Box:
315
+ """
316
+ Updates the details for the specified user.
317
+
318
+ Args:
319
+ user_id (str):
320
+ The unique identifier for the user.
321
+ **kwargs:
322
+ Optional parameters
323
+
324
+ Keyword Args:
325
+ **adminUser (bool):
326
+ True if this user is an Admin user.
327
+ **comments (str):
328
+ Additional information about this user.
329
+ **department (dict, optional):
330
+ The updated department object. Defaults to existing department if not specified.
331
+ **email (str, optional):
332
+ The updated email. Defaults to existing email if not specified.
333
+ **groups (:obj:`list` of :obj:`dict`, optional):
334
+ The updated list of groups. Defaults to existing groups if not specified.
335
+ **name (str, optional):
336
+ The updated name. Defaults to existing name if not specified.
337
+ **password (str):
338
+ User's password. Applicable only when authentication type is Hosted DB. Password strength must follow
339
+ what is defined in the auth settings.
340
+ **tempAuthEmail (str):
341
+ Temporary Authentication Email. If you enabled one-time tokens or links, enter the email address to
342
+ which the Zscaler service sends the tokens or links. If this is empty, the service will send the
343
+ email to the User email.
344
+ **type (str):
345
+ User type. Provided only if this user is not an end user. Accepted values are SUPERADMIN, ADMIN,
346
+ AUDITOR, GUEST, REPORT_USER and UNAUTH_TRAFFIC_DEFAULT.
347
+
348
+ Returns:
349
+ :obj:`Box`: The resource record of the updated user.
350
+
351
+ Examples:
352
+ Update the user name:
353
+
354
+ >>> zia.users.update_user('99999',
355
+ ... name='Joe Bloggs')
356
+
357
+ Update the email and add a comment:
358
+
359
+ >>> zia.users.update_user('99999',
360
+ ... name='Joe Bloggs',
361
+ ... comment='External auditor.')
362
+
363
+ """
364
+ payload = convert_keys(self.get_user(user_id))
365
+
366
+ # Add optional parameters to payload
367
+ for key, value in kwargs.items():
368
+ payload[snake_to_camel(key)] = value
369
+
370
+ return self.rest.put(f"users/{user_id}", json=payload)
371
+
372
+ def delete_user(self, user_id: str) -> int:
373
+ """
374
+ Deletes the specified user ID.
375
+
376
+ Args:
377
+ user_id (str): The unique identifier of the user that will be deleted.
378
+
379
+ Returns:
380
+ :obj:`int`: The response code for the request.
381
+
382
+ Examples:
383
+ >>> user = zia.users.delete_user('99999')
384
+ """
385
+ response = self.rest.delete(f"users/{user_id}")
386
+ return response.status_code