splunk-soar-sdk 2.3.0__tar.gz → 2.3.2__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.
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/PKG-INFO +1 -1
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/pyproject.toml +1 -1
- splunk_soar_sdk-2.3.2/release_notes.txt +23 -0
- splunk_soar_sdk-2.3.2/release_version.txt +1 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/abstract.py +1 -1
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app.py +4 -9
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_client.py +2 -2
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/init/cli.py +2 -2
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/manifests/deserializers.py +1 -10
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/compat.py +10 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/make_request.py +17 -5
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/app.py +18 -3
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/params.py +30 -2
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_convert_cli.py +1 -1
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_deserializers.py +7 -5
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_utils.py +17 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/app.json +4 -7
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/app.json +1 -4
- splunk_soar_sdk-2.3.2/tests/mocks/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_actions_manager.py +6 -18
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_make_request_action.py +17 -2
- splunk_soar_sdk-2.3.2/tests/test_params.py +43 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/uv.lock +1 -1
- splunk_soar_sdk-2.3.0/release_notes.txt +0 -31
- splunk_soar_sdk-2.3.0/release_version.txt +0 -1
- splunk_soar_sdk-2.3.0/tests/test_params.py +0 -21
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/ISSUE_TEMPLATE/bug.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/pull_request_template.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/utils/github.js +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/utils/update_version.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/workflows/code_quality.yml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/workflows/commit_hygiene.yml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/workflows/generate_docs.yml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.github/workflows/semantic_release.yml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.gitignore +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.pre-commit-config.yaml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/.releaserc +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/LICENSE +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/README.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/commitlint.config.js +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/api_reference.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/app_structure/index.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/app_structure/pre-commit-config.yaml.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/app_structure/pyproject.toml.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/app_structure/src_app.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/changelog.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/cli_reference.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/conf.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/custom_views/index.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/custom_views/reusable_components.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/custom_views/templates.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/custom_views/view_handlers.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/defining_asset.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/first_action.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/index.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/init_app.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/installation.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/getting_started/testing_and_building.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/docs/index.rst +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/action_results.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/actions_manager.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/apis/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/apis/artifact.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/apis/container.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/apis/utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/apis/vault.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_cli_runner.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/.gitignore +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/.pre-commit-config.yaml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/logo.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/logo_dark.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/src/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/app_templates/basic_app/uv.lock +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/asset.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/async_utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/init/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/manifests/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/manifests/cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/manifests/processors.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/manifests/serializers.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/package/cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/package/utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/path_utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/cli/utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/action_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/app_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/asset_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/templates/pyproject.toml.jinja +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/code_renderers/toml_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/colors.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/crypto.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/action.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/on_poll.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/test_connectivity.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/view_handler.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/decorators/webhook.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/exceptions.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/input_spec.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/logging.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/actions.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/adapters.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/datatypes.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/dependencies.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/meta/webhooks.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/models/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/models/artifact.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/models/container.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/models/vault_attachment.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/models/view.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/paths.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/py.typed +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/action_result.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/app.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/base_connector.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/connector_result.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/consts.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/encryption_helper.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/install_info.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/json_keys.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/ph_ipc.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom/vault.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom_common/app_interface/app_interface.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/shims/phantom_common/encryption/encryption_manager_factory.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/base/base_template.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/base/error.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/base/header.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/base/logo_header.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/components/pie_chart.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/widgets/widget_resize_snippet.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/templates/widgets/widget_template.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/types.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/component_registry.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/components/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/components/pie_chart.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/template_filters.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/template_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/views/view_parser.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/webhooks/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/webhooks/models.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/src/soar_sdk/webhooks/routing.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/test.png +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/test.txt +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/datapath_parse.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/manifests/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/manifests/test_processors.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_assets/converted_app/actions.py.txt +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_init_cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_manifests_cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_package_cli.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/cli/test_serializers.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/code_renderers/test_action_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/conftest.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/example_asset.json +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/logo.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/logo_dark.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/pyproject.toml +0 -0
- /splunk_soar_sdk-2.3.0/tests/example_app/src/actions/__init__.py → /splunk_soar_sdk-2.3.2/tests/example_app/release_notes/v1.md +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0/tests/interfaces → splunk_soar_sdk-2.3.2/tests/example_app/src/actions}/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/actions/async_action.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/actions/generate_category.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/actions/reverse_string.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/app.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/src/ignoreme.txt +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/templates/reverse_string.html +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app/uv.lock +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/logo.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/logo_dark.svg +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/pyproject.toml +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/src/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/src/app.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/example_app_with_webhook/uv.lock +0 -0
- {splunk_soar_sdk-2.3.0/tests/meta → splunk_soar_sdk-2.3.2/tests/interfaces}/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/interfaces/test_artifact_interface.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/interfaces/test_container_interface.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/interfaces/test_vault_interface.py +0 -0
- {splunk_soar_sdk-2.3.0/tests/mocks → splunk_soar_sdk-2.3.2/tests/meta}/__init__.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/meta/test_actions.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/meta/test_adapters.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/meta/test_datatypes.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/meta/test_dependencies.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/meta/test_webhooks.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/mocks/dynamic_mocks.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/mocks/importable_action.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/stubs.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_action_results.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app_action.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app_action_params.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app_action_results.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app_client.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_app_runner.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_asset.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_assets/splunk-sdk-2.1.0.tar.gz +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_async_integration.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_async_utils.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_code_renderers.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_compat.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_container.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_custom_views.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_encryption.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_logging.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_on_poll.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_template_filters.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_template_renderer.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_test_connectivity.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/test_view_parser.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/webhooks/test_models.py +0 -0
- {splunk_soar_sdk-2.3.0 → splunk_soar_sdk-2.3.2}/tests/webhooks/test_routing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: splunk-soar-sdk
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
4
4
|
Summary: The official framework for developing and testing Splunk SOAR Apps
|
|
5
5
|
Project-URL: Homepage, https://github.com/phantomcyber/splunk-soar-sdk
|
|
6
6
|
Project-URL: Documentation, https://github.com/phantomcyber/splunk-soar-sdk
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## [2.3.2](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.3.1...2.3.2) (2025-10-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* python versions should be strings not list ([b21b0d5](https://github.com/phantomcyber/splunk-soar-sdk/commit/b21b0d500300bd70440f5c9267f6a12746975fec))
|
|
7
|
+
* release notes are required in the app for soars app updates and new apps modals ([f5ca7ad](https://github.com/phantomcyber/splunk-soar-sdk/commit/f5ca7ad1136801a393e4ffb6d209990fc4bfab80))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [2.3.2](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.3.1...2.3.2) (2025-10-10)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* python versions should be strings not list ([b21b0d5](https://github.com/phantomcyber/splunk-soar-sdk/commit/b21b0d500300bd70440f5c9267f6a12746975fec))
|
|
19
|
+
* release notes are required in the app for soars app updates and new apps modals ([f5ca7ad](https://github.com/phantomcyber/splunk-soar-sdk/commit/f5ca7ad1136801a393e4ffb6d209990fc4bfab80))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.3.2
|
|
@@ -101,7 +101,7 @@ class App:
|
|
|
101
101
|
product_name: str,
|
|
102
102
|
publisher: str,
|
|
103
103
|
appid: str,
|
|
104
|
-
python_version: Optional[list[PythonVersion]] = None,
|
|
104
|
+
python_version: Optional[Union[list[PythonVersion], str]] = None,
|
|
105
105
|
min_phantom_version: str = MIN_PHANTOM_VERSION,
|
|
106
106
|
fips_compliant: bool = False,
|
|
107
107
|
asset_cls: type[BaseAsset] = BaseAsset,
|
|
@@ -113,7 +113,7 @@ class App:
|
|
|
113
113
|
raise ValueError(f"Appid is not a valid uuid: {appid}")
|
|
114
114
|
|
|
115
115
|
if python_version is None:
|
|
116
|
-
python_version = PythonVersion.
|
|
116
|
+
python_version = PythonVersion.all_csv()
|
|
117
117
|
|
|
118
118
|
self.app_meta_info = {
|
|
119
119
|
"name": name,
|
|
@@ -636,7 +636,7 @@ class App:
|
|
|
636
636
|
],
|
|
637
637
|
actions_manager: ActionsManager,
|
|
638
638
|
action_params: Optional[Params] = None,
|
|
639
|
-
message:
|
|
639
|
+
message: str = "",
|
|
640
640
|
summary: Optional[ActionOutput] = None,
|
|
641
641
|
) -> bool:
|
|
642
642
|
"""Handles multiple ways of returning response from action.
|
|
@@ -657,9 +657,7 @@ class App:
|
|
|
657
657
|
)
|
|
658
658
|
# Handle empty list/iterator case
|
|
659
659
|
if not statuses:
|
|
660
|
-
result = ActionOutput(
|
|
661
|
-
status=True, message=message or "Action completed successfully"
|
|
662
|
-
)
|
|
660
|
+
result = ActionOutput(status=True, message=message)
|
|
663
661
|
else:
|
|
664
662
|
return all(statuses)
|
|
665
663
|
|
|
@@ -667,9 +665,6 @@ class App:
|
|
|
667
665
|
output_dict = result.dict(by_alias=True)
|
|
668
666
|
param_dict = action_params.dict() if action_params else None
|
|
669
667
|
|
|
670
|
-
if not message:
|
|
671
|
-
message = "Action completed successfully"
|
|
672
|
-
|
|
673
668
|
result = ActionResult(
|
|
674
669
|
status=True,
|
|
675
670
|
message=message,
|
|
@@ -44,7 +44,7 @@ class AppClient(SOARClient[SummaryType]):
|
|
|
44
44
|
self.basic_auth: Optional[BasicAuth] = None
|
|
45
45
|
|
|
46
46
|
self._summary: Optional[SummaryType] = None
|
|
47
|
-
self._message:
|
|
47
|
+
self._message: str = ""
|
|
48
48
|
self.__container_id: int = 0
|
|
49
49
|
self.__asset_id: str = ""
|
|
50
50
|
|
|
@@ -171,6 +171,6 @@ class AppClient(SOARClient[SummaryType]):
|
|
|
171
171
|
"""Get the summary for the action result."""
|
|
172
172
|
return self._summary
|
|
173
173
|
|
|
174
|
-
def get_message(self) ->
|
|
174
|
+
def get_message(self) -> str:
|
|
175
175
|
"""Get the message for the action result."""
|
|
176
176
|
return self._message
|
|
@@ -269,11 +269,11 @@ def convert_connector_to_sdk(
|
|
|
269
269
|
# Convert the main module path to the SDK format, but save a reference to the original
|
|
270
270
|
app_meta.main_module = "src.app:app"
|
|
271
271
|
|
|
272
|
-
app_python_versions = app_meta.python_version
|
|
272
|
+
app_python_versions = PythonVersion.from_csv(app_meta.python_version)
|
|
273
273
|
enforced_python_versions = PythonVersion.all()
|
|
274
274
|
if set(app_python_versions) != set(enforced_python_versions):
|
|
275
275
|
rprint(
|
|
276
|
-
f"[yellow]The provided app declares support for Python versions {
|
|
276
|
+
f"[yellow]The provided app declares support for Python versions '{app_meta.python_version}'.[/]"
|
|
277
277
|
)
|
|
278
278
|
rprint(
|
|
279
279
|
f"[yellow]The converted app will support the default versions {[str(v) for v in enforced_python_versions]}.[/]"
|
|
@@ -6,7 +6,7 @@ import pydantic
|
|
|
6
6
|
|
|
7
7
|
from soar_sdk.action_results import ActionOutput, OutputFieldSpecification, OutputField
|
|
8
8
|
from soar_sdk.cli.utils import normalize_field_name, NormalizationResult
|
|
9
|
-
from soar_sdk.compat import
|
|
9
|
+
from soar_sdk.compat import remove_when_soar_newer_than
|
|
10
10
|
from soar_sdk.meta.actions import ActionMeta
|
|
11
11
|
from soar_sdk.meta.app import AppMeta
|
|
12
12
|
from soar_sdk.params import Params, Param
|
|
@@ -41,15 +41,6 @@ class AppMetaDeserializer:
|
|
|
41
41
|
"""
|
|
42
42
|
manifest: dict[str, Any] = json.loads(json_path.read_text())
|
|
43
43
|
|
|
44
|
-
# Massage the python_version field, which may be a comma-separated string
|
|
45
|
-
python_version = manifest.pop("python_version", None)
|
|
46
|
-
if isinstance(python_version, str):
|
|
47
|
-
manifest["python_version"] = PythonVersion.from_csv(python_version)
|
|
48
|
-
elif isinstance(python_version, list):
|
|
49
|
-
manifest["python_version"] = [
|
|
50
|
-
PythonVersion.from_str(py) for py in python_version
|
|
51
|
-
]
|
|
52
|
-
|
|
53
44
|
deserialized_actions = [
|
|
54
45
|
ActionDeserializer.from_action_json(action)
|
|
55
46
|
for action in manifest.get("actions", [])
|
|
@@ -59,11 +59,21 @@ class PythonVersion(str, Enum):
|
|
|
59
59
|
cls.from_str(version.strip()) for version in versions if version.strip()
|
|
60
60
|
]
|
|
61
61
|
|
|
62
|
+
@classmethod
|
|
63
|
+
def to_csv(cls, versions: list["PythonVersion"]) -> str:
|
|
64
|
+
"""Converts a list of PythonVersion enums to a comma-separated string."""
|
|
65
|
+
return ",".join(str(v) for v in versions)
|
|
66
|
+
|
|
62
67
|
@classmethod
|
|
63
68
|
def all(cls) -> list["PythonVersion"]:
|
|
64
69
|
"""Returns a list of all supported Python versions."""
|
|
65
70
|
return [cls.PY_3_9, cls.PY_3_13]
|
|
66
71
|
|
|
72
|
+
@classmethod
|
|
73
|
+
def all_csv(cls) -> str:
|
|
74
|
+
"""Returns a comma-separated string of all supported Python versions."""
|
|
75
|
+
return ",".join(str(v) for v in cls.all())
|
|
76
|
+
|
|
67
77
|
@classmethod
|
|
68
78
|
def to_requires_python(cls, versions: list["PythonVersion"]) -> str:
|
|
69
79
|
"""Converts a list of PythonVersions to a PEP-508 compatible requires-python string."""
|
|
@@ -43,19 +43,31 @@ class MakeRequestDecorator:
|
|
|
43
43
|
"The 'make_request' decorator can only be used once per App instance."
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
# Validate function signature - must have
|
|
46
|
+
# Validate function signature - must have exactly one parameter of type MakeRequestParams
|
|
47
47
|
signature = inspect.signature(function)
|
|
48
48
|
params = list(signature.parameters.values())
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
make_request_params = [
|
|
51
|
+
param
|
|
52
|
+
for param in params
|
|
53
|
+
if inspect.isclass(param.annotation)
|
|
54
|
+
and issubclass(param.annotation, MakeRequestParams)
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
if len(make_request_params) == 0:
|
|
58
|
+
raise TypeError(
|
|
59
|
+
"Make request action function must have exactly one parameter of type MakeRequestParams or its subclass."
|
|
60
|
+
)
|
|
61
|
+
elif len(make_request_params) > 1:
|
|
62
|
+
param_names = [p.name for p in make_request_params]
|
|
51
63
|
raise TypeError(
|
|
52
|
-
f"Make request action function
|
|
64
|
+
f"Make request action function can only have one MakeRequestParams parameter, "
|
|
65
|
+
f"but found {len(make_request_params)}: {param_names}"
|
|
53
66
|
)
|
|
54
67
|
|
|
55
68
|
action_identifier = "make_request"
|
|
56
69
|
action_name = "make request"
|
|
57
|
-
|
|
58
|
-
validated_params_class = MakeRequestParams
|
|
70
|
+
validated_params_class = make_request_params[0].annotation
|
|
59
71
|
|
|
60
72
|
return_type = inspect.signature(function).return_annotation
|
|
61
73
|
if return_type is not inspect.Signature.empty:
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field
|
|
2
|
-
from typing import Optional
|
|
1
|
+
from pydantic import BaseModel, Field, validator
|
|
2
|
+
from typing import Optional, Union
|
|
3
3
|
|
|
4
4
|
from soar_sdk.asset import AssetFieldSpecification
|
|
5
5
|
from soar_sdk.compat import PythonVersion
|
|
@@ -32,7 +32,7 @@ class AppMeta(BaseModel):
|
|
|
32
32
|
logo: str = ""
|
|
33
33
|
logo_dark: str = ""
|
|
34
34
|
product_name: str = ""
|
|
35
|
-
python_version:
|
|
35
|
+
python_version: str = Field(default_factory=PythonVersion.all_csv)
|
|
36
36
|
product_version_regex: str = ".*"
|
|
37
37
|
publisher: str = ""
|
|
38
38
|
utctime_updated: str = ""
|
|
@@ -47,6 +47,21 @@ class AppMeta(BaseModel):
|
|
|
47
47
|
|
|
48
48
|
webhook: Optional[WebhookMeta]
|
|
49
49
|
|
|
50
|
+
@validator("python_version", pre=True)
|
|
51
|
+
def convert_python_version_to_csv(cls, v: Union[list, str]) -> str:
|
|
52
|
+
"""Converts python_version to a comma-separated string if it's a list and validates versions."""
|
|
53
|
+
if isinstance(v, list):
|
|
54
|
+
# Validate each version in the list and convert to CSV
|
|
55
|
+
validated_versions = [PythonVersion.from_str(str(version)) for version in v]
|
|
56
|
+
return PythonVersion.to_csv(validated_versions)
|
|
57
|
+
elif isinstance(v, str):
|
|
58
|
+
# Validate the CSV string by parsing it and convert back to CSV
|
|
59
|
+
validated_versions = PythonVersion.from_csv(v)
|
|
60
|
+
return PythonVersion.to_csv(validated_versions)
|
|
61
|
+
raise ValueError(
|
|
62
|
+
f"Invalid python_version type must be a list or a comma-separated string: {v}"
|
|
63
|
+
)
|
|
64
|
+
|
|
50
65
|
def to_json_manifest(self) -> dict:
|
|
51
66
|
"""Converts the AppMeta instance to a JSON-compatible dictionary."""
|
|
52
67
|
return self.dict(exclude_none=True)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional, Union, Any
|
|
1
|
+
from typing import Optional, Union, Any, ClassVar
|
|
2
2
|
from typing_extensions import NotRequired, TypedDict
|
|
3
3
|
|
|
4
4
|
from pydantic.fields import Field, Undefined
|
|
@@ -178,6 +178,34 @@ class OnPollParams(Params):
|
|
|
178
178
|
class MakeRequestParams(Params):
|
|
179
179
|
"""Canonical parameters for the special make request action."""
|
|
180
180
|
|
|
181
|
+
# Define allowed field names for subclasses
|
|
182
|
+
_ALLOWED_FIELDS: ClassVar[set[str]] = {
|
|
183
|
+
"http_method",
|
|
184
|
+
"endpoint",
|
|
185
|
+
"headers",
|
|
186
|
+
"query_parameters",
|
|
187
|
+
"body",
|
|
188
|
+
"timeout",
|
|
189
|
+
"verify_ssl",
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
def __init_subclass__(cls, **kwargs: dict[str, Any]) -> None:
|
|
193
|
+
"""Validate that subclasses only define allowed fields."""
|
|
194
|
+
super().__init_subclass__(**kwargs)
|
|
195
|
+
cls._validate_make_request_fields()
|
|
196
|
+
|
|
197
|
+
@classmethod
|
|
198
|
+
def _validate_make_request_fields(cls) -> None:
|
|
199
|
+
"""Ensure subclasses only define allowed MakeRequest fields."""
|
|
200
|
+
# Check if any fields are not in the allowed set
|
|
201
|
+
invalid_fields = set(cls.__fields__.keys()) - cls._ALLOWED_FIELDS
|
|
202
|
+
|
|
203
|
+
if invalid_fields:
|
|
204
|
+
raise TypeError(
|
|
205
|
+
f"MakeRequestParams subclass '{cls.__name__}' can only define these fields: "
|
|
206
|
+
f"{sorted(cls._ALLOWED_FIELDS)}. Invalid fields: {sorted(invalid_fields)}"
|
|
207
|
+
)
|
|
208
|
+
|
|
181
209
|
http_method: str = Param(
|
|
182
210
|
description="The HTTP method to use for the request.",
|
|
183
211
|
required=True,
|
|
@@ -194,7 +222,7 @@ class MakeRequestParams(Params):
|
|
|
194
222
|
required=False,
|
|
195
223
|
)
|
|
196
224
|
|
|
197
|
-
|
|
225
|
+
query_parameters: str = Param(
|
|
198
226
|
description="The query string to send with the request.",
|
|
199
227
|
required=False,
|
|
200
228
|
)
|
|
@@ -223,7 +223,7 @@ def test_convert_cli_updates_py_versions(runner, tmp_path, app_meta):
|
|
|
223
223
|
print(result.output) # For debugging purposes
|
|
224
224
|
|
|
225
225
|
assert result.exit_code == 0
|
|
226
|
-
assert "declares support for Python versions
|
|
226
|
+
assert "declares support for Python versions '3.9'" in result.output
|
|
227
227
|
assert "will support the default versions ['3.9', '3.13']" in result.output
|
|
228
228
|
assert (
|
|
229
229
|
'requires-python = ">=3.9, <3.14"'
|
|
@@ -100,9 +100,9 @@ def test_from_app_json_basic_deserialization(basic_app_data, create_app_json):
|
|
|
100
100
|
@pytest.mark.parametrize(
|
|
101
101
|
"python_version_input,expected",
|
|
102
102
|
[
|
|
103
|
-
("3.9,3.13",
|
|
104
|
-
(["3.9", "3.13"],
|
|
105
|
-
(None, PythonVersion.
|
|
103
|
+
("3.9,3.13", f"{PythonVersion.PY_3_9},{PythonVersion.PY_3_13}"),
|
|
104
|
+
(["3.9", "3.13"], f"{PythonVersion.PY_3_9},{PythonVersion.PY_3_13}"),
|
|
105
|
+
(None, PythonVersion.all_csv()), # Should use default when None
|
|
106
106
|
],
|
|
107
107
|
)
|
|
108
108
|
def test_from_app_json_python_version_handling(
|
|
@@ -127,7 +127,7 @@ def test_from_app_json_python_version_missing(basic_app_data, create_app_json):
|
|
|
127
127
|
|
|
128
128
|
# Should use default from AppMeta model
|
|
129
129
|
result = deserialized_result.app_meta
|
|
130
|
-
assert result.python_version == PythonVersion.
|
|
130
|
+
assert result.python_version == PythonVersion.all_csv()
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
def test_from_app_json_invalid_python_version(basic_app_data, create_app_json):
|
|
@@ -322,7 +322,9 @@ def test_from_app_json_complex_example(create_app_json):
|
|
|
322
322
|
assert result.name == "example_app"
|
|
323
323
|
assert result.appid == "9b388c08-67de-4ca4-817f-26f8fb7cbf55"
|
|
324
324
|
assert result.product_vendor == "Splunk Inc."
|
|
325
|
-
assert
|
|
325
|
+
assert (
|
|
326
|
+
result.python_version == f"{PythonVersion.PY_3_9},{PythonVersion.PY_3_13}"
|
|
327
|
+
)
|
|
326
328
|
assert result.project_name == "example_app"
|
|
327
329
|
assert len(result.actions) == 1
|
|
328
330
|
assert result.fips_compliant is False
|
|
@@ -2,6 +2,7 @@ import pytest
|
|
|
2
2
|
import keyword
|
|
3
3
|
|
|
4
4
|
from soar_sdk.cli.utils import normalize_field_name
|
|
5
|
+
from soar_sdk.meta.app import AppMeta
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
class TestNormalizeFieldName:
|
|
@@ -60,3 +61,19 @@ class TestNormalizeFieldName:
|
|
|
60
61
|
|
|
61
62
|
with pytest.raises(ValueError, match="must contain at least one letter"):
|
|
62
63
|
normalize_field_name("______")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_bad_python_version_type():
|
|
67
|
+
"""Test that an invalid python_version type raises a ValueError."""
|
|
68
|
+
with pytest.raises(
|
|
69
|
+
ValueError,
|
|
70
|
+
match="Invalid python_version type must be a list or a comma-separated string",
|
|
71
|
+
):
|
|
72
|
+
AppMeta(
|
|
73
|
+
project_name="test_app",
|
|
74
|
+
description="Test app",
|
|
75
|
+
license="Copyright (c) 2025 Splunk Inc.",
|
|
76
|
+
app_version="1.0.0",
|
|
77
|
+
package_name="test_app",
|
|
78
|
+
python_version=123,
|
|
79
|
+
)
|
|
@@ -12,10 +12,7 @@
|
|
|
12
12
|
"logo": "logo.svg",
|
|
13
13
|
"logo_dark": "logo_dark.svg",
|
|
14
14
|
"product_name": "Example App",
|
|
15
|
-
"python_version":
|
|
16
|
-
"3.9",
|
|
17
|
-
"3.13"
|
|
18
|
-
],
|
|
15
|
+
"python_version": "3.9,3.13",
|
|
19
16
|
"product_version_regex": ".*",
|
|
20
17
|
"publisher": "Splunk Inc.",
|
|
21
18
|
"utctime_updated": "2025-09-09T15:29:27.279851Z",
|
|
@@ -499,9 +496,9 @@
|
|
|
499
496
|
"primary": false,
|
|
500
497
|
"allow_list": false
|
|
501
498
|
},
|
|
502
|
-
"
|
|
499
|
+
"query_parameters": {
|
|
503
500
|
"order": 3,
|
|
504
|
-
"name": "
|
|
501
|
+
"name": "query_parameters",
|
|
505
502
|
"description": "The query string to send with the request.",
|
|
506
503
|
"data_type": "string",
|
|
507
504
|
"required": false,
|
|
@@ -562,7 +559,7 @@
|
|
|
562
559
|
"data_type": "string"
|
|
563
560
|
},
|
|
564
561
|
{
|
|
565
|
-
"data_path": "action_result.parameter.
|
|
562
|
+
"data_path": "action_result.parameter.query_parameters",
|
|
566
563
|
"data_type": "string"
|
|
567
564
|
},
|
|
568
565
|
{
|
|
@@ -12,10 +12,7 @@
|
|
|
12
12
|
"logo": "logo.svg",
|
|
13
13
|
"logo_dark": "logo_dark.svg",
|
|
14
14
|
"product_name": "Example App",
|
|
15
|
-
"python_version":
|
|
16
|
-
"3.9",
|
|
17
|
-
"3.13"
|
|
18
|
-
],
|
|
15
|
+
"python_version": "3.9,3.13",
|
|
19
16
|
"product_version_regex": ".*",
|
|
20
17
|
"publisher": "Splunk Inc.",
|
|
21
18
|
"utctime_updated": "2025-04-17T12:00:00.000000Z",
|
|
File without changes
|
|
@@ -98,10 +98,7 @@ def test_action_called_returning_iterator(
|
|
|
98
98
|
example_app.handle(simple_action_input.json())
|
|
99
99
|
|
|
100
100
|
assert len(example_app.actions_manager.get_results()) == 5
|
|
101
|
-
assert all(
|
|
102
|
-
"success" in result.message
|
|
103
|
-
for result in example_app.actions_manager.get_results()
|
|
104
|
-
)
|
|
101
|
+
assert all(result.status for result in example_app.actions_manager.get_results())
|
|
105
102
|
|
|
106
103
|
|
|
107
104
|
def test_async_action_called_returning_iterator(
|
|
@@ -120,10 +117,7 @@ def test_async_action_called_returning_iterator(
|
|
|
120
117
|
example_app.handle(simple_action_input.json())
|
|
121
118
|
|
|
122
119
|
assert len(example_app.actions_manager.get_results()) == 5
|
|
123
|
-
assert all(
|
|
124
|
-
"success" in result.message
|
|
125
|
-
for result in example_app.actions_manager.get_results()
|
|
126
|
-
)
|
|
120
|
+
assert all(result.status for result in example_app.actions_manager.get_results())
|
|
127
121
|
|
|
128
122
|
|
|
129
123
|
def test_action_called_returning_list(
|
|
@@ -139,10 +133,7 @@ def test_action_called_returning_list(
|
|
|
139
133
|
example_app.handle(simple_action_input.json())
|
|
140
134
|
|
|
141
135
|
assert len(example_app.actions_manager.get_results()) == 5
|
|
142
|
-
assert all(
|
|
143
|
-
"success" in result.message
|
|
144
|
-
for result in example_app.actions_manager.get_results()
|
|
145
|
-
)
|
|
136
|
+
assert all(result.status for result in example_app.actions_manager.get_results())
|
|
146
137
|
|
|
147
138
|
|
|
148
139
|
def test_async_action_called_returning_list(
|
|
@@ -158,10 +149,7 @@ def test_async_action_called_returning_list(
|
|
|
158
149
|
example_app.handle(simple_action_input.json())
|
|
159
150
|
|
|
160
151
|
assert len(example_app.actions_manager.get_results()) == 5
|
|
161
|
-
assert all(
|
|
162
|
-
"success" in result.message
|
|
163
|
-
for result in example_app.actions_manager.get_results()
|
|
164
|
-
)
|
|
152
|
+
assert all(result.status for result in example_app.actions_manager.get_results())
|
|
165
153
|
|
|
166
154
|
|
|
167
155
|
def test_action_called_with_default_message_set(
|
|
@@ -174,7 +162,7 @@ def test_action_called_with_default_message_set(
|
|
|
174
162
|
example_app.handle(simple_action_input.json())
|
|
175
163
|
|
|
176
164
|
assert len(example_app.actions_manager.get_results()) == 1
|
|
177
|
-
assert
|
|
165
|
+
assert example_app.actions_manager.get_results()[0].status
|
|
178
166
|
|
|
179
167
|
|
|
180
168
|
def test_action_called_with_timezone_asset(example_app: App):
|
|
@@ -204,7 +192,7 @@ def test_action_called_with_timezone_asset(example_app: App):
|
|
|
204
192
|
example_app.handle(action_input.json())
|
|
205
193
|
|
|
206
194
|
assert len(example_app.actions_manager.get_results()) == 1
|
|
207
|
-
assert
|
|
195
|
+
assert example_app.actions_manager.get_results()[0].status
|
|
208
196
|
|
|
209
197
|
|
|
210
198
|
def test_actions_provider_running_undefined_action(
|
|
@@ -61,7 +61,7 @@ def test_make_request_action_without_make_request_params(app_with_action: App):
|
|
|
61
61
|
pass
|
|
62
62
|
|
|
63
63
|
assert (
|
|
64
|
-
"Make request action function must have
|
|
64
|
+
"Make request action function must have exactly one parameter of type MakeRequestParams or its subclass."
|
|
65
65
|
in str(exception_info)
|
|
66
66
|
)
|
|
67
67
|
|
|
@@ -72,7 +72,22 @@ def test_make_request_action_without_make_request_params(app_with_action: App):
|
|
|
72
72
|
pass
|
|
73
73
|
|
|
74
74
|
assert (
|
|
75
|
-
"Make request action function must have
|
|
75
|
+
"Make request action function must have exactly one parameter of type MakeRequestParams or its subclass."
|
|
76
|
+
in str(exception_info)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_make_request_action_with_multiple_params(app_with_action: App):
|
|
81
|
+
with pytest.raises(TypeError) as exception_info:
|
|
82
|
+
|
|
83
|
+
@app_with_action.make_request()
|
|
84
|
+
def http_action(
|
|
85
|
+
params: MakeRequestParams, params2: MakeRequestParams, asset: ValidAsset
|
|
86
|
+
) -> MakeRequestOutput:
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
assert (
|
|
90
|
+
"Make request action function can only have one MakeRequestParams parameter, but found 2: ['params', 'params2']"
|
|
76
91
|
in str(exception_info)
|
|
77
92
|
)
|
|
78
93
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from pydantic import ValidationError
|
|
3
|
+
|
|
4
|
+
from soar_sdk.params import Param, Params, MakeRequestParams
|
|
5
|
+
|
|
6
|
+
from tests.stubs import SampleActionParams
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_models_have_params_validated():
|
|
10
|
+
with pytest.raises(ValidationError):
|
|
11
|
+
SampleActionParams(field1="five")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_sensitive_param_must_be_str():
|
|
15
|
+
class BrokenParams(Params):
|
|
16
|
+
secret: bool = Param(sensitive=True)
|
|
17
|
+
|
|
18
|
+
with pytest.raises(TypeError) as e:
|
|
19
|
+
BrokenParams._to_json_schema()
|
|
20
|
+
|
|
21
|
+
assert e.match("Sensitive parameter secret must be type str, not bool")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_make_request_params_validation():
|
|
25
|
+
with pytest.raises(TypeError) as e:
|
|
26
|
+
|
|
27
|
+
class BrokenMakeRequestParams(MakeRequestParams):
|
|
28
|
+
not_allowed: str = Param(description="Not allowed")
|
|
29
|
+
|
|
30
|
+
assert (
|
|
31
|
+
str(e.value)
|
|
32
|
+
== "MakeRequestParams subclass 'BrokenMakeRequestParams' can only define these fields: ['body', 'endpoint', 'headers', 'http_method', 'query_parameters', 'timeout', 'verify_ssl']. Invalid fields: ['not_allowed']"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_make_request_params_subclass_schema():
|
|
37
|
+
class MakeRequestParamsSubclass(MakeRequestParams):
|
|
38
|
+
query_parameters: str = Param(description="Query parameters for virustotal")
|
|
39
|
+
|
|
40
|
+
assert (
|
|
41
|
+
MakeRequestParamsSubclass._to_json_schema()["query_parameters"]["description"]
|
|
42
|
+
== "Query parameters for virustotal"
|
|
43
|
+
)
|
|
@@ -1291,7 +1291,7 @@ wheels = [
|
|
|
1291
1291
|
|
|
1292
1292
|
[[package]]
|
|
1293
1293
|
name = "splunk-soar-sdk"
|
|
1294
|
-
version = "2.3.
|
|
1294
|
+
version = "2.3.2"
|
|
1295
1295
|
source = { editable = "." }
|
|
1296
1296
|
dependencies = [
|
|
1297
1297
|
{ name = "beautifulsoup4", marker = "(python_full_version < '3.10' and platform_machine == 'arm64' and sys_platform == 'darwin') or (python_full_version >= '3.13' and platform_machine == 'arm64' and sys_platform == 'darwin') or (python_full_version < '3.10' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version >= '3.13' and platform_machine == 'x86_64' and sys_platform == 'darwin') or (python_full_version < '3.10' and platform_machine == 'aarch64' and sys_platform == 'linux') or (python_full_version >= '3.13' and platform_machine == 'aarch64' and sys_platform == 'linux') or (python_full_version < '3.10' and platform_machine == 'x86_64' and sys_platform == 'linux') or (python_full_version >= '3.13' and platform_machine == 'x86_64' and sys_platform == 'linux')" },
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# [2.3.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.2.0...2.3.0) (2025-10-02)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
### Bug Fixes
|
|
5
|
-
|
|
6
|
-
* get rid of column_order and maintain counter instead ([c9b011d](https://github.com/phantomcyber/splunk-soar-sdk/commit/c9b011d84688f22b5ac2aa7f32a29468762ebe0d))
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Features
|
|
10
|
-
|
|
11
|
-
* adding column name and column order to params as well ([69a752e](https://github.com/phantomcyber/splunk-soar-sdk/commit/69a752e19d9c730ef319277480aa0a24fca03c2e))
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
# [2.3.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/2.2.0...2.3.0) (2025-10-02)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
### Bug Fixes
|
|
21
|
-
|
|
22
|
-
* get rid of column_order and maintain counter instead ([c9b011d](https://github.com/phantomcyber/splunk-soar-sdk/commit/c9b011d84688f22b5ac2aa7f32a29468762ebe0d))
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### Features
|
|
26
|
-
|
|
27
|
-
* adding column name and column order to params as well ([69a752e](https://github.com/phantomcyber/splunk-soar-sdk/commit/69a752e19d9c730ef319277480aa0a24fca03c2e))
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.3.0
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from pydantic import ValidationError
|
|
3
|
-
|
|
4
|
-
from soar_sdk.params import Param, Params
|
|
5
|
-
|
|
6
|
-
from tests.stubs import SampleActionParams
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def test_models_have_params_validated():
|
|
10
|
-
with pytest.raises(ValidationError):
|
|
11
|
-
SampleActionParams(field1="five")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def test_sensitive_param_must_be_str():
|
|
15
|
-
class BrokenParams(Params):
|
|
16
|
-
secret: bool = Param(sensitive=True)
|
|
17
|
-
|
|
18
|
-
with pytest.raises(TypeError) as e:
|
|
19
|
-
BrokenParams._to_json_schema()
|
|
20
|
-
|
|
21
|
-
assert e.match("Sensitive parameter secret must be type str, not bool")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|