Skip to content

Commit 73bcf71

Browse files
committed
chore: utilize helper methods.
1 parent 20228cd commit 73bcf71

4 files changed

Lines changed: 215 additions & 147 deletions

File tree

src/secops/chronicle/soar/integration/integration_instances.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from secops.chronicle.utils.format_utils import (
2121
format_resource_id,
2222
build_patch_body,
23+
remove_none_values,
2324
)
2425
from secops.chronicle.utils.request_utils import (
2526
chronicle_paginated_request,
@@ -64,13 +65,12 @@ def list_integration_instances(
6465
Raises:
6566
APIError: If the API request fails.
6667
"""
67-
extra_params = {
68-
"filter": filter_string,
69-
"orderBy": order_by,
70-
}
71-
72-
# Remove keys with None values
73-
extra_params = {k: v for k, v in extra_params.items() if v is not None}
68+
extra_params = remove_none_values(
69+
{
70+
"filter": filter_string,
71+
"orderBy": order_by,
72+
}
73+
)
7474

7575
return chronicle_paginated_request(
7676
client,
@@ -200,16 +200,15 @@ def create_integration_instance(
200200
else None
201201
)
202202

203-
body = {
204-
"environment": environment,
205-
"displayName": display_name,
206-
"description": description,
207-
"parameters": resolved_parameters,
208-
"agent": agent,
209-
}
210-
211-
# Remove keys with None values
212-
body = {k: v for k, v in body.items() if v is not None}
203+
body = remove_none_values(
204+
{
205+
"environment": environment,
206+
"displayName": display_name,
207+
"description": description,
208+
"parameters": resolved_parameters,
209+
"agent": agent,
210+
}
211+
)
213212

214213
return chronicle_request(
215214
client,

src/secops/chronicle/soar/integration/integrations.py

Lines changed: 107 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,25 @@
1414
#
1515
"""Integrations functionality for Chronicle."""
1616

17-
from typing import Any, TYPE_CHECKING
17+
from typing import TYPE_CHECKING, Any
1818

1919
from secops.chronicle.models import (
2020
APIVersion,
2121
DiffType,
2222
IntegrationParam,
23-
TargetMode,
24-
PythonVersion,
2523
IntegrationType,
24+
PythonVersion,
25+
TargetMode,
26+
)
27+
from secops.chronicle.utils.format_utils import (
28+
build_patch_body,
29+
format_resource_id,
30+
remove_none_values,
2631
)
27-
28-
from secops.chronicle.utils.format_utils import build_patch_body
2932
from secops.chronicle.utils.request_utils import (
3033
chronicle_paginated_request,
31-
chronicle_request_bytes,
3234
chronicle_request,
35+
chronicle_request_bytes,
3336
)
3437

3538
if TYPE_CHECKING:
@@ -106,7 +109,7 @@ def get_integration(
106109
return chronicle_request(
107110
client,
108111
method="GET",
109-
endpoint_path=f"integrations/{integration_name}",
112+
endpoint_path=f"integrations/{format_resource_id(integration_name)}",
110113
api_version=api_version,
111114
)
112115

@@ -130,7 +133,7 @@ def delete_integration(
130133
chronicle_request(
131134
client,
132135
method="DELETE",
133-
endpoint_path=f"integrations/{integration_name}",
136+
endpoint_path=f"integrations/{format_resource_id(integration_name)}",
134137
api_version=api_version,
135138
)
136139

@@ -175,27 +178,26 @@ def create_integration(
175178
Raises:
176179
APIError: If the API request fails
177180
"""
178-
serialised_params: list[dict[str, Any]] | None = None
181+
serialized_params: list[dict[str, Any]] | None = None
179182
if parameters is not None:
180-
serialised_params = [
183+
serialized_params = [
181184
p.to_dict() if isinstance(p, IntegrationParam) else p
182185
for p in parameters
183186
]
184187

185-
body_fields = {
186-
"displayName": display_name,
187-
"staging": staging,
188-
"description": description,
189-
"imageBase64": image_base64,
190-
"svgIcon": svg_icon,
191-
"pythonVersion": python_version,
192-
"parameters": serialised_params,
193-
"categories": categories,
194-
"type": integration_type,
195-
}
196-
197-
# Remove keys with None values
198-
body_fields = {k: v for k, v in body_fields.items() if v is not None}
188+
body_fields = remove_none_values(
189+
{
190+
"displayName": display_name,
191+
"staging": staging,
192+
"description": description,
193+
"imageBase64": image_base64,
194+
"svgIcon": svg_icon,
195+
"pythonVersion": python_version,
196+
"parameters": serialized_params,
197+
"categories": categories,
198+
"type": integration_type,
199+
}
200+
)
199201

200202
return chronicle_request(
201203
client,
@@ -271,12 +273,12 @@ def download_integration_dependency(
271273
def export_integration_items(
272274
client: "ChronicleClient",
273275
integration_name: str,
274-
actions: list[str] | None = None,
275-
jobs: list[str] | None = None,
276-
connectors: list[str] | None = None,
277-
managers: list[str] | None = None,
278-
transformers: list[str] | None = None,
279-
logical_operators: list[str] | None = None,
276+
actions: list[str] | str | None = None,
277+
jobs: list[str] | str | None = None,
278+
connectors: list[str] | str | None = None,
279+
managers: list[str] | str | None = None,
280+
transformers: list[str] | str | None = None,
281+
logical_operators: list[str] | str | None = None,
280282
api_version: APIVersion | None = APIVersion.V1BETA,
281283
) -> bytes:
282284
"""Exports specific items from an integration into a ZIP folder. Use
@@ -286,18 +288,18 @@ def export_integration_items(
286288
Args:
287289
client: ChronicleClient instance
288290
integration_name: name of the integration to export items from
289-
actions: Optional. A list the ids of the actions to export. Format:
290-
[1,2,3]
291-
jobs: Optional. A list the ids of the jobs to export. Format:
292-
[1,2,3]
293-
connectors: Optional. A list the ids of the connectors to export.
294-
Format: [1,2,3]
295-
managers: Optional. A list the ids of the managers to export. Format:
296-
[1,2,3]
297-
transformers: Optional. A list the ids of the transformers to export.
298-
Format: [1,2,3]
299-
logical_operators: Optional. A list the ids of the logical
300-
operators to export. Format: [1,2,3]
291+
actions: Optional. IDs of the actions to export as a list or
292+
comma-separated string. Format: [1,2,3] or "1,2,3"
293+
jobs: Optional. IDs of the jobs to export as a list or
294+
comma-separated string.
295+
connectors: Optional. IDs of the connectors to export as a
296+
list or comma-separated string.
297+
managers: Optional. IDs of the managers to export as a list
298+
or comma-separated string.
299+
transformers: Optional. IDs of the transformers to export as
300+
a list or comma-separated string.
301+
logical_operators: Optional. IDs of the logical operators to
302+
export as a list or comma-separated string.
301303
api_version: API version to use for the request. Default is V1BETA.
302304
303305
Returns:
@@ -306,23 +308,49 @@ def export_integration_items(
306308
Raises:
307309
APIError: If the API request fails
308310
"""
309-
export_items = {
310-
"actions": ",".join(actions) if actions else None,
311-
"jobs": jobs,
312-
"connectors": connectors,
313-
"managers": managers,
314-
"transformers": transformers,
315-
"logicalOperators": logical_operators,
316-
"alt": "media",
317-
}
318-
319-
# Remove keys with None values
320-
export_items = {k: v for k, v in export_items.items() if v is not None}
311+
export_items = remove_none_values(
312+
{
313+
"actions": (
314+
",".join(actions)
315+
if isinstance(actions, list)
316+
else actions if actions else None
317+
),
318+
"jobs": (
319+
",".join(jobs)
320+
if isinstance(jobs, list)
321+
else jobs if jobs else None
322+
),
323+
"connectors": (
324+
",".join(connectors)
325+
if isinstance(connectors, list)
326+
else connectors if connectors else None
327+
),
328+
"managers": (
329+
",".join(managers)
330+
if isinstance(managers, list)
331+
else managers if managers else None
332+
),
333+
"transformers": (
334+
",".join(transformers)
335+
if isinstance(transformers, list)
336+
else transformers if transformers else None
337+
),
338+
"logicalOperators": (
339+
",".join(logical_operators)
340+
if isinstance(logical_operators, list)
341+
else logical_operators if logical_operators else None
342+
),
343+
"alt": "media",
344+
}
345+
)
321346

322347
return chronicle_request_bytes(
323348
client,
324349
method="GET",
325-
endpoint_path=f"integrations/{integration_name}:exportItems",
350+
endpoint_path=(
351+
f"integrations/{format_resource_id(integration_name)}:"
352+
"exportItems"
353+
),
326354
params=export_items,
327355
api_version=api_version,
328356
headers={"Accept": "application/zip"},
@@ -440,13 +468,12 @@ def get_integration_restricted_agents(
440468
Raises:
441469
APIError: If the API request fails
442470
"""
443-
params_fields = {
444-
"requiredPythonVersion": required_python_version.value,
445-
"pushRequest": push_request,
446-
}
447-
448-
# Remove keys with None values
449-
params_fields = {k: v for k, v in params_fields.items() if v is not None}
471+
params_fields = remove_none_values(
472+
{
473+
"requiredPythonVersion": required_python_version.value,
474+
"pushRequest": push_request,
475+
}
476+
)
450477

451478
return chronicle_request(
452479
client,
@@ -487,7 +514,7 @@ def get_integration_diff(
487514
return chronicle_request(
488515
client,
489516
method="GET",
490-
endpoint_path=f"integrations/{integration_name}"
517+
endpoint_path=f"integrations/{format_resource_id(integration_name)}"
491518
f":fetch{diff_type.value}Diff",
492519
api_version=api_version,
493520
)
@@ -519,7 +546,7 @@ def transition_integration(
519546
return chronicle_request(
520547
client,
521548
method="POST",
522-
endpoint_path=f"integrations/{integration_name}"
549+
endpoint_path=f"integrations/{format_resource_id(integration_name)}"
523550
f":pushTo{target_mode.value}",
524551
api_version=api_version,
525552
)
@@ -592,7 +619,7 @@ def update_integration(
592619
return chronicle_request(
593620
client,
594621
method="PATCH",
595-
endpoint_path=f"integrations/{integration_name}",
622+
endpoint_path=f"integrations/{format_resource_id(integration_name)}",
596623
json=body,
597624
params=params,
598625
api_version=api_version,
@@ -650,23 +677,20 @@ def update_custom_integration(
650677
Raises:
651678
APIError: If the API request fails
652679
"""
653-
integration_fields = {
654-
"name": integration_name,
655-
"displayName": display_name,
656-
"description": description,
657-
"imageBase64": image_base64,
658-
"svgIcon": svg_icon,
659-
"pythonVersion": python_version,
660-
"parameters": parameters,
661-
"categories": categories,
662-
"type": integration_type,
663-
"staging": staging,
664-
}
665-
666-
# Remove keys with None values
667-
integration_fields = {
668-
k: v for k, v in integration_fields.items() if v is not None
669-
}
680+
integration_fields = remove_none_values(
681+
{
682+
"name": integration_name,
683+
"displayName": display_name,
684+
"description": description,
685+
"imageBase64": image_base64,
686+
"svgIcon": svg_icon,
687+
"pythonVersion": python_version,
688+
"parameters": parameters,
689+
"categories": categories,
690+
"type": integration_type,
691+
"staging": staging,
692+
}
693+
)
670694

671695
body = {"integration": integration_fields}
672696

@@ -679,7 +703,7 @@ def update_custom_integration(
679703
client,
680704
method="POST",
681705
endpoint_path=f"integrations/"
682-
f"{integration_name}:updateCustomIntegration",
706+
f"{format_resource_id(integration_name)}:updateCustomIntegration",
683707
json=body,
684708
params=params,
685709
api_version=api_version,

0 commit comments

Comments
 (0)