xsoar-cli 2.1.1__tar.gz → 2.3.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.1 → xsoar_cli-2.3.0}/CHANGELOG.md +49 -1
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/CLAUDE.md +7 -7
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/CONTRIBUTING.md +5 -30
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/PKG-INFO +2 -1
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/_version.py +2 -2
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/pyproject.toml +1 -1
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/cli.py +63 -10
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/case/commands.py +14 -7
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/completions/commands.py +2 -1
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/config/README.md +18 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/config/commands.py +26 -6
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/content/README.md +2 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/content/commands.py +23 -17
- xsoar_cli-2.3.0/src/xsoar_cli/commands/execute/README.md +67 -0
- xsoar_cli-2.3.0/src/xsoar_cli/commands/execute/commands.py +337 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/graph/commands.py +4 -3
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/integration/commands.py +8 -8
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/manifest/README.md +4 -1
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/manifest/commands.py +42 -40
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/pack/commands.py +4 -4
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/plugins/README.md +13 -2
- xsoar_cli-2.3.0/src/xsoar_cli/commands/plugins/commands.py +257 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/rbac/commands.py +8 -8
- xsoar_cli-2.3.0/src/xsoar_cli/plugins/README.md +45 -0
- xsoar_cli-2.3.0/src/xsoar_cli/plugins/__init__.py +48 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/plugins/manager.py +59 -73
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/content.py +18 -18
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/validators.py +19 -26
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/artifact_providers/azure.py +4 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/artifact_providers/s3.py +3 -3
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/client.py +2 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/content.py +38 -11
- xsoar_cli-2.3.0/src/xsoar_cli/xsoar_client/execution.py +260 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/conftest.py +85 -14
- xsoar_cli-2.3.0/tests/cli/test_base.py +71 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_config.py +39 -0
- xsoar_cli-2.3.0/tests/cli/test_execute.py +287 -0
- xsoar_cli-2.3.0/tests/cli/test_manifest.py +225 -0
- xsoar_cli-2.3.0/tests/cli/test_plugins.py +244 -0
- xsoar_cli-2.3.0/tests/unit/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_content_domain.py +36 -5
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_content_filters.py +7 -7
- xsoar_cli-2.3.0/tests/unit/test_execution.py +225 -0
- xsoar_cli-2.3.0/tests/unit/test_plugin_manager.py +319 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_validators.py +4 -4
- xsoar_cli-2.1.1/src/xsoar_cli/commands/plugins/commands.py +0 -184
- xsoar_cli-2.1.1/src/xsoar_cli/plugins/README.md +0 -53
- xsoar_cli-2.1.1/src/xsoar_cli/plugins/__init__.py +0 -62
- xsoar_cli-2.1.1/tests/cli/test_base.py +0 -17
- xsoar_cli-2.1.1/tests/cli/test_manifest.py +0 -18
- xsoar_cli-2.1.1/tests/cli/test_plugins.py +0 -104
- xsoar_cli-2.1.1/tests/unit/test_plugin_manager.py +0 -213
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/.github/workflows/main.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/.github/workflows/pull-request-open.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/.github/workflows/release.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/.github/workflows/update-changelog.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/.gitignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/LICENSE.txt +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/case/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/case/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/completions/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/completions/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/config/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/content/__init__.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/graph → xsoar_cli-2.3.0/src/xsoar_cli/commands/execute}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/graph/README.md +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/integration → xsoar_cli-2.3.0/src/xsoar_cli/commands/graph}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/integration/README.md +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/manifest → xsoar_cli-2.3.0/src/xsoar_cli/commands/integration}/__init__.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/pack → xsoar_cli-2.3.0/src/xsoar_cli/commands/manifest}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/pack/README.md +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/plugins → xsoar_cli-2.3.0/src/xsoar_cli/commands/pack}/__init__.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/commands/rbac → xsoar_cli-2.3.0/src/xsoar_cli/commands/plugins}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/commands/rbac/README.md +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/error_handling → xsoar_cli-2.3.0/src/xsoar_cli/commands/rbac}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/configuration.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/utilities → xsoar_cli-2.3.0/src/xsoar_cli/error_handling}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/error_handling/connection.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/error_handling/http.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/log.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/xsoar_client → xsoar_cli-2.3.0/src/xsoar_cli/utilities}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/config_file.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/download_content_handlers.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/manifest.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/utilities/version_check.py +0 -0
- {xsoar_cli-2.1.1/src/xsoar_cli/xsoar_client/artifact_providers → xsoar_cli-2.3.0/src/xsoar_cli/xsoar_client}/__init__.py +0 -0
- {xsoar_cli-2.1.1/tests/cli → xsoar_cli-2.3.0/src/xsoar_cli/xsoar_client/artifact_providers}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/artifact_providers/base.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/cases.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/constants.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/integrations.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/packs.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/src/xsoar_cli/xsoar_client/rbac.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/__init__.py +0 -0
- {xsoar_cli-2.1.1/tests/unit → xsoar_cli-2.3.0/tests/cli}/__init__.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_case.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_completions.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_content.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_graph.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/cli/test_pack.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/conftest.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/cases/create.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/cases/get.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/content/automation_search.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/content/playbook_search.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/content/user_commands.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/integrations/instances.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/manifest_base.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/manifest_invalid.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/manifest_with_pack_not_on_server.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/server_base_response.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/server_base_response_missing_one_pack.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/server_base_response_with_updates.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/manifest/server_base_response_with_updates_and_one_extra.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/packs/installed.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/packs/installed_expired.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/rbac/roles.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/rbac/user_groups.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/fixtures/rbac/users.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Download/playbook-empty.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.pack-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/.secrets-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Author_image.png +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/Playbooks/GenericPlaybook.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonPlaybooks/pack_metadata.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.pack-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/.secrets-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Author_image.png +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/GenericScript.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/Scripts/GenericScript/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_CommonScripts/pack_metadata.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/.pack-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/.secrets-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Author_image.png +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Playbooks/EDR_InitialTriage.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/EDR_FetchFile.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_FetchFile/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/EDR_Triage.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/EDR_Triage/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/LegacyItem.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/Scripts/LegacyItem/test_data/basescript-dummy.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_EDR/pack_metadata.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/.pack-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/.secrets-ignore +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/Author_image.png +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/Layouts/layoutscontainer-GenericLayout.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/README.md +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/MyOrg_Layouts/pack_metadata.json +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/mock_content/Packs/Not_applicable/Playbooks/Empty.yml +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/conftest.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_artifact_azure.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_artifact_base.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_artifact_s3.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_cases.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_client.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_config_file.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_content_handlers.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_error_handling.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_integrations.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_main.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_manifest_utils.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_packs.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_rbac.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/tests/unit/test_version_check.py +0 -0
- {xsoar_cli-2.1.1 → xsoar_cli-2.3.0}/uv.lock +0 -0
|
@@ -6,6 +6,54 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `execute command NAME [ARGS]...` runs an automation script or integration command against XSOAR, in the user's playground by default or a specific case with `--case-id`. See the [execute README](src/xsoar_cli/commands/execute/README.md) for details.
|
|
12
|
+
- `execute playbook NAME` starts a playbook in the user's playground, or a specific case with `--case-id`. See the [execute README](src/xsoar_cli/commands/execute/README.md) for details.
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- `content download` now correctly resolves playbooks whose ID differs from their name when the name contains spaces. Previously, the name search query was not quoted, causing it to return no results. In practice this affected custom playbooks created in the XSOAR UI, which use a UUID as their ID.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **Breaking:** `manifest validate` now validates all packs by default (previously defaulted to `--mode diff`). Use the new `--only-changed` flag to validate only packs that differ from what is installed on the server.
|
|
21
|
+
- **Breaking:** `content list` now uses a single `--detail-level` option (choices: `short`, `extended`, `full`, default: `short`) instead of the separate `--details` and `--verbose` flags.
|
|
22
|
+
- Plugin commands are now listed under a separate `Plugins:` section in `--help` output instead of being mixed with core commands.
|
|
23
|
+
|
|
24
|
+
### Removed
|
|
25
|
+
|
|
26
|
+
- `manifest validate --mode` option. Use `--only-changed` instead of `--mode diff`. Full validation is now the default.
|
|
27
|
+
- `content list --details` flag. Use `--detail-level extended` instead.
|
|
28
|
+
- `content list --verbose` flag. Use `--detail-level full` instead.
|
|
29
|
+
|
|
30
|
+
## [2.2.0] - 2026-04-10
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- `config set-version-check` command to enable or disable the version update check on CLI startup. Accepts `--enable` or `--disable`.
|
|
35
|
+
- `plugins init` command to create the plugins directory and generate an example plugin.
|
|
36
|
+
|
|
37
|
+
### Changed
|
|
38
|
+
|
|
39
|
+
- **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.
|
|
40
|
+
- Plugin commands (`list`, `info`, `validate`) now report a clear error when the plugins directory has not been initialized.
|
|
41
|
+
- Plugin registration failures no longer prevent remaining plugins from loading.
|
|
42
|
+
- `content get-detached --type` is now required. The `all` choice has been removed; specify `scripts` or `playbooks` explicitly.
|
|
43
|
+
- `integration dump`, `rbac getroles`, `rbac getusers`, and `rbac getusergroups` no longer emit a trailing blank line after JSON output.
|
|
44
|
+
- `config show` now uses `click.echo()` instead of `print()`, improving behavior when piping output to other tools.
|
|
45
|
+
|
|
46
|
+
### Removed
|
|
47
|
+
|
|
48
|
+
- The plugins directory is no longer automatically created on CLI startup. Run `xsoar-cli plugins init` to create it explicitly.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
|
|
52
|
+
- `content get-detached` no longer fails when invoked without `--type` due to a stale default value that referenced the removed `all` choice.
|
|
53
|
+
- Content bundle download (`get_content_bundle`) now raises on HTTP errors instead of silently proceeding and failing with a confusing `tarfile` error.
|
|
54
|
+
|
|
55
|
+
## [2.1.1] - 2026-04-08
|
|
56
|
+
|
|
9
57
|
### Changed
|
|
10
58
|
|
|
11
59
|
- `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.
|
|
@@ -83,4 +131,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
83
131
|
|
|
84
132
|
### Removed
|
|
85
133
|
|
|
86
|
-
- `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
|
|
134
|
+
- `config validate --stacktrace` option. Use `--verbose` / `-v` instead.
|
|
@@ -28,7 +28,7 @@ for confirmation before executing any terminal commands as they may have consequ
|
|
|
28
28
|
- **Build System**: Hatchling (`pyproject.toml`)
|
|
29
29
|
- **Package Manager**: uv (`uv.lock`)
|
|
30
30
|
- **Linting**: Ruff
|
|
31
|
-
- **Formatting**: Black
|
|
31
|
+
- **Formatting**: Ruff formatter (>99.9% Black-compatible)
|
|
32
32
|
- **Testing**: pytest, pytest-cov
|
|
33
33
|
- **CI**: GitHub Actions (Python 3.10-3.14)
|
|
34
34
|
|
|
@@ -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
|
|
@@ -144,10 +142,10 @@ uv run pytest tests/cli/
|
|
|
144
142
|
uv run pytest tests/unit/
|
|
145
143
|
|
|
146
144
|
# Format code
|
|
147
|
-
|
|
145
|
+
uv run ruff format src/ tests/
|
|
148
146
|
|
|
149
147
|
# Lint
|
|
150
|
-
ruff check src/ tests/
|
|
148
|
+
uv run ruff check src/ tests/
|
|
151
149
|
|
|
152
150
|
# Run the CLI
|
|
153
151
|
uv run xsoar-cli --help
|
|
@@ -208,9 +206,11 @@ The user's live configuration at `~/.config/xsoar-cli/config.json` contains API
|
|
|
208
206
|
|
|
209
207
|
## Changelog
|
|
210
208
|
|
|
209
|
+
**Every PR that changes user-facing behavior MUST include a `CHANGELOG.md` update. Do not treat this as optional or as a follow-up step. The changelog entry is part of the implementation, not separate from it.**
|
|
210
|
+
|
|
211
211
|
- The project maintains a `CHANGELOG.md` in the repository root.
|
|
212
212
|
- The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
213
|
-
-
|
|
213
|
+
- Changes that require a changelog entry:
|
|
214
214
|
- Adding, removing, or renaming commands, options, or arguments (`Added` / `Removed`)
|
|
215
215
|
- Changes to default behavior or output format (`Changed`)
|
|
216
216
|
- Bug fixes (`Fixed`)
|
|
@@ -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.3.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.3.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 3, 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"
|
|
@@ -17,6 +17,7 @@ from .commands.case import commands as case_commands
|
|
|
17
17
|
from .commands.completions import commands as completions_commands
|
|
18
18
|
from .commands.config import commands as config_commands
|
|
19
19
|
from .commands.content import commands as content_commands
|
|
20
|
+
from .commands.execute import commands as execute_commands
|
|
20
21
|
from .commands.graph import commands as graph_commands
|
|
21
22
|
from .commands.integration import commands as integration_commands
|
|
22
23
|
from .commands.manifest import commands as manifest_commands
|
|
@@ -30,12 +31,46 @@ from .utilities.version_check import check_for_update
|
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class XSOARCliGroup(click.Group):
|
|
33
|
-
"""Custom Click group
|
|
34
|
+
"""Custom Click group with separate help sections for core and plugin commands.
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
"No such command" error with no indication that a
|
|
36
|
+
Also surfaces plugin load failures when a command is not found, so the user
|
|
37
|
+
does not get a generic "No such command" error with no indication that a
|
|
38
|
+
plugin was involved.
|
|
37
39
|
"""
|
|
38
40
|
|
|
41
|
+
def __init__(self, *args, **kwargs):
|
|
42
|
+
super().__init__(*args, **kwargs)
|
|
43
|
+
self.core_commands: set[str] = set()
|
|
44
|
+
|
|
45
|
+
def format_commands(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
|
|
46
|
+
"""Format help output with core commands and plugin commands in separate sections."""
|
|
47
|
+
core_rows = []
|
|
48
|
+
plugin_rows = []
|
|
49
|
+
|
|
50
|
+
for subcommand in self.list_commands(ctx):
|
|
51
|
+
cmd = self.get_command(ctx, subcommand)
|
|
52
|
+
if cmd is None or cmd.hidden:
|
|
53
|
+
continue
|
|
54
|
+
target = core_rows if subcommand in self.core_commands else plugin_rows
|
|
55
|
+
target.append((subcommand, cmd))
|
|
56
|
+
|
|
57
|
+
if not core_rows and not plugin_rows:
|
|
58
|
+
return
|
|
59
|
+
|
|
60
|
+
all_names = core_rows + plugin_rows
|
|
61
|
+
limit = formatter.width - 6 - max(len(name) for name, _ in all_names)
|
|
62
|
+
|
|
63
|
+
def make_rows(commands):
|
|
64
|
+
return [(name, cmd.get_short_help_str(limit)) for name, cmd in commands]
|
|
65
|
+
|
|
66
|
+
if core_rows:
|
|
67
|
+
with formatter.section("Commands"):
|
|
68
|
+
formatter.write_dl(make_rows(core_rows))
|
|
69
|
+
|
|
70
|
+
if plugin_rows:
|
|
71
|
+
with formatter.section("Plugins"):
|
|
72
|
+
formatter.write_dl(make_rows(plugin_rows))
|
|
73
|
+
|
|
39
74
|
def resolve_command(self, ctx: click.Context, args: list) -> tuple:
|
|
40
75
|
try:
|
|
41
76
|
return super().resolve_command(ctx, args)
|
|
@@ -70,6 +105,7 @@ def _register_commands() -> None:
|
|
|
70
105
|
cli.add_command(config_commands.config)
|
|
71
106
|
cli.add_command(content_commands.content)
|
|
72
107
|
|
|
108
|
+
cli.add_command(execute_commands.execute)
|
|
73
109
|
cli.add_command(graph_commands.graph)
|
|
74
110
|
cli.add_command(integration_commands.integration)
|
|
75
111
|
cli.add_command(manifest_commands.manifest)
|
|
@@ -83,13 +119,29 @@ def _load_plugins() -> tuple[list[str], PluginManager]:
|
|
|
83
119
|
"""Captures core command names, then loads and registers plugins. Returns both."""
|
|
84
120
|
core_commands = list(cli.commands.keys())
|
|
85
121
|
manager = PluginManager()
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
122
|
+
|
|
123
|
+
if not manager.plugins_dir_exists:
|
|
124
|
+
logging.getLogger(__name__).debug("Plugins directory not found, skipping plugin loading")
|
|
125
|
+
return core_commands, manager
|
|
126
|
+
|
|
127
|
+
manager.load_all_plugins(ignore_errors=True)
|
|
128
|
+
|
|
129
|
+
# Report load failures on stderr. These warnings run at module level before
|
|
130
|
+
# logging is configured, so logger.warning would be invisible. Plugin load
|
|
131
|
+
# failures are important enough to surface unconditionally.
|
|
132
|
+
load_failures = set(manager.get_failed_plugins().keys())
|
|
133
|
+
for plugin_name, error in manager.get_failed_plugins().items():
|
|
134
|
+
click.echo(f"Warning: plugin '{plugin_name}' failed to load: {error}", err=True)
|
|
135
|
+
|
|
136
|
+
manager.register_plugin_commands(cli)
|
|
137
|
+
|
|
138
|
+
# Registration failures are recorded in failed_plugins by the manager
|
|
139
|
+
# (skip-and-record pattern). Report only the new ones added during registration.
|
|
140
|
+
for plugin_name, error in manager.get_failed_plugins().items():
|
|
141
|
+
if plugin_name in load_failures:
|
|
142
|
+
continue # Already reported above
|
|
143
|
+
click.echo(f"Warning: plugin '{plugin_name}' failed to register: {error}", err=True)
|
|
144
|
+
|
|
93
145
|
return core_commands, manager
|
|
94
146
|
|
|
95
147
|
|
|
@@ -113,6 +165,7 @@ def _configure_logging(config_data: dict | None) -> LoggingSetup:
|
|
|
113
165
|
# "Exit:" entries for pytest invocations.
|
|
114
166
|
_register_commands()
|
|
115
167
|
CORE_COMMANDS, plugin_manager = _load_plugins()
|
|
168
|
+
cli.core_commands = set(CORE_COMMANDS)
|
|
116
169
|
|
|
117
170
|
# Initialized in main(). None when the module is imported without calling main(),
|
|
118
171
|
# which is the case during test runs.
|
|
@@ -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)
|
|
@@ -29,12 +29,14 @@ List available content items. Enumerates commands, playbooks and scripts availab
|
|
|
29
29
|
**Options:**
|
|
30
30
|
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
31
31
|
- `--type [scripts|playbooks|commands|all]` - Type of content items to list (default: all)
|
|
32
|
+
- `--detail-level [short|extended|full]` - Amount of detail in the output (default: short)
|
|
32
33
|
|
|
33
34
|
**Examples:**
|
|
34
35
|
```
|
|
35
36
|
xsoar-cli content list
|
|
36
37
|
xsoar-cli content list --environment prod
|
|
37
38
|
xsoar-cli content list --type commands
|
|
39
|
+
xsoar-cli content list --type commands --detail-level extended
|
|
38
40
|
xsoar-cli content list --type playbooks --environment dev
|
|
39
41
|
```
|
|
40
42
|
|
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING
|
|
|
7
7
|
import click
|
|
8
8
|
|
|
9
9
|
from xsoar_cli.utilities.config_file import get_xsoar_config, load_config
|
|
10
|
-
from xsoar_cli.utilities.content import filter_content
|
|
10
|
+
from xsoar_cli.utilities.content import DETAIL_LEVELS, filter_content
|
|
11
11
|
from xsoar_cli.utilities.download_content_handlers import HANDLERS, resolve_output_path
|
|
12
12
|
from xsoar_cli.utilities.validators import validate_xsoar_connectivity
|
|
13
13
|
|
|
@@ -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.
|
|
@@ -55,19 +55,25 @@ def get_detached(ctx: click.Context, environment: str | None, content_type: str)
|
|
|
55
55
|
show_default=True,
|
|
56
56
|
help="Type of content items to list.",
|
|
57
57
|
)
|
|
58
|
-
@click.option(
|
|
59
|
-
|
|
58
|
+
@click.option(
|
|
59
|
+
"--detail-level",
|
|
60
|
+
type=click.Choice(DETAIL_LEVELS, case_sensitive=False),
|
|
61
|
+
default="short",
|
|
62
|
+
show_default=True,
|
|
63
|
+
help="Amount of detail to include in the output.",
|
|
64
|
+
)
|
|
60
65
|
@click.pass_context
|
|
61
66
|
@load_config
|
|
62
|
-
@validate_xsoar_connectivity
|
|
63
|
-
def list_content(ctx: click.Context, environment: str | None, content_type: str,
|
|
67
|
+
@validate_xsoar_connectivity
|
|
68
|
+
def list_content(ctx: click.Context, environment: str | None, content_type: str, detail_level: str) -> None:
|
|
64
69
|
"""
|
|
65
|
-
List
|
|
66
|
-
|
|
70
|
+
List available content items. Enumerates commands, playbooks and scripts
|
|
71
|
+
available on the server, primarily to facilitate better AI generated
|
|
72
|
+
playbooks."""
|
|
67
73
|
config = get_xsoar_config(ctx)
|
|
68
74
|
xsoar_client: Client = config.get_client(environment)
|
|
69
75
|
json_blob = xsoar_client.content.list(content_type)
|
|
70
|
-
if
|
|
76
|
+
if detail_level == "full":
|
|
71
77
|
click.echo(json.dumps(json_blob, indent=4))
|
|
72
78
|
ctx.exit(0)
|
|
73
79
|
|
|
@@ -75,7 +81,7 @@ def list_content(ctx: click.Context, environment: str | None, content_type: str,
|
|
|
75
81
|
if isinstance(json_blob, list):
|
|
76
82
|
json_blob = {content_type: json_blob}
|
|
77
83
|
|
|
78
|
-
filtered = filter_content(json_blob,
|
|
84
|
+
filtered = filter_content(json_blob, detail_level=detail_level)
|
|
79
85
|
click.echo(json.dumps(filtered, indent=4))
|
|
80
86
|
|
|
81
87
|
|
|
@@ -98,7 +104,7 @@ def list_content(ctx: click.Context, environment: str | None, content_type: str,
|
|
|
98
104
|
@click.argument("name", type=str)
|
|
99
105
|
@click.pass_context
|
|
100
106
|
@load_config
|
|
101
|
-
@validate_xsoar_connectivity
|
|
107
|
+
@validate_xsoar_connectivity
|
|
102
108
|
def download(ctx: click.Context, environment: str | None, content_type: str, output_path: str | None, name: str) -> None:
|
|
103
109
|
"""Download a content item by name.
|
|
104
110
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Execute
|
|
2
|
+
|
|
3
|
+
Execute scripts, integration commands, and playbooks against an XSOAR investigation.
|
|
4
|
+
|
|
5
|
+
By default, execution happens in the user's playground. Pass `--case-id` to run against a specific case instead.
|
|
6
|
+
|
|
7
|
+
## Command
|
|
8
|
+
|
|
9
|
+
Execute an automation script or integration command. There is no difference in how scripts and integration commands are invoked.
|
|
10
|
+
|
|
11
|
+
Use the bare command or script name, the same way you would reference it in a playbook. A leading `!` is accepted but optional.
|
|
12
|
+
|
|
13
|
+
Arguments are supplied as space-separated `key=value` pairs. Values containing whitespace are quoted automatically. A malformed argument (one without a `=`) causes the command to exit with an error.
|
|
14
|
+
|
|
15
|
+
**Shell note:** interactive shells (zsh, bash) treat characters like `!` and `|` specially. Prefer omitting the `!`, and wrap argument values in single quotes when they contain shell metacharacters, for example `query='index=zscaler | head 1'`.
|
|
16
|
+
|
|
17
|
+
**Syntax:** `xsoar-cli execute command [OPTIONS] NAME [ARGS]...`
|
|
18
|
+
|
|
19
|
+
**Options:**
|
|
20
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
21
|
+
- `--case-id INTEGER` - Case ID to execute against (default: the user's playground)
|
|
22
|
+
- `--mode [sync|async]` - Wait for results (`sync`) or submit and return the created entry (`async`) (default: "sync")
|
|
23
|
+
- `--timeout INTEGER` - Seconds to wait for results in sync mode before reporting the command is still running (default: 30)
|
|
24
|
+
|
|
25
|
+
**Arguments:**
|
|
26
|
+
- `NAME` - The script or integration command to run
|
|
27
|
+
- `ARGS` - Zero or more `key=value` argument pairs
|
|
28
|
+
|
|
29
|
+
**Output:**
|
|
30
|
+
|
|
31
|
+
On success, prints a completion line with the entry count, then for each resulting entry a short `Entry <id>:` header followed by two links: a War Room link (to view the entry in context) and an artifact viewer link (which offers a direct download of the entry content in XSOAR). The entry contents are not printed. If a command produces an error entry, the error contents are printed alongside its links and the command exits non-zero.
|
|
32
|
+
|
|
33
|
+
In sync mode, the command submits the request and then polls for the resulting War Room entries. If no results appear within `--timeout` seconds, the command is reported as still running with a War Room link to the submitted entry, and the exit code stays zero. A failed submission surfaces immediately as an error with a non-zero exit code.
|
|
34
|
+
|
|
35
|
+
**Examples:**
|
|
36
|
+
```
|
|
37
|
+
xsoar-cli execute command MyScript arg1=val1 arg2=val2
|
|
38
|
+
xsoar-cli execute command whois query=example.com --case-id 12345
|
|
39
|
+
xsoar-cli execute command splunk-search query='index=zscaler | head 1'
|
|
40
|
+
xsoar-cli execute command MyScript arg1=val1 --mode async
|
|
41
|
+
xsoar-cli execute command LongRunningScript --timeout 60
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Playbook
|
|
45
|
+
|
|
46
|
+
Start a playbook in the playground or a specific case. The playbook name is resolved to its ID before starting, so the display name works even for custom playbooks whose ID is a UUID.
|
|
47
|
+
|
|
48
|
+
This is fire-and-forget: the playbook is started via the `setPlaybook` command and the CLI returns without waiting for the playbook to finish. Follow up in the XSOAR War Room to see its progress.
|
|
49
|
+
|
|
50
|
+
**Syntax:** `xsoar-cli execute playbook [OPTIONS] NAME`
|
|
51
|
+
|
|
52
|
+
**Options:**
|
|
53
|
+
- `--environment TEXT` - Target environment (default: uses default environment from config)
|
|
54
|
+
- `--case-id INTEGER` - Case ID to start the playbook in (default: the user's playground)
|
|
55
|
+
|
|
56
|
+
**Arguments:**
|
|
57
|
+
- `NAME` - The playbook to start
|
|
58
|
+
|
|
59
|
+
**Output:**
|
|
60
|
+
|
|
61
|
+
Prints `Started playbook <name> in playground` or `Started playbook <name> in case <id>`. If the playbook name cannot be found, the command exits non-zero with an error.
|
|
62
|
+
|
|
63
|
+
**Examples:**
|
|
64
|
+
```
|
|
65
|
+
xsoar-cli execute playbook "My Playbook"
|
|
66
|
+
xsoar-cli execute playbook "My Playbook" --case-id 12345
|
|
67
|
+
```
|