xsoar-cli 2.1.0__tar.gz → 2.2.0__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.
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/CHANGELOG.md +37 -1
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/CLAUDE.md +1 -3
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/CONTRIBUTING.md +5 -30
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/PKG-INFO +2 -1
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/_version.py +2 -2
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/pyproject.toml +1 -1
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/cli.py +23 -7
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/commands.py +14 -7
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/commands.py +2 -1
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/README.md +18 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/commands.py +26 -6
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/commands.py +9 -9
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/commands.py +4 -3
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/commands.py +8 -8
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/README.md +6 -7
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/commands.py +25 -11
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/commands.py +4 -4
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/plugins/README.md +13 -2
- xsoar_cli-2.2.0/src/xsoar_cli/commands/plugins/commands.py +257 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/commands.py +8 -8
- xsoar_cli-2.2.0/src/xsoar_cli/plugins/README.md +45 -0
- xsoar_cli-2.2.0/src/xsoar_cli/plugins/__init__.py +48 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/plugins/manager.py +59 -73
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/validators.py +19 -26
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/azure.py +4 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/s3.py +3 -3
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/content.py +3 -2
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/conftest.py +48 -14
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_config.py +39 -0
- xsoar_cli-2.2.0/tests/cli/test_plugins.py +244 -0
- xsoar_cli-2.2.0/tests/unit/test_plugin_manager.py +319 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_validators.py +4 -4
- xsoar_cli-2.1.0/src/xsoar_cli/commands/plugins/commands.py +0 -184
- xsoar_cli-2.1.0/src/xsoar_cli/plugins/README.md +0 -53
- xsoar_cli-2.1.0/src/xsoar_cli/plugins/__init__.py +0 -62
- xsoar_cli-2.1.0/tests/cli/test_plugins.py +0 -104
- xsoar_cli-2.1.0/tests/unit/test_plugin_manager.py +0 -213
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/.github/workflows/main.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/.github/workflows/pull-request-open.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/.github/workflows/release.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/.github/workflows/update-changelog.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/.gitignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/LICENSE.txt +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/case/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/completions/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/config/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/content/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/graph/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/integration/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/manifest/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/pack/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/plugins/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/commands/rbac/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/configuration.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/connection.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/error_handling/http.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/log.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/config_file.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/content.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/download_content_handlers.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/manifest.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/utilities/version_check.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/artifact_providers/base.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/cases.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/client.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/constants.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/integrations.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/packs.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/src/xsoar_cli/xsoar_client/rbac.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_base.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_case.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_completions.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_content.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_graph.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_manifest.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/cli/test_pack.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/conftest.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/cases/create.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/cases/get.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/content/automation_search.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/content/playbook_search.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/content/user_commands.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/integrations/instances.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_base.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_invalid.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/manifest_with_pack_not_on_server.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_missing_one_pack.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_with_updates.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/manifest/server_base_response_with_updates_and_one_extra.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/packs/installed.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/packs/installed_expired.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/rbac/roles.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/rbac/user_groups.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/fixtures/rbac/users.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Download/playbook-empty.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.pack-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.secrets-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Author_image.png +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Playbooks/GenericPlaybook.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/pack_metadata.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.pack-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.secrets-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Author_image.png +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_CommonScripts/pack_metadata.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/.pack-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/.secrets-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Author_image.png +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/test_data/basescript-dummy.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_EDR/pack_metadata.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/.pack-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/.secrets-ignore +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/Author_image.png +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/Layouts/layoutscontainer-GenericLayout.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/README.md +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/MyOrg_Layouts/pack_metadata.json +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/mock_content/Packs/Not_applicable/Playbooks/Empty.yml +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/__init__.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/conftest.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_artifact_azure.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_artifact_base.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_artifact_s3.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_cases.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_client.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_config_file.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_content_domain.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_content_filters.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_content_handlers.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_error_handling.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_integrations.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_main.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_manifest_utils.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_packs.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_rbac.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/tests/unit/test_version_check.py +0 -0
- {xsoar_cli-2.1.0 → xsoar_cli-2.2.0}/uv.lock +0 -0
|
@@ -8,6 +8,38 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- `config set-version-check` command to enable or disable the version update check on CLI startup. Accepts `--enable` or `--disable`.
|
|
12
|
+
- `plugins init` command to create the plugins directory and generate an example plugin.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- **Breaking:** Plugins must explicitly import `XSOARPlugin` (`from xsoar_cli.plugins import XSOARPlugin`). The base class is no longer injected automatically and so old plugins require modification. See the [plugin README](src/xsoar_cli/plugins/README.md) for details.
|
|
17
|
+
- Plugin commands (`list`, `info`, `validate`) now report a clear error when the plugins directory has not been initialized.
|
|
18
|
+
- Plugin registration failures no longer prevent remaining plugins from loading.
|
|
19
|
+
- `content get-detached --type` is now required. The `all` choice has been removed; specify `scripts` or `playbooks` explicitly.
|
|
20
|
+
- `integration dump`, `rbac getroles`, `rbac getusers`, and `rbac getusergroups` no longer emit a trailing blank line after JSON output.
|
|
21
|
+
- `config show` now uses `click.echo()` instead of `print()`, improving behavior when piping output to other tools.
|
|
22
|
+
|
|
23
|
+
### Removed
|
|
24
|
+
|
|
25
|
+
- The plugins directory is no longer automatically created on CLI startup. Run `xsoar-cli plugins init` to create it explicitly.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- `content get-detached` no longer fails when invoked without `--type` due to a stale default value that referenced the removed `all` choice.
|
|
30
|
+
- Content bundle download (`get_content_bundle`) now raises on HTTP errors instead of silently proceeding and failing with a confusing `tarfile` error.
|
|
31
|
+
|
|
32
|
+
## [2.1.1] - 2026-04-08
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- `manifest generate` now uses an `--output-dir` option (default: current directory) instead of a positional path argument. The output file is always named `xsoar_config.json`. Prompts for confirmation if the file already exists.
|
|
37
|
+
- `manifest update`, `manifest validate`, `manifest diff`, and `manifest deploy` now support file path tab completion for the manifest argument.
|
|
38
|
+
|
|
39
|
+
## [2.1.0] - 2026-04-08
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
11
43
|
- `completions install` command to generate and install shell completion scripts for Bash, Zsh (including Oh My Zsh), and Fish. Auto-detects the current shell from `$SHELL`, overridable with `--shell`.
|
|
12
44
|
- `completions uninstall` command to remove previously installed completion scripts.
|
|
13
45
|
- Shell completion no longer triggers the version update check or logging setup, which previously leaked output into completion results.
|
|
@@ -27,6 +59,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
27
59
|
### Added
|
|
28
60
|
|
|
29
61
|
- `content download` subcommand for downloading individual content items by name. Supports playbooks and layouts (`xsoar-cli content download --type playbook|layout <name>`).
|
|
62
|
+
- `content download --output` option to specify the content repository root directory. Useful when running xsoar-cli from outside the content repository.
|
|
63
|
+
- `content download` automatically runs `demisto-sdk format` on downloaded files to ensure they conform to the content repository standard.
|
|
64
|
+
- `content download` re-attaches downloaded content items to their pack after writing, so they no longer appear as detached in XSOAR.
|
|
65
|
+
- `content download` resolves the content item's pack ID and writes to the correct `Packs/<pack_id>/` directory. Prompts for fallback to the current working directory if the pack directory does not exist.
|
|
30
66
|
|
|
31
67
|
## [2.0.0] - 2026-04-07
|
|
32
68
|
|
|
@@ -72,4 +108,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
72
108
|
|
|
73
109
|
### Removed
|
|
74
110
|
|
|
75
|
-
- `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
|
|
111
|
+
- `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
|
|
@@ -64,6 +64,7 @@ src/xsoar_cli/ # Main package (src layout)
|
|
|
64
64
|
azure.py # AzureArtifactProvider (Azure Blob Storage)
|
|
65
65
|
commands/ # CLI command groups
|
|
66
66
|
case/ # Case operations command group
|
|
67
|
+
completions/ # Shell autocompletion command group
|
|
67
68
|
config/ # Config management command group
|
|
68
69
|
content/ # Content download/list command group
|
|
69
70
|
graph/ # Dependency graph command group
|
|
@@ -124,9 +125,6 @@ Always use `--no-pager` when running git commands (e.g. `git --no-pager log`, `g
|
|
|
124
125
|
```sh
|
|
125
126
|
# Install dependencies
|
|
126
127
|
uv sync
|
|
127
|
-
uv pip install -r requirements.txt
|
|
128
|
-
uv pip install -r requirements_dev.txt
|
|
129
|
-
uv pip install -e .
|
|
130
128
|
|
|
131
129
|
# Run all tests
|
|
132
130
|
uv run pytest
|
|
@@ -44,40 +44,16 @@ For other platforms and installation options, see the [uv installation docs](htt
|
|
|
44
44
|
|
|
45
45
|
### 3. Set Up Development Environment
|
|
46
46
|
|
|
47
|
-
**Recommended: uv**
|
|
48
|
-
|
|
49
|
-
You may find that you will need to make modifications in [xsoar-client](https://github.com/tlium/xsoar-client) and/or [xsoar-dependency-graph](https://github.com/tlium/xsoar-dependency-graph) in order
|
|
50
|
-
to fix bugs or add new features to `xsoar-cli`. If you need to work on `xsoar-client` or `xsoar-dependency-graph`, install them in editable mode from your local Git clones:
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
uv pip install -e /path/to/your/xsoar-client
|
|
54
|
-
uv pip install -e /path/to/your/xsoar-dependency-graph
|
|
55
|
-
```
|
|
56
|
-
|
|
57
47
|
```bash
|
|
58
48
|
# Install dependencies and xsoar-cli in editable mode
|
|
59
49
|
uv sync
|
|
60
50
|
uv pip install -e .
|
|
61
51
|
```
|
|
62
|
-
**Alternative: pip/venv**
|
|
63
52
|
|
|
64
|
-
|
|
65
|
-
# Create and activate a virtual environment
|
|
66
|
-
python -m venv venv
|
|
67
|
-
source venv/bin/activate
|
|
68
|
-
|
|
69
|
-
# Install development dependencies
|
|
70
|
-
pip install -r requirements_dev.txt
|
|
71
|
-
|
|
72
|
-
# Install xsoar-cli in editable mode
|
|
73
|
-
pip install -e .
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
If you need to work on the supporting libraries, install them in editable mode as well:
|
|
53
|
+
You may need to make modifications in [xsoar-dependency-graph](https://github.com/tlium/xsoar-dependency-graph) to fix bugs or add new features to `xsoar-cli`. If so, install it in editable mode from your local Git clone:
|
|
77
54
|
|
|
78
55
|
```bash
|
|
79
|
-
pip install -e /path/to/your/xsoar-
|
|
80
|
-
pip install -e /path/to/your/xsoar-dependency-graph
|
|
56
|
+
uv pip install -e /path/to/your/xsoar-dependency-graph
|
|
81
57
|
```
|
|
82
58
|
|
|
83
59
|
## Development Workflow
|
|
@@ -115,16 +91,15 @@ pip install -e /path/to/your/xsoar-dependency-graph
|
|
|
115
91
|
|
|
116
92
|
#### Lazy imports
|
|
117
93
|
|
|
118
|
-
Heavy third-party packages like `
|
|
94
|
+
Heavy third-party packages like `xsoar_dependency_graph` and `demisto_client` pull in large dependency trees (boto3, azure-storage-blob, matplotlib, networkx, etc.) that are expensive to load. To keep everyday invocations like `--help` and `--version` fast, these imports are placed inside the functions that need them rather than at the top of the file. Each lazy import is marked with the comment `# Lazy import for performance reasons`.
|
|
119
95
|
|
|
120
|
-
Type hints for the deferred types still appear in function signatures. To
|
|
96
|
+
Type hints for the deferred types still appear in function signatures. To keep them clean, use a `TYPE_CHECKING` block at the top of the module:
|
|
121
97
|
|
|
122
98
|
```python
|
|
123
|
-
from __future__ import annotations
|
|
124
99
|
from typing import TYPE_CHECKING
|
|
125
100
|
|
|
126
101
|
if TYPE_CHECKING:
|
|
127
|
-
from xsoar_client.
|
|
102
|
+
from xsoar_cli.xsoar_client.client import Client
|
|
128
103
|
```
|
|
129
104
|
|
|
130
105
|
See `configuration.py` for a complete example.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xsoar-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: A command-line interface for managing Palo Alto Networks XSOAR (Cortex XSOAR)
|
|
4
5
|
Project-URL: Documentation, https://github.com/tlium/xsoar-cli#readme
|
|
5
6
|
Project-URL: Issues, https://github.com/tlium/xsoar-cli/issues
|
|
6
7
|
Project-URL: Source, https://github.com/tlium/xsoar-cli
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2.
|
|
22
|
-
__version_tuple__ = version_tuple = (2,
|
|
21
|
+
__version__ = version = '2.2.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 2, 0)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xsoar-cli"
|
|
7
7
|
dynamic = ["version"]
|
|
8
|
-
description = ''
|
|
8
|
+
description = 'A command-line interface for managing Palo Alto Networks XSOAR (Cortex XSOAR)'
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
license = "MIT"
|
|
@@ -83,13 +83,29 @@ def _load_plugins() -> tuple[list[str], PluginManager]:
|
|
|
83
83
|
"""Captures core command names, then loads and registers plugins. Returns both."""
|
|
84
84
|
core_commands = list(cli.commands.keys())
|
|
85
85
|
manager = PluginManager()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
|
|
87
|
+
if not manager.plugins_dir_exists:
|
|
88
|
+
logging.getLogger(__name__).debug("Plugins directory not found, skipping plugin loading")
|
|
89
|
+
return core_commands, manager
|
|
90
|
+
|
|
91
|
+
manager.load_all_plugins(ignore_errors=True)
|
|
92
|
+
|
|
93
|
+
# Report load failures on stderr. These warnings run at module level before
|
|
94
|
+
# logging is configured, so logger.warning would be invisible. Plugin load
|
|
95
|
+
# failures are important enough to surface unconditionally.
|
|
96
|
+
load_failures = set(manager.get_failed_plugins().keys())
|
|
97
|
+
for plugin_name, error in manager.get_failed_plugins().items():
|
|
98
|
+
click.echo(f"Warning: plugin '{plugin_name}' failed to load: {error}", err=True)
|
|
99
|
+
|
|
100
|
+
manager.register_plugin_commands(cli)
|
|
101
|
+
|
|
102
|
+
# Registration failures are recorded in failed_plugins by the manager
|
|
103
|
+
# (skip-and-record pattern). Report only the new ones added during registration.
|
|
104
|
+
for plugin_name, error in manager.get_failed_plugins().items():
|
|
105
|
+
if plugin_name in load_failures:
|
|
106
|
+
continue # Already reported above
|
|
107
|
+
click.echo(f"Warning: plugin '{plugin_name}' failed to register: {error}", err=True)
|
|
108
|
+
|
|
93
109
|
return core_commands, manager
|
|
94
110
|
|
|
95
111
|
|
|
@@ -8,7 +8,10 @@ from requests.exceptions import HTTPError
|
|
|
8
8
|
from xsoar_cli.error_handling.connection import ConnectionErrorHandler
|
|
9
9
|
from xsoar_cli.error_handling.http import HTTPErrorHandler
|
|
10
10
|
from xsoar_cli.utilities.config_file import get_xsoar_config, load_config
|
|
11
|
-
from xsoar_cli.utilities.validators import validate_environments
|
|
11
|
+
from xsoar_cli.utilities.validators import validate_environments, validate_xsoar_connectivity
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from xsoar_cli.xsoar_client.client import Client
|
|
12
15
|
|
|
13
16
|
logger = logging.getLogger(__name__)
|
|
14
17
|
|
|
@@ -22,12 +25,9 @@ def parse_string_to_dict(input_string: str | None, delimiter: str) -> dict:
|
|
|
22
25
|
return {key.strip(): value.strip() for key, value in valid_pairs}
|
|
23
26
|
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
from xsoar_cli.xsoar_client.client import Client
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@click.group(help="Create, retrieve, and clone cases")
|
|
28
|
+
@click.group()
|
|
30
29
|
def case() -> None:
|
|
30
|
+
"""Create, retrieve, and clone cases"""
|
|
31
31
|
pass
|
|
32
32
|
|
|
33
33
|
|
|
@@ -36,6 +36,7 @@ def case() -> None:
|
|
|
36
36
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
37
37
|
@click.pass_context
|
|
38
38
|
@load_config
|
|
39
|
+
@validate_xsoar_connectivity
|
|
39
40
|
def get(ctx: click.Context, casenumber: int, environment: str | None) -> None:
|
|
40
41
|
"""Retrieve and display a single case.
|
|
41
42
|
|
|
@@ -82,7 +83,12 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
|
|
|
82
83
|
click.echo(f"Error: cannot find environments {source} and/or {dest} in config")
|
|
83
84
|
ctx.exit(1)
|
|
84
85
|
|
|
85
|
-
# Test connectivity to both environments before proceeding
|
|
86
|
+
# Test connectivity to both environments before proceeding. This is the only function that does
|
|
87
|
+
# explicit connectivity testing and error handling due to the fact that it is the only function
|
|
88
|
+
# that operates on multiple environments. If later a new command or sub-command is added to
|
|
89
|
+
# xsoar-cli that operates on multiple environments, then a new decorator should be created to
|
|
90
|
+
# handle connectivity testing for multiple environments (@validate_xsoar_connectivity only tests
|
|
91
|
+
# a single environment)
|
|
86
92
|
config = get_xsoar_config(ctx)
|
|
87
93
|
for env_name in (source, dest):
|
|
88
94
|
logger.debug("Testing XSOAR connectivity for environment '%s'", env_name)
|
|
@@ -159,6 +165,7 @@ def clone(ctx: click.Context, casenumber: int, source: str, dest: str) -> None:
|
|
|
159
165
|
@click.argument("name", type=str, default="Test case created from xsoar-cli")
|
|
160
166
|
@click.pass_context
|
|
161
167
|
@load_config
|
|
168
|
+
@validate_xsoar_connectivity
|
|
162
169
|
def create( # noqa: PLR0913
|
|
163
170
|
ctx: click.Context,
|
|
164
171
|
environment: str | None,
|
|
@@ -73,8 +73,9 @@ def _resolve_shell(shell_name: str | None) -> str:
|
|
|
73
73
|
return detected
|
|
74
74
|
|
|
75
75
|
|
|
76
|
-
@click.group(
|
|
76
|
+
@click.group()
|
|
77
77
|
def completions() -> None:
|
|
78
|
+
"""Install and manage shell completion for xsoar-cli"""
|
|
78
79
|
pass
|
|
79
80
|
|
|
80
81
|
|
|
@@ -101,3 +101,21 @@ Set the Azure Blob Storage SAS token for an environment in the configuration fil
|
|
|
101
101
|
xsoar-cli config set-azure-token my-sas-token
|
|
102
102
|
xsoar-cli config set-azure-token --environment prod my-sas-token
|
|
103
103
|
```
|
|
104
|
+
|
|
105
|
+
## Set Version Check
|
|
106
|
+
|
|
107
|
+
Enable or disable the version update check on CLI startup. When enabled, the CLI checks PyPI for newer versions and prints a notice to stderr.
|
|
108
|
+
|
|
109
|
+
**Syntax:** `xsoar-cli config set-version-check [OPTIONS]`
|
|
110
|
+
|
|
111
|
+
**Options:**
|
|
112
|
+
- `--enable` - Enable the version update check
|
|
113
|
+
- `--disable` - Disable the version update check
|
|
114
|
+
|
|
115
|
+
One of `--enable` or `--disable` must be provided.
|
|
116
|
+
|
|
117
|
+
**Examples:**
|
|
118
|
+
```
|
|
119
|
+
xsoar-cli config set-version-check --enable
|
|
120
|
+
xsoar-cli config set-version-check --disable
|
|
121
|
+
```
|
|
@@ -5,9 +5,6 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
|
|
6
6
|
import click
|
|
7
7
|
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
from xsoar_cli.xsoar_client.client import Client
|
|
10
|
-
|
|
11
8
|
from xsoar_cli.utilities.config_file import (
|
|
12
9
|
get_config_file_contents,
|
|
13
10
|
get_config_file_path,
|
|
@@ -15,6 +12,9 @@ from xsoar_cli.utilities.config_file import (
|
|
|
15
12
|
load_config,
|
|
16
13
|
)
|
|
17
14
|
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from xsoar_cli.xsoar_client.client import Client
|
|
17
|
+
|
|
18
18
|
logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
20
20
|
|
|
@@ -47,8 +47,9 @@ def get_config_file_template_contents() -> dict:
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
@click.group(
|
|
50
|
+
@click.group()
|
|
51
51
|
def config() -> None:
|
|
52
|
+
"""Create, validate, and manage CLI configuration"""
|
|
52
53
|
pass
|
|
53
54
|
|
|
54
55
|
|
|
@@ -67,8 +68,7 @@ def show(ctx: click.Context, masked: bool) -> None:
|
|
|
67
68
|
if "azure_storage_access_token" in config["server_config"][key]:
|
|
68
69
|
config["server_config"][key]["azure_storage_access_token"] = "*****" # noqa: S105
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
ctx.exit()
|
|
71
|
+
click.echo(json.dumps(config, indent=4))
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
@click.command()
|
|
@@ -203,8 +203,28 @@ def set_azure_token(ctx: click.Context, environment: str, sastoken: str) -> None
|
|
|
203
203
|
logger.info("Azure SAS token updated for environment '%s'", environment)
|
|
204
204
|
|
|
205
205
|
|
|
206
|
+
@click.command()
|
|
207
|
+
@click.option("--enable", "action", flag_value="enable", help="Enable the version update check on CLI startup.")
|
|
208
|
+
@click.option("--disable", "action", flag_value="disable", help="Disable the version update check on CLI startup.")
|
|
209
|
+
@click.pass_context
|
|
210
|
+
@load_config
|
|
211
|
+
def set_version_check(ctx: click.Context, action: str | None) -> None: # noqa: ARG001
|
|
212
|
+
"""Enable or disable the version update check on CLI startup."""
|
|
213
|
+
if action is None:
|
|
214
|
+
raise click.UsageError("Specify either --enable or --disable.")
|
|
215
|
+
config_file = get_config_file_path()
|
|
216
|
+
config_data = json.loads(config_file.read_text())
|
|
217
|
+
# skip_version_check is the inverse: enabling the check means skip=False.
|
|
218
|
+
config_data["skip_version_check"] = action == "disable"
|
|
219
|
+
config_file.write_text(json.dumps(config_data, indent=4))
|
|
220
|
+
state = "enabled" if action == "enable" else "disabled"
|
|
221
|
+
logger.info("Version check %s", state)
|
|
222
|
+
click.echo(f"Version check {state}.")
|
|
223
|
+
|
|
224
|
+
|
|
206
225
|
config.add_command(create)
|
|
207
226
|
config.add_command(validate)
|
|
208
227
|
config.add_command(show)
|
|
209
228
|
config.add_command(set_credentials)
|
|
210
229
|
config.add_command(set_azure_token)
|
|
230
|
+
config.add_command(set_version_check)
|
|
@@ -19,7 +19,8 @@ logger = logging.getLogger(__name__)
|
|
|
19
19
|
|
|
20
20
|
@click.group()
|
|
21
21
|
def content() -> None:
|
|
22
|
-
"""Inspect and manage content items
|
|
22
|
+
"""Inspect and manage content items"""
|
|
23
|
+
pass
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
@click.command()
|
|
@@ -27,21 +28,20 @@ def content() -> None:
|
|
|
27
28
|
@click.option(
|
|
28
29
|
"--type",
|
|
29
30
|
"content_type",
|
|
30
|
-
type=click.Choice(["scripts", "playbooks"
|
|
31
|
-
|
|
32
|
-
show_default=True,
|
|
31
|
+
type=click.Choice(["scripts", "playbooks"], case_sensitive=False),
|
|
32
|
+
required=True,
|
|
33
33
|
help="Type of content items to retrieve.",
|
|
34
34
|
)
|
|
35
35
|
@click.pass_context
|
|
36
36
|
@load_config
|
|
37
|
-
@validate_xsoar_connectivity
|
|
37
|
+
@validate_xsoar_connectivity
|
|
38
38
|
def get_detached(ctx: click.Context, environment: str | None, content_type: str) -> None:
|
|
39
39
|
"""List detached content items."""
|
|
40
40
|
config = get_xsoar_config(ctx)
|
|
41
41
|
xsoar_client: Client = config.get_client(environment)
|
|
42
42
|
response = xsoar_client.content.get_detached(content_type)
|
|
43
|
-
|
|
44
|
-
click.echo(
|
|
43
|
+
data = json.loads(response)
|
|
44
|
+
click.echo(json.dumps(data, indent=4))
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
# We name the command in the decorator here to avoid shadowing the builtin list.
|
|
@@ -59,7 +59,7 @@ def get_detached(ctx: click.Context, environment: str | None, content_type: str)
|
|
|
59
59
|
@click.option("--verbose", is_flag=True, default=False, help="Output the full unfiltered response.")
|
|
60
60
|
@click.pass_context
|
|
61
61
|
@load_config
|
|
62
|
-
@validate_xsoar_connectivity
|
|
62
|
+
@validate_xsoar_connectivity
|
|
63
63
|
def list_content(ctx: click.Context, environment: str | None, content_type: str, detail: bool, verbose: bool) -> None:
|
|
64
64
|
"""
|
|
65
65
|
List detached content items. The purpose of this function is to list out available commands,
|
|
@@ -98,7 +98,7 @@ def list_content(ctx: click.Context, environment: str | None, content_type: str,
|
|
|
98
98
|
@click.argument("name", type=str)
|
|
99
99
|
@click.pass_context
|
|
100
100
|
@load_config
|
|
101
|
-
@validate_xsoar_connectivity
|
|
101
|
+
@validate_xsoar_connectivity
|
|
102
102
|
def download(ctx: click.Context, environment: str | None, content_type: str, output_path: str | None, name: str) -> None:
|
|
103
103
|
"""Download a content item by name.
|
|
104
104
|
|
|
@@ -67,8 +67,9 @@ def _build_content_graph(
|
|
|
67
67
|
return cg
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
@click.group(
|
|
70
|
+
@click.group()
|
|
71
71
|
def graph() -> None:
|
|
72
|
+
"""(BETA) Create dependency graphs from one or more content packs"""
|
|
72
73
|
pass
|
|
73
74
|
|
|
74
75
|
|
|
@@ -76,7 +77,7 @@ def graph() -> None:
|
|
|
76
77
|
@click.command()
|
|
77
78
|
@click.pass_context
|
|
78
79
|
@load_config
|
|
79
|
-
@validate_xsoar_connectivity
|
|
80
|
+
@validate_xsoar_connectivity
|
|
80
81
|
def generate(ctx: click.Context, packs: tuple[Path], repo_path: str, upstream_repo_path: str, environment: str | None) -> None:
|
|
81
82
|
"""BETA
|
|
82
83
|
|
|
@@ -99,7 +100,7 @@ def generate(ctx: click.Context, packs: tuple[Path], repo_path: str, upstream_re
|
|
|
99
100
|
@_common_graph_options
|
|
100
101
|
@click.pass_context
|
|
101
102
|
@load_config
|
|
102
|
-
@validate_xsoar_connectivity
|
|
103
|
+
@validate_xsoar_connectivity
|
|
103
104
|
def export(
|
|
104
105
|
ctx: click.Context,
|
|
105
106
|
packs: tuple[Path],
|
|
@@ -14,25 +14,25 @@ logger = logging.getLogger(__name__)
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
@click.group()
|
|
17
|
-
|
|
18
|
-
def integration(ctx: click.Context) -> None:
|
|
17
|
+
def integration() -> None:
|
|
19
18
|
"""(BETA) Save/load integration configuration for an integration instance."""
|
|
19
|
+
pass
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@click.command()
|
|
23
23
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
24
|
-
@click.option("--all", is_flag=True, default=False)
|
|
24
|
+
@click.option("--all", "all_integrations", is_flag=True, default=False, help="Dump all integrations")
|
|
25
25
|
@click.argument("name", type=str, required=False, default=None)
|
|
26
26
|
@click.pass_context
|
|
27
27
|
@load_config
|
|
28
|
-
@validate_xsoar_connectivity
|
|
29
|
-
def dump(ctx: click.Context, environment: str | None, name: str | None,
|
|
28
|
+
@validate_xsoar_connectivity
|
|
29
|
+
def dump(ctx: click.Context, environment: str | None, name: str | None, all_integrations: bool) -> None:
|
|
30
30
|
"""Dump integration instance configuration to stdout as JSON."""
|
|
31
31
|
config = get_xsoar_config(ctx)
|
|
32
32
|
xsoar_client: Client = config.get_client(environment)
|
|
33
33
|
logger.debug("Dumping integration config (environment: '%s')", environment or config.default_environment)
|
|
34
34
|
integrations = xsoar_client.integrations.get_instances()
|
|
35
|
-
if
|
|
35
|
+
if all_integrations:
|
|
36
36
|
logger.debug("Fetching config for all integrations (environment: '%s')", environment or config.default_environment)
|
|
37
37
|
integration_data = integrations
|
|
38
38
|
else:
|
|
@@ -41,11 +41,11 @@ def dump(ctx: click.Context, environment: str | None, name: str | None, all: boo
|
|
|
41
41
|
if not integration_data:
|
|
42
42
|
click.echo(f"Cannot find integration instance '{name}'")
|
|
43
43
|
ctx.exit(1)
|
|
44
|
-
click.echo(json.dumps(integration_data, sort_keys=True, indent=4)
|
|
44
|
+
click.echo(json.dumps(integration_data, sort_keys=True, indent=4))
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
@click.command()
|
|
48
|
-
def load(
|
|
48
|
+
def load() -> None:
|
|
49
49
|
"""Load integration instance configuration into XSOAR from a JSON file. Not yet implemented."""
|
|
50
50
|
logger.debug("integration loadconfig command not implemented")
|
|
51
51
|
click.echo("Command not implemented")
|
|
@@ -4,20 +4,19 @@ Content pack deployment management commands using a declarative configuration fi
|
|
|
4
4
|
|
|
5
5
|
## Generate
|
|
6
6
|
|
|
7
|
-
Generate a new manifest file from currently installed content packs. Assumes all packs are marketplace packs (no custom packs).
|
|
7
|
+
Generate a new manifest file from currently installed content packs. Assumes all packs are marketplace packs (no custom packs). The output file is always named `xsoar_config.json`. Prompts for confirmation if the file already exists.
|
|
8
8
|
|
|
9
|
-
**Syntax:** `xsoar-cli manifest generate [OPTIONS]
|
|
9
|
+
**Syntax:** `xsoar-cli manifest generate [OPTIONS]`
|
|
10
10
|
|
|
11
11
|
**Options:**
|
|
12
12
|
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
13
|
-
|
|
14
|
-
**Arguments:**
|
|
15
|
-
- `MANIFEST_PATH` - Path where the new manifest file will be created
|
|
13
|
+
- `--output-dir DIRECTORY` - Directory to write xsoar_config.json to (default: current directory)
|
|
16
14
|
|
|
17
15
|
**Examples:**
|
|
18
16
|
```
|
|
19
|
-
xsoar-cli manifest generate
|
|
20
|
-
xsoar-cli manifest generate --
|
|
17
|
+
xsoar-cli manifest generate
|
|
18
|
+
xsoar-cli manifest generate --output-dir /path/to/repo
|
|
19
|
+
xsoar-cli manifest generate --environment prod
|
|
21
20
|
```
|
|
22
21
|
|
|
23
22
|
## Validate
|
|
@@ -116,20 +116,34 @@ def _check_pack_availability(
|
|
|
116
116
|
@click.group()
|
|
117
117
|
def manifest() -> None:
|
|
118
118
|
"""Various commands to interact/update/deploy content packs defined in the xsoar_config.json manifest."""
|
|
119
|
+
pass
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
MANIFEST_FILENAME = "xsoar_config.json"
|
|
119
123
|
|
|
120
124
|
|
|
121
125
|
@click.command()
|
|
122
126
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
123
|
-
@click.
|
|
127
|
+
@click.option(
|
|
128
|
+
"--output-dir",
|
|
129
|
+
type=click.Path(exists=True, file_okay=False),
|
|
130
|
+
default=".",
|
|
131
|
+
show_default=True,
|
|
132
|
+
help="Directory to write xsoar_config.json to.",
|
|
133
|
+
)
|
|
124
134
|
@click.pass_context
|
|
125
135
|
@load_config
|
|
126
|
-
@validate_xsoar_connectivity
|
|
127
|
-
def generate(ctx: click.Context, environment: str | None,
|
|
136
|
+
@validate_xsoar_connectivity
|
|
137
|
+
def generate(ctx: click.Context, environment: str | None, output_dir: str) -> None:
|
|
128
138
|
"""Generate a new xsoar_config.json manifest from installed content packs.
|
|
129
139
|
|
|
130
140
|
This command assumes that you do not have any custom content packs uploaded to XSOAR.
|
|
131
141
|
All packs will be added as "marketplace_packs" in the manifest.
|
|
132
142
|
"""
|
|
143
|
+
manifest_path = str(Path(output_dir) / MANIFEST_FILENAME)
|
|
144
|
+
if Path(manifest_path).is_file():
|
|
145
|
+
click.confirm(f"{manifest_path} already exists. Overwrite?", abort=True)
|
|
146
|
+
|
|
133
147
|
config = get_xsoar_config(ctx)
|
|
134
148
|
xsoar_client: Client = config.get_client(environment)
|
|
135
149
|
logger.info("Generating manifest from installed packs (environment: '%s')", environment or config.default_environment)
|
|
@@ -151,11 +165,11 @@ def generate(ctx: click.Context, environment: str | None, manifest_path: str) ->
|
|
|
151
165
|
|
|
152
166
|
@click.command()
|
|
153
167
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
154
|
-
@click.argument("manifest", type=
|
|
168
|
+
@click.argument("manifest", type=click.Path(exists=True))
|
|
155
169
|
@click.pass_context
|
|
156
170
|
@load_config
|
|
157
171
|
@validate_artifacts_provider
|
|
158
|
-
@validate_xsoar_connectivity
|
|
172
|
+
@validate_xsoar_connectivity
|
|
159
173
|
def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
|
|
160
174
|
"""Update manifest on disk with latest available content pack versions."""
|
|
161
175
|
# Lazy import for performance reasons
|
|
@@ -239,11 +253,11 @@ def update(ctx: click.Context, environment: str | None, manifest: str) -> None:
|
|
|
239
253
|
default="diff",
|
|
240
254
|
help="Validate the full manifest, or only the definitions that diff with installed versions",
|
|
241
255
|
)
|
|
242
|
-
@click.argument("manifest", type=
|
|
256
|
+
@click.argument("manifest", type=click.Path(exists=True))
|
|
243
257
|
@click.pass_context
|
|
244
258
|
@load_config
|
|
245
259
|
@validate_artifacts_provider
|
|
246
|
-
@validate_xsoar_connectivity
|
|
260
|
+
@validate_xsoar_connectivity
|
|
247
261
|
def validate(ctx: click.Context, environment: str | None, mode: str, manifest: str) -> None:
|
|
248
262
|
"""Validate manifest JSON and content pack availability.
|
|
249
263
|
|
|
@@ -304,10 +318,10 @@ def validate(ctx: click.Context, environment: str | None, mode: str, manifest: s
|
|
|
304
318
|
|
|
305
319
|
@click.command()
|
|
306
320
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
307
|
-
@click.argument("manifest", type=
|
|
321
|
+
@click.argument("manifest", type=click.Path(exists=True))
|
|
308
322
|
@click.pass_context
|
|
309
323
|
@load_config
|
|
310
|
-
@validate_xsoar_connectivity
|
|
324
|
+
@validate_xsoar_connectivity
|
|
311
325
|
def diff(ctx: click.Context, manifest: str, environment: str | None) -> None:
|
|
312
326
|
"""Prints out the differences (if any) between what is defined in the xsoar_config.json manifest and what is actually
|
|
313
327
|
installed on the XSOAR server."""
|
|
@@ -362,11 +376,11 @@ def diff(ctx: click.Context, manifest: str, environment: str | None) -> None:
|
|
|
362
376
|
@click.option("--environment", default=None, help="Default environment set in config file.")
|
|
363
377
|
@click.option("--verbose", is_flag=True, default=False)
|
|
364
378
|
@click.option("--yes", is_flag=True, default=False)
|
|
365
|
-
@click.argument("manifest", type=
|
|
379
|
+
@click.argument("manifest", type=click.Path(exists=True))
|
|
366
380
|
@click.pass_context
|
|
367
381
|
@load_config
|
|
368
382
|
@validate_artifacts_provider
|
|
369
|
-
@validate_xsoar_connectivity
|
|
383
|
+
@validate_xsoar_connectivity
|
|
370
384
|
def deploy(ctx: click.Context, environment: str | None, manifest: str, verbose: bool, yes: bool) -> None: # noqa: FBT001
|
|
371
385
|
"""Deploy content packs to the server as defined in the xsoar_config.json manifest.
|
|
372
386
|
|
|
@@ -13,9 +13,9 @@ logger = logging.getLogger(__name__)
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@click.group()
|
|
16
|
-
|
|
17
|
-
def pack(ctx: click.Context) -> None:
|
|
16
|
+
def pack() -> None:
|
|
18
17
|
"""Various content pack related commands."""
|
|
18
|
+
pass
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@click.command()
|
|
@@ -23,7 +23,7 @@ def pack(ctx: click.Context) -> None:
|
|
|
23
23
|
@click.argument("pack_id", type=str)
|
|
24
24
|
@click.pass_context
|
|
25
25
|
@load_config
|
|
26
|
-
@validate_xsoar_connectivity
|
|
26
|
+
@validate_xsoar_connectivity
|
|
27
27
|
def delete(ctx: click.Context, environment: str | None, pack_id: str) -> None:
|
|
28
28
|
"""Delete a content pack from the server."""
|
|
29
29
|
config = get_xsoar_config(ctx)
|
|
@@ -45,7 +45,7 @@ def delete(ctx: click.Context, environment: str | None, pack_id: str) -> None:
|
|
|
45
45
|
@click.pass_context
|
|
46
46
|
@load_config
|
|
47
47
|
@validate_artifacts_provider
|
|
48
|
-
@validate_xsoar_connectivity
|
|
48
|
+
@validate_xsoar_connectivity
|
|
49
49
|
def get_outdated(ctx: click.Context, environment: str | None) -> None:
|
|
50
50
|
"""Print a list of outdated content packs."""
|
|
51
51
|
config = get_xsoar_config(ctx)
|