xsoar-cli 1.0.4__py3-none-any.whl → 1.0.5__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.

Potentially problematic release.


This version of xsoar-cli might be problematic. Click here for more details.

xsoar_cli/__about__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # SPDX-FileCopyrightText: 2025-present Torbjørn Lium <torben@lium.org>
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
- __version__ = "1.0.4"
4
+ __version__ = "1.0.5"
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
3
3
 
4
4
  import click
5
5
 
6
- from xsoar_cli.utilities import load_config, validate_environments
6
+ from xsoar_cli.utilities import load_config, parse_string_to_dict, validate_environments
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from xsoar_client.xsoar_client import Client
@@ -15,11 +15,13 @@ def case() -> None:
15
15
 
16
16
 
17
17
  @click.argument("casenumber", type=int)
18
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
18
+ @click.option("--environment", default=None, help="Default environment set in config file.")
19
19
  @click.command(help="Get basic information about a single case in XSOAR")
20
20
  @click.pass_context
21
21
  @load_config
22
- def get(ctx: click.Context, casenumber: int, environment: str) -> None:
22
+ def get(ctx: click.Context, casenumber: int, environment: str | None) -> None:
23
+ if not environment:
24
+ environment = ctx.obj["default_environment"]
23
25
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
24
26
  response = xsoar_client.get_case(casenumber)
25
27
  if response["total"] == 0 and not response["data"]:
@@ -62,15 +64,31 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
62
64
  click.echo(json.dumps(case_data, indent=4))
63
65
 
64
66
 
65
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
67
+ @click.option("--environment", default=None, help="Default environment set in config file.")
66
68
  @click.option("--casetype", default="", show_default=True, help="Create case of specified type. Default type set in config file.")
69
+ @click.option(
70
+ "--custom-fields",
71
+ default=None,
72
+ help='Additional fields on the form "myfield=my_value,anotherfield=another value". Use machine name for field names, e.g mycustomfieldname.',
73
+ )
74
+ @click.option("--custom-fields-delimiter", default=",", help='Delimiter when specifying additional fields. Default is ","')
67
75
  @click.argument("details", type=str, default="Placeholder case details")
68
76
  @click.argument("name", type=str, default="Test case created from xsoar-cli")
69
77
  @click.command()
70
78
  @click.pass_context
71
79
  @load_config
72
- def create(ctx: click.Context, environment: str, casetype: str, name: str, details: str) -> None:
80
+ def create( # noqa: PLR0913
81
+ ctx: click.Context,
82
+ environment: str | None,
83
+ casetype: str,
84
+ name: str,
85
+ custom_fields: str | None,
86
+ custom_fields_delimiter: str | None,
87
+ details: str,
88
+ ) -> None:
73
89
  """Creates a new case in XSOAR. If invalid case type is specified as a command option, XSOAR will default to using Unclassified."""
90
+ if not environment:
91
+ environment = ctx.obj["default_environment"]
74
92
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
75
93
  if not casetype:
76
94
  casetype = ctx.obj["default_new_case_type"]
@@ -79,6 +97,7 @@ def create(ctx: click.Context, environment: str, casetype: str, name: str, detai
79
97
  "name": name,
80
98
  "type": casetype,
81
99
  "details": details,
100
+ "CustomFields": parse_string_to_dict(custom_fields, custom_fields_delimiter),
82
101
  }
83
102
  case_data = xsoar_client.create_case(data=data)
84
103
  case_id = case_data["id"]
@@ -39,13 +39,42 @@ def manifest() -> None:
39
39
  """Various commands to interact/update/deploy content packs defined in the xsoar_config.json manifest."""
40
40
 
41
41
 
