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,85 @@
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 BoxList
19
+
20
+ from zscaler.zpa.client import ZPAClient
21
+
22
+
23
+ class IsolationProfileAPI:
24
+ def __init__(self, client: ZPAClient):
25
+ self.rest = client
26
+
27
+ def list_profiles(self, **kwargs) -> BoxList:
28
+ """
29
+ Returns a list of all configured isolation profiles.
30
+
31
+ Keyword Args:
32
+ max_items (int): The maximum number of items to request before stopping iteration.
33
+ max_pages (int): The maximum number of pages to request before stopping iteration.
34
+ pagesize (int): Specifies the page size. The default size is 20, but the maximum size is 500.
35
+ search (str, optional): The search string used to match against features and fields.
36
+
37
+ Returns:
38
+ BoxList: A list of all configured isolation profiles.
39
+
40
+ Examples:
41
+ >>> for isolation_profile in zpa.isolation_profiles.list_profiles():
42
+ ... pprint(isolation_profile)
43
+ """
44
+ list, _ = self.rest.get_paginated_data(path="/isolation/profiles", **kwargs)
45
+ return list
46
+
47
+ def get_profile_by_name(self, name: str):
48
+ """
49
+ Retrieves a specific isolation profile by its name.
50
+
51
+ Args:
52
+ name (str): The name of the isolation profile to search for.
53
+
54
+ Returns:
55
+ dict or None: The isolation profile with the specified name if found, otherwise None.
56
+
57
+ Examples:
58
+ >>> profile = zpa.isolation_profiles.get_profile_by_name('DefaultProfile')
59
+ >>> print(profile)
60
+ """
61
+ profiles = self.list_profiles()
62
+ for profile in profiles:
63
+ if profile.get("name") == name:
64
+ return profile
65
+ return None
66
+
67
+ def get_profile_by_id(self, profile_id: str):
68
+ """
69
+ Retrieves a specific isolation profile by its unique identifier (ID).
70
+
71
+ Args:
72
+ profile_id (str): The ID of the isolation profile to retrieve.
73
+
74
+ Returns:
75
+ dict or None: The isolation profile with the specified ID if found, otherwise None.
76
+
77
+ Examples:
78
+ >>> profile = zpa.isolation_profiles.get_profile_by_id('12345')
79
+ >>> print(profile)
80
+ """
81
+ profiles = self.list_profiles()
82
+ for profile in profiles:
83
+ if str(profile.get("id")) == str(profile_id): # Ensuring ID comparison as strings
84
+ return profile
85
+ return None
zscaler/zpa/lss.py ADDED
@@ -0,0 +1,568 @@
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
+ import requests
19
+ from box import Box, BoxList
20
+ from requests import Response
21
+
22
+ from zscaler.utils import convert_keys, keys_exists, snake_to_camel
23
+ from zscaler.zpa.client import ZPAClient
24
+
25
+
26
+ class LSSConfigControllerAPI:
27
+ source_log_map = {
28
+ "app_connector_metrics": "zpn_ast_comprehensive_stats",
29
+ "app_connector_status": "zpn_ast_auth_log",
30
+ "audit_logs": "zpn_audit_log",
31
+ "browser_access": "zpn_http_trans_log",
32
+ "private_svc_edge_status": "zpn_sys_auth_log",
33
+ "user_activity": "zpn_trans_log",
34
+ "user_status": "zpn_auth_log",
35
+ "web_inspection": "zpn_waf_http_exchanges_log",
36
+ }
37
+
38
+ def __init__(self, client: ZPAClient):
39
+ self.rest = client
40
+
41
+ self.v2_admin_url = (
42
+ "https://config.private.zscaler.com/mgmtconfig/v2/admin/lssConfig"
43
+ )
44
+
45
+ def _create_policy(self, conditions: list) -> list:
46
+ """
47
+ Creates a dict template for feeding conditions into the ZPA Policies API when adding or updating a policy.
48
+
49
+ Args:
50
+ conditions (list): List of condition tuples.
51
+
52
+ Returns:
53
+ :obj:`dict`: Dictionary containing the LSS Log Receiver Policy conditions template.
54
+
55
+ """
56
+
57
+ template = []
58
+
59
+ for condition in conditions:
60
+ # Template for SAML Policy Rule objects
61
+ if (
62
+ isinstance(condition, tuple)
63
+ and len(condition) == 2
64
+ and condition[0] == "saml"
65
+ ):
66
+ operand = {"operands": [{"objectType": "SAML", "entryValues": []}]}
67
+ for item in condition[1]:
68
+ entry_values = {
69
+ "lhs": item[0],
70
+ "rhs": item[1],
71
+ }
72
+ operand["operands"][0]["entryValues"].append(entry_values)
73
+ # Template for client_type Policy Rule objects
74
+ elif condition[0] == "client_type":
75
+ operand = {
76
+ "operands": [
77
+ {
78
+ "objectType": condition[0].upper(),
79
+ "values": [
80
+ self.get_client_types()[item] for item in condition[1]
81
+ ],
82
+ }
83
+ ]
84
+ }
85
+ # Template for all other object types
86
+ else:
87
+ operand = {
88
+ "operands": [
89
+ {
90
+ "objectType": condition[0].upper(),
91
+ "values": condition[1],
92
+ }
93
+ ]
94
+ }
95
+ template.append(operand)
96
+
97
+ return template
98
+
99
+ def get_client_types(self) -> Box:
100
+ """
101
+ Returns all available LSS Client Types.
102
+
103
+ Client Types are used when creating LSS Receiver configs. ZPA uses an internal code for Client Types, e.g.
104
+ ``zpn_client_type_ip_anchoring`` is the Client Type for a ZIA Service Edge. zscaler-sdk-python inverts the key/value so
105
+ that you can perform a lookup using a human-readable name in your code (e.g. ``cloud_connector``).
106
+
107
+ Returns:
108
+ :obj:`Box`: Dictionary containing all LSS Client Types with human-readable name as the key.
109
+
110
+ Examples:
111
+ Print all LSS Client Types:
112
+
113
+ >>> print(zpa.lss.get_client_types())
114
+
115
+ """
116
+ # ZPA returns a dictionary of client types but the keys are the internal ZPA codes, which our users probably
117
+ # won't know. This method reverses the dictionary, converts the 'normalised' Client Type name to snake_case
118
+ # before returning it so that a lookup can be easily performed using the Client Type name in plain english.
119
+ #
120
+ # Example before:
121
+ # {'zpn_client_type_exporter': 'Web Browser'}
122
+ # Example after:
123
+ # {'web_browser': 'zpn_client_type_exporter'}
124
+
125
+ response = requests.get(
126
+ f"{self.v2_admin_url}/clientTypes", headers=self.rest.headers
127
+ )
128
+
129
+ if response.status_code == 200:
130
+ return response.json()
131
+ else:
132
+ response.raise_for_status()
133
+
134
+ reverse_map = {v.lower().replace(" ", "_"): k for k, v in response.items()}
135
+ return Box(reverse_map)
136
+
137
+ def list_configs(self, **kwargs) -> BoxList:
138
+ """
139
+ Returns all configured LSS receivers.
140
+
141
+ Keyword Args:
142
+ **max_items (int):
143
+ The maximum number of items to request before stopping iteration.
144
+ **max_pages (int):
145
+ The maximum number of pages to request before stopping iteration.
146
+ **pagesize (int):
147
+ Specifies the page size. The default size is 20, but the maximum size is 500.
148
+ **search (str, optional):
149
+ The search string used to match against features and fields.
150
+
151
+ Returns:
152
+ :obj:`BoxList`: List of all configured LSS receivers.
153
+
154
+ Examples:
155
+ Print all configured LSS Receivers.
156
+
157
+ >>> for lss_config in zpa.lss.list_configs():
158
+ ... print(config)
159
+ """
160
+ list, _ = self.rest.get_paginated_data(
161
+ path="/lssConfig", **kwargs, api_version="v2"
162
+ )
163
+ return list
164
+
165
+ def get_config(self, lss_id: str) -> Box:
166
+ """
167
+ Returns information on the specified LSS Receiver config.
168
+
169
+ Args:
170
+ lss_id (str):
171
+ The unique identifier for the LSS Receiver config.
172
+
173
+ Returns:
174
+ :obj:`Box`: The resource record for the LSS Receiver config.
175
+
176
+ Examples:
177
+ Print information on the specified LSS Receiver config.
178
+
179
+ >>> print(zpa.lss.get_config('99999'))
180
+
181
+ """
182
+ response = self.rest.get("/lssConfig/%s" % (lss_id), api_version="v2")
183
+ if isinstance(response, Response):
184
+ status_code = response.status_code
185
+ if status_code != 200:
186
+ return None
187
+ return response
188
+
189
+ def get_log_formats(self) -> Box:
190
+ """
191
+ Returns all available pre-configured LSS Log Formats.
192
+
193
+ LSS Log Formats are provided as either CSV, JSON or TSV. LSS Log Format values can be used when
194
+ creating or updating LSS Log Receiver configs.
195
+
196
+ Returns:
197
+ :obj:`Box`: Dictionary containing pre-configured LSS Log Formats.
198
+
199
+ Examples:
200
+ >>> for item in zpa.lss.get_log_formats():
201
+ ... print(item)
202
+
203
+ """
204
+ response = requests.get(
205
+ f"{self.v2_admin_url}/logType/formats", headers=self.rest.headers
206
+ )
207
+
208
+ if response.status_code == 200:
209
+ return response.json()
210
+ else:
211
+ response.raise_for_status()
212
+
213
+ def get_status_codes(self, log_type: str = "all") -> Box:
214
+ """
215
+ Returns a list of LSS Session Status Codes.
216
+
217
+ The LSS Session Status codes are used to filter the messages received by LSS. LSS Session Status Codes can be
218
+ used when adding or updating the filters for an LSS Log Receiver.
219
+
220
+ Args:
221
+ log_type (str):
222
+ Filter the LSS Session Status Codes by Log Type, accepted values are:
223
+
224
+ - ``all``
225
+ - ``app_connector_status``
226
+ - ``private_svc_edge_status``
227
+ - ``user_activity``
228
+ - ``user_status``
229
+
230
+ `Defaults to all.`
231
+
232
+ Returns:
233
+ :obj:`Box`: Dictionary containing all LSS Session Status Codes.
234
+
235
+ Examples:
236
+ Print all LSS Session Status Codes.
237
+
238
+ >>> for item in zpa.lss.get_status_codes():
239
+ ... print(item)
240
+
241
+ Print LSS Session Status Codes for `User Activity` log types.
242
+
243
+ >>> for item in zpa.lss.get_status_codes(log_type="user_activity"):
244
+ ... print(item)
245
+
246
+ """
247
+ path = "/statusCodes"
248
+ if log_type != "all":
249
+ if log_type in [
250
+ "user_activity",
251
+ "user_status",
252
+ "private_svc_edge_status",
253
+ "app_connector_status",
254
+ ]:
255
+ path = f"{path}/{self.source_log_map[log_type]}"
256
+ else:
257
+ raise ValueError("Incorrect log_type provided.")
258
+
259
+ full_url = f"{self.v2_admin_url}{path}"
260
+ response = requests.get(full_url, headers=self.rest.headers)
261
+
262
+ if response.status_code == 200:
263
+ # Assuming that the response is a JSON object that needs to be converted to a Box
264
+ response_data = Box(response.json())
265
+ return response_data if log_type == "all" else response_data[log_type]
266
+ else:
267
+ response.raise_for_status()
268
+
269
+ def add_lss_config(
270
+ self,
271
+ lss_host: str,
272
+ lss_port: str,
273
+ name: str,
274
+ source_log_type: str,
275
+ app_connector_group_ids: list = None,
276
+ enabled: bool = True,
277
+ source_log_format: str = "csv",
278
+ use_tls: bool = False,
279
+ **kwargs,
280
+ ) -> Box:
281
+ """
282
+ Adds a new LSS Receiver Config to ZPA.
283
+
284
+ Args:
285
+ app_connector_group_ids (list): A list of unique IDs for the App Connector Groups associated with this
286
+ LSS Config. `Defaults to None.`
287
+ enabled (bool): Enable the LSS Receiver. `Defaults to True`.
288
+ lss_host (str): The IP address of the LSS Receiver.
289
+ lss_port (str): The port number for the LSS Receiver.
290
+ name (str): The name of the LSS Config.
291
+ source_log_format (str):
292
+ The format for the logs. Must be one of the following options:
293
+
294
+ - ``csv`` - send logs in CSV format
295
+ - ``json`` - send logs in JSON format
296
+ - ``tsv`` - send logs in TSV format
297
+
298
+ `Defaults to csv.`
299
+ source_log_type (str):
300
+ The type of logs that will be sent to the receiver as part of this config. Must be one of the following
301
+ options:
302
+
303
+ - ``app_connector_metrics``
304
+ - ``app_connector_status``
305
+ - ``audit_logs``
306
+ - ``browser_access``
307
+ - ``private_svc_edge_status``
308
+ - ``user_activity``
309
+ - ``user_status``
310
+ use_tls (bool):
311
+ Enable to use TLS on the log traffic between LSS components. `Defaults to False.`
312
+
313
+ Keyword Args:
314
+ description (str):
315
+ Additional information about the LSS Config.
316
+ filter_status_codes (list):
317
+ A list of Session Status Codes that will be excluded by LSS.
318
+ log_stream_content (str):
319
+ Formatter for the log stream content that will be sent to the LSS Host. Only pass this parameter if you
320
+ intend on using custom log stream content.
321
+ policy_rules (list):
322
+ A list of policy rule tuples. Tuples must follow the convention:
323
+
324
+ (`object_type`, [`object_id`]).
325
+
326
+ E.g.
327
+
328
+ .. code-block:: python
329
+
330
+ ('app_segment_ids', ['11111', '22222']),
331
+ ('segment_group_ids', ['88888']),
332
+ ('idp_ids', ['99999']),
333
+ ('client_type', ['zia_service_edge'])
334
+ ('saml', [('33333', 'value')])
335
+
336
+ Returns:
337
+ :obj:`Box`: The newly created LSS Config resource record.
338
+
339
+ Examples:
340
+
341
+ Add an LSS Receiver config that receives App Connector Metrics logs.
342
+
343
+ .. code-block:: python
344
+
345
+ zpa.lss.add_config(
346
+ app_connector_group_ids=["app_conn_group_id"],
347
+ lss_host="192.0.2.100,
348
+ lss_port="8080",
349
+ name="app_con_metrics_to_siem",
350
+ source_log_type="app_connector_metrics")
351
+
352
+ Add an LSS Receiver config that receives User Activity logs.
353
+
354
+ .. code-block:: python
355
+
356
+ zpa.lss.add_config(
357
+ app_connector_group_ids=["app_conn_group_id"],
358
+ lss_host="192.0.2.100,
359
+ lss_port="8080",
360
+ name="user_activity_to_siem",
361
+ policy_rules=[
362
+ ("idp", ["idp_id"]),
363
+ ("app", ["app_seg_id"]),
364
+ ("app_group", ["app_seg_group_id"]),
365
+ ("saml", [("saml_attr_id", "saml_attr_value")]),
366
+ ],
367
+ source_log_type="user_activity")
368
+
369
+ Add an LSS Receiver config that receives User Status logs.
370
+
371
+ .. code-block:: python
372
+
373
+ zpa.lss.add_config(
374
+ app_connector_group_ids=["app_conn_group_id"],
375
+ lss_host="192.0.2.100,
376
+ lss_port="8080",
377
+ name="user_activity_to_siem",
378
+ policy_rules=[
379
+ ("idp", ["idp_id"]),
380
+ ("client_type", ["web_browser", "client_connector"]),
381
+ ("saml", [("attribute_id", "test3")]),
382
+ ],
383
+ source_log_type="user_status")
384
+
385
+ """
386
+ source_log_type = self.source_log_map[source_log_type]
387
+
388
+ # If the user has supplied custom log stream content formatting then we'll use that. Otherwise map the log
389
+ # type to internal ZPA log codes and get the preformatted log stream content formatting directly from ZPA.
390
+ if kwargs.get("log_stream_content"):
391
+ log_stream_content = kwargs.pop("log_stream_content")
392
+ else:
393
+ log_stream_content = self.get_log_formats()[source_log_type][
394
+ source_log_format
395
+ ]
396
+
397
+ payload = {
398
+ "config": {
399
+ "enabled": enabled,
400
+ "lssHost": lss_host,
401
+ "lssPort": lss_port,
402
+ "name": name,
403
+ "format": log_stream_content,
404
+ "sourceLogType": source_log_type,
405
+ "useTls": use_tls,
406
+ },
407
+ "connectorGroups": [
408
+ {"id": group_id} for group_id in app_connector_group_ids
409
+ ],
410
+ }
411
+
412
+ # Convert tuple list to dict and add to payload
413
+ if kwargs.get("policy_rules"):
414
+ payload["policyRuleResource"] = {
415
+ "conditions": self._create_policy(kwargs.pop("policy_rules")),
416
+ "name": kwargs.get("policy_name", "SIEM_POLICY"),
417
+ }
418
+
419
+ # Add Session Status Codes to filter if provided
420
+ if kwargs.get("filter_status_codes"):
421
+ payload["config"]["filter"] = kwargs.pop("filter_status_codes")
422
+
423
+ # Add optional parameters to payload
424
+ for key, value in kwargs.items():
425
+ payload[snake_to_camel(key)] = value
426
+
427
+ response = self.rest.post("/lssConfig", api_version="v2", json=payload)
428
+ if isinstance(response, Response):
429
+ # this is only true when the creation failed (status code is not 2xx)
430
+ status_code = response.status_code
431
+ # Handle error response
432
+ raise Exception(
433
+ f"API call failed with status {status_code}: {response.json()}"
434
+ )
435
+ return response
436
+
437
+ def update_lss_config(self, lss_config_id: str, **kwargs):
438
+ """
439
+ Update the LSS Receiver Config.
440
+
441
+ Args:
442
+ lss_config_id (str): The unique id for the LSS Receiver config.
443
+ **kwargs: Optional keyword args.
444
+
445
+ Keyword Args:
446
+ description (str):
447
+ Additional information about the LSS Config.
448
+ enabled (bool):
449
+ Enable the LSS host. Defaults to ``True``.
450
+ filter_status_codes (list):
451
+ A list of Session Status Codes that will be excluded by LSS. If you would like to filter all error codes
452
+ then pass the string "all".
453
+ log_stream_content (str):
454
+ Formatter for the log stream content that will be sent to the LSS Host.
455
+ policy_rules (list):
456
+ A list of policy rule tuples. Tuples must follow the convention:
457
+
458
+ (`object_type`, [`object_id`]).
459
+
460
+ E.g.
461
+
462
+ .. code-block:: python
463
+
464
+ ('app_segment_ids', ['11111', '22222']),
465
+ ('segment_group_ids', ['88888']),
466
+ ('idp_ids', ['99999']),
467
+ ('client_type', ['zpn_client_type_exporter'])
468
+ ('saml_attributes', [('33333', 'value')])
469
+ source_log_format (str):
470
+ The format for the logs. Must be one of the following options:
471
+
472
+ - ``csv`` - send logs in CSV format
473
+ - ``json`` - send logs in JSON format
474
+ - ``tsv`` - send logs in TSV format
475
+ source_log_type (str):
476
+ The type of logs that will be sent to the receiver as part of this config. Must be one of the following
477
+ options:
478
+
479
+ - ``app_connector_metrics``
480
+ - ``app_connector_status``
481
+ - ``audit_logs``
482
+ - ``browser_access``
483
+ - ``private_svc_edge_status``
484
+ - ``user_activity``
485
+ - ``user_status``
486
+ use_tls (bool):
487
+ Enable to use TLS on the log traffic between LSS components. Defaults to ``False``.
488
+
489
+ Examples:
490
+
491
+ Update an LSS Log Receiver config to change from user activity to user status.
492
+
493
+ Note that the ``policy_rules`` will need to be modified to be compatible with the chosen
494
+ ``source_log_type``.
495
+
496
+ .. code-block:: python
497
+
498
+ zpa.lss.update_config(
499
+ name="user_status_to_siem",
500
+ policy_rules=[
501
+ ("idp", ["idp_id"]),
502
+ ("client_type", ["machine_tunnel"]),
503
+ ("saml", [("attribute_id", "11111")]),
504
+ ],
505
+ source_log_type="user_status")
506
+ """
507
+ # Set payload to value of existing record
508
+ payload = convert_keys(self.get_config(lss_config_id))
509
+
510
+ # If the user has supplied custom log stream content formatting then we'll use that. Otherwise, map the log
511
+ # type to internal ZPA log codes and get the preformatted log stream content formatting directly from ZPA.
512
+ if kwargs.get("log_stream_content"):
513
+ payload["config"]["format"] = kwargs.pop("log_stream_content")
514
+ elif kwargs.get("source_log_type"):
515
+ source_log_type = self.source_log_map[kwargs.pop("source_log_type")]
516
+ payload["config"]["sourceLogType"] = source_log_type
517
+ payload["config"]["format"] = self.get_log_formats()[source_log_type][
518
+ kwargs.pop("source_log_format", "csv")
519
+ ]
520
+
521
+ # Iterate kwargs and update payload for keys that we've renamed.
522
+ for k in list(kwargs):
523
+ if k in ["name", "lss_host", "lss_port", "enabled", "use_tls"]:
524
+ payload["config"][snake_to_camel(k)] = kwargs.pop(k)
525
+ elif k == "filter_status_codes":
526
+ payload["config"]["filter"] = kwargs.pop(k)
527
+
528
+ # Convert tuple list to dict and add to payload
529
+ if kwargs.get("policy_rules"):
530
+ if keys_exists(payload, "policyRuleResource", "name"):
531
+ policy_name = payload["policyRuleResource"]["name"]
532
+ else:
533
+ policy_name = "SIEM_POLICY"
534
+ payload["policyRuleResource"] = {
535
+ "conditions": self._create_policy(kwargs.pop("policy_rules")),
536
+ "name": kwargs.pop("policy_name", policy_name),
537
+ }
538
+
539
+ # Add additional provided parameters to payload
540
+ for key, value in kwargs.items():
541
+ payload[snake_to_camel(key)] = value
542
+
543
+ resp = self.rest.put(
544
+ f"/lssConfig/{lss_config_id}", api_version="v2", json=payload
545
+ ).status_code
546
+
547
+ # Return the object if it was updated successfully
548
+ if not isinstance(resp, Response):
549
+ return self.get_config(lss_config_id)
550
+
551
+ def delete_lss_config(self, lss_id: str) -> int:
552
+ """
553
+ Delete the specified LSS Receiver Config.
554
+
555
+ Args:
556
+ lss_id (str): The unique identifier for the LSS Receiver Config to be deleted.
557
+
558
+ Returns:
559
+ :obj:`int`:
560
+ The response code for the operation.
561
+
562
+ Examples:
563
+ Delete an LSS Receiver config.
564
+
565
+ >>> zpa.lss.delete_config('99999')
566
+
567
+ """
568
+ return self.rest.delete(f"/lssConfig/{lss_id}", api_version="v2").status_code