splunk-soar-sdk 1.3.3__tar.gz → 1.4.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.
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/workflows/generate_docs.yml +1 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.pre-commit-config.yaml +0 -3
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/PKG-INFO +1 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/pyproject.toml +1 -1
- splunk_soar_sdk-1.4.0/release_notes.txt +21 -0
- splunk_soar_sdk-1.4.0/release_version.txt +1 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/abstract.py +8 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/action_results.py +2 -3
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/actions_manager.py +16 -2
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app.py +3 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_client.py +9 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/manifests/cli.py +2 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/manifests/deserializers.py +53 -17
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/on_poll.py +2 -5
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/params.py +10 -17
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/template_renderer.py +43 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/app.py +2 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app_action.py +2 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app_client.py +4 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/uv.lock +1 -1
- splunk_soar_sdk-1.3.3/release_notes.txt +0 -23
- splunk_soar_sdk-1.3.3/release_version.txt +0 -1
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/ISSUE_TEMPLATE/bug.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/pull_request_template.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/utils/github.js +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/utils/update_version.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/workflows/code_quality.yml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/workflows/commit_hygiene.yml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.github/workflows/semantic_release.yml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.gitignore +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/.releaserc +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/LICENSE +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/README.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/commitlint.config.js +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/api_reference.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/app_structure/index.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/app_structure/pre-commit-config.yaml.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/app_structure/pyproject.toml.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/app_structure/src_app.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/changelog.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/cli_reference.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/conf.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/custom_views/index.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/custom_views/reusable_components.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/custom_views/templates.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/custom_views/view_handlers.md +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/getting_started/index.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/getting_started/init_app.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/getting_started/installation.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/index.rst +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/apis/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/apis/artifact.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/apis/container.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/apis/utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/apis/vault.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_cli_runner.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/.gitignore +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/.pre-commit-config.yaml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/logo.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/logo_dark.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/src/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/app_templates/basic_app/uv.lock +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/asset.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/async_utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/init/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/init/cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/manifests/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/manifests/processors.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/manifests/serializers.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/package/cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/package/utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/path_utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/cli/utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/action_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/app_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/asset_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/templates/pyproject.toml.jinja +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/code_renderers/toml_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/colors.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/compat.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/crypto.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/action.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/generic_action.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/test_connectivity.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/view_handler.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/decorators/webhook.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/exceptions.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/input_spec.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/logging.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/actions.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/adapters.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/app.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/datatypes.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/dependencies.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/meta/webhooks.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/models/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/models/artifact.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/models/container.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/models/vault_attachment.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/models/view.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/paths.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/py.typed +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/action_result.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/app.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/base_connector.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/connector_result.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/consts.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/encryption_helper.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/install_info.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/json_keys.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/ph_ipc.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom/vault.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom_common/app_interface/app_interface.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/shims/phantom_common/encryption/encryption_manager_factory.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/base/base_template.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/base/error.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/base/header.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/base/logo_header.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/components/pie_chart.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/widgets/widget_resize_snippet.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/templates/widgets/widget_template.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/types.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/component_registry.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/components/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/components/pie_chart.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/template_filters.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/views/view_parser.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/webhooks/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/webhooks/models.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/src/soar_sdk/webhooks/routing.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/test.png +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/test.txt +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/datapath_parse.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/manifests/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/manifests/test_processors.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_assets/converted_app/actions.py.txt +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_convert_cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_deserializers.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_init_cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_manifests_cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_package_cli.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_serializers.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/cli/test_utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/code_renderers/test_action_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/conftest.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/app.json +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/example_asset.json +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/logo.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/logo_dark.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/pyproject.toml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/actions/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/actions/async_action.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/actions/generate_category.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/actions/reverse_string.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/src/ignoreme.txt +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/templates/reverse_string.html +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app/uv.lock +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/app.json +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/logo.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/logo_dark.svg +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/pyproject.toml +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/src/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/src/app.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/example_app_with_webhook/uv.lock +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/interfaces/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/interfaces/test_artifact_interface.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/interfaces/test_container_interface.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/interfaces/test_vault_interface.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/test_actions.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/test_adapters.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/test_datatypes.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/test_dependencies.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/meta/test_webhooks.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/mocks/__init__.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/mocks/dynamic_mocks.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/mocks/importable_action.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/stubs.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_action_results.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_actions_manager.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app_action_params.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app_action_results.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_app_runner.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_asset.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_assets/splunk-sdk-2.1.0.tar.gz +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_async_integration.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_async_utils.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_code_renderers.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_compat.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_container.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_custom_views.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_encryption.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_generic_action.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_logging.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_on_poll.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_params.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_template_renderer.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_test_connectivity.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/test_view_parser.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/webhooks/test_models.py +0 -0
- {splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/tests/webhooks/test_routing.py +0 -0
|
@@ -26,7 +26,6 @@ repos:
|
|
|
26
26
|
rev: 6.3.0
|
|
27
27
|
hooks:
|
|
28
28
|
- id: pydocstyle
|
|
29
|
-
name: pydocstyle (warning only)
|
|
30
29
|
args:
|
|
31
30
|
- --convention=google
|
|
32
31
|
- --add-ignore=D100,D104,D105,D107
|
|
@@ -34,8 +33,6 @@ repos:
|
|
|
34
33
|
exclude: ^(src/soar_sdk/shims/)
|
|
35
34
|
additional_dependencies: [tomli]
|
|
36
35
|
verbose: true
|
|
37
|
-
# Override the command to make it non-blocking
|
|
38
|
-
entry: bash -c 'pydocstyle "$@" || true' --
|
|
39
36
|
|
|
40
37
|
- repo: local
|
|
41
38
|
hooks:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: splunk-soar-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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,21 @@
|
|
|
1
|
+
# [1.4.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/1.3.4...1.4.0) (2025-09-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* function to get container id on soar client ([2329956](https://github.com/phantomcyber/splunk-soar-sdk/commit/232995679cc5c568fc9ebd895c96aaf8f3f6448e))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# [1.4.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/1.3.4...1.4.0) (2025-09-10)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
* function to get container id on soar client ([2329956](https://github.com/phantomcyber/splunk-soar-sdk/commit/232995679cc5c568fc9ebd895c96aaf8f3f6448e))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.4.0
|
|
@@ -63,6 +63,11 @@ class SOARClient(Generic[SummaryType]):
|
|
|
63
63
|
"""Object governing interaction with the SOAR container API. Subclasses must define."""
|
|
64
64
|
pass
|
|
65
65
|
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def get_executing_container_id(self) -> int:
|
|
68
|
+
"""Return the current Container ID passed in the Connector Run Action JSON."""
|
|
69
|
+
pass
|
|
70
|
+
|
|
66
71
|
def get(
|
|
67
72
|
self,
|
|
68
73
|
endpoint: str,
|
|
@@ -202,7 +207,9 @@ class SOARClient(Generic[SummaryType]):
|
|
|
202
207
|
return "https://localhost:9999/"
|
|
203
208
|
|
|
204
209
|
@abstractmethod
|
|
205
|
-
def update_client(
|
|
210
|
+
def update_client(
|
|
211
|
+
self, soar_auth: SOARClientAuth, asset_id: str, container_id: int = 0
|
|
212
|
+
) -> None:
|
|
206
213
|
"""Hook to update the SOAR API client before any actions run with the input data.
|
|
207
214
|
|
|
208
215
|
An example of what this function might do is authenticate the API client.
|
|
@@ -151,9 +151,7 @@ class ActionOutput(BaseModel):
|
|
|
151
151
|
"""
|
|
152
152
|
|
|
153
153
|
def generate_action_summary_message(self) -> str:
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
Generate a summary message for the action output.
|
|
154
|
+
"""Generate a summary message for the action output.
|
|
157
155
|
|
|
158
156
|
This method provides a human-readable summary of the action results,
|
|
159
157
|
which appears when running the action in a SOAR playbook or container.
|
|
@@ -161,6 +159,7 @@ class ActionOutput(BaseModel):
|
|
|
161
159
|
Returns:
|
|
162
160
|
A string summarizing the action output.
|
|
163
161
|
|
|
162
|
+
.. deprecated:: 1.3.0
|
|
164
163
|
"""
|
|
165
164
|
return "Action completed successfully."
|
|
166
165
|
|
|
@@ -97,8 +97,12 @@ class ActionsManager(BaseConnector):
|
|
|
97
97
|
raise RuntimeError(f"Action {action_id} not found.")
|
|
98
98
|
|
|
99
99
|
def initialize(self) -> bool:
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
"""Load asset state into memory at initialization, splitting it into 3 categories.
|
|
101
|
+
|
|
102
|
+
Asset state is used to store data that needs to be accessed across actions.
|
|
103
|
+
Chiefly, it is used to store ingestion state, authentication state, and/or
|
|
104
|
+
used as an asset cache. Returns True only to conform with the BaseConnector interface.
|
|
105
|
+
"""
|
|
102
106
|
state = self.load_state() or {}
|
|
103
107
|
self.ingestion_state = state.get(_INGEST_STATE_KEY, {})
|
|
104
108
|
self.auth_state = state.get(_AUTH_STATE_KEY, {})
|
|
@@ -107,6 +111,12 @@ class ActionsManager(BaseConnector):
|
|
|
107
111
|
return True
|
|
108
112
|
|
|
109
113
|
def finalize(self) -> bool:
|
|
114
|
+
"""Save asset state from memory into persistent storage at finalization.
|
|
115
|
+
|
|
116
|
+
Joins the SDK's 3 categories of asset state into a single dictionary, conforming
|
|
117
|
+
to the platform's expectations, and saves it.
|
|
118
|
+
Returns True only to conform with the BaseConnector interface.
|
|
119
|
+
"""
|
|
110
120
|
state = {
|
|
111
121
|
_INGEST_STATE_KEY: self.ingestion_state,
|
|
112
122
|
_AUTH_STATE_KEY: self.auth_state,
|
|
@@ -116,12 +126,15 @@ class ActionsManager(BaseConnector):
|
|
|
116
126
|
return True
|
|
117
127
|
|
|
118
128
|
def add_result(self, action_result: PhantomActionResult) -> PhantomActionResult:
|
|
129
|
+
"""Wrapper for BaseConnector's add_action_result method."""
|
|
119
130
|
return self.add_action_result(action_result)
|
|
120
131
|
|
|
121
132
|
def get_results(self) -> list[PhantomActionResult]:
|
|
133
|
+
"""Wrapper for BaseConnector's get_action_results method."""
|
|
122
134
|
return self.get_action_results()
|
|
123
135
|
|
|
124
136
|
def add_exception(self, exception: Exception) -> None:
|
|
137
|
+
"""Public method for adding an exception to an app run result set."""
|
|
125
138
|
self._BaseConnector__conn_result.add_exception(exception)
|
|
126
139
|
|
|
127
140
|
def set_csrf_info(self, token: str, referer: str) -> None:
|
|
@@ -130,4 +143,5 @@ class ActionsManager(BaseConnector):
|
|
|
130
143
|
|
|
131
144
|
@classmethod
|
|
132
145
|
def get_soar_base_url(cls) -> str:
|
|
146
|
+
"""Get the base URL of the Splunk SOAR instance this app is running on."""
|
|
133
147
|
return cls._get_phantom_base_url()
|
|
@@ -187,7 +187,9 @@ class App:
|
|
|
187
187
|
|
|
188
188
|
self.__logger.handler.set_handle(handle)
|
|
189
189
|
soar_auth = App.create_soar_client_auth_object(input_data)
|
|
190
|
-
self.soar_client.update_client(
|
|
190
|
+
self.soar_client.update_client(
|
|
191
|
+
soar_auth, input_data.asset_id, input_data.container_id
|
|
192
|
+
)
|
|
191
193
|
return self.actions_manager.handle(input_data, handle=handle)
|
|
192
194
|
|
|
193
195
|
@staticmethod
|
|
@@ -45,6 +45,7 @@ class AppClient(SOARClient[SummaryType]):
|
|
|
45
45
|
|
|
46
46
|
self._summary: Optional[SummaryType] = None
|
|
47
47
|
self._message: Optional[str] = None
|
|
48
|
+
self.__container_id: int = 0
|
|
48
49
|
|
|
49
50
|
@property
|
|
50
51
|
def client(self) -> httpx.Client:
|
|
@@ -66,10 +67,17 @@ class AppClient(SOARClient[SummaryType]):
|
|
|
66
67
|
"""The SOAR Vault API."""
|
|
67
68
|
return self._vault_api
|
|
68
69
|
|
|
69
|
-
def
|
|
70
|
+
def get_executing_container_id(self) -> int:
|
|
71
|
+
"""Return the current Container ID passed in the Connector Run Action JSON."""
|
|
72
|
+
return self.__container_id
|
|
73
|
+
|
|
74
|
+
def update_client(
|
|
75
|
+
self, soar_auth: SOARClientAuth, asset_id: str, container_id: int = 0
|
|
76
|
+
) -> None:
|
|
70
77
|
"""Update the SOAR client with the given authentication and asset ID."""
|
|
71
78
|
self.authenticate_soar_client(soar_auth)
|
|
72
79
|
self._containers_api.set_executing_asset(asset_id)
|
|
80
|
+
self.__container_id = container_id
|
|
73
81
|
|
|
74
82
|
def authenticate_soar_client(self, soar_auth: SOARClientAuth) -> None:
|
|
75
83
|
"""Authenticate the SOAR client with the given authentication credentials."""
|
|
@@ -10,6 +10,7 @@ manifests = typer.Typer()
|
|
|
10
10
|
|
|
11
11
|
@manifests.command()
|
|
12
12
|
def display(filename: str) -> None:
|
|
13
|
+
"""Parse and print the contents of a manifest JSON file."""
|
|
13
14
|
with open(filename) as f:
|
|
14
15
|
meta = json.load(f)
|
|
15
16
|
|
|
@@ -18,4 +19,5 @@ def display(filename: str) -> None:
|
|
|
18
19
|
|
|
19
20
|
@manifests.command()
|
|
20
21
|
def create(filename: str, project_context: str) -> None:
|
|
22
|
+
"""Create a manifest file from the given project context."""
|
|
21
23
|
ManifestProcessor(filename, project_context).create()
|
|
@@ -14,6 +14,11 @@ from soar_sdk.meta.datatypes import to_python_type
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class DeserializedAppMeta(NamedTuple):
|
|
17
|
+
"""Named tuple containing a deserialized app metadata and related info.
|
|
18
|
+
|
|
19
|
+
Used to return multiple values from AppMetaDeserializer.from_app_json.
|
|
20
|
+
"""
|
|
21
|
+
|
|
17
22
|
app_meta: AppMeta
|
|
18
23
|
actions_with_custom_views: list[str]
|
|
19
24
|
has_rest_handlers: bool
|
|
@@ -21,8 +26,19 @@ class DeserializedAppMeta(NamedTuple):
|
|
|
21
26
|
|
|
22
27
|
|
|
23
28
|
class AppMetaDeserializer:
|
|
29
|
+
"""Namespace class responsible for deserializing an AppMeta from a JSON manifest file."""
|
|
30
|
+
|
|
24
31
|
@staticmethod
|
|
25
32
|
def from_app_json(json_path: Path) -> DeserializedAppMeta:
|
|
33
|
+
"""Deserialize an AppMeta from a JSON manifest file.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
json_path: The path to the JSON manifest file.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
A DeserializedAppMeta named tuple containing the AppMeta and info
|
|
40
|
+
about actions with custom views, REST handlers, and webhooks.
|
|
41
|
+
"""
|
|
26
42
|
manifest: dict[str, Any] = json.loads(json_path.read_text())
|
|
27
43
|
|
|
28
44
|
# Massage the python_version field, which may be a comma-separated string
|
|
@@ -60,12 +76,16 @@ class AppMetaDeserializer:
|
|
|
60
76
|
|
|
61
77
|
|
|
62
78
|
class FieldSpec(NamedTuple):
|
|
79
|
+
"""Named tuple representing the metadata required to create a pydantic field specification."""
|
|
80
|
+
|
|
63
81
|
type_: type
|
|
64
82
|
default: Any
|
|
65
83
|
|
|
66
84
|
|
|
67
85
|
@dataclasses.dataclass
|
|
68
86
|
class OutputFieldModel:
|
|
87
|
+
"""Canonical representation of an output field specification in an app manifest."""
|
|
88
|
+
|
|
69
89
|
data_path: str
|
|
70
90
|
data_type: str
|
|
71
91
|
contains: Optional[list[str]] = None
|
|
@@ -75,13 +95,29 @@ class OutputFieldModel:
|
|
|
75
95
|
|
|
76
96
|
|
|
77
97
|
class DeserializedActionMeta(NamedTuple):
|
|
98
|
+
"""Named tuple containing a deserialized action metadata and related info.
|
|
99
|
+
|
|
100
|
+
Used to return multiple values from ActionDeserializer.from_app_json.
|
|
101
|
+
"""
|
|
102
|
+
|
|
78
103
|
action_meta: ActionMeta
|
|
79
104
|
has_custom_view: bool
|
|
80
105
|
|
|
81
106
|
|
|
82
107
|
class ActionDeserializer:
|
|
108
|
+
"""Namespace class responsible for deserializing an ActionMeta from a JSON action definition."""
|
|
109
|
+
|
|
83
110
|
@classmethod
|
|
84
111
|
def from_action_json(cls, action: dict[str, Any]) -> DeserializedActionMeta:
|
|
112
|
+
"""Deserialize an ActionMeta from a JSON action definition.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
action: The JSON dictionary representing the action.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
A DeserializedActionMeta named tuple containing the ActionMeta and
|
|
119
|
+
info about whether the action has a custom view.
|
|
120
|
+
"""
|
|
85
121
|
action["parameters"] = cls.parse_parameters(
|
|
86
122
|
action["action"], action.get("parameters", {})
|
|
87
123
|
)
|
|
@@ -95,9 +131,7 @@ class ActionDeserializer:
|
|
|
95
131
|
def parse_parameters(
|
|
96
132
|
cls, action_name: str, parameters: dict[str, Any]
|
|
97
133
|
) -> type[Params]:
|
|
98
|
-
"""
|
|
99
|
-
Parses the parameters from a dictionary to generate a Params model class
|
|
100
|
-
"""
|
|
134
|
+
"""Parses the parameters from a dictionary to generate a Params model class."""
|
|
101
135
|
# If no parameters, return base Params class
|
|
102
136
|
if not parameters:
|
|
103
137
|
return Params
|
|
@@ -122,9 +156,7 @@ class ActionDeserializer:
|
|
|
122
156
|
|
|
123
157
|
@staticmethod
|
|
124
158
|
def _create_param_field(param_spec: dict[str, Any]) -> FieldSpec:
|
|
125
|
-
"""
|
|
126
|
-
Create a parameter field from a parameter specification.
|
|
127
|
-
"""
|
|
159
|
+
"""Create a parameter field from a parameter specification."""
|
|
128
160
|
# Get the Python type from data_type
|
|
129
161
|
data_type = param_spec.get("data_type", "string")
|
|
130
162
|
python_type = to_python_type(data_type)
|
|
@@ -147,9 +179,7 @@ class ActionDeserializer:
|
|
|
147
179
|
def parse_output(
|
|
148
180
|
cls, action_name: str, output: list[OutputFieldSpecification]
|
|
149
181
|
) -> type[ActionOutput]:
|
|
150
|
-
"""
|
|
151
|
-
Parses the output from a list of OutputFieldSpecification to generate an ActionOutput model class
|
|
152
|
-
"""
|
|
182
|
+
"""Parses a list of OutputFieldSpecification to generate an ActionOutput model class."""
|
|
153
183
|
# Filter out automatic fields and extract the action's real output fields
|
|
154
184
|
output_fields = cls._filter_output_fields(output)
|
|
155
185
|
|
|
@@ -173,8 +203,7 @@ class ActionDeserializer:
|
|
|
173
203
|
def _build_output_structure(
|
|
174
204
|
datapath_specs: dict[str, OutputFieldModel],
|
|
175
205
|
) -> dict[str, Union[list, dict, OutputFieldModel]]:
|
|
176
|
-
"""
|
|
177
|
-
Parse a datapath string into a dictionary.
|
|
206
|
+
"""Parse a datapath string into a dictionary.
|
|
178
207
|
|
|
179
208
|
Args:
|
|
180
209
|
datapath_specs: The set of datapaths and their types to parse.
|
|
@@ -261,9 +290,10 @@ class ActionDeserializer:
|
|
|
261
290
|
action_name: str,
|
|
262
291
|
output_structure: dict[str, Union[dict, list, OutputFieldModel]],
|
|
263
292
|
) -> type[ActionOutput]:
|
|
264
|
-
"""
|
|
265
|
-
|
|
266
|
-
|
|
293
|
+
"""Build dynamic pydantic models for an action output, from the output data paths.
|
|
294
|
+
|
|
295
|
+
This function is part of a depth-first recursive approach to build nested
|
|
296
|
+
models, in tandem with _build_output_field.
|
|
267
297
|
|
|
268
298
|
Returns:
|
|
269
299
|
A dynamically created ActionOutput class with nested structure based on the output fields.
|
|
@@ -285,6 +315,14 @@ class ActionDeserializer:
|
|
|
285
315
|
def _build_output_field(
|
|
286
316
|
cls, field_name: str, output_structure: Union[list, dict, OutputFieldModel]
|
|
287
317
|
) -> tuple[str, FieldSpec]:
|
|
318
|
+
"""Build dynamic specs for an action output field, from an output data path.
|
|
319
|
+
|
|
320
|
+
This function is part of a depth-first recursive approach to build nested
|
|
321
|
+
models, in tandem with _build_output_class.
|
|
322
|
+
|
|
323
|
+
Returns:
|
|
324
|
+
A tuple containing the normalized field name and its FieldSpec.
|
|
325
|
+
"""
|
|
288
326
|
normalized_name = normalize_field_name(field_name)
|
|
289
327
|
|
|
290
328
|
# Base case: primitive (leaf node) output field
|
|
@@ -331,9 +369,7 @@ class ActionDeserializer:
|
|
|
331
369
|
def _filter_output_fields(
|
|
332
370
|
output: list[OutputFieldSpecification],
|
|
333
371
|
) -> list[OutputFieldSpecification]:
|
|
334
|
-
"""
|
|
335
|
-
Filter out automatic fields and extract the action's real output fields.
|
|
336
|
-
"""
|
|
372
|
+
"""Filter out automatic fields and extract the action's real output fields."""
|
|
337
373
|
output_fields: list[OutputFieldSpecification] = []
|
|
338
374
|
for output_spec in output:
|
|
339
375
|
data_path = output_spec["data_path"].removeprefix("action_result.")
|
|
@@ -20,16 +20,13 @@ if TYPE_CHECKING:
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class OnPollDecorator:
|
|
23
|
-
"""
|
|
24
|
-
Class-based decorator for on_poll functionality.
|
|
25
|
-
"""
|
|
23
|
+
"""Class-based decorator for tagging a function as the special 'on poll' action."""
|
|
26
24
|
|
|
27
25
|
def __init__(self, app: "App") -> None:
|
|
28
26
|
self.app = app
|
|
29
27
|
|
|
30
28
|
def __call__(self, function: Callable) -> Action:
|
|
31
|
-
"""
|
|
32
|
-
Decorator for the on_poll action.
|
|
29
|
+
"""Decorator for the 'on poll' action.
|
|
33
30
|
|
|
34
31
|
The decorated function must be a generator (using yield) or return an Iterator that yields Container and/or Artifact objects. Only one on_poll action is allowed per app.
|
|
35
32
|
|
|
@@ -22,11 +22,10 @@ def Param(
|
|
|
22
22
|
allow_list: bool = False,
|
|
23
23
|
sensitive: bool = False,
|
|
24
24
|
) -> Any: # noqa: ANN401
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
JSON file and fills in defaults.
|
|
25
|
+
"""Representation of a single complex action parameter.
|
|
26
|
+
|
|
27
|
+
Use this function to define the default value for an action parameter that requires
|
|
28
|
+
extra metadata for the manifest. This function is a thin wrapper around pydantic.Field.
|
|
30
29
|
|
|
31
30
|
:param order: The order key, starting at 0, allows the app
|
|
32
31
|
author to control the display order of the controls in the UI.
|
|
@@ -69,6 +68,8 @@ def Param(
|
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
class InputFieldSpecification(TypedDict):
|
|
71
|
+
"""Canonical data format for the JSON dictionary given to action runs by the SOAR platform."""
|
|
72
|
+
|
|
72
73
|
order: int
|
|
73
74
|
name: str
|
|
74
75
|
description: str
|
|
@@ -82,9 +83,9 @@ class InputFieldSpecification(TypedDict):
|
|
|
82
83
|
|
|
83
84
|
|
|
84
85
|
class Params(BaseModel):
|
|
85
|
-
"""
|
|
86
|
-
Params defines the inputs for an action. It can contain strings, booleans, or numbers -- no lists or dictionaries.
|
|
86
|
+
"""Params defines the full set of inputs for an action.
|
|
87
87
|
|
|
88
|
+
It can contain strings, booleans, or numbers -- no lists or dictionaries.
|
|
88
89
|
Params fields can be optional if desired, or optionally have a default value, CEF type, and other metadata defined in soar_sdk.params.Param.
|
|
89
90
|
"""
|
|
90
91
|
|
|
@@ -140,11 +141,7 @@ class Params(BaseModel):
|
|
|
140
141
|
|
|
141
142
|
|
|
142
143
|
class OnPollParams(Params):
|
|
143
|
-
"""
|
|
144
|
-
Parameters for on_poll.
|
|
145
|
-
|
|
146
|
-
Used to define the specific parameters for the on_poll action.
|
|
147
|
-
"""
|
|
144
|
+
"""Canonical parameters for the special 'on poll' action."""
|
|
148
145
|
|
|
149
146
|
start_time: int = Param(
|
|
150
147
|
description="Start of time range, in epoch time (milliseconds).",
|
|
@@ -174,11 +171,7 @@ class OnPollParams(Params):
|
|
|
174
171
|
|
|
175
172
|
|
|
176
173
|
class GenericActionParams(Params):
|
|
177
|
-
"""
|
|
178
|
-
Parameters for generic actions.
|
|
179
|
-
|
|
180
|
-
Used to define the specific parameters for the generic action.
|
|
181
|
-
"""
|
|
174
|
+
"""Canonical parameters for the special generic HTTP actions."""
|
|
182
175
|
|
|
183
176
|
http_method: str = Param(
|
|
184
177
|
description="The HTTP method to use for the request.",
|
|
@@ -60,6 +60,15 @@ class JinjaTemplateRenderer(TemplateRenderer):
|
|
|
60
60
|
setup_jinja_env(self.env)
|
|
61
61
|
|
|
62
62
|
def render_template(self, template_name: str, context: dict[str, Any]) -> str:
|
|
63
|
+
"""Render a template with its name and the given context.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
template_name: The name of the template to render.
|
|
67
|
+
context: The context dictionary to pass to the Jinja rendering engine.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The rendered template as a string.
|
|
71
|
+
"""
|
|
63
72
|
template = self.env.get_template(template_name)
|
|
64
73
|
return template.render(**context)
|
|
65
74
|
|
|
@@ -70,6 +79,17 @@ class JinjaTemplateRenderer(TemplateRenderer):
|
|
|
70
79
|
function_name: str,
|
|
71
80
|
template_name: str,
|
|
72
81
|
) -> str:
|
|
82
|
+
"""Render the standard error template with error information.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
error_type: The type or category of the error.
|
|
86
|
+
error_message: A descriptive error message.
|
|
87
|
+
function_name: The name of the function where the error occurred.
|
|
88
|
+
template_name: The name of the template being rendered.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
The rendered error template as a string.
|
|
92
|
+
"""
|
|
73
93
|
try:
|
|
74
94
|
template = self.env.get_template(ERROR_TEMPLATE_PATH)
|
|
75
95
|
|
|
@@ -89,6 +109,21 @@ class JinjaTemplateRenderer(TemplateRenderer):
|
|
|
89
109
|
def get_template_renderer(
|
|
90
110
|
engine: Optional[str] = None, templates_dir: Optional[str] = None
|
|
91
111
|
) -> TemplateRenderer:
|
|
112
|
+
"""Factory function to get the appropriate template renderer.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
engine: The template engine to use (default is "jinja").
|
|
116
|
+
templates_dir: The directory where templates are located (default is "./templates").
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
An instance of the appropriate TemplateRenderer subclass.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
ValueError: If an unsupported template engine is specified.
|
|
123
|
+
|
|
124
|
+
.. note::
|
|
125
|
+
Currently, only the Jinja2 template engine is supported.
|
|
126
|
+
"""
|
|
92
127
|
if engine is None:
|
|
93
128
|
engine = DEFAULT_TEMPLATE_ENGINE
|
|
94
129
|
|
|
@@ -102,6 +137,14 @@ def get_template_renderer(
|
|
|
102
137
|
|
|
103
138
|
|
|
104
139
|
def get_templates_dir(function_globals: dict[str, Any]) -> str:
|
|
140
|
+
"""Determine an app's templates directory based on a view handler's file location.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
function_globals: The ``.__globals`` dictionary from a view handler function.
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
The path to the templates directory as a string.
|
|
147
|
+
"""
|
|
105
148
|
caller_file = function_globals.get("__file__")
|
|
106
149
|
if caller_file:
|
|
107
150
|
app_dir = Path(caller_file).parent
|
|
@@ -43,6 +43,8 @@ app = App(
|
|
|
43
43
|
@app.test_connectivity()
|
|
44
44
|
def test_connectivity(soar: SOARClient, asset: Asset) -> None:
|
|
45
45
|
soar.get("rest/version")
|
|
46
|
+
container_id = soar.get_executing_container_id()
|
|
47
|
+
logger.info(f"current executing container's container_id is: {container_id}")
|
|
46
48
|
logger.info(f"testing connectivity against {asset.base_url}")
|
|
47
49
|
logger.debug("hello")
|
|
48
50
|
logger.warning("this is a warning")
|
|
@@ -198,7 +198,8 @@ def test_action_decoration_uses_meta_identifier_for_action_name(simple_app):
|
|
|
198
198
|
def test_action_with_mocked_client(simple_app, sample_params):
|
|
199
199
|
@simple_app.action()
|
|
200
200
|
def action_function(params: SampleParams, soar: SOARClient) -> ActionOutput:
|
|
201
|
-
soar.
|
|
201
|
+
container_id = str(soar.get_executing_container_id())
|
|
202
|
+
soar.save_progress(f"Container ID is: {container_id}")
|
|
202
203
|
|
|
203
204
|
client_mock = mock.Mock()
|
|
204
205
|
client_mock.save_progress = mock.Mock()
|
|
@@ -31,3 +31,7 @@ def test_authenticate_soar_client_on_platform(
|
|
|
31
31
|
):
|
|
32
32
|
simple_connector.authenticate_soar_client(soar_client_auth_token)
|
|
33
33
|
assert mock_get_any_soar_call.call_count == 1
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_get_executing_container_id(simple_connector: AppClient):
|
|
37
|
+
assert simple_connector.get_executing_container_id() == 0
|
|
@@ -1291,7 +1291,7 @@ wheels = [
|
|
|
1291
1291
|
|
|
1292
1292
|
[[package]]
|
|
1293
1293
|
name = "splunk-soar-sdk"
|
|
1294
|
-
version = "1.
|
|
1294
|
+
version = "1.4.0"
|
|
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,23 +0,0 @@
|
|
|
1
|
-
## [1.3.3](https://github.com/phantomcyber/splunk-soar-sdk/compare/1.3.2...1.3.3) (2025-09-08)
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
### Bug Fixes
|
|
5
|
-
|
|
6
|
-
* **docs:** resolve a lot of pydocstyle warnings ([0e4fce6](https://github.com/phantomcyber/splunk-soar-sdk/commit/0e4fce648ae3a76fa64e319a34c2ad14a33783a4))
|
|
7
|
-
* **docs:** use 'Splunk SOAR' everywhere ([adaa616](https://github.com/phantomcyber/splunk-soar-sdk/commit/adaa6168159a7a9f50be3d024fb9af33a3ebd817))
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## [1.3.3](https://github.com/phantomcyber/splunk-soar-sdk/compare/1.3.2...1.3.3) (2025-09-08)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
### Bug Fixes
|
|
17
|
-
|
|
18
|
-
* **docs:** resolve a lot of pydocstyle warnings ([0e4fce6](https://github.com/phantomcyber/splunk-soar-sdk/commit/0e4fce648ae3a76fa64e319a34c2ad14a33783a4))
|
|
19
|
-
* **docs:** use 'Splunk SOAR' everywhere ([adaa616](https://github.com/phantomcyber/splunk-soar-sdk/commit/adaa6168159a7a9f50be3d024fb9af33a3ebd817))
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.3.3
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{splunk_soar_sdk-1.3.3 → splunk_soar_sdk-1.4.0}/docs/app_structure/pre-commit-config.yaml.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|