42
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
42
+ @click.option("--environment", default=None, help="Default environment set in config file.")
43
+ @click.argument("manifest_path", type=str)
44
+ @click.command()
45
+ @click.pass_context
46
+ @load_config
47
+ def generate(ctx: click.Context, environment: str | None, manifest_path: str) -> None:
48
+ """Generate a new xsoar_config.json manifest from installed content packs.
49
+
50
+ This command assumes that you do not have any custom content packs uploaded to XSOAR.
51
+ All packs will be added as "marketplace_packs" in the manifest.
52
+ """
53
+ if not environment:
54
+ environment = ctx.obj["default_environment"]
55
+ xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
56
+ installed_packs = xsoar_client.get_installed_packs()
57
+ manifest_data = {
58
+ "marketplace_packs": [],
59
+ }
60
+ for item in installed_packs:
61
+ tmpobj = {
62
+ "id": item["id"],
63
+ "version": item["currentVersion"],
64
+ }
65
+ manifest_data["marketplace_packs"].append(tmpobj)
66
+ write_manifest(manifest_path, manifest_data)
67
+
68
+
69
+ @click.option("--environment", default=None, help="Default environment set in config file.")
43
70
  @click.argument("manifest", type=str)
44
71
  @click.command()
45
72
  @click.pass_context
46
73
  @load_config
47
- def update(ctx: click.Context, environment: str, manifest: str) -> None:
74
+ def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
48
75
  """Update manifest on disk with latest available content pack versions."""
76
+ if not environment:
77
+ environment = ctx.obj["default_environment"]
49
78
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
50
79
  manifest_data = load_manifest(manifest)
51
80
  click.echo("Fetching outdated packs from XSOAR server. This may take a minute...", nl=False)
@@ -81,14 +110,16 @@ def update(ctx: click.Context, environment: str, manifest: str) -> None:
81
110
  write_manifest(manifest, manifest_data)
82
111
 
83
112
 
84
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
113
+ @click.option("--environment", default=None, help="Default environment set in config file.")
85
114
  @click.argument("manifest", type=str)
86
115
  @click.command()
87
116
  @click.pass_context
88
117
  @load_config
89
- def validate(ctx: click.Context, environment: str, manifest: str) -> None:
118
+ def validate(ctx: click.Context, environment: str | None, manifest: str) -> None:
90
119
  """Validate manifest JSON and all pack availability. Validates upstream pack availability by doing HTTP CONNECT.
91
120
  Custom pack availability is implementation dependant."""
121
+ if not environment:
122
+ environment = ctx.obj["default_environment"]
92
123
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
93
124
  manifest_data = load_manifest(manifest)
94
125
  click.echo("Manifest is valid JSON")
@@ -121,14 +152,16 @@ def validate(ctx: click.Context, environment: str, manifest: str) -> None:
121
152
  click.echo("Manifest is valid JSON and all packs are reachable.")
122
153
 
123
154
 
124
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
155
+ @click.option("--environment", default=None, help="Default environment set in config file.")
125
156
  @click.argument("manifest", type=str)
126
157
  @click.command()
127
158
  @click.pass_context
128
159
  @load_config
129
- def diff(ctx: click.Context, manifest: str, environment: str) -> None:
160
+ def diff(ctx: click.Context, manifest: str, environment: str | None) -> None:
130
161
  """Prints out the differences (if any) between what is defined in the xsoar_config.json manifest and what is actually
131
162
  installed on the XSOAR server."""
163
+ if not environment:
164
+ environment = ctx.obj["default_environment"]
132
165
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
133
166
  manifest_data = load_manifest(manifest)
134
167
  installed_packs = xsoar_client.get_installed_packs()
@@ -147,14 +180,14 @@ def diff(ctx: click.Context, manifest: str, environment: str) -> None:
147
180
  click.echo("All packs up to date.")
148
181
 
149
182
 
150
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
183
+ @click.option("--environment", default=None, help="Default environment set in config file.")
151
184
  @click.option("--verbose", is_flag=True, default=False)
152
185
  @click.option("--yes", is_flag=True, default=False)
153
186
  @click.command()
154
187
  @click.argument("manifest", type=str)
155
188
  @click.pass_context
156
189
  @load_config
