xsoar-cli 1.0.3__tar.gz → 1.0.4__tar.gz
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-1.0.3 → xsoar_cli-1.0.4}/.github/workflows/release.yml +2 -31
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/PKG-INFO +1 -1
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/__about__.py +1 -1
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/case/commands.py +4 -4
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/config/commands.py +12 -2
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/manifest/commands.py +5 -5
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/pack/commands.py +2 -2
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/plugins/README.md +22 -22
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/utilities.py +27 -1
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/.github/workflows/pull-request-open.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/.gitignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/CONTRIBUTING.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/LICENSE.txt +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/examples/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/examples/advanced_plugin.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/pyproject.toml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/requirements.txt +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/requirements_dev.txt +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/case/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/case/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/cli.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/config/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/config/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/graph/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/graph/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/graph/commands.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/manifest/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/manifest/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/pack/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/pack/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/playbook/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/playbook/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/playbook/commands.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/plugins/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/plugins/commands.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/src/xsoar_cli/plugins/manager.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/__init__.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/conftest.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_base.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_case.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_config.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Download/playbook-empty.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.pack-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.secrets-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/Author_image.png +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/Playbooks/GenericPlaybook.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/pack_metadata.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/.pack-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/.secrets-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/Author_image.png +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/Scripts/GenericScript/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/pack_metadata.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/.pack-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/.secrets-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Author_image.png +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/test_data/basescript-dummy.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/pack_metadata.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/.pack-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/.secrets-ignore +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/Author_image.png +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/Layouts/layoutscontainer-GenericLayout.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/README.md +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_Layouts/pack_metadata.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/Not_applicable/Playbooks/Empty.yml +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/manifest_base.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/manifest_invalid.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/manifest_with_pack_not_on_server.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/server_base_response.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/server_base_response_missing_one_pack.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/server_base_response_with_updates.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/server_base_response_with_updates_and_one_extra.json +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_graph.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_manifest.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_pack.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_playbook.py +0 -0
- {xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_plugins.py +0 -0
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
name: release
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
- "[0-9]+.[0-9]+.[0-9]+"
|
|
7
|
-
- "[0-9]+.[0-9]+.[0-9]+a[0-9]+"
|
|
8
|
-
- "[0-9]+.[0-9]+.[0-9]+b[0-9]+"
|
|
9
|
-
- "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
10
6
|
|
|
11
7
|
env:
|
|
12
8
|
PACKAGE_NAME: "xsoar-cli"
|
|
@@ -117,28 +113,3 @@ jobs:
|
|
|
117
113
|
|
|
118
114
|
- name: Publish distribution to PyPI
|
|
119
115
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
120
|
-
|
|
121
|
-
github_release:
|
|
122
|
-
name: Create GitHub Release
|
|
123
|
-
needs: [setup_and_build, details]
|
|
124
|
-
runs-on: ubuntu-latest
|
|
125
|
-
permissions:
|
|
126
|
-
contents: write
|
|
127
|
-
steps:
|
|
128
|
-
- name: Checkout Code
|
|
129
|
-
uses: actions/checkout@v3
|
|
130
|
-
with:
|
|
131
|
-
fetch-depth: 0
|
|
132
|
-
|
|
133
|
-
- name: Download artifacts
|
|
134
|
-
uses: actions/download-artifact@v4
|
|
135
|
-
with:
|
|
136
|
-
name: dist
|
|
137
|
-
path: dist/
|
|
138
|
-
|
|
139
|
-
- name: Create GitHub Release
|
|
140
|
-
id: create_release
|
|
141
|
-
env:
|
|
142
|
-
GH_TOKEN: ${{ github.token }}
|
|
143
|
-
run: |
|
|
144
|
-
gh release create ${{ needs.details.outputs.tag_name }} dist/* --title ${{ needs.details.outputs.tag_name }} --generate-notes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xsoar-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
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
|
|
@@ -20,7 +20,7 @@ def case() -> None:
|
|
|
20
20
|
@click.pass_context
|
|
21
21
|
@load_config
|
|
22
22
|
def get(ctx: click.Context, casenumber: int, environment: str) -> None:
|
|
23
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
23
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
24
24
|
response = xsoar_client.get_case(casenumber)
|
|
25
25
|
if response["total"] == 0 and not response["data"]:
|
|
26
26
|
click.echo(f"Cannot find case ID {casenumber}")
|
|
@@ -40,7 +40,7 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
|
|
|
40
40
|
if not valid_envs:
|
|
41
41
|
click.echo(f"Error: cannot find environments {source} and/or {dest} in config")
|
|
42
42
|
ctx.exit(1)
|
|
43
|
-
xsoar_source_client: Client = ctx.obj["server_envs"][source]
|
|
43
|
+
xsoar_source_client: Client = ctx.obj["server_envs"][source]["xsoar_client"]
|
|
44
44
|
results = xsoar_source_client.get_case(casenumber)
|
|
45
45
|
data = results["data"][0]
|
|
46
46
|
# Dbot mirror info is irrelevant. This will be added again if applicable by XSOAR after ticket creation in dev.
|
|
@@ -57,7 +57,7 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
|
|
|
57
57
|
# Ensure that playbooks run immediately when the case is created
|
|
58
58
|
data["createInvestigation"] = True
|
|
59
59
|
|
|
60
|
-
xsoar_dest_client: Client = ctx.obj["server_envs"][dest]
|
|
60
|
+
xsoar_dest_client: Client = ctx.obj["server_envs"][dest]["xsoar_client"]
|
|
61
61
|
case_data = xsoar_dest_client.create_case(data=data)
|
|
62
62
|
click.echo(json.dumps(case_data, indent=4))
|
|
63
63
|
|
|
@@ -71,7 +71,7 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
|
|
|
71
71
|
@load_config
|
|
72
72
|
def create(ctx: click.Context, environment: str, casetype: str, name: str, details: str) -> None:
|
|
73
73
|
"""Creates a new case in XSOAR. If invalid case type is specified as a command option, XSOAR will default to using Unclassified."""
|
|
74
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
74
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
75
75
|
if not casetype:
|
|
76
76
|
casetype = ctx.obj["default_new_case_type"]
|
|
77
77
|
data = {
|
|
@@ -8,7 +8,13 @@ if TYPE_CHECKING:
|
|
|
8
8
|
|
|
9
9
|
import contextlib
|
|
10
10
|
|
|
11
|
-
from xsoar_cli.utilities import
|
|
11
|
+
from xsoar_cli.utilities import (
|
|
12
|
+
fail_if_no_artifacts_provider,
|
|
13
|
+
get_config_file_contents,
|
|
14
|
+
get_config_file_path,
|
|
15
|
+
get_config_file_template_contents,
|
|
16
|
+
load_config,
|
|
17
|
+
)
|
|
12
18
|
|
|
13
19
|
|
|
14
20
|
@click.group(help="Create/validate etc")
|
|
@@ -35,6 +41,7 @@ def show(ctx: click.Context, masked: bool) -> None:
|
|
|
35
41
|
@click.option("--only-test-environment", default=None, show_default=True, help="Environment as defined in config file")
|
|
36
42
|
@click.pass_context
|
|
37
43
|
@load_config
|
|
44
|
+
@fail_if_no_artifacts_provider
|
|
38
45
|
def validate(ctx: click.Context, only_test_environment: str) -> None:
|
|
39
46
|
"""Validates that the configuration file is JSON and tests connectivity for each XSOAR Client environment defined."""
|
|
40
47
|
return_code = 0
|
|
@@ -44,7 +51,7 @@ def validate(ctx: click.Context, only_test_environment: str) -> None:
|
|
|
44
51
|
# what the user specified in option
|
|
45
52
|
continue
|
|
46
53
|
click.echo(f'Testing "{server_env}" environment...', nl=False)
|
|
47
|
-
xsoar_client: Client = ctx.obj["server_envs"][server_env]
|
|
54
|
+
xsoar_client: Client = ctx.obj["server_envs"][server_env]["xsoar_client"]
|
|
48
55
|
try:
|
|
49
56
|
xsoar_client.test_connectivity()
|
|
50
57
|
except ConnectionError as ex:
|
|
@@ -53,6 +60,9 @@ def validate(ctx: click.Context, only_test_environment: str) -> None:
|
|
|
53
60
|
return_code = 1
|
|
54
61
|
continue
|
|
55
62
|
click.echo("OK")
|
|
63
|
+
if ctx.obj["default_environment"] not in ctx.obj["server_envs"]:
|
|
64
|
+
click.echo(f'Error: default environment "{ctx.obj["default_environment"]}" not found in server config.')
|
|
65
|
+
return_code = 1
|
|
56
66
|
ctx.exit(return_code)
|
|
57
67
|
|
|
58
68
|
|
|
@@ -46,7 +46,7 @@ def manifest() -> None:
|
|
|
46
46
|
@load_config
|
|
47
47
|
def update(ctx: click.Context, environment: str, manifest: str) -> None:
|
|
48
48
|
"""Update manifest on disk with latest available content pack versions."""
|
|
49
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
49
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
50
50
|
manifest_data = load_manifest(manifest)
|
|
51
51
|
click.echo("Fetching outdated packs from XSOAR server. This may take a minute...", nl=False)
|
|
52
52
|
results = xsoar_client.get_outdated_packs()
|
|
@@ -89,7 +89,7 @@ def update(ctx: click.Context, environment: str, manifest: str) -> None:
|
|
|
89
89
|
def validate(ctx: click.Context, environment: str, manifest: str) -> None:
|
|
90
90
|
"""Validate manifest JSON and all pack availability. Validates upstream pack availability by doing HTTP CONNECT.
|
|
91
91
|
Custom pack availability is implementation dependant."""
|
|
92
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
92
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
93
93
|
manifest_data = load_manifest(manifest)
|
|
94
94
|
click.echo("Manifest is valid JSON")
|
|
95
95
|
keys = ["custom_packs", "marketplace_packs"]
|
|
@@ -129,7 +129,7 @@ def validate(ctx: click.Context, environment: str, manifest: str) -> None:
|
|
|
129
129
|
def diff(ctx: click.Context, manifest: str, environment: str) -> None:
|
|
130
130
|
"""Prints out the differences (if any) between what is defined in the xsoar_config.json manifest and what is actually
|
|
131
131
|
installed on the XSOAR server."""
|
|
132
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
132
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
133
133
|
manifest_data = load_manifest(manifest)
|
|
134
134
|
installed_packs = xsoar_client.get_installed_packs()
|
|
135
135
|
all_good = True
|
|
@@ -170,7 +170,7 @@ def deploy(ctx: click.Context, environment: str, manifest: str, verbose: bool, y
|
|
|
170
170
|
if not should_continue:
|
|
171
171
|
ctx.exit()
|
|
172
172
|
|
|
173
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
173
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
174
174
|
manifest_data = load_manifest(manifest)
|
|
175
175
|
click.echo("Fetching installed packs...", err=True)
|
|
176
176
|
installed_packs = xsoar_client.get_installed_packs()
|
|
@@ -191,7 +191,7 @@ def deploy(ctx: click.Context, environment: str, manifest: str, verbose: bool, y
|
|
|
191
191
|
# Print message that install is skipped
|
|
192
192
|
|
|
193
193
|
if none_installed:
|
|
194
|
-
click.echo("No packs to install.
|
|
194
|
+
click.echo("No packs to install. All packs and versions in manifest is already installed on XSOAR server.")
|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
manifest.add_command(deploy)
|
|
@@ -22,7 +22,7 @@ def pack(ctx: click.Context) -> None:
|
|
|
22
22
|
@load_config
|
|
23
23
|
def delete(ctx: click.Context, environment: str, pack_id: str) -> None:
|
|
24
24
|
"""Deletes a content pack from the XSOAR server."""
|
|
25
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
25
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
26
26
|
if not xsoar_client.is_installed(pack_id=pack_id):
|
|
27
27
|
click.echo(f"Pack ID {pack_id} is not installed. Cannot delete.")
|
|
28
28
|
sys.exit(1)
|
|
@@ -36,7 +36,7 @@ def delete(ctx: click.Context, environment: str, pack_id: str) -> None:
|
|
|
36
36
|
@load_config
|
|
37
37
|
def get_outdated(ctx: click.Context, environment: str) -> None:
|
|
38
38
|
"""Prints out a list of outdated content packs."""
|
|
39
|
-
xsoar_client: Client = ctx.obj["server_envs"][environment]
|
|
39
|
+
xsoar_client: Client = ctx.obj["server_envs"][environment]["xsoar_client"]
|
|
40
40
|
click.echo("Fetching outdated packs. This may take a little while...", err=True)
|
|
41
41
|
outdated_packs = xsoar_client.get_outdated_packs()
|
|
42
42
|
if not outdated_packs:
|
|
@@ -40,20 +40,20 @@ class MyPlugin(XSOARPlugin):
|
|
|
40
40
|
@property
|
|
41
41
|
def name(self) -> str:
|
|
42
42
|
return "myplugin"
|
|
43
|
-
|
|
44
|
-
@property
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
45
|
def version(self) -> str:
|
|
46
46
|
return "1.0.0"
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
@property
|
|
49
49
|
def description(self) -> str:
|
|
50
50
|
return "My custom plugin"
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
def get_command(self) -> click.Command:
|
|
53
53
|
@click.command(help="My custom command")
|
|
54
54
|
def mycommand():
|
|
55
55
|
click.echo("Hello from my plugin!")
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
return mycommand
|
|
58
58
|
```
|
|
59
59
|
|
|
@@ -75,23 +75,23 @@ class MyCustomPlugin(XSOARPlugin):
|
|
|
75
75
|
@property
|
|
76
76
|
def name(self) -> str:
|
|
77
77
|
return "mycustom"
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
@property
|
|
80
80
|
def version(self) -> str:
|
|
81
81
|
return "1.0.0"
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
@property
|
|
84
84
|
def description(self) -> str:
|
|
85
85
|
return "A custom plugin with multiple commands"
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
def get_command(self) -> click.Command:
|
|
88
88
|
"""Return the main command group for this plugin."""
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
@click.group(help="My custom commands")
|
|
91
91
|
def mycustom():
|
|
92
92
|
"""Main command group for my custom plugin."""
|
|
93
93
|
pass
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
@click.command(help="Greet someone")
|
|
96
96
|
@click.option("--name", default="World", help="Name to greet")
|
|
97
97
|
@click.option("--times", default=1, help="Number of times to greet")
|
|
@@ -99,7 +99,7 @@ class MyCustomPlugin(XSOARPlugin):
|
|
|
99
99
|
"""Greet someone multiple times."""
|
|
100
100
|
for i in range(times):
|
|
101
101
|
click.echo(f"Hello, {name}!")
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
@click.command(help="Show current status")
|
|
104
104
|
@click.option("--verbose", "-v", is_flag=True, help="Verbose output")
|
|
105
105
|
def status(verbose: bool):
|
|
@@ -108,7 +108,7 @@ class MyCustomPlugin(XSOARPlugin):
|
|
|
108
108
|
if verbose:
|
|
109
109
|
click.echo(f"Description: {self.description}")
|
|
110
110
|
click.echo("Status: Active")
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
@click.command(help="Process a file")
|
|
113
113
|
@click.argument("filename", type=click.Path(exists=True))
|
|
114
114
|
@click.option("--output", "-o", help="Output file")
|
|
@@ -118,18 +118,18 @@ class MyCustomPlugin(XSOARPlugin):
|
|
|
118
118
|
if output:
|
|
119
119
|
click.echo(f"Output will be saved to: {output}")
|
|
120
120
|
# Your processing logic here
|
|
121
|
-
|
|
121
|
+
|
|
122
122
|
# Add commands to the group
|
|
123
123
|
mycustom.add_command(greet)
|
|
124
124
|
mycustom.add_command(status)
|
|
125
125
|
mycustom.add_command(process)
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
return mycustom
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
def initialize(self):
|
|
130
130
|
"""Initialize the plugin."""
|
|
131
131
|
click.echo("My custom plugin initialized!")
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
def cleanup(self):
|
|
134
134
|
"""Cleanup when the plugin is unloaded."""
|
|
135
135
|
pass
|
|
@@ -176,7 +176,7 @@ from xsoar_cli.utilities import load_config
|
|
|
176
176
|
@load_config
|
|
177
177
|
def my_command(ctx: click.Context):
|
|
178
178
|
# Access XSOAR client
|
|
179
|
-
xsoar_client = ctx.obj["server_envs"]["dev"]
|
|
179
|
+
xsoar_client = ctx.obj["server_envs"]["dev"]["xsoar_client"]
|
|
180
180
|
# Use the client...
|
|
181
181
|
```
|
|
182
182
|
|
|
@@ -284,11 +284,11 @@ class MyPlugin(XSOARPlugin):
|
|
|
284
284
|
@click.group()
|
|
285
285
|
def myplugin():
|
|
286
286
|
pass
|
|
287
|
-
|
|
287
|
+
|
|
288
288
|
@click.command()
|
|
289
289
|
def case(): # ✅ Namespaced as 'myplugin case'
|
|
290
290
|
click.echo("My case command")
|
|
291
|
-
|
|
291
|
+
|
|
292
292
|
myplugin.add_command(case)
|
|
293
293
|
return myplugin
|
|
294
294
|
```
|
|
@@ -297,7 +297,7 @@ class MyPlugin(XSOARPlugin):
|
|
|
297
297
|
|
|
298
298
|
These command names are reserved by the core CLI:
|
|
299
299
|
- `case` - Case/incident management
|
|
300
|
-
- `config` - Configuration management
|
|
300
|
+
- `config` - Configuration management
|
|
301
301
|
- `graph` - Dependency graphs
|
|
302
302
|
- `manifest` - Manifest operations
|
|
303
303
|
- `pack` - Content pack operations
|
|
@@ -330,7 +330,7 @@ def get_command(self) -> click.Command:
|
|
|
330
330
|
except Exception as e:
|
|
331
331
|
click.echo(f"Error: {e}", err=True)
|
|
332
332
|
raise click.Abort()
|
|
333
|
-
|
|
333
|
+
|
|
334
334
|
return mycommand
|
|
335
335
|
```
|
|
336
336
|
|
|
@@ -430,4 +430,4 @@ except ImportError:
|
|
|
430
430
|
|
|
431
431
|
You can share plugins by simply sharing the Python file. Users can place it in their plugins directory and it will be automatically discovered.
|
|
432
432
|
|
|
433
|
-
For more complex plugins, consider packaging them as proper Python packages that install the plugin file automatically.
|
|
433
|
+
For more complex plugins, consider packaging them as proper Python packages that install the plugin file automatically.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import contextlib
|
|
1
2
|
import json
|
|
2
3
|
from collections.abc import Callable
|
|
3
4
|
from functools import update_wrapper
|
|
@@ -75,6 +76,29 @@ def load_config(f: Callable) -> Callable:
|
|
|
75
76
|
return update_wrapper(wrapper, f)
|
|
76
77
|
|
|
77
78
|
|
|
79
|
+
def fail_if_no_artifacts_provider(f: Callable) -> Callable:
|
|
80
|
+
"""
|
|
81
|
+
This function is only to be used as a decorator for various xsoar-cli subcommands, and only AFTER the load_config decorator has been called.
|
|
82
|
+
The intention is to fail gracefully if any subcommand is executed which requires an artifacts provider."
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
@click.pass_context
|
|
86
|
+
def wrapper(ctx: click.Context, *args, **kwargs) -> Callable: # noqa: ANN002, ANN003
|
|
87
|
+
if "environment" in ctx.params: # noqa: SIM108
|
|
88
|
+
key = ctx.params["environment"]
|
|
89
|
+
else:
|
|
90
|
+
key = ctx.obj["default_environment"]
|
|
91
|
+
|
|
92
|
+
with contextlib.suppress(KeyError):
|
|
93
|
+
location = ctx.obj["server_envs"][key].get("artifacts_location", None)
|
|
94
|
+
if not location:
|
|
95
|
+
click.echo("Command requires artifacts repository, but no artifacts_location defined in config.")
|
|
96
|
+
ctx.exit(1)
|
|
97
|
+
return ctx.invoke(f, *args, **kwargs)
|
|
98
|
+
|
|
99
|
+
return update_wrapper(wrapper, f)
|
|
100
|
+
|
|
101
|
+
|
|
78
102
|
def parse_config(config: dict, ctx: click.Context) -> None:
|
|
79
103
|
# Set the two XSOAR client objects in Click Context for use in later functions
|
|
80
104
|
ctx.obj = {}
|
|
@@ -83,7 +107,8 @@ def parse_config(config: dict, ctx: click.Context) -> None:
|
|
|
83
107
|
ctx.obj["default_new_case_type"] = config["default_new_case_type"]
|
|
84
108
|
ctx.obj["server_envs"] = {}
|
|
85
109
|
for key in config["server_config"]:
|
|
86
|
-
ctx.obj["server_envs"][key] =
|
|
110
|
+
ctx.obj["server_envs"][key] = {}
|
|
111
|
+
ctx.obj["server_envs"][key]["xsoar_client"] = Client(
|
|
87
112
|
api_token=config["server_config"][key]["api_token"],
|
|
88
113
|
server_url=config["server_config"][key]["base_url"],
|
|
89
114
|
verify_ssl=config["server_config"][key]["verify_ssl"],
|
|
@@ -93,3 +118,4 @@ def parse_config(config: dict, ctx: click.Context) -> None:
|
|
|
93
118
|
artifacts_location=config["server_config"][key].get("artifacts_location", None),
|
|
94
119
|
s3_bucket_name=config["server_config"][key].get("s3_bucket_name", None),
|
|
95
120
|
)
|
|
121
|
+
ctx.obj["server_envs"][key]["artifacts_location"] = config["server_config"][key].get("artifacts_location", None)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.pack-ignore
RENAMED
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/.secrets-ignore
RENAMED
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/Author_image.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonPlaybooks/pack_metadata.json
RENAMED
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/.secrets-ignore
RENAMED
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/Author_image.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_CommonScripts/pack_metadata.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md
RENAMED
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py
RENAMED
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md
RENAMED
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py
RENAMED
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/Packs/Not_applicable/Playbooks/Empty.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xsoar_cli-1.0.3 → xsoar_cli-1.0.4}/tests/test_data/server_base_response_missing_one_pack.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|