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.
- zscaler/__init__.py +34 -0
- zscaler/cache/__init__.py +0 -0
- zscaler/cache/cache.py +105 -0
- zscaler/cache/no_op_cache.py +68 -0
- zscaler/cache/zscaler_cache.py +161 -0
- zscaler/constants.py +26 -0
- zscaler/errors/__init__.py +0 -0
- zscaler/errors/error.py +10 -0
- zscaler/errors/http_error.py +20 -0
- zscaler/errors/zscaler_api_error.py +24 -0
- zscaler/exceptions/__init__.py +1 -0
- zscaler/exceptions/exceptions.py +101 -0
- zscaler/logger.py +57 -0
- zscaler/ratelimiter/__init__.py +0 -0
- zscaler/ratelimiter/ratelimiter.py +39 -0
- zscaler/user_agent.py +23 -0
- zscaler/utils.py +577 -0
- zscaler/zia/__init__.py +657 -0
- zscaler/zia/activate.py +52 -0
- zscaler/zia/admin_and_role_management.py +344 -0
- zscaler/zia/apptotal.py +71 -0
- zscaler/zia/audit_logs.py +95 -0
- zscaler/zia/authentication_settings.py +98 -0
- zscaler/zia/client.py +88 -0
- zscaler/zia/cloud_apps.py +406 -0
- zscaler/zia/device_management.py +90 -0
- zscaler/zia/dlp.py +784 -0
- zscaler/zia/errors.py +37 -0
- zscaler/zia/firewall.py +1104 -0
- zscaler/zia/forwarding_control.py +271 -0
- zscaler/zia/isolation_profile.py +83 -0
- zscaler/zia/labels.py +180 -0
- zscaler/zia/locations.py +661 -0
- zscaler/zia/sandbox.py +180 -0
- zscaler/zia/security.py +236 -0
- zscaler/zia/ssl_inspection.py +175 -0
- zscaler/zia/traffic.py +853 -0
- zscaler/zia/url_categories.py +442 -0
- zscaler/zia/url_filtering.py +310 -0
- zscaler/zia/users.py +386 -0
- zscaler/zia/web_dlp.py +295 -0
- zscaler/zia/workload_groups.py +58 -0
- zscaler/zia/zpa_gateway.py +187 -0
- zscaler/zpa/__init__.py +683 -0
- zscaler/zpa/app_segments.py +331 -0
- zscaler/zpa/app_segments_inspection.py +311 -0
- zscaler/zpa/app_segments_pra.py +310 -0
- zscaler/zpa/certificates.py +234 -0
- zscaler/zpa/client.py +113 -0
- zscaler/zpa/cloud_connector_groups.py +75 -0
- zscaler/zpa/connectors.py +518 -0
- zscaler/zpa/emergency_access.py +178 -0
- zscaler/zpa/errors.py +37 -0
- zscaler/zpa/idp.py +83 -0
- zscaler/zpa/inspection.py +1012 -0
- zscaler/zpa/isolation_profile.py +85 -0
- zscaler/zpa/lss.py +568 -0
- zscaler/zpa/machine_groups.py +79 -0
- zscaler/zpa/policies.py +848 -0
- zscaler/zpa/posture_profiles.py +122 -0
- zscaler/zpa/privileged_remote_access.py +862 -0
- zscaler/zpa/provisioning.py +271 -0
- zscaler/zpa/saml_attributes.py +100 -0
- zscaler/zpa/scim_attributes.py +117 -0
- zscaler/zpa/scim_groups.py +146 -0
- zscaler/zpa/segment_groups.py +191 -0
- zscaler/zpa/server_groups.py +217 -0
- zscaler/zpa/servers.py +202 -0
- zscaler/zpa/service_edges.py +404 -0
- zscaler/zpa/trusted_networks.py +127 -0
- zscaler_sdk_python-1.0.0.dist-info/LICENSE.md +21 -0
- zscaler_sdk_python-1.0.0.dist-info/METADATA +59 -0
- zscaler_sdk_python-1.0.0.dist-info/RECORD +75 -0
- zscaler_sdk_python-1.0.0.dist-info/WHEEL +6 -0
- zscaler_sdk_python-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1012 @@
|
|
|
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
|
+
from requests.utils import quote
|
|
21
|
+
|
|
22
|
+
from zscaler.utils import convert_keys, snake_to_camel
|
|
23
|
+
from zscaler.zpa.client import ZPAClient
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class InspectionControllerAPI:
|
|
27
|
+
def __init__(self, client: ZPAClient):
|
|
28
|
+
self.rest = client
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _create_rule(rule: dict) -> dict:
|
|
32
|
+
rule_set = {
|
|
33
|
+
"type": rule["type"],
|
|
34
|
+
"conditions": [],
|
|
35
|
+
}
|
|
36
|
+
if "names" in rule:
|
|
37
|
+
rule_set["names"] = rule["names"]
|
|
38
|
+
for condition in rule["conditions"]:
|
|
39
|
+
rule_set["conditions"].append(
|
|
40
|
+
{
|
|
41
|
+
"lhs": condition["lhs"],
|
|
42
|
+
"op": condition["op"],
|
|
43
|
+
"rhs": condition["rhs"],
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
return rule_set
|
|
47
|
+
|
|
48
|
+
def add_custom_control(
|
|
49
|
+
self,
|
|
50
|
+
name: str,
|
|
51
|
+
default_action: str,
|
|
52
|
+
severity: str,
|
|
53
|
+
type: str,
|
|
54
|
+
rules: list,
|
|
55
|
+
**kwargs,
|
|
56
|
+
) -> Box:
|
|
57
|
+
"""
|
|
58
|
+
Adds a new ZPA Inspection Custom Control.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
name (str): The name of the custom control.
|
|
62
|
+
default_action (str): The default action to take for matches against this custom control.
|
|
63
|
+
severity (str): The severity for events that match this custom control.
|
|
64
|
+
type (str): The type of HTTP message this control matches.
|
|
65
|
+
rules (list): A list of Inspection Control rule objects.
|
|
66
|
+
**kwargs: Optional keyword args.
|
|
67
|
+
|
|
68
|
+
Keyword Args:
|
|
69
|
+
description (str): Additional information about the custom control.
|
|
70
|
+
paranoia_level (int): The paranoia level for the custom control.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
:obj:`Box`: The newly created custom Inspection Control resource record.
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
payload = {
|
|
78
|
+
"name": name,
|
|
79
|
+
"defaultAction": default_action,
|
|
80
|
+
"severity": severity,
|
|
81
|
+
"rules": [],
|
|
82
|
+
"type": type,
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Handle default_action_value
|
|
86
|
+
if "default_action_value" in kwargs:
|
|
87
|
+
payload["defaultActionValue"] = kwargs["default_action_value"]
|
|
88
|
+
|
|
89
|
+
# Use the _create_rule method to restructure the Inspection Control rule and add to the payload.
|
|
90
|
+
for rule in rules:
|
|
91
|
+
payload["rules"].append(self._create_rule(rule))
|
|
92
|
+
|
|
93
|
+
# Add optional parameters to payload
|
|
94
|
+
for key, value in kwargs.items():
|
|
95
|
+
if key == "paranoia_level":
|
|
96
|
+
payload["paranoiaLevel"] = int(value)
|
|
97
|
+
elif key == "description":
|
|
98
|
+
payload["description"] = value
|
|
99
|
+
# Add other optional parameters if necessary
|
|
100
|
+
|
|
101
|
+
# Convert snake to camelcase
|
|
102
|
+
payload = convert_keys(payload)
|
|
103
|
+
|
|
104
|
+
response = self.rest.post("inspectionControls/custom", json=payload)
|
|
105
|
+
if isinstance(response, Response):
|
|
106
|
+
# this is only true when the creation failed (status code is not 2xx)
|
|
107
|
+
status_code = response.status_code
|
|
108
|
+
# Handle error response
|
|
109
|
+
raise Exception(
|
|
110
|
+
f"API call failed with status {status_code}: {response.json()}"
|
|
111
|
+
)
|
|
112
|
+
return response
|
|
113
|
+
|
|
114
|
+
# response = self.rest.post("/inspectionControls/custom", json=payload)
|
|
115
|
+
# if isinstance(response, Response):
|
|
116
|
+
# status_code = response.status_code
|
|
117
|
+
# if status_code > 299:
|
|
118
|
+
# return None
|
|
119
|
+
# return self.get_custom_control(response.get("id"))
|
|
120
|
+
|
|
121
|
+
def add_profile(
|
|
122
|
+
self, name: str, paranoia_level: int, predef_controls_version: str, **kwargs
|
|
123
|
+
):
|
|
124
|
+
"""
|
|
125
|
+
Adds a ZPA Inspection Profile.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
name (str):
|
|
129
|
+
The name of the Inspection Profile.
|
|
130
|
+
paranoia_level (int):
|
|
131
|
+
The paranoia level for the Inspection Profile.
|
|
132
|
+
predef_controls_version (str):
|
|
133
|
+
The version of the predefined controls that will be added.
|
|
134
|
+
**kwargs:
|
|
135
|
+
Additional keyword args.
|
|
136
|
+
|
|
137
|
+
Keyword Args:
|
|
138
|
+
**description (str):
|
|
139
|
+
Additional information about the Inspection Profile.
|
|
140
|
+
**custom_controls (list):
|
|
141
|
+
A tuple list of custom controls to be added to the Inspection profile.
|
|
142
|
+
|
|
143
|
+
Custom control tuples must follow the convention below:
|
|
144
|
+
|
|
145
|
+
``(control_id, action)``
|
|
146
|
+
|
|
147
|
+
e.g.
|
|
148
|
+
|
|
149
|
+
.. code-block:: python
|
|
150
|
+
|
|
151
|
+
custom_controls = [(99999, "BLOCK"), (88888, "PASS")]
|
|
152
|
+
**predef_controls (list):
|
|
153
|
+
A tuple list of predefined controls to be added to the Inspection profile.
|
|
154
|
+
|
|
155
|
+
Predefined control tuples must follow the convention below:
|
|
156
|
+
|
|
157
|
+
``(control_id, action)``
|
|
158
|
+
|
|
159
|
+
e.g.
|
|
160
|
+
|
|
161
|
+
.. code-block:: python
|
|
162
|
+
|
|
163
|
+
predef_controls = [(77777, "BLOCK"), (66666, "PASS")]
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
:obj:`Box`: The newly created Inspection Profile resource record.
|
|
167
|
+
|
|
168
|
+
Examples:
|
|
169
|
+
Add a new ZPA Inspection Profile with the minimum required parameters, printing the object to
|
|
170
|
+
console after creation:
|
|
171
|
+
|
|
172
|
+
.. code-block:: python
|
|
173
|
+
|
|
174
|
+
print(
|
|
175
|
+
zpa.inspection.add_profile(
|
|
176
|
+
name="predefined_controls",
|
|
177
|
+
paranoia_level=3,
|
|
178
|
+
predef_controls_version="OWASP_CRS/3.3.0",
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
Add a new ZPA Inspection Profile that uses additional predefined controls and custom controls, printing the
|
|
183
|
+
object to console after creation:
|
|
184
|
+
|
|
185
|
+
.. code-block:: python
|
|
186
|
+
|
|
187
|
+
print(
|
|
188
|
+
zpa.inspection.add_profile(
|
|
189
|
+
name="block_common_xss",
|
|
190
|
+
paranoia_level=2,
|
|
191
|
+
predefined_controls=[("99999", "BLOCK")],
|
|
192
|
+
predef_controls_version="OWASP_CRS/3.3.0",
|
|
193
|
+
custom_controls=[("88888", "BLOCK")],
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
# Inspection Profiles require the default predefined controls to be added. zscaler-sdk-python adds these in
|
|
200
|
+
# automatically for our users.
|
|
201
|
+
|
|
202
|
+
predef_controls = self.list_predef_controls("OWASP_CRS/3.3.0")
|
|
203
|
+
default_controls = []
|
|
204
|
+
for group in predef_controls:
|
|
205
|
+
if group.default_group:
|
|
206
|
+
default_controls = group.predefined_inspection_controls
|
|
207
|
+
|
|
208
|
+
payload = {
|
|
209
|
+
"name": name,
|
|
210
|
+
"paranoiaLevel": paranoia_level,
|
|
211
|
+
"predefinedControls": default_controls,
|
|
212
|
+
"predefinedControlsVersion": predef_controls_version,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Extend existing list of default predefined controls if the user supplies more
|
|
216
|
+
if kwargs.get("predef_controls"):
|
|
217
|
+
controls = kwargs.pop("predef_controls")
|
|
218
|
+
for control in controls:
|
|
219
|
+
payload["predefinedControls"].append(
|
|
220
|
+
{"id": control[0], "action": control[1]}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
# Add custom controls if provided
|
|
224
|
+
if kwargs.get("custom_controls"):
|
|
225
|
+
controls = kwargs.pop("custom_controls")
|
|
226
|
+
payload["customControls"] = [
|
|
227
|
+
{"id": control[0], "action": control[1]} for control in controls
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
# Add optional parameters to payload
|
|
231
|
+
for key, value in kwargs.items():
|
|
232
|
+
payload[key] = value
|
|
233
|
+
|
|
234
|
+
payload = convert_keys(payload)
|
|
235
|
+
|
|
236
|
+
response = self.rest.post("inspectionProfile", json=payload)
|
|
237
|
+
if isinstance(response, Response):
|
|
238
|
+
# this is only true when the creation failed (status code is not 2xx)
|
|
239
|
+
status_code = response.status_code
|
|
240
|
+
# Handle error response
|
|
241
|
+
raise Exception(
|
|
242
|
+
f"API call failed with status {status_code}: {response.json()}"
|
|
243
|
+
)
|
|
244
|
+
return response
|
|
245
|
+
|
|
246
|
+
# response = self.rest.post("/inspectionProfile", json=payload)
|
|
247
|
+
# if isinstance(response, Response):
|
|
248
|
+
# status_code = response.status_code
|
|
249
|
+
# if status_code > 299:
|
|
250
|
+
# return None
|
|
251
|
+
# return self.get_profile(response.get("id"))
|
|
252
|
+
|
|
253
|
+
def delete_custom_control(self, control_id: str) -> int:
|
|
254
|
+
"""
|
|
255
|
+
Deletes the specified custom ZPA Inspection Control.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
control_id (str):
|
|
259
|
+
The unique id for the custom control that will be deleted.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
:obj:`int`: The status code for the operation.
|
|
263
|
+
|
|
264
|
+
Examples:
|
|
265
|
+
Delete a custom ZPA Inspection Control with an id of `99999`.
|
|
266
|
+
|
|
267
|
+
.. code-block:: python
|
|
268
|
+
|
|
269
|
+
zpa.inspection.delete_custom_control("99999")
|
|
270
|
+
|
|
271
|
+
"""
|
|
272
|
+
return self.rest.delete(f"inspectionControls/custom/{control_id}").status_code
|
|
273
|
+
|
|
274
|
+
def delete_profile(self, profile_id: str):
|
|
275
|
+
"""
|
|
276
|
+
Deletes the specified Inspection Profile.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
profile_id (str):
|
|
280
|
+
The unique id for the Inspection Profile that will be deleted.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
:obj:`int`: The status code for the operation.
|
|
284
|
+
|
|
285
|
+
Examples:
|
|
286
|
+
Delete an Inspection Profile with an id of *999999*:
|
|
287
|
+
|
|
288
|
+
.. code-block:: python
|
|
289
|
+
|
|
290
|
+
zpa.inspection.delete_profile("999999")
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
return self.rest.delete(f"inspectionProfile/{profile_id}").status_code
|
|
294
|
+
|
|
295
|
+
def get_custom_control(self, control_id: str) -> Box:
|
|
296
|
+
"""
|
|
297
|
+
Returns the specified custom ZPA Inspection Control.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
control_id (str):
|
|
301
|
+
The unique id of the custom ZPA Inspection Control to be returned.
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
:obj:`Box`: The custom ZPA Inspection Control resource record.
|
|
305
|
+
|
|
306
|
+
Examples:
|
|
307
|
+
Print the Custom Inspection Control with an id of `99999`:
|
|
308
|
+
|
|
309
|
+
.. code-block:: python
|
|
310
|
+
|
|
311
|
+
print(zpa.inspection.get_custom_control("99999"))
|
|
312
|
+
|
|
313
|
+
"""
|
|
314
|
+
response = self.rest.get("/inspectionControls/custom/%s" % (control_id))
|
|
315
|
+
if isinstance(response, Response):
|
|
316
|
+
status_code = response.status_code
|
|
317
|
+
if status_code != 200:
|
|
318
|
+
return None
|
|
319
|
+
return response
|
|
320
|
+
|
|
321
|
+
def get_predef_control(self, control_id: str):
|
|
322
|
+
"""
|
|
323
|
+
Returns the specified predefined ZPA Inspection Control.
|
|
324
|
+
|
|
325
|
+
Args:
|
|
326
|
+
control_id (str):
|
|
327
|
+
The unique id of the predefined ZPA Inspection Control to be returned.
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
:obj:`Box`: The ZPA Inspection Predefined Control resource record.
|
|
331
|
+
|
|
332
|
+
Examples:
|
|
333
|
+
Print the ZPA Inspection Predefined Control with an id of `99999`:
|
|
334
|
+
|
|
335
|
+
.. code-block:: python
|
|
336
|
+
|
|
337
|
+
print(zpa.inspection.get_predef_control("99999"))
|
|
338
|
+
|
|
339
|
+
"""
|
|
340
|
+
response = self.rest.get("/inspectionControls/predefined/%s" % (control_id))
|
|
341
|
+
if isinstance(response, Response):
|
|
342
|
+
status_code = response.status_code
|
|
343
|
+
if status_code != 200:
|
|
344
|
+
return None
|
|
345
|
+
return response
|
|
346
|
+
|
|
347
|
+
def get_profile(self, profile_id: str) -> Box:
|
|
348
|
+
"""
|
|
349
|
+
Returns the specified ZPA Inspection Profile.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
profile_id (str):
|
|
353
|
+
The unique id of the ZPA Inspection Profile
|
|
354
|
+
|
|
355
|
+
Returns:
|
|
356
|
+
:obj:`Box`: The specified ZPA Inspection Profile resource record.
|
|
357
|
+
|
|
358
|
+
Examples:
|
|
359
|
+
Print the ZPA Inspection Profile with an id of `99999`:
|
|
360
|
+
|
|
361
|
+
.. code-block:: python
|
|
362
|
+
|
|
363
|
+
print(zpa.inspection.get_profile("99999"))
|
|
364
|
+
|
|
365
|
+
"""
|
|
366
|
+
response = self.rest.get("/inspectionProfile/%s" % (profile_id))
|
|
367
|
+
if isinstance(response, Response):
|
|
368
|
+
status_code = response.status_code
|
|
369
|
+
if status_code != 200:
|
|
370
|
+
return None
|
|
371
|
+
return response
|
|
372
|
+
|
|
373
|
+
def list_control_action_types(self) -> Box:
|
|
374
|
+
"""
|
|
375
|
+
Returns a list of ZPA Inspection Control Action Types.
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
:obj:`BoxList`: A list containing the ZPA Inspection Control Action Types.
|
|
379
|
+
|
|
380
|
+
Examples:
|
|
381
|
+
Iterate over the ZPA Inspection Control Action Types and print each one:
|
|
382
|
+
|
|
383
|
+
.. code-block:: python
|
|
384
|
+
|
|
385
|
+
for action_type in zpa.inspection.list_control_action_types():
|
|
386
|
+
print(action_type)
|
|
387
|
+
|
|
388
|
+
"""
|
|
389
|
+
return self.rest.get("inspectionControls/actionTypes")
|
|
390
|
+
|
|
391
|
+
def list_control_severity_types(self) -> BoxList:
|
|
392
|
+
"""
|
|
393
|
+
Returns a list of Inspection Control Severity Types.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
:obj:`BoxList`: A list containing all valid Inspection Control Severity Types.
|
|
397
|
+
|
|
398
|
+
Examples:
|
|
399
|
+
Print all Inspection Control Severity Types
|
|
400
|
+
|
|
401
|
+
.. code-block:: python
|
|
402
|
+
|
|
403
|
+
for severity in zpa.inspection.list_control_severity_types():
|
|
404
|
+
print(severity)
|
|
405
|
+
|
|
406
|
+
"""
|
|
407
|
+
return self.rest.get("inspectionControls/severityTypes")
|
|
408
|
+
|
|
409
|
+
def list_control_types(self) -> BoxList:
|
|
410
|
+
"""
|
|
411
|
+
Returns a list of ZPA Inspection Control Types.
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
:obj:`BoxList`: A list containing ZPA Inspection Control Types.
|
|
415
|
+
|
|
416
|
+
Examples:
|
|
417
|
+
Print all ZPA Inspection Control Types:
|
|
418
|
+
|
|
419
|
+
.. code-block:: python
|
|
420
|
+
|
|
421
|
+
for control_type in zpa.inspection.list_control_types():
|
|
422
|
+
print(control_type)
|
|
423
|
+
|
|
424
|
+
"""
|
|
425
|
+
return self.rest.get("inspectionControls/controlTypes")
|
|
426
|
+
|
|
427
|
+
def list_custom_control_types(self) -> BoxList:
|
|
428
|
+
"""
|
|
429
|
+
Returns a list of custom ZPA Inspection Control Types.
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
:obj:`BoxList`: A list containing custom ZPA Inspection Control Types.
|
|
433
|
+
|
|
434
|
+
Examples:
|
|
435
|
+
|
|
436
|
+
Print all custom ZPA Inspection Control Types
|
|
437
|
+
|
|
438
|
+
.. code-block:: python
|
|
439
|
+
|
|
440
|
+
for control_type in zpa.inspection.list_custom_control_types():
|
|
441
|
+
print(control_type)
|
|
442
|
+
|
|
443
|
+
"""
|
|
444
|
+
return self.rest.get(
|
|
445
|
+
"https://config.private.zscaler.com/mgmtconfig/v1/admin/inspectionControls/customControlTypes"
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
def list_custom_controls(self, **kwargs) -> BoxList:
|
|
449
|
+
"""
|
|
450
|
+
Returns a list of all custom ZPA Inspection Controls.
|
|
451
|
+
|
|
452
|
+
Args:
|
|
453
|
+
**kwargs: Optional keyword arguments.
|
|
454
|
+
|
|
455
|
+
Keyword Args:
|
|
456
|
+
**search (str):
|
|
457
|
+
The string used to search for a custom control by features and fields.
|
|
458
|
+
**sortdir (str):
|
|
459
|
+
Specifies the sorting order for the search results.
|
|
460
|
+
|
|
461
|
+
Accepted values are:
|
|
462
|
+
|
|
463
|
+
- ``ASC`` - ascending order
|
|
464
|
+
- ``DESC`` - descending order
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
:obj:`BoxList`: A list containing all custom ZPA Inspection Controls.
|
|
468
|
+
|
|
469
|
+
Examples:
|
|
470
|
+
Print a list of all custom ZPA Inspection Controls:
|
|
471
|
+
|
|
472
|
+
.. code-block:: python
|
|
473
|
+
|
|
474
|
+
for control in zpa.inspection.list_custom_controls():
|
|
475
|
+
print(control)
|
|
476
|
+
|
|
477
|
+
"""
|
|
478
|
+
list, _ = self.rest.get_paginated_data(
|
|
479
|
+
path="/inspectionControls/custom",
|
|
480
|
+
)
|
|
481
|
+
return list
|
|
482
|
+
|
|
483
|
+
def list_custom_http_methods(self) -> BoxList:
|
|
484
|
+
"""
|
|
485
|
+
Returns a list of custom ZPA Inspection Control HTTP Methods.
|
|
486
|
+
|
|
487
|
+
Returns:
|
|
488
|
+
:obj:`BoxList`: A list containing custom ZPA Inspection Control HTTP Methods.
|
|
489
|
+
|
|
490
|
+
Examples:
|
|
491
|
+
|
|
492
|
+
Print all custom ZPA Inspection Control HTTP Methods:
|
|
493
|
+
|
|
494
|
+
.. code-block:: python
|
|
495
|
+
|
|
496
|
+
for method in zpa.inspection.list_custom_http_methods():
|
|
497
|
+
print(method)
|
|
498
|
+
|
|
499
|
+
"""
|
|
500
|
+
return self.rest.get("inspectionControls/custom/httpMethods")
|
|
501
|
+
|
|
502
|
+
def list_predef_control_versions(self) -> BoxList:
|
|
503
|
+
"""
|
|
504
|
+
Returns a list of predefined ZPA Inspection Control versions.
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
:obj:`BoxList`: A list containing all predefined ZPA Inspection Control versions.
|
|
508
|
+
|
|
509
|
+
Examples:
|
|
510
|
+
Print all predefined ZPA Inspection Control versions::
|
|
511
|
+
|
|
512
|
+
for version in zpa.inspection.list_predef_control_versions():
|
|
513
|
+
print(version)
|
|
514
|
+
|
|
515
|
+
"""
|
|
516
|
+
return self.rest.get("inspectionControls/predefined/versions")
|
|
517
|
+
|
|
518
|
+
def list_predef_controls(self, version: str, **kwargs) -> BoxList:
|
|
519
|
+
"""
|
|
520
|
+
Returns a list of predefined ZPA Inspection Controls.
|
|
521
|
+
|
|
522
|
+
Args:
|
|
523
|
+
version (str):
|
|
524
|
+
The version of the predefined controls to return.
|
|
525
|
+
**kwargs:
|
|
526
|
+
Optional keyword args.
|
|
527
|
+
|
|
528
|
+
Keyword Args:
|
|
529
|
+
**search (str):
|
|
530
|
+
The string used to search for predefined inspection controls by features and fields.
|
|
531
|
+
|
|
532
|
+
Returns:
|
|
533
|
+
:obj:`BoxList`: A list containing all predefined ZPA Inspection Controls that match the Version and Search
|
|
534
|
+
string.
|
|
535
|
+
|
|
536
|
+
Examples:
|
|
537
|
+
Return all predefined ZPA Inspection Controls for the given version:
|
|
538
|
+
|
|
539
|
+
.. code-block:: python
|
|
540
|
+
|
|
541
|
+
for control in zpa.inspection.list_predef_controls(version="OWASP_CRS/3.3.0"):
|
|
542
|
+
print(control)
|
|
543
|
+
|
|
544
|
+
Return predefined ZPA Inspection Controls matching a search string:
|
|
545
|
+
|
|
546
|
+
.. code-block:: python
|
|
547
|
+
|
|
548
|
+
for control in zpa.inspection.list_predef_controls(search="new_control", version="OWASP_CRS/3.3.0"):
|
|
549
|
+
print(control)
|
|
550
|
+
|
|
551
|
+
"""
|
|
552
|
+
# Encode the version parameter to be URL safe
|
|
553
|
+
encoded_version = quote(version, safe="")
|
|
554
|
+
|
|
555
|
+
# Construct the full URL with version query param
|
|
556
|
+
url = f"/inspectionControls/predefined?version={encoded_version}"
|
|
557
|
+
|
|
558
|
+
# If you have additional query parameters, add them to the URL
|
|
559
|
+
if kwargs:
|
|
560
|
+
additional_params = "&".join(
|
|
561
|
+
f"{key}={quote(str(value))}" for key, value in kwargs.items()
|
|
562
|
+
)
|
|
563
|
+
url += f"&{additional_params}"
|
|
564
|
+
|
|
565
|
+
# Make the GET request
|
|
566
|
+
response = self.rest.get(url)
|
|
567
|
+
if isinstance(response, Response):
|
|
568
|
+
status_code = response.status_code
|
|
569
|
+
if status_code != 200:
|
|
570
|
+
# Handle error or return None based on your API handling
|
|
571
|
+
return None
|
|
572
|
+
return response
|
|
573
|
+
|
|
574
|
+
def get_predef_control_by_name(
|
|
575
|
+
self, name: str, version: str = "OWASP_CRS/3.3.0"
|
|
576
|
+
) -> Box:
|
|
577
|
+
"""
|
|
578
|
+
Returns the specified predefined ZPA Inspection Control by its name.
|
|
579
|
+
|
|
580
|
+
Args:
|
|
581
|
+
name (str):
|
|
582
|
+
The name of the predefined ZPA Inspection Control to be returned.
|
|
583
|
+
version (str):
|
|
584
|
+
The version of the predefined control to return.
|
|
585
|
+
|
|
586
|
+
Returns:
|
|
587
|
+
:obj:`Box`: The ZPA Inspection Predefined Control resource record.
|
|
588
|
+
|
|
589
|
+
Examples:
|
|
590
|
+
Print the ZPA Inspection Predefined Control with the name `Failed to parse request body`:
|
|
591
|
+
|
|
592
|
+
.. code-block:: python
|
|
593
|
+
|
|
594
|
+
print(zpa.inspection.get_predef_control_by_name("Failed to parse request body", "OWASP_CRS/3.3.0"))
|
|
595
|
+
|
|
596
|
+
"""
|
|
597
|
+
# Use the list_predef_controls method to get all controls
|
|
598
|
+
all_controls = self.list_predef_controls(version)
|
|
599
|
+
|
|
600
|
+
# Iterate through the controls to find the one with the desired name
|
|
601
|
+
for control_group in all_controls:
|
|
602
|
+
for control in control_group.get("predefined_inspection_controls", []):
|
|
603
|
+
if control["name"] == name:
|
|
604
|
+
return control
|
|
605
|
+
|
|
606
|
+
# If we reach here, the control was not found
|
|
607
|
+
raise ValueError(f"No predefined control named '{name}' found")
|
|
608
|
+
|
|
609
|
+
def get_predef_control_group_by_name(
|
|
610
|
+
self, group_name: str, version: str = "OWASP_CRS/3.3.0"
|
|
611
|
+
) -> Box:
|
|
612
|
+
"""
|
|
613
|
+
Returns the specified predefined ZPA Inspection Control Group by its name.
|
|
614
|
+
|
|
615
|
+
Args:
|
|
616
|
+
group_name (str):
|
|
617
|
+
The name of the predefined ZPA Inspection Control Group to be returned.
|
|
618
|
+
version (str):
|
|
619
|
+
The version of the predefined control to return.
|
|
620
|
+
|
|
621
|
+
Returns:
|
|
622
|
+
:obj:`Box`: The ZPA Inspection Predefined Control Group resource record.
|
|
623
|
+
|
|
624
|
+
Examples:
|
|
625
|
+
Print the ZPA Inspection Predefined Control Group with the name `Preprocessors`:
|
|
626
|
+
|
|
627
|
+
.. code-block:: python
|
|
628
|
+
|
|
629
|
+
print(zpa.inspection.get_predef_control_group_by_name("Preprocessors", "OWASP_CRS/3.3.0"))
|
|
630
|
+
|
|
631
|
+
"""
|
|
632
|
+
# Use the list_predef_controls method to get all control groups
|
|
633
|
+
all_control_groups = self.list_predef_controls(version)
|
|
634
|
+
|
|
635
|
+
# Iterate through the control groups to find the one with the desired name
|
|
636
|
+
for control_group in all_control_groups:
|
|
637
|
+
if control_group["control_group"] == group_name:
|
|
638
|
+
return control_group
|
|
639
|
+
|
|
640
|
+
# If we reach here, the control group was not found
|
|
641
|
+
raise ValueError(f"No predefined control group named '{group_name}' found")
|
|
642
|
+
|
|
643
|
+
def list_profiles(self, **kwargs) -> BoxList:
|
|
644
|
+
"""
|
|
645
|
+
Returns the list of ZPA Inspection Profiles.
|
|
646
|
+
|
|
647
|
+
Args:
|
|
648
|
+
**kwargs:
|
|
649
|
+
Optional keyword args.
|
|
650
|
+
|
|
651
|
+
Keyword Args:
|
|
652
|
+
**pagesize (int):
|
|
653
|
+
Specifies the page size. The default size is 20 and the maximum size is 500.
|
|
654
|
+
**search (str, optional):
|
|
655
|
+
The search string used to match against features and fields.
|
|
656
|
+
|
|
657
|
+
Returns:
|
|
658
|
+
:obj:`BoxList`: The list of ZPA Inspection Profile resource records.
|
|
659
|
+
|
|
660
|
+
Examples:
|
|
661
|
+
Iterate over all ZPA Inspection Profiles and print them:
|
|
662
|
+
|
|
663
|
+
.. code-block:: python
|
|
664
|
+
|
|
665
|
+
for profile in zpa.inspection.list_profiles():
|
|
666
|
+
print(profile)
|
|
667
|
+
|
|
668
|
+
"""
|
|
669
|
+
list, _ = self.rest.get_paginated_data(
|
|
670
|
+
path="/inspectionProfile",
|
|
671
|
+
)
|
|
672
|
+
return list
|
|
673
|
+
|
|
674
|
+
def profile_control_attach(self, profile_id: str, action: str, **kwargs) -> Box:
|
|
675
|
+
"""
|
|
676
|
+
Attaches or detaches all predefined ZPA Inspection Controls to a ZPA Inspection Profile.
|
|
677
|
+
|
|
678
|
+
Args:
|
|
679
|
+
profile_id (str):
|
|
680
|
+
The unique id for the ZPA Inspection Profile that will be modified.
|
|
681
|
+
action (str):
|
|
682
|
+
The association action that will be taken, accepted values are:
|
|
683
|
+
|
|
684
|
+
* ``attach``: Attaches all predefined controls to the Inspection Profile with the specified version.
|
|
685
|
+
* ``detach``: Detaches all predefined controls from the Inspection Profile.
|
|
686
|
+
**kwargs:
|
|
687
|
+
Additional keyword arguments.
|
|
688
|
+
|
|
689
|
+
Keyword Args:
|
|
690
|
+
profile_version (str):
|
|
691
|
+
The version of the Predefined Controls to attach. Only required when using the
|
|
692
|
+
attach action. Defaults to ``OWASP_CRS/3.3.0``.
|
|
693
|
+
|
|
694
|
+
Returns:
|
|
695
|
+
:obj:`Box`: The updated ZPA Inspection Profile resource record.
|
|
696
|
+
|
|
697
|
+
Examples:
|
|
698
|
+
Attach all predefined controls to a ZPA Inspection Profile with an id of 99999:
|
|
699
|
+
|
|
700
|
+
.. code-block:: python
|
|
701
|
+
|
|
702
|
+
updated_profile = zpa.inspection.profile_control_attach("99999", action="attach")
|
|
703
|
+
|
|
704
|
+
Attach all predefined controls to a ZPA Inspection Profile with an id of 99999 and specified version:
|
|
705
|
+
|
|
706
|
+
.. code-block:: python
|
|
707
|
+
|
|
708
|
+
updated_profile = zpa.inspection.profile_control_attach(
|
|
709
|
+
"99999",
|
|
710
|
+
action="attach",
|
|
711
|
+
profile_version="OWASP_CRS/3.2.0",
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
Detach all predefined controls from a ZPA Inspection Profile with an id of 99999:
|
|
715
|
+
|
|
716
|
+
.. code-block:: python
|
|
717
|
+
|
|
718
|
+
updated_profile = zpa.inspection.profile_control_attach(
|
|
719
|
+
"99999",
|
|
720
|
+
action="detach",
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
Raises:
|
|
724
|
+
ValueError: If an incorrect value is supplied for `action`.
|
|
725
|
+
|
|
726
|
+
"""
|
|
727
|
+
if action == "attach":
|
|
728
|
+
payload = {"version": kwargs.pop("profile_version", "OWASP_CRS/3.3.0")}
|
|
729
|
+
resp = self.rest.put(
|
|
730
|
+
f"inspectionProfile/{profile_id}/associateAllPredefinedControls",
|
|
731
|
+
params=payload,
|
|
732
|
+
)
|
|
733
|
+
return (
|
|
734
|
+
self.get_profile(profile_id)
|
|
735
|
+
if resp.status_code == 204
|
|
736
|
+
else resp.status_code
|
|
737
|
+
)
|
|
738
|
+
elif action == "detach":
|
|
739
|
+
resp = self.rest.put(
|
|
740
|
+
f"inspectionProfile/{profile_id}/deAssociateAllPredefinedControls"
|
|
741
|
+
)
|
|
742
|
+
return (
|
|
743
|
+
self.get_profile(profile_id)
|
|
744
|
+
if resp.status_code == 204
|
|
745
|
+
else resp.status_code
|
|
746
|
+
)
|
|
747
|
+
else:
|
|
748
|
+
raise ValueError(
|
|
749
|
+
"Unknown action provided. Valid actions are 'attach' or 'detach'."
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
def update_custom_control(self, control_id: str, **kwargs) -> Box:
|
|
753
|
+
"""
|
|
754
|
+
Updates the specified custom ZPA Inspection Control.
|
|
755
|
+
|
|
756
|
+
Args:
|
|
757
|
+
control_id (str):
|
|
758
|
+
The unique id for the custom control that will be updated.
|
|
759
|
+
**kwargs:
|
|
760
|
+
Optional keyword args.
|
|
761
|
+
|
|
762
|
+
Keyword Args:
|
|
763
|
+
**description (str):
|
|
764
|
+
Additional information about the custom control.
|
|
765
|
+
**default_action (str):
|
|
766
|
+
The default action to take for matches against this custom control. Valid options are:
|
|
767
|
+
|
|
768
|
+
- ``PASS``
|
|
769
|
+
- ``BLOCK``
|
|
770
|
+
- ``REDIRECT``
|
|
771
|
+
**name (str):
|
|
772
|
+
The name of the custom control.
|
|
773
|
+
**paranoia_level (int):
|
|
774
|
+
The paranoia level for the custom control.
|
|
775
|
+
**rules (list):
|
|
776
|
+
A list of Inspection Control rule objects, with each object using the format::
|
|
777
|
+
|
|
778
|
+
{
|
|
779
|
+
"names": ["name1", "name2"],
|
|
780
|
+
"type": "rule_type",
|
|
781
|
+
"conditions": [
|
|
782
|
+
("LHS", "OP", "RHS"),
|
|
783
|
+
("LHS", "OP", "RHS"),
|
|
784
|
+
],
|
|
785
|
+
}
|
|
786
|
+
**severity (str):
|
|
787
|
+
The severity for events that match this custom control. Valid options are:
|
|
788
|
+
|
|
789
|
+
- ``CRITICAL``
|
|
790
|
+
- ``ERROR``
|
|
791
|
+
- ``WARNING``
|
|
792
|
+
- ``INFO``
|
|
793
|
+
**type (str):
|
|
794
|
+
The type of HTTP message this control matches. Valid options are:
|
|
795
|
+
|
|
796
|
+
- ``REQUEST``
|
|
797
|
+
- ``RESPONSE``
|
|
798
|
+
|
|
799
|
+
Returns:
|
|
800
|
+
:obj:`Box`: The updated custom ZPA Inspection Control resource record.
|
|
801
|
+
|
|
802
|
+
Examples:
|
|
803
|
+
Update the description of a custom ZPA Inspection Control with an id of 99999:
|
|
804
|
+
|
|
805
|
+
.. code-block:: python
|
|
806
|
+
|
|
807
|
+
print(
|
|
808
|
+
zpa.inspection.update_custom_control(
|
|
809
|
+
"99999",
|
|
810
|
+
description="Updated description",
|
|
811
|
+
)
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
Update the rules of a custom ZPA Inspection Control with an id of 88888:
|
|
815
|
+
|
|
816
|
+
.. code-block:: python
|
|
817
|
+
|
|
818
|
+
print(
|
|
819
|
+
zpa.inspection.update_custom_control(
|
|
820
|
+
"88888",
|
|
821
|
+
rules=[
|
|
822
|
+
{
|
|
823
|
+
"names": ["xforwardedfor_ge_20"],
|
|
824
|
+
"type": "REQUEST_HEADERS",
|
|
825
|
+
"conditions": [
|
|
826
|
+
("SIZE", "GE", "20"),
|
|
827
|
+
("VALUE", "CONTAINS", "X-Forwarded-For"),
|
|
828
|
+
],
|
|
829
|
+
}
|
|
830
|
+
],
|
|
831
|
+
)
|
|
832
|
+
)
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
"""
|
|
836
|
+
|
|
837
|
+
# Set payload to value of existing record and recursively convert nested dict keys from snake_case
|
|
838
|
+
# to camelCase.
|
|
839
|
+
payload = convert_keys(self.get_custom_control(control_id))
|
|
840
|
+
|
|
841
|
+
# If the user provides rules for an update, clear the current rules then use the create_rule method to
|
|
842
|
+
# restructure the Inspection Control rule and add to the payload.
|
|
843
|
+
if kwargs.get("rules"):
|
|
844
|
+
payload["rules"] = []
|
|
845
|
+
for rule in kwargs.pop("rules"):
|
|
846
|
+
payload["rules"].append(self._create_rule(rule))
|
|
847
|
+
|
|
848
|
+
# Add optional parameters to payload
|
|
849
|
+
for key, value in kwargs.items():
|
|
850
|
+
payload_key = snake_to_camel(key)
|
|
851
|
+
payload[payload_key] = value
|
|
852
|
+
|
|
853
|
+
# Special handling for default_action_value
|
|
854
|
+
if key == "default_action_value":
|
|
855
|
+
payload["defaultActionValue"] = value
|
|
856
|
+
|
|
857
|
+
resp = self.rest.put(
|
|
858
|
+
f"inspectionControls/custom/{control_id}", json=payload
|
|
859
|
+
).status_code
|
|
860
|
+
|
|
861
|
+
# Return the object if it was updated successfully
|
|
862
|
+
if not isinstance(resp, Response):
|
|
863
|
+
return self.get_custom_control(control_id)
|
|
864
|
+
|
|
865
|
+
def update_profile(self, profile_id: str, **kwargs):
|
|
866
|
+
"""
|
|
867
|
+
Updates the specified ZPA Inspection Profile.
|
|
868
|
+
|
|
869
|
+
Args:
|
|
870
|
+
profile_id (str):
|
|
871
|
+
The unique id for the ZPA Inspection Profile that will be updated.
|
|
872
|
+
predef_controls_version (str):
|
|
873
|
+
The predefined controls version for the ZPA Inspection Profile. Defaults to `OWASP_CRS/3.3.0`.
|
|
874
|
+
**kwargs:
|
|
875
|
+
Optional keyword args.
|
|
876
|
+
|
|
877
|
+
Keyword Args:
|
|
878
|
+
**custom_controls (list):
|
|
879
|
+
A tuple list of custom controls to be added to the Inspection profile.
|
|
880
|
+
|
|
881
|
+
Custom control tuples must follow the convention below:
|
|
882
|
+
|
|
883
|
+
``(control_id, action)``
|
|
884
|
+
|
|
885
|
+
e.g.
|
|
886
|
+
|
|
887
|
+
.. code-block:: python
|
|
888
|
+
|
|
889
|
+
custom_controls = [(99999, "BLOCK"), (88888, "PASS")]
|
|
890
|
+
**description (str):
|
|
891
|
+
Additional information about the Inspection Profile.
|
|
892
|
+
**name (str):
|
|
893
|
+
The name of the Inspection Profile.
|
|
894
|
+
**paranoia_level (int):
|
|
895
|
+
The paranoia level for the Inspection Profile.
|
|
896
|
+
**predef_controls (list):
|
|
897
|
+
A tuple list of predefined controls to be added to the Inspection profile.
|
|
898
|
+
|
|
899
|
+
Predefined control tuples must follow the convention below:
|
|
900
|
+
|
|
901
|
+
``(control_id, action)``
|
|
902
|
+
|
|
903
|
+
e.g.
|
|
904
|
+
|
|
905
|
+
.. code-block:: python
|
|
906
|
+
|
|
907
|
+
predef_controls = [(77777, "BLOCK"), (66666, "PASS")]
|
|
908
|
+
**predef_controls_version (str):
|
|
909
|
+
The version of the predefined controls that will be added.
|
|
910
|
+
|
|
911
|
+
Returns:
|
|
912
|
+
:obj:`Box`: The updated ZPA Inspection Profile resource record.
|
|
913
|
+
|
|
914
|
+
Examples:
|
|
915
|
+
Update the name and description of a ZPA Inspection Profile with the id 99999:
|
|
916
|
+
|
|
917
|
+
.. code-block:: python
|
|
918
|
+
|
|
919
|
+
print(
|
|
920
|
+
zpa.inspection.update_profile(
|
|
921
|
+
"99999",
|
|
922
|
+
name="inspect_common_predef_controls",
|
|
923
|
+
description="Inspects common controls from the Predefined set.",
|
|
924
|
+
)
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
Add a custom control to the ZPA Inspection Profile with the id 88888:
|
|
928
|
+
|
|
929
|
+
.. code-block:: python
|
|
930
|
+
|
|
931
|
+
print(
|
|
932
|
+
zpa.inspection.update_profile(
|
|
933
|
+
"88888",
|
|
934
|
+
custom_controls=[("2", "BLOCK")],
|
|
935
|
+
)
|
|
936
|
+
)
|
|
937
|
+
|
|
938
|
+
"""
|
|
939
|
+
# Set payload to value of existing record
|
|
940
|
+
payload = self.get_profile(profile_id)
|
|
941
|
+
payload["predefinedControlsVersion"] = kwargs.get(
|
|
942
|
+
"predef_controls_version", "OWASP_CRS/3.3.0"
|
|
943
|
+
)
|
|
944
|
+
|
|
945
|
+
# Extend existing list of default predefined controls if the user supplies more
|
|
946
|
+
if kwargs.get("predef_controls"):
|
|
947
|
+
controls = kwargs.pop("predef_controls")
|
|
948
|
+
for control in controls:
|
|
949
|
+
payload["predefined_controls"] = [
|
|
950
|
+
{"id": control[0], "action": control[1]} for control in controls
|
|
951
|
+
]
|
|
952
|
+
|
|
953
|
+
# Add custom controls if provided
|
|
954
|
+
if kwargs.get("custom_controls"):
|
|
955
|
+
controls = kwargs.pop("custom_controls")
|
|
956
|
+
payload["custom_controls"] = [
|
|
957
|
+
{"id": control[0], "action": control[1]} for control in controls
|
|
958
|
+
]
|
|
959
|
+
|
|
960
|
+
# Add optional parameters to payload
|
|
961
|
+
for key, value in kwargs.items():
|
|
962
|
+
payload[key] = value
|
|
963
|
+
|
|
964
|
+
# Convert from snake case to camel case
|
|
965
|
+
payload = convert_keys(payload)
|
|
966
|
+
|
|
967
|
+
resp = self.rest.put(
|
|
968
|
+
f"inspectionProfile/{profile_id}", json=payload
|
|
969
|
+
).status_code
|
|
970
|
+
|
|
971
|
+
# Return the object if it was updated successfully
|
|
972
|
+
if not isinstance(resp, Response):
|
|
973
|
+
return self.get_profile(profile_id)
|
|
974
|
+
|
|
975
|
+
def update_profile_and_controls(
|
|
976
|
+
self, profile_id: str, inspection_profile: dict, **kwargs
|
|
977
|
+
):
|
|
978
|
+
"""
|
|
979
|
+
Updates the inspection profile and controls for the specified ID.
|
|
980
|
+
|
|
981
|
+
Note:
|
|
982
|
+
This method has not been fully implemented and will not be maintained. There seems to be functionality
|
|
983
|
+
duplication with the default Inspection Profile update API call. `**kwargs` has been provided as a parameter
|
|
984
|
+
for you to be able to add any additional args that Zscaler may add.
|
|
985
|
+
|
|
986
|
+
If you feel that this is in error and that this functionality should be correctly implemented by zscaler-sdk-python
|
|
987
|
+
`raise an issue <https://github.com/zscaler/zscaler-sdk-python/issues>` in the zscaler-sdk-python Github repo
|
|
988
|
+
|
|
989
|
+
Args:
|
|
990
|
+
profile_id (str):
|
|
991
|
+
The unique id of the inspection profile.
|
|
992
|
+
inspection_profile (dict):
|
|
993
|
+
The new inspection profile object.
|
|
994
|
+
**kwargs:
|
|
995
|
+
Additional keyword args.
|
|
996
|
+
|
|
997
|
+
"""
|
|
998
|
+
|
|
999
|
+
payload = {
|
|
1000
|
+
"inspection_profile_id": profile_id,
|
|
1001
|
+
"inspection_profile": inspection_profile,
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
payload = convert_keys(payload)
|
|
1005
|
+
|
|
1006
|
+
resp = self.rest.put(
|
|
1007
|
+
"inspectionProfile/{profile_id}/patch", json=payload
|
|
1008
|
+
).status_code
|
|
1009
|
+
|
|
1010
|
+
# Return the object if it was updated successfully
|
|
1011
|
+
if not isinstance(resp, Response):
|
|
1012
|
+
return self.get_profile(profile_id)
|