157
- def deploy(ctx: click.Context, environment: str, manifest: str, verbose: bool, yes: bool) -> None: # noqa: FBT001
190
+ def deploy(ctx: click.Context, environment: str | None, manifest: str, verbose: bool, yes: bool) -> None: # noqa: FBT001
158
191
  """
159
192
  Deploys content packs to the XSOAR server as defined in the xsoar_config.json manifest.
160
193
  The PATH argument expects the full or relative path to xsoar_config.json
@@ -169,7 +202,8 @@ def deploy(ctx: click.Context, environment: str, manifest: str, verbose: bool, y
169
202
  )
170
203
  if not should_continue:
171
204
  ctx.exit()
172
-
205
+ if not environment:
206
+ environment = ctx.obj["default_environment"]
173
207
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
174
208
  manifest_data = load_manifest(manifest)
175
209
  click.echo("Fetching installed packs...", err=True)
@@ -198,3 +232,4 @@ manifest.add_command(deploy)
198
232
  manifest.add_command(diff)
199
233
  manifest.add_command(update)
200
234
  manifest.add_command(validate)
235
+ manifest.add_command(generate)
@@ -15,13 +15,15 @@ def pack(ctx: click.Context) -> None:
15
15
  """Various content pack related commands."""
16
16
 
17
17
 
18
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
18
+ @click.option("--environment", default=None, help="Default environment set in config file.")
19
19
  @click.command()
20
20
  @click.argument("pack_id", type=str)
21
21
  @click.pass_context
22
22
  @load_config
23
- def delete(ctx: click.Context, environment: str, pack_id: str) -> None:
23
+ def delete(ctx: click.Context, environment: str | None, pack_id: str) -> None:
24
24
  """Deletes a content pack from the XSOAR server."""
25
+ if not environment:
26
+ environment = ctx.obj["default_environment"]
25
27
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
26
28
  if not xsoar_client.is_installed(pack_id=pack_id):
27
29
  click.echo(f"Pack ID {pack_id} is not installed. Cannot delete.")
@@ -30,12 +32,14 @@ def delete(ctx: click.Context, environment: str, pack_id: str) -> None:
30
32
  click.echo(f"Deleted pack {pack_id} from XSOAR {environment}")
31
33
 
32
34
 
33
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
35
+ @click.option("--environment", default=None, help="Default environment set in config file.")
34
36
  @click.command()
35
37
  @click.pass_context
36
38
  @load_config
37
- def get_outdated(ctx: click.Context, environment: str) -> None:
39
+ def get_outdated(ctx: click.Context, environment: str | None) -> None:
38
40
  """Prints out a list of outdated content packs."""
41
+ if not environment:
42
+ environment = ctx.obj["default_environment"]
39
43
  xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
40
44
  click.echo("Fetching outdated packs. This may take a little while...", err=True)
41
45
  outdated_packs = xsoar_client.get_outdated_packs()
@@ -19,12 +19,12 @@ def playbook(ctx: click.Context) -> None:
19
19
  """Download/attach/detach playbooks"""
20
20
 
21
21
 
22
- @click.option("--environment", default="dev", show_default=True, help="Environment as defined in config file")
22
+ @click.option("--environment", default=None, help="Default environment set in config file.")
23
23
  @click.command()
24
24
  @click.argument("name", type=str)
25
25
  @click.pass_context
26
26
  @load_config
27
- def download(ctx: click.Context, environment: str, name: str) -> None:
27
+ def download(ctx: click.Context, environment: str | None, name: str) -> None:
28
28
  """Download and reattach playbook.
29
29
 
30
30
  We try to detect output path to $(cwd)/Packs/<Pack ID>/Playbooks/<name>.yml
@@ -32,7 +32,8 @@ def download(ctx: click.Context, environment: str, name: str) -> None:
32
32
  then demisto-sdk format --assume-yes --no-validate --no-graph is done on the downloaded playbook before the item
33
33
  is re-attached in XSOAR.
