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,271 @@
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 snake_to_camel
22
+ from zscaler.zpa.client import ZPAClient
23
+
24
+
25
+ def simplify_key_type(key_type):
26
+ # Simplify the key type for our users
27
+ if key_type == "connector":
28
+ return "CONNECTOR_GRP"
29
+ elif key_type == "service_edge":
30
+ return "SERVICE_EDGE_GRP"
31
+ else:
32
+ raise ValueError("Unexpected key type.")
33
+
34
+
35
+ class ProvisioningKeyAPI:
36
+ def __init__(self, client: ZPAClient):
37
+ self.rest = client
38
+
39
+ def list_provisioning_keys(self, key_type: str, **kwargs) -> BoxList:
40
+ """
41
+ Returns a list of all configured provisioning keys that match the specified ``key_type``.
42
+
43
+ Args:
44
+ key_type (str): The type of provisioning key, accepted values are:
45
+ ``connector`` and ``service_edge``.
46
+ **kwargs: Optional keyword args.
47
+
48
+ Keyword Args:
49
+ max_items (int, optional):
50
+ The maximum number of items to request before stopping iteration.
51
+ max_pages (int, optional):
52
+ The maximum number of pages to request before stopping iteration.
53
+ pagesize (int, optional):
54
+ Specifies the page size. The default size is 20, but the maximum size is 500.
55
+ search (str, optional):
56
+ The search string used to match against features and fields.
57
+
58
+ Returns:
59
+ :obj:`BoxList`: A list containing the requested provisioning keys.
60
+
61
+ Examples:
62
+ List all App Connector provisioning keys.
63
+
64
+ >>> for key in zpa.provisioning.list_provisioning_keys(key_type="connector"):
65
+ ... print(key)
66
+
67
+ List all Service Edge provisioning keys.
68
+
69
+ >>> for key in zpa.provisioning.list_provisioning_keys(key_type="service_edge"):
70
+ ... print(key)
71
+
72
+ """
73
+ list, _ = self.rest.get_paginated_data(
74
+ path=f"/associationType/{simplify_key_type(key_type)}/provisioningKey",
75
+ **kwargs,
76
+ )
77
+ return list
78
+
79
+ def get_provisioning_key(self, key_id: str, key_type: str) -> Box:
80
+ """
81
+ Returns information on the specified provisioning key.
82
+
83
+ Args:
84
+ key_id (str): The unique id of the provisioning key.
85
+ key_type (str): The type of provisioning key, accepted values are:
86
+
87
+ ``connector`` and ``service_edge``.
88
+
89
+ Returns:
90
+ :obj:`Box`: The requested provisioning key resource record.
91
+
92
+ Examples:
93
+ Get the specified App Connector key.
94
+
95
+ >>> provisioning_key = zpa.provisioning.get_provisioning_key("999999",
96
+ ... key_type="connector")
97
+
98
+ Get the specified Service Edge key.
99
+
100
+ >>> provisioning_key = zpa.provisioning.get_provisioning_key("888888",
101
+ ... key_type="service_edge")
102
+
103
+ """
104
+ return self.rest.get(
105
+ f"associationType/{simplify_key_type(key_type)}/provisioningKey/{key_id}"
106
+ )
107
+
108
+ def add_provisioning_key(
109
+ self,
110
+ key_type: str,
111
+ name: str,
112
+ max_usage: str,
113
+ enrollment_cert_id: str,
114
+ component_id: str,
115
+ **kwargs,
116
+ ) -> Box:
117
+ """
118
+ Adds a new provisioning key to ZPA.
119
+
120
+ Args:
121
+ key_type (str): The type of provisioning key, accepted values are:
122
+
123
+ ``connector`` and ``service_edge``.
124
+ name (str): The name of the provisioning key.
125
+ max_usage (int): The maximum amount of times this key can be used.
126
+ enrollment_cert_id (str):
127
+ The unique id of the enrollment certificate that will be used for this provisioning key.
128
+ component_id (str):
129
+ The unique id of the component that this provisioning key will be linked to. For App Connectors, this
130
+ will be the App Connector Group Id. For Service Edges, this will be the Service Edge Group Id.
131
+ **kwargs: Optional keyword args.
132
+
133
+ Keyword Args:
134
+ enabled (bool): Enable the provisioning key. Defaults to ``True``.
135
+
136
+ Returns:
137
+ :obj:`Box`: The newly created Provisioning Key resource record.
138
+
139
+ Examples:
140
+ Add a new App Connector Provisioning Key that can be used a maximum of 2 times.
141
+
142
+ >>> key = zpa.provisioning.add_provisioning_key(key_type="connector",
143
+ ... name="Example App Connector Provisioning Key",
144
+ ... max_usage=2,
145
+ ... enrollment_cert_id="99999",
146
+ ... component_id="888888")
147
+
148
+ Add a new Service Edge Provisioning Key in the disabled state that can be used once.
149
+
150
+ >>> key = zpa.provisioning.add_provisioning_key(key_type="service_edge",
151
+ ... name="Example Service Edge Provisioning Key",
152
+ ... max_usage=1,
153
+ ... enrollment_cert_id="99999",
154
+ ... component_id="777777"
155
+ ... enabled=False)
156
+
157
+ """
158
+
159
+ payload = {
160
+ "name": name,
161
+ "maxUsage": max_usage,
162
+ "enrollmentCertId": enrollment_cert_id,
163
+ "zcomponentId": component_id,
164
+ }
165
+
166
+ # Add optional parameters to payload
167
+ for key, value in kwargs.items():
168
+ payload[snake_to_camel(key)] = value
169
+
170
+ response = self.rest.post(
171
+ f"associationType/{simplify_key_type(key_type)}/provisioningKey",
172
+ json=payload,
173
+ )
174
+ if isinstance(response, Response):
175
+ # this is only true when the creation failed (status code is not 2xx)
176
+ status_code = response.status_code
177
+ # Handle error response
178
+ raise Exception(
179
+ f"API call failed with status {status_code}: {response.json()}"
180
+ )
181
+ return response
182
+
183
+ def update_provisioning_key(self, key_id: str, key_type: str, **kwargs) -> Box:
184
+ """
185
+ Updates the specified provisioning key.
186
+
187
+ Args:
188
+ key_id (str): The unique id of the Provisioning Key being updated.
189
+ key_type (str): The type of provisioning key, accepted values are:
190
+
191
+ ``connector`` and ``service_edge``.
192
+ **kwargs: Optional keyword args.
193
+
194
+ Keyword Args:
195
+ name (str): The name of the provisioning key.
196
+ max_usage (int): The maximum amount of times this key can be used.
197
+ enrollment_cert_id (str):
198
+ The unique id of the enrollment certificate that will be used for this provisioning key.
199
+ component_id (str):
200
+ The unique id of the component that this provisioning key will be linked to. For App Connectors, this
201
+ will be the App Connector Group Id. For Service Edges, this will be the Service Edge Group Id.
202
+
203
+ Returns:
204
+ :obj:`Box`: The updated Provisioning Key resource record.
205
+
206
+ Examples:
207
+ Update the name of an App Connector provisioning key:
208
+
209
+ >>> updated_key = zpa.provisioning.update_provisioning_key('999999',
210
+ ... key_type="connector",
211
+ ... name="Updated Name")
212
+
213
+ Change the max usage of a Service Edge provisioning key:
214
+
215
+ >>> updated_key = zpa.provisioning.update_provisioning_key('888888',
216
+ ... key_type="service_edge",
217
+ ... max_usage=10)
218
+
219
+ """
220
+
221
+ # Get the provided provisioning key record
222
+ payload = {
223
+ snake_to_camel(k): v
224
+ for k, v in self.get_provisioning_key(key_id, key_type=key_type).items()
225
+ }
226
+
227
+ # Add optional parameters to payload
228
+ for key, value in kwargs.items():
229
+ payload[snake_to_camel(key)] = value
230
+
231
+ resp = self.rest.put(
232
+ f"associationType/{simplify_key_type(key_type)}/provisioningKey/{key_id}",
233
+ json=payload,
234
+ ).status_code
235
+
236
+ # Return the object if it was updated successfully
237
+ if not isinstance(resp, Response):
238
+ return self.get_provisioning_key(key_id, key_type=key_type)
239
+
240
+ # Return the object if it was updated successfully
241
+ if not isinstance(resp, Response):
242
+ return self.get_provisioning_key(key_id, key_type=key_type)
243
+
244
+ def delete_provisioning_key(self, key_id: str, key_type: str) -> int:
245
+ """
246
+ Deletes the specified provisioning key from ZPA.
247
+
248
+ Args:
249
+ key_id (str): The unique id of the provisioning key that will be deleted.
250
+ key_type (str): The type of provisioning key, accepted values are:
251
+
252
+ ``connector`` and ``service_edge``.
253
+
254
+ Returns:
255
+ :obj:`int`: The status code for the operation.
256
+
257
+ Examples:
258
+ Delete an App Connector provisioning key:
259
+
260
+ >>> zpa.provisioning.delete_provisioning_key(key_id="999999",
261
+ ... key_type="connector")
262
+
263
+ Delete a Service Edge provisioning key:
264
+
265
+ >>> zpa.provisioning.delete_provisioning_key(key_id="888888",
266
+ ... key_type="service_edge")
267
+
268
+ """
269
+ return self.rest.delete(
270
+ f"associationType/{simplify_key_type(key_type)}/provisioningKey/{key_id}"
271
+ ).status_code
@@ -0,0 +1,100 @@
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.zpa.client import ZPAClient
21
+
22
+
23
+ class SAMLAttributesAPI:
24
+ def __init__(self, client: ZPAClient):
25
+ self.rest = client
26
+
27
+ def list_attributes(self, **kwargs) -> BoxList:
28
+ """
29
+ Returns a list of all configured SAML attributes.
30
+
31
+ Keyword Args:
32
+ **max_items (int):
33
+ The maximum number of items to request before stopping iteration.
34
+ **max_pages (int):
35
+ The maximum number of pages to request before stopping iteration.
36
+ **pagesize (int):
37
+ Specifies the page size. The default size is 20, but the maximum size is 500.
38
+ **search (str, optional):
39
+ The search string used to match against features and fields.
40
+
41
+ Returns:
42
+ :obj:`BoxList`: A list of all configured SAML attributes.
43
+
44
+ Examples:
45
+ >>> for saml_attribute in zpa.saml_attributes.list_attributes():
46
+ ... pprint(saml_attribute)
47
+
48
+ """
49
+ list, _ = self.rest.get_paginated_data(
50
+ path="/samlAttribute", **kwargs, api_version="v2"
51
+ )
52
+ return list
53
+
54
+ def list_attributes_by_idp(self, idp_id: str, **kwargs) -> BoxList:
55
+ """
56
+ Returns a list of all configured SAML attributes for the specified IdP.
57
+
58
+ Args:
59
+ idp_id (str): The unique id of the IdP to retrieve SAML attributes from.
60
+
61
+ Keyword Args:
62
+ **max_items (int):
63
+ The maximum number of items to request before stopping iteration.
64
+ **max_pages (int):
65
+ The maximum number of pages to request before stopping iteration.
66
+ **pagesize (int):
67
+ Specifies the page size. The default size is 20, but the maximum size is 500.
68
+ **search (str, optional):
69
+ The search string used to match against features and fields.
70
+
71
+ Returns:
72
+ :obj:`BoxList`: A list of all configured SAML attributes for the specified IdP.
73
+
74
+ Examples:
75
+ >>> for saml_attribute in zpa.saml_attributes.list_attributes_by_idp('99999'):
76
+ ... pprint(saml_attribute)
77
+
78
+ """
79
+ path = (
80
+ f"/samlAttribute/idp/{idp_id}" # Correctly format the path with the idp_id
81
+ )
82
+ list, _ = self.rest.get_paginated_data(path=path, **kwargs, api_version="v2")
83
+ return list
84
+
85
+ def get_attribute(self, attribute_id: str) -> Box:
86
+ """
87
+ Returns information on the specified SAML attributes.
88
+
89
+ Args:
90
+ attribute_id (str):
91
+ The unique identifier for the SAML attributes.
92
+
93
+ Returns:
94
+ :obj:`dict`: The resource record for the SAML attributes.
95
+
96
+ Examples:
97
+ >>> pprint(zpa.saml_attributes.get_attribute('99999'))
98
+
99
+ """
100
+ return self.rest.get(f"samlAttribute/{attribute_id}")
@@ -0,0 +1,117 @@
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.zpa.client import ZPAClient
21
+
22
+
23
+ class ScimAttributeHeaderAPI:
24
+ def __init__(self, client: ZPAClient):
25
+ self.rest = client
26
+
27
+ def list_attributes_by_idp(self, idp_id: str, **kwargs) -> BoxList:
28
+ """
29
+ Returns a list of all configured SCIM attributes for the specified IdP.
30
+
31
+ Args:
32
+ idp_id (str): The unique id of the IdP to retrieve SCIM attributes for.
33
+ **kwargs: Optional keyword args.
34
+
35
+ Keyword Args:
36
+ max_items (int):
37
+ The maximum number of items to request before stopping iteration.
38
+ max_pages (int):
39
+ The maximum number of pages to request before stopping iteration.
40
+ pagesize (int):
41
+ Specifies the page size. The default size is 20, but the maximum size is 500.
42
+ search (str, optional):
43
+ The search string used to match against features and fields.
44
+
45
+ Returns:
46
+ :obj:`BoxList`: A list of all configured SCIM attributes for the specified IdP.
47
+
48
+ Examples:
49
+ >>> for scim_attribute in zpa.scim_attributes.list_attributes_by_idp('99999'):
50
+ ... pprint(scim_attribute)
51
+
52
+ """
53
+ list, _ = self.rest.get_paginated_data(
54
+ path=f"/idp/{idp_id}/scimattribute",
55
+ **kwargs,
56
+ api_version="v1",
57
+ )
58
+ return list
59
+
60
+ def get_attribute(self, idp_id: str, attribute_id: str) -> Box:
61
+ """
62
+ Returns information on the specified SCIM attribute.
63
+
64
+ Args:
65
+ idp_id (str):
66
+ The unique id of the Idp corresponding to the SCIM attribute.
67
+ attribute_id (str):
68
+ The unique id of the SCIM attribute.
69
+
70
+ Returns:
71
+ :obj:`Box`: The resource record for the SCIM attribute.
72
+
73
+ Examples:
74
+ >>> pprint(zpa.scim_attributes.get_attribute('99999',
75
+ ... scim_attribute_id="88888"))
76
+
77
+ """
78
+ response = self.rest.get(
79
+ f"/idp/{idp_id}/scimattribute/{attribute_id}", api_version="v1"
80
+ )
81
+ return response
82
+
83
+ def get_values(self, idp_id: str, attribute_id: str, **kwargs) -> BoxList:
84
+ """
85
+ Returns information on the specified SCIM attributes.
86
+
87
+ Args:
88
+ idp_id (str):
89
+ The unique identifier for the IDP.
90
+ attribute_id (str):
91
+ The unique identifier for the attribute.
92
+ **kwargs:
93
+ Optional keyword args.
94
+
95
+ Keyword Args:
96
+ max_items (int):
97
+ The maximum number of items to request before stopping iteration.
98
+ max_pages (int):
99
+ The maximum number of pages to request before stopping iteration.
100
+ pagesize (int):
101
+ Specifies the page size. Default is 20, maximum is 500.
102
+ search (str, optional):
103
+ The search string used to match against features and fields.
104
+
105
+ Returns:
106
+ :obj:`BoxList`: The resource record for the SCIM attribute values.
107
+
108
+ Examples:
109
+ >>> pprint(zpa.scim_attributes.get_values('99999', '88888'))
110
+
111
+ """
112
+ list, _ = self.rest.get_paginated_data(
113
+ path=f"/scimattribute/idpId/{idp_id}/attributeId/{attribute_id}",
114
+ **kwargs,
115
+ api_version="userconfig_v1",
116
+ )
117
+ return list
@@ -0,0 +1,146 @@
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.zpa.client import ZPAClient
21
+
22
+
23
+ class SCIMGroupsAPI:
24
+ def __init__(self, client: ZPAClient):
25
+ self.rest = client
26
+
27
+ def list_groups(self, idp_id: str, **kwargs) -> BoxList:
28
+ """
29
+ Returns a list of all configured SCIM groups for the specified IdP.
30
+
31
+ Args:
32
+ idp_id (str):
33
+ The unique id of the IdP.
34
+ sort_by (str):
35
+ The field name to sort by, supported values: id, name, creationTime or modifiedTime (default to name)
36
+ sort_order (str):
37
+ The sort order, values: ASC or DSC (default DSC)
38
+
39
+
40
+ Keyword Args:
41
+ **end_time (str):
42
+ The end of a time range for requesting last updated data (modified_time) for the SCIM group.
43
+ This requires setting the ``start_time`` parameter as well.
44
+ **idp_group_id (str):
45
+ The unique id of the IdP group.
46
+ **max_items (int):
47
+ The maximum number of items to request before stopping iteration.
48
+ **max_pages (int):
49
+ The maximum number of pages to request before stopping iteration.
50
+ **pagesize (int):
51
+ Specifies the page size. The default size is 20, but the maximum size is 500.
52
+ **scim_user_id (str):
53
+ The unique id for the SCIM user.
54
+ **search (str, optional):
55
+ The search string used to match against features and fields.
56
+ **sort_order (str):
57
+ Sort the last updated time (modified_time) by ascending ``ASC`` or descending ``DSC`` order. Defaults to
58
+ ``DSC``.
59
+ **start_time (str):
60
+ The start of a time range for requesting last updated data (modified_time) for the SCIM group.
61
+ This requires setting the ``end_time`` parameter as well.
62
+
63
+ Returns:
64
+ :obj:`list`: A list of all configured SCIM groups.
65
+
66
+ Examples:
67
+ >>> for scim_group in zpa.scim_groups.list_groups("999999"):
68
+ ... pprint(scim_group)
69
+
70
+ """
71
+ list, _ = self.rest.get_paginated_data(
72
+ path=f"/scimgroup/idpId/{idp_id}",
73
+ **kwargs,
74
+ api_version="userconfig_v1",
75
+ )
76
+ return list
77
+ # params = {}
78
+ # if sort_order != "" and sort_by != "":
79
+ # params["sortBy"] = sort_by
80
+ # params["sortOrder"] = sort_order
81
+ # list, _ = self.rest.get_paginated_data(
82
+ # path=f"/scimgroup/idpId/{idp_id}",
83
+ # params=params,
84
+ # **kwargs,
85
+ # api_version="userconfig_v1",
86
+ # )
87
+ # return list
88
+
89
+ def get_group(self, group_id: str, **kwargs) -> Box:
90
+ """
91
+ Returns information on the specified SCIM group.
92
+
93
+ Args:
94
+ group_id (str):
95
+ The unique identifier for the SCIM group.
96
+ **kwargs:
97
+ Optional keyword args.
98
+
99
+ Returns:
100
+ :obj:`dict`: The resource record for the SCIM group.
101
+
102
+ Examples:
103
+ >>> pprint(zpa.scim_groups.get_group('99999'))
104
+
105
+ """
106
+ response = self.rest.get(
107
+ f"/scimgroup/{group_id}", **kwargs, api_version="userconfig_v1"
108
+ )
109
+ return response
110
+
111
+ def search_group(self, idp_id: str, group_name: str, **kwargs) -> dict:
112
+ """
113
+ Searches and returns the SCIM group with the specified name for the given IdP.
114
+ """
115
+ page_size = kwargs.get("pagesize", 500) # Adjust the page size as needed
116
+
117
+ # Calculate the total pages using a synchronous call
118
+ total_pages = 1
119
+ page_number = 1
120
+
121
+ # Loop over each page to search for the group
122
+ while True:
123
+ page = self._get_page(idp_id, page_number, group_name, page_size)
124
+ total_pages = int(page.get("total_pages", "0"))
125
+ for group in page.get("list", []):
126
+ if group.get("name") == group_name:
127
+ return group # Return the found group immediately
128
+ if page_number >= total_pages:
129
+ break
130
+ page_number = page_number + 1
131
+ return None # Return None if the group wasn't found
132
+
133
+ def _get_page(self, idp_id, page_number, search, page_size):
134
+ params = {
135
+ "page": page_number,
136
+ "search": search,
137
+ "pagesize": page_size,
138
+ "sortBy": "name",
139
+ "sortOrder": "DSC",
140
+ }
141
+ page = self.rest.get(
142
+ path=f"/scimgroup/idpId/{idp_id}",
143
+ params=params,
144
+ api_version="userconfig_v1",
145
+ )
146
+ return page