34
34
  """
35
-
35
+ if not environment:
36
+ environment = ctx.obj["default_environment"]
36
37
  xsoar_client: Client = ctx.obj["server_envs"][environment]
37
38
  # Maybe we should search for the playbook before attempting download in
38
39
  # case user specifies a cutsom playbook and not a system playbook
@@ -346,7 +346,7 @@ def my_command(ctx: click.Context):
346
346
  # Access configuration
347
347
  config = ctx.obj
348
348
  # Access XSOAR clients
349
- dev_client = ctx.obj["server_envs"]["dev"]
349
+ dev_client = ctx.obj["server_envs"]["dev"]["xsoar_client"]
350
350
  ```
351
351
 
352
352
  ### 5. Logging
xsoar_cli/utilities.py CHANGED
@@ -8,6 +8,16 @@ import click
8
8
  from xsoar_client.xsoar_client import Client
9
9
 
10
10
 
11
+ def parse_string_to_dict(input_string: str | None, delimiter: str) -> dict:
12
+ if not input_string:
13
+ return {}
14
+ # Parse a string into a python dictionary
15
+ pairs = [pair.split("=", 1) for pair in input_string.split(delimiter)]
16
+ # Filter pairs that have exactly 2 parts (key and value) after splitting by "="
17
+ valid_pairs = [pair for pair in pairs if len(pair) == 2]
18
+ return {key.strip(): value.strip() for key, value in valid_pairs}
19
+
20
+
11
21
  def get_config_file_template_contents() -> dict:
12
22
  return {
13
23
  "default_environment": "dev",
@@ -67,7 +77,11 @@ def load_config(f: Callable) -> Callable:
67
77
  ctx.exit(1)
68
78
  config = get_config_file_contents(config_file_path)
69
79
  parse_config(config, ctx)
70
- if "environment" in ctx.params and ctx.params["environment"] not in ctx.obj["server_envs"]:
80
+ if (
81
+ "environment" in ctx.params
82
+ and ctx.params["environment"] not in ctx.obj["server_envs"]
83
+ and ctx.params["environment"] is not None
84
+ ):
71
85
  click.echo(f"Invalid environment: {ctx.params['environment']}")
72
86
  click.echo(f"Available environments as defined in config file are: {list(ctx.obj['server_envs'])}")
73
87
  ctx.exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xsoar-cli
3
- Version: 1.0.4
3
+ Version: 1.0.5
4
4
  Project-URL: Documentation, https://github.com/tlium/xsoar-cli#readme
5
5
  Project-URL: Issues, https://github.com/tlium/xsoar-cli/issues
6
6
  Project-URL: Source, https://github.com/tlium/xsoar-cli
@@ -9,10 +9,12 @@ License-Expression: MIT
9
9
  License-File: LICENSE.txt
10
10
  Classifier: Development Status :: 4 - Beta
11
11
  Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
12
14
  Classifier: Programming Language :: Python :: 3.12
13
15
  Classifier: Programming Language :: Python :: Implementation :: CPython
14
16
  Classifier: Programming Language :: Python :: Implementation :: PyPy
15
- Requires-Python: >=3.12
17
+ Requires-Python: <3.13,>=3.10
16
18
  Requires-Dist: click==8.1.8
17
19
  Requires-Dist: pyyaml>=6.0.2
18
20
  Requires-Dist: xsoar-client>=1.0.0
@@ -1,10 +1,10 @@
1
- xsoar_cli/__about__.py,sha256=ppSrh4dfP4K0nr9jdlBQ1YkT9cD5CyaRnZQz5wDhG94,127
1
+ xsoar_cli/__about__.py,sha256=WJ_NW-EdxC6N1rZ9OTTVUtKWWLaNJ0AvBoPxIYQkuYc,127
2
2
  xsoar_cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
3
3
  xsoar_cli/cli.py,sha256=iAlSeZe2iR6ciTVrJYLt-CDZk7b5I-hzHFXbYoXhupA,1342
4
- xsoar_cli/utilities.py,sha256=aW0lmPAf06YyGlq0ayQg0h2uCmvqgIHSuLdpCTJQN_0,5150
4
+ xsoar_cli/utilities.py,sha256=ZK0rW4jl1hSbphU_auuuBgwUSmDDP9kq3ZoAFp6D-3g,5697
5
5
  xsoar_cli/case/README.md,sha256=MTfgVeW3qJXRPNFo8CkZvulm2vwbN8sgiW86V-qXRFw,1342
6
6
  xsoar_cli/case/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- xsoar_cli/case/commands.py,sha256=UXXOrE3qmYF4z8mtKRkIP7onatib5x55fwprtbNxTBA,3575
7
+ xsoar_cli/case/commands.py,sha256=fdAqX_anYkyRKzzoUNZVYhkTJBqBieUXJX5QqpfEdbE,4255
8
8
  xsoar_cli/config/README.md,sha256=pcO858PDL9c0qtwj3_a6B8q2CGvcka3dwclVnwi2vlA,516
9
9
  xsoar_cli/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  xsoar_cli/config/commands.py,sha256=i6lWaR0LjAzMpNVPZyCsDPaT0GMVqTUXdau6Id0iOrs,4193
@@ -13,19 +13,19 @@ xsoar_cli/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  xsoar_cli/graph/commands.py,sha256=LKOpUu8r6KThJ5HdyjZlhpwLKRgMcEu7btBOQXwDkMs,1069
14
14
  xsoar_cli/manifest/README.md,sha256=0oiA6rZEAUQMOYM7VmtUBtW3PRo7-exfkjw5JLt_whU,9282
15
15
  xsoar_cli/manifest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- xsoar_cli/manifest/commands.py,sha256=6IU9k-UFCeZUnM9CHNqafaouiTOrK3OXtWxsr3LTCV4,8792
16
+ xsoar_cli/manifest/commands.py,sha256=nd7-xIJs9qda5iXfFvyfXUG6gctbW9yeUry5KWltisc,10127
17
17
  xsoar_cli/pack/README.md,sha256=CA7jAEphHxK0gh58rLRKL-u3wx29QgNAXojd_tGBXnY,46
18
18
  xsoar_cli/pack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- xsoar_cli/pack/commands.py,sha256=A1CYdzvdXNAy63rPVoBOAXddRzl8PRmuSCQOSDeRlRk,1931
19
+ xsoar_cli/pack/commands.py,sha256=1vGF8_mMemZt75qCBTau_M3dihSr79vc2vea8xr5h_Y,2063
20
20
  xsoar_cli/playbook/README.md,sha256=8y_YhvZtLP7KzYG83jiVBF-wBAEh8UTJcgmTOTynmbc,977
21
21
  xsoar_cli/playbook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- xsoar_cli/playbook/commands.py,sha256=mFmXJ3D8plvrUC9ylMlkrAa2T1yhydByEBhrBVbaZec,2729
23
- xsoar_cli/plugins/README.md,sha256=19AAhaYi2Rk6h95MkDGoh8n73KB-BcbaznQ0nfW2rpc,11220
22
+ xsoar_cli/playbook/commands.py,sha256=fZnL5L3pG2gKC4h6q6jmfOQFTa0Tpwnn4e8E5YhDbk0,2794
23
+ xsoar_cli/plugins/README.md,sha256=pxBZlEvWyhRhS4x79dPudYLJHctzuiVxLXBlQ8o2BPI,11236
24
24
  xsoar_cli/plugins/__init__.py,sha256=81IZsMbZsqrLdB6TjA9t6s3yS8FkuihliBFX4xZUpTo,1753
25
25
  xsoar_cli/plugins/commands.py,sha256=HC0sWu149uQG9Ztag4t2CNPKXTM4WJbEdLSvFMEjw80,10660
26
26
  xsoar_cli/plugins/manager.py,sha256=7RPk3lAYDifGMLOU-hFOqyPxTVk8ibBVzBqH7R8wy4g,13012
27
- xsoar_cli-1.0.4.dist-info/METADATA,sha256=cKIkFA52ep6NsbFDXtpcZLatvMtKs473AAAP2bfF-o0,9110
28
- xsoar_cli-1.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
- xsoar_cli-1.0.4.dist-info/entry_points.txt,sha256=s6Klu4QRekXsmZaBxMyFlE4Q-4_jIA9uijk4qIYUPvE,48
30
- xsoar_cli-1.0.4.dist-info/licenses/LICENSE.txt,sha256=l6xnqWKshqwwTXt6ayO6MX8Uvygq0YnkUuFTNnR3ba4,1097
31
- xsoar_cli-1.0.4.dist-info/RECORD,,
27
+ xsoar_cli-1.0.5.dist-info/METADATA,sha256=PQLPj12eaIU_U0WJWW07jmVl-5gQmIJLFjdvNihGPfQ,9218
28
+ xsoar_cli-1.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ xsoar_cli-1.0.5.dist-info/entry_points.txt,sha256=s6Klu4QRekXsmZaBxMyFlE4Q-4_jIA9uijk4qIYUPvE,48
30
+ xsoar_cli-1.0.5.dist-info/licenses/LICENSE.txt,sha256=l6xnqWKshqwwTXt6ayO6MX8Uvygq0YnkUuFTNnR3ba4,1097
31
+ xsoar_cli-1.0.5.dist-info/RECORD,,