splunk-soar-sdk 3.6.1__tar.gz → 3.7.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.
Files changed (285) hide show
  1. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/PKG-INFO +3 -1
  2. splunk_soar_sdk-3.7.0/docs/authentication/basic.rst +18 -0
  3. splunk_soar_sdk-3.7.0/docs/authentication/index.rst +13 -0
  4. splunk_soar_sdk-3.7.0/docs/authentication/oauth.rst +168 -0
  5. splunk_soar_sdk-3.7.0/docs/authentication/static_token.rst +46 -0
  6. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/index.rst +1 -0
  7. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/pyproject.toml +4 -1
  8. splunk_soar_sdk-3.7.0/release_notes.txt +41 -0
  9. splunk_soar_sdk-3.7.0/release_version.txt +1 -0
  10. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/actions_manager.py +40 -0
  11. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app.py +52 -4
  12. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/asset.py +49 -69
  13. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/asset_state.py +13 -3
  14. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/__init__.py +41 -0
  15. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/client.py +540 -0
  16. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/factories.py +120 -0
  17. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/flows.py +172 -0
  18. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/httpx_auth.py +97 -0
  19. splunk_soar_sdk-3.7.0/src/soar_sdk/auth/models.py +101 -0
  20. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/package/cli.py +6 -4
  21. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/base_connector.py +7 -0
  22. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_convert_cli.py +4 -0
  23. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_deserializers.py +4 -0
  24. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/app.json +10 -5
  25. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/app.py +4 -2
  26. splunk_soar_sdk-3.7.0/tests/example_app_with_oauth/example_asset.json +11 -0
  27. splunk_soar_sdk-3.7.0/tests/example_app_with_oauth/logo.svg +1 -0
  28. splunk_soar_sdk-3.7.0/tests/example_app_with_oauth/logo_dark.svg +1 -0
  29. splunk_soar_sdk-3.7.0/tests/example_app_with_oauth/pyproject.toml +48 -0
  30. splunk_soar_sdk-3.7.0/tests/example_app_with_oauth/src/app.py +183 -0
  31. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/app.json +6 -3
  32. splunk_soar_sdk-3.7.0/tests/example_app_with_webhook/src/__init__.py +3 -0
  33. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_actions_manager.py +106 -0
  34. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app.py +111 -0
  35. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_asset.py +6 -2
  36. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_asset_state.py +19 -0
  37. splunk_soar_sdk-3.7.0/tests/test_oauth_certificate_client.py +304 -0
  38. splunk_soar_sdk-3.7.0/tests/test_oauth_client.py +784 -0
  39. splunk_soar_sdk-3.7.0/tests/test_oauth_factories.py +287 -0
  40. splunk_soar_sdk-3.7.0/tests/test_oauth_flows.py +379 -0
  41. splunk_soar_sdk-3.7.0/tests/test_oauth_httpx_auth.py +338 -0
  42. splunk_soar_sdk-3.7.0/tests/test_oauth_models.py +279 -0
  43. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/uv.lock +122 -1
  44. splunk_soar_sdk-3.6.1/release_notes.txt +0 -21
  45. splunk_soar_sdk-3.6.1/release_version.txt +0 -1
  46. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  47. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  48. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/pull_request_template.md +0 -0
  49. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/scripts/generate_test_summary.py +0 -0
  50. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/utils/github.js +0 -0
  51. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/utils/update_version.py +0 -0
  52. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/workflows/code_quality.yml +0 -0
  53. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/workflows/commit_hygiene.yml +0 -0
  54. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/workflows/generate_docs.yml +0 -0
  55. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/workflows/integration_tests.yml +0 -0
  56. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.github/workflows/semantic_release.yml +0 -0
  57. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.gitignore +0 -0
  58. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.pre-commit-config.yaml +0 -0
  59. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/.releaserc +0 -0
  60. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/LICENSE +0 -0
  61. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/README.md +0 -0
  62. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/commitlint.config.js +0 -0
  63. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/api_reference.rst +0 -0
  64. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/app_structure/index.rst +0 -0
  65. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/app_structure/pre-commit-config.yaml.rst +0 -0
  66. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/app_structure/pyproject.toml.rst +0 -0
  67. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/app_structure/src_app.rst +0 -0
  68. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/changelog.rst +0 -0
  69. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/cli_reference.rst +0 -0
  70. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/conf.py +0 -0
  71. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/custom_views/index.rst +0 -0
  72. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/custom_views/reusable_components.md +0 -0
  73. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/custom_views/templates.md +0 -0
  74. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/custom_views/view_handlers.md +0 -0
  75. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/defining_asset.rst +0 -0
  76. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/first_action.rst +0 -0
  77. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/index.rst +0 -0
  78. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/init_app.rst +0 -0
  79. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/installation.rst +0 -0
  80. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/docs/getting_started/testing_and_building.rst +0 -0
  81. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/README.md +0 -0
  82. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/install.sh +0 -0
  83. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/mcp_config.json +0 -0
  84. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/pyproject.toml +0 -0
  85. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/pytest.ini +0 -0
  86. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/src/soar_test_assistant/__init__.py +0 -0
  87. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/src/soar_test_assistant/server.py +0 -0
  88. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/tests/__init__.py +0 -0
  89. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/tests/test_analyzer.py +0 -0
  90. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/mcp_server/uv.lock +0 -0
  91. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/__init__.py +0 -0
  92. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/abstract.py +0 -0
  93. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/action_results.py +0 -0
  94. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/__init__.py +0 -0
  95. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/artifact.py +0 -0
  96. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/container.py +0 -0
  97. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/es/findings.py +0 -0
  98. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/utils.py +0 -0
  99. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/apis/vault.py +0 -0
  100. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_cli_runner.py +0 -0
  101. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_client.py +0 -0
  102. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/.gitignore +0 -0
  103. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/.pre-commit-config.yaml +0 -0
  104. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/logo.svg +0 -0
  105. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/logo_dark.svg +0 -0
  106. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/src/__init__.py +0 -0
  107. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/app_templates/basic_app/uv.lock +0 -0
  108. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/async_utils.py +0 -0
  109. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/__init__.py +0 -0
  110. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/cli.py +0 -0
  111. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/init/__init__.py +0 -0
  112. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/init/cli.py +0 -0
  113. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/manifests/__init__.py +0 -0
  114. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/manifests/cli.py +0 -0
  115. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/manifests/deserializers.py +0 -0
  116. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/manifests/processors.py +0 -0
  117. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/manifests/serializers.py +0 -0
  118. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/package/utils.py +0 -0
  119. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/path_utils.py +0 -0
  120. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/test/__init__.py +0 -0
  121. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/test/cli.py +0 -0
  122. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/cli/utils.py +0 -0
  123. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/__init__.py +0 -0
  124. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/action_renderer.py +0 -0
  125. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/app_renderer.py +0 -0
  126. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/asset_renderer.py +0 -0
  127. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/renderer.py +0 -0
  128. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/templates/pyproject.toml.jinja +0 -0
  129. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/code_renderers/toml_renderer.py +0 -0
  130. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/colors.py +0 -0
  131. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/compat.py +0 -0
  132. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/crypto.py +0 -0
  133. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/__init__.py +0 -0
  134. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/action.py +0 -0
  135. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/make_request.py +0 -0
  136. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/on_es_poll.py +0 -0
  137. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/on_poll.py +0 -0
  138. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/test_connectivity.py +0 -0
  139. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/view_handler.py +0 -0
  140. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/decorators/webhook.py +0 -0
  141. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/es_client.py +0 -0
  142. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/exceptions.py +0 -0
  143. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/extras/__init__.py +0 -0
  144. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/extras/email/__init__.py +0 -0
  145. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/extras/email/processor.py +0 -0
  146. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/extras/email/rfc5322.py +0 -0
  147. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/extras/email/utils.py +0 -0
  148. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/field_utils.py +0 -0
  149. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/input_spec.py +0 -0
  150. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/logging.py +0 -0
  151. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/__init__.py +0 -0
  152. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/actions.py +0 -0
  153. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/adapters.py +0 -0
  154. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/app.py +0 -0
  155. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/datatypes.py +0 -0
  156. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/dependencies.py +0 -0
  157. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/meta/webhooks.py +0 -0
  158. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/__init__.py +0 -0
  159. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/artifact.py +0 -0
  160. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/attachment_input.py +0 -0
  161. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/container.py +0 -0
  162. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/finding.py +0 -0
  163. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/vault_attachment.py +0 -0
  164. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/models/view.py +0 -0
  165. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/params.py +0 -0
  166. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/paths.py +0 -0
  167. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/py.typed +0 -0
  168. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/action_result.py +0 -0
  169. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/app.py +0 -0
  170. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/connector_result.py +0 -0
  171. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/consts.py +0 -0
  172. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/encryption_helper.py +0 -0
  173. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/install_info.py +0 -0
  174. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/json_keys.py +0 -0
  175. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/ph_ipc.py +0 -0
  176. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom/vault.py +0 -0
  177. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom_common/app_interface/app_interface.py +0 -0
  178. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/shims/phantom_common/encryption/encryption_manager_factory.py +0 -0
  179. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/base/base_template.html +0 -0
  180. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/base/error.html +0 -0
  181. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/base/header.html +0 -0
  182. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/base/logo_header.html +0 -0
  183. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/components/pie_chart.html +0 -0
  184. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/widgets/widget_resize_snippet.html +0 -0
  185. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/templates/widgets/widget_template.html +0 -0
  186. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/types.py +0 -0
  187. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/__init__.py +0 -0
  188. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/component_registry.py +0 -0
  189. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/components/__init__.py +0 -0
  190. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/components/pie_chart.py +0 -0
  191. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/template_filters.py +0 -0
  192. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/template_renderer.py +0 -0
  193. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/views/view_parser.py +0 -0
  194. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/webhooks/__init__.py +0 -0
  195. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/webhooks/models.py +0 -0
  196. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/src/soar_sdk/webhooks/routing.py +0 -0
  197. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/__init__.py +0 -0
  198. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/__init__.py +0 -0
  199. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/datapath_parse.py +0 -0
  200. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/manifests/__init__.py +0 -0
  201. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/manifests/test_processors.py +0 -0
  202. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/manifests/test_python_version_resolution.py +0 -0
  203. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_assets/converted_app/actions.py.txt +0 -0
  204. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_cli.py +0 -0
  205. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_init_cli.py +0 -0
  206. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_manifests_cli.py +0 -0
  207. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_package_cli.py +0 -0
  208. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_serializers.py +0 -0
  209. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_test_cli.py +0 -0
  210. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/cli/test_utils.py +0 -0
  211. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/code_renderers/test_action_renderer.py +0 -0
  212. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/conftest.py +0 -0
  213. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/example_asset.json +0 -0
  214. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/logo.svg +0 -0
  215. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/logo_dark.svg +0 -0
  216. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/pyproject.toml +0 -0
  217. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/release_notes/v1.md +0 -0
  218. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/__init__.py +0 -0
  219. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/actions/__init__.py +0 -0
  220. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/actions/async_action.py +0 -0
  221. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/actions/generate_category.py +0 -0
  222. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/actions/reverse_string.py +0 -0
  223. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/src/ignoreme.txt +0 -0
  224. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/templates/reverse_string.html +0 -0
  225. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app/uv.lock +0 -0
  226. {splunk_soar_sdk-3.6.1/tests/example_app_with_webhook → splunk_soar_sdk-3.7.0/tests/example_app_with_oauth}/src/__init__.py +0 -0
  227. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/example_asset.json +0 -0
  228. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/logo.svg +0 -0
  229. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/logo_dark.svg +0 -0
  230. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/pyproject.toml +0 -0
  231. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/src/app.py +0 -0
  232. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/example_app_with_webhook/uv.lock +0 -0
  233. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/__init__.py +0 -0
  234. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/conftest.py +0 -0
  235. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/phantom_constants.py +0 -0
  236. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/phantom_instance.py +0 -0
  237. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/soar_client.py +0 -0
  238. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/test_example_app.py +0 -0
  239. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/integration/test_example_app_with_webhook.py +0 -0
  240. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/interfaces/__init__.py +0 -0
  241. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/interfaces/test_artifact_interface.py +0 -0
  242. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/interfaces/test_container_interface.py +0 -0
  243. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/interfaces/test_vault_interface.py +0 -0
  244. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/__init__.py +0 -0
  245. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/test_actions.py +0 -0
  246. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/test_adapters.py +0 -0
  247. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/test_datatypes.py +0 -0
  248. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/test_dependencies.py +0 -0
  249. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/meta/test_webhooks.py +0 -0
  250. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/mocks/__init__.py +0 -0
  251. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/mocks/dynamic_mocks.py +0 -0
  252. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/mocks/importable_action.py +0 -0
  253. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/stubs.py +0 -0
  254. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_action_results.py +0 -0
  255. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app_action.py +0 -0
  256. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app_action_params.py +0 -0
  257. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app_action_results.py +0 -0
  258. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app_client.py +0 -0
  259. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_app_runner.py +0 -0
  260. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_assets/splunk-sdk-2.1.0.tar.gz +0 -0
  261. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_async_integration.py +0 -0
  262. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_async_utils.py +0 -0
  263. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_attachment_input.py +0 -0
  264. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_code_renderers.py +0 -0
  265. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_compat.py +0 -0
  266. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_container.py +0 -0
  267. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_custom_views.py +0 -0
  268. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_email_processor.py +0 -0
  269. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_encryption.py +0 -0
  270. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_es_client.py +0 -0
  271. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_es_on_poll.py +0 -0
  272. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_field_utils.py +0 -0
  273. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_finding.py +0 -0
  274. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_input_spec.py +0 -0
  275. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_logging.py +0 -0
  276. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_make_request_action.py +0 -0
  277. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_on_poll.py +0 -0
  278. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_params.py +0 -0
  279. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_rfc5322.py +0 -0
  280. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_template_filters.py +0 -0
  281. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_template_renderer.py +0 -0
  282. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_test_connectivity.py +0 -0
  283. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/test_view_parser.py +0 -0
  284. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/tests/webhooks/test_models.py +0 -0
  285. {splunk_soar_sdk-3.6.1 → splunk_soar_sdk-3.7.0}/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: 3.6.1
3
+ Version: 3.7.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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
18
  Classifier: Typing :: Typed
19
19
  Requires-Python: <3.15,>=3.13
20
+ Requires-Dist: authlib>=1.3.0
20
21
  Requires-Dist: beautifulsoup4>=4.10.0
21
22
  Requires-Dist: bleach>=6.2.0
22
23
  Requires-Dist: build>=1.3.0
@@ -29,6 +30,7 @@ Requires-Dist: humanize>=4.12.2
29
30
  Requires-Dist: jinja2>=3.1.0
30
31
  Requires-Dist: packaging>=25.0
31
32
  Requires-Dist: pydantic<3,>=2
33
+ Requires-Dist: pyjwt[crypto]>=2.8.0
32
34
  Requires-Dist: requests<3
33
35
  Requires-Dist: setuptools>=80.9.0
34
36
  Requires-Dist: toml<1,>=0.10.2
@@ -0,0 +1,18 @@
1
+ .. _basic_auth:
2
+
3
+ Basic Authentication
4
+ ====================
5
+
6
+ For APIs that use HTTP Basic Authentication (username/password):
7
+
8
+ .. code-block:: python
9
+
10
+ from soar_sdk.auth import BasicAuth
11
+ import httpx
12
+
13
+ auth = BasicAuth(asset.username, asset.password)
14
+
15
+ with httpx.Client(auth=auth) as client:
16
+ response = client.get("https://api.example.com/data")
17
+
18
+ This sends the ``Authorization: Basic <base64(username:password)>`` header with each request.
@@ -0,0 +1,13 @@
1
+ .. _authentication:
2
+
3
+ Authentication
4
+ ==============
5
+
6
+ These pages cover authentication mechanisms supported by the SDK for integrating with external services.
7
+
8
+ .. toctree::
9
+ :maxdepth: 2
10
+
11
+ basic
12
+ static_token
13
+ oauth
@@ -0,0 +1,168 @@
1
+ .. _oauth:
2
+
3
+ OAuth 2.0 Authentication
4
+ ========================
5
+
6
+ The SDK provides OAuth 2.0 support for SOAR connectors, with automatic token management and secure storage.
7
+
8
+ Supported Flows
9
+ ---------------
10
+
11
+ - **Authorization Code** (with PKCE support) - For user-delegated access
12
+ - **Client Credentials** - For service-to-service authentication
13
+ - **Certificate-based** - For certificate authentication (e.g., Microsoft Entra ID)
14
+
15
+ Client Credentials Flow
16
+ -----------------------
17
+
18
+ The simplest flow for service accounts:
19
+
20
+ .. code-block:: python
21
+
22
+ from soar_sdk.auth import ClientCredentialsFlow
23
+
24
+ flow = ClientCredentialsFlow(
25
+ auth_state=asset.auth_state,
26
+ client_id=asset.client_id,
27
+ client_secret=asset.client_secret,
28
+ token_endpoint="https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token",
29
+ scope=["https://graph.microsoft.com/.default"],
30
+ )
31
+
32
+ token = flow.get_token()
33
+
34
+ Authorization Code Flow
35
+ -----------------------
36
+
37
+ For user-delegated access requiring browser authorization:
38
+
39
+ .. code-block:: python
40
+
41
+ from soar_sdk.auth import AuthorizationCodeFlow
42
+
43
+ flow = AuthorizationCodeFlow(
44
+ auth_state=asset.auth_state,
45
+ asset_id=soar.get_asset_id(),
46
+ client_id=asset.client_id,
47
+ client_secret=asset.client_secret,
48
+ authorization_endpoint=asset.auth_url,
49
+ token_endpoint=asset.token_url,
50
+ redirect_uri=app.get_webhook_url("oauth_callback"),
51
+ scope=["openid", "profile", "email"],
52
+ use_pkce=True,
53
+ )
54
+
55
+ auth_url = flow.get_authorization_url()
56
+ logger.progress(f"Please authorize: {auth_url}")
57
+ token = flow.wait_for_authorization()
58
+
59
+ Using with HTTPX
60
+ ----------------
61
+
62
+ For automatic token injection in HTTP requests, use ``create_oauth_client``:
63
+
64
+ .. code-block:: python
65
+
66
+ from soar_sdk.auth import create_oauth_client
67
+
68
+ with create_oauth_client(asset) as client:
69
+ response = client.get("https://api.example.com/resource")
70
+
71
+ The factory infers ``client_id``, ``client_secret``, and ``token_endpoint`` from common
72
+ asset field names and returns a fully configured ``httpx.Client``.
73
+
74
+ For more control over the client, you can pass additional httpx options:
75
+
76
+ .. code-block:: python
77
+
78
+ with create_oauth_client(asset, timeout=60.0, follow_redirects=True) as client:
79
+ response = client.get("https://api.example.com/resource")
80
+
81
+ If you need just the auth handler (e.g., for async clients), use ``create_oauth_auth``:
82
+
83
+ .. code-block:: python
84
+
85
+ from soar_sdk.auth import create_oauth_auth
86
+ import httpx
87
+
88
+ auth = create_oauth_auth(asset)
89
+
90
+ with httpx.Client(auth=auth) as client:
91
+ response = client.get("https://api.example.com/resource")
92
+
93
+ For custom configuration:
94
+
95
+ .. code-block:: python
96
+
97
+ from soar_sdk.auth import OAuthBearerAuth, OAuthConfig, SOARAssetOAuthClient
98
+
99
+ config = OAuthConfig(
100
+ client_id=asset.client_id,
101
+ client_secret=asset.client_secret,
102
+ token_endpoint=asset.token_url,
103
+ scope=["custom_scope"],
104
+ )
105
+ oauth_client = SOARAssetOAuthClient(config, asset.auth_state)
106
+ auth = OAuthBearerAuth(oauth_client)
107
+
108
+ The auth handler automatically:
109
+
110
+ - Fetches tokens on first request
111
+ - Refreshes expired tokens when a refresh token is available
112
+ - Retries on 401 responses
113
+
114
+ Token Storage
115
+ -------------
116
+
117
+ Tokens are automatically stored in the asset's ``auth_state`` and encrypted at rest. The SDK handles:
118
+
119
+ - Token persistence across action runs
120
+ - Automatic refresh when tokens expire
121
+ - Credential change detection (forces re-authorization if client_id changes)
122
+
123
+ Certificate-based Authentication
124
+ ---------------------------------
125
+
126
+ For certificate-based authentication (e.g., Microsoft Entra ID):
127
+
128
+ .. code-block:: python
129
+
130
+ from soar_sdk.auth import CertificateCredentials, CertificateOAuthClient, OAuthConfig
131
+
132
+ config = OAuthConfig(
133
+ client_id=asset.client_id,
134
+ token_endpoint=f"https://login.microsoftonline.com/{asset.tenant_id}/oauth2/v2.0/token",
135
+ scope=["https://graph.microsoft.com/.default"],
136
+ )
137
+
138
+ certificate = CertificateCredentials(
139
+ certificate_thumbprint=asset.cert_thumbprint,
140
+ private_key=asset.private_key,
141
+ )
142
+
143
+ client = CertificateOAuthClient(config, asset.auth_state, certificate)
144
+ token = client.fetch_token_with_certificate()
145
+
146
+ OAuth Callback Webhook
147
+ ----------------------
148
+
149
+ For Authorization Code flow, register a webhook to receive the OAuth callback.
150
+ Use ``create_oauth_callback_handler`` to reduce boilerplate:
151
+
152
+ .. code-block:: python
153
+
154
+ from soar_sdk.auth import create_oauth_callback_handler, OAuthConfig, SOARAssetOAuthClient
155
+
156
+ def get_oauth_client(asset: Asset) -> SOARAssetOAuthClient:
157
+ config = OAuthConfig(
158
+ client_id=asset.client_id,
159
+ client_secret=asset.client_secret,
160
+ token_endpoint=asset.token_url,
161
+ )
162
+ return SOARAssetOAuthClient(config, asset.auth_state)
163
+
164
+ @app.webhook("oauth_callback")
165
+ def oauth_callback(request: WebhookRequest[Asset]) -> WebhookResponse:
166
+ return create_oauth_callback_handler(get_oauth_client)(request)
167
+
168
+ The factory handles error checking, code extraction, and success responses automatically.
@@ -0,0 +1,46 @@
1
+ .. _static_token:
2
+
3
+ Static Token Authentication
4
+ ===========================
5
+
6
+ For APIs that use API keys or pre-obtained tokens, use ``StaticTokenAuth`` with httpx:
7
+
8
+ .. code-block:: python
9
+
10
+ from soar_sdk.auth import StaticTokenAuth
11
+ import httpx
12
+
13
+ auth = StaticTokenAuth(asset.api_key)
14
+
15
+ with httpx.Client(auth=auth) as client:
16
+ response = client.get("https://api.example.com/data")
17
+
18
+ Custom Token Types
19
+ ------------------
20
+
21
+ By default, tokens are sent as ``Bearer`` tokens. For APIs that use different token types:
22
+
23
+ .. code-block:: python
24
+
25
+ # For APIs expecting "ApiKey" prefix
26
+ auth = StaticTokenAuth(asset.api_key, token_type="ApiKey")
27
+
28
+ # For APIs expecting "Token" prefix
29
+ auth = StaticTokenAuth(asset.api_key, token_type="Token")
30
+
31
+ This sends the header as ``Authorization: ApiKey <token>`` or ``Authorization: Token <token>``.
32
+
33
+ Custom Header Names
34
+ -------------------
35
+
36
+ For APIs that expect tokens in headers other than ``Authorization``:
37
+
38
+ .. code-block:: python
39
+
40
+ # For APIs using X-API-Key header
41
+ auth = StaticTokenAuth(asset.api_key, header_name="X-API-Key", token_type="")
42
+
43
+ # For SOAR's ph-auth-token header
44
+ auth = StaticTokenAuth(asset.token, header_name="ph-auth-token", token_type="")
45
+
46
+ Setting ``token_type=""`` sends the raw token without a prefix.
@@ -48,6 +48,7 @@ Contents
48
48
  getting_started/index
49
49
  app_structure/index
50
50
  custom_views/index
51
+ authentication/index
51
52
  api_reference
52
53
  cli_reference
53
54
  changelog
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "splunk-soar-sdk"
3
- version = "3.6.1"
3
+ version = "3.7.0"
4
4
  description = "The official framework for developing and testing Splunk SOAR Apps"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13, <3.15"
@@ -46,6 +46,9 @@ dependencies = [
46
46
  "setuptools>=80.9.0",
47
47
  "httpx-retries>=0.4.5",
48
48
  "hatchling>=1.28.0",
49
+ # OAuth 2.0 support
50
+ "authlib>=1.3.0",
51
+ "pyjwt[crypto]>=2.8.0",
49
52
  ]
50
53
 
51
54
  [project.urls]
@@ -0,0 +1,41 @@
1
+ # [3.7.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.6.1...3.7.0) (2025-12-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * cleanup webhook port access and webhook state storage ([54da088](https://github.com/phantomcyber/splunk-soar-sdk/commit/54da0889cf1b5202194964f5ac1b1adb744141d3))
7
+ * cleanup webhook state access ([0cdf11e](https://github.com/phantomcyber/splunk-soar-sdk/commit/0cdf11e568bffffe9b80160dfd051f383c19d307))
8
+ * improve webhook state access ([9d3b650](https://github.com/phantomcyber/splunk-soar-sdk/commit/9d3b650dc349395937d07d1c481ed84c605f0f2d))
9
+
10
+
11
+ ### Features
12
+
13
+ * add a category to asset fields ([8e03fa5](https://github.com/phantomcyber/splunk-soar-sdk/commit/8e03fa5289c93213ac02286a4f9f5dd1ee00bc1a))
14
+ * add other auth types to standardize sdk authorization ([7a1b753](https://github.com/phantomcyber/splunk-soar-sdk/commit/7a1b7531a34c94c6a15f4d446e517fa62c06467c))
15
+ * implement sdk oauth flow ([31396fb](https://github.com/phantomcyber/splunk-soar-sdk/commit/31396fb14ff42145f9a56692b1817d4f9abb24a0))
16
+ * improve webhook redirect url generation and usage ([cfbc0f0](https://github.com/phantomcyber/splunk-soar-sdk/commit/cfbc0f02096593af7caf39866431957876a707bc))
17
+
18
+
19
+
20
+
21
+
22
+ # [3.7.0](https://github.com/phantomcyber/splunk-soar-sdk/compare/3.6.1...3.7.0) (2025-12-18)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * cleanup webhook port access and webhook state storage ([54da088](https://github.com/phantomcyber/splunk-soar-sdk/commit/54da0889cf1b5202194964f5ac1b1adb744141d3))
28
+ * cleanup webhook state access ([0cdf11e](https://github.com/phantomcyber/splunk-soar-sdk/commit/0cdf11e568bffffe9b80160dfd051f383c19d307))
29
+ * improve webhook state access ([9d3b650](https://github.com/phantomcyber/splunk-soar-sdk/commit/9d3b650dc349395937d07d1c481ed84c605f0f2d))
30
+
31
+
32
+ ### Features
33
+
34
+ * add a category to asset fields ([8e03fa5](https://github.com/phantomcyber/splunk-soar-sdk/commit/8e03fa5289c93213ac02286a4f9f5dd1ee00bc1a))
35
+ * add other auth types to standardize sdk authorization ([7a1b753](https://github.com/phantomcyber/splunk-soar-sdk/commit/7a1b7531a34c94c6a15f4d446e517fa62c06467c))
36
+ * implement sdk oauth flow ([31396fb](https://github.com/phantomcyber/splunk-soar-sdk/commit/31396fb14ff42145f9a56692b1817d4f9abb24a0))
37
+ * improve webhook redirect url generation and usage ([cfbc0f0](https://github.com/phantomcyber/splunk-soar-sdk/commit/cfbc0f02096593af7caf39866431957876a707bc))
38
+
39
+
40
+
41
+
@@ -0,0 +1 @@
1
+ 3.7.0
@@ -1,4 +1,7 @@
1
+ import json
1
2
  import os
3
+ import shutil
4
+ import tempfile
2
5
  from pathlib import Path
3
6
  from typing import Any
4
7
 
@@ -135,3 +138,40 @@ class ActionsManager(BaseConnector):
135
138
  This is useful for contexts such as Webhooks, where the app dir isn't necessarily the cwd, but we still need to load the app JSON reliably.
136
139
  """
137
140
  self.__app_dir = app_dir
141
+
142
+ def _get_state_file_path(self, asset_id: str) -> Path:
143
+ """Get the state file path for an asset."""
144
+ return Path(self.get_state_dir()) / f"{asset_id}_state.json"
145
+
146
+ def load_state_from_file(self, asset_id: str) -> dict:
147
+ """Load state directly from file."""
148
+ state_file = self._get_state_file_path(asset_id)
149
+ if state_file.exists():
150
+ return json.loads(state_file.read_text())
151
+ return {}
152
+
153
+ def save_state_to_file(self, asset_id: str, state: dict) -> None:
154
+ """Save state directly to file using atomic write."""
155
+ state_file = self._get_state_file_path(asset_id)
156
+ state_file.parent.mkdir(parents=True, exist_ok=True)
157
+
158
+ fd, tmp_path = tempfile.mkstemp(dir=state_file.parent)
159
+ tmp_file = Path(tmp_path)
160
+ try:
161
+ with os.fdopen(fd, "w") as f:
162
+ f.write(json.dumps(state))
163
+ shutil.move(tmp_file, state_file)
164
+ except Exception:
165
+ if tmp_file.exists():
166
+ tmp_file.unlink()
167
+ raise
168
+
169
+ def reload_state_from_file(self, asset_id: str) -> dict:
170
+ """Reload state from file and update in-memory state.
171
+
172
+ Needed for OAuth flow where one process (webhook) updates the state file and another process (action) needs to see those changes.
173
+ """
174
+ state = self.load_state_from_file(asset_id)
175
+ if state:
176
+ self.save_state(state)
177
+ return state
@@ -6,6 +6,7 @@ import uuid
6
6
  from collections.abc import Callable, Iterator
7
7
  from pathlib import Path
8
8
  from typing import Any
9
+ from urllib.parse import urlparse
9
10
  from zoneinfo import ZoneInfo
10
11
 
11
12
  from soar_sdk.abstract import SOARClient, SOARClientAuth
@@ -226,12 +227,16 @@ class App:
226
227
  self._asset = self.asset_cls.model_validate(self._raw_asset_config)
227
228
 
228
229
  asset_id = self.soar_client.get_asset_id()
229
- self._asset._auth_state = AssetState(self.actions_manager, "auth", asset_id)
230
+ app_id = str(self.app_meta_info["appid"])
231
+
232
+ self._asset._auth_state = AssetState(
233
+ self.actions_manager, "auth", asset_id, app_id=app_id
234
+ )
230
235
  self._asset._cache_state = AssetState(
231
- self.actions_manager, "cache", asset_id
236
+ self.actions_manager, "cache", asset_id, app_id=app_id
232
237
  )
233
238
  self._asset._ingest_state = AssetState(
234
- self.actions_manager, "ingest", asset_id
239
+ self.actions_manager, "ingest", asset_id, app_id=app_id
235
240
  )
236
241
  return self._asset
237
242
 
@@ -789,6 +794,47 @@ class App:
789
794
  """Decorator for registering a webhook handler."""
790
795
  return WebhookDecorator(self, url_pattern, allowed_methods)
791
796
 
797
+ def get_webhook_url(self, route: str) -> str:
798
+ """Build the full URL for a webhook route (used for OAuth flow)."""
799
+ system_info = self.soar_client.get("rest/system_info").json()
800
+ base_url = system_info.get("base_url", "").rstrip("/")
801
+ parsed = urlparse(base_url)
802
+
803
+ webhook_port = self._get_webhook_port()
804
+ webhook_base = f"{parsed.scheme}://{parsed.hostname}:{webhook_port}"
805
+
806
+ config = self.actions_manager.get_config()
807
+ directory = config.get(
808
+ "directory", f"{self.app_meta_info['name']}_{self.app_meta_info['appid']}"
809
+ )
810
+ asset_id = str(self.soar_client.get_asset_id())
811
+
812
+ return f"{webhook_base}/webhook/{directory}/{asset_id}/{route}"
813
+
814
+ def _get_webhook_port(self) -> int:
815
+ """Get the webhook port from the feature flag configuration."""
816
+ try:
817
+ response = self.soar_client.get("rest/feature_flag/webhooks")
818
+ if response.status_code == 200:
819
+ data = response.json()
820
+ config = data.get("config", {})
821
+ if port := config.get("webhooks_port"):
822
+ return int(port)
823
+ except Exception: # noqa: S110
824
+ pass
825
+ return 3500
826
+
827
+ def _load_webhook_state(self, asset_id: str) -> None:
828
+ """Load state from file for webhooks."""
829
+ state = self.actions_manager.load_state_from_file(asset_id)
830
+ if state:
831
+ self.actions_manager.save_state(state)
832
+
833
+ def _save_webhook_state(self, asset_id: str) -> None:
834
+ """Save state to file for webhooks."""
835
+ state = self.actions_manager.load_state() or {}
836
+ self.actions_manager.save_state_to_file(asset_id, state)
837
+
792
838
  def handle_webhook(
793
839
  self,
794
840
  method: str,
@@ -813,7 +859,7 @@ class App:
813
859
  user_session_token=soar_auth_token,
814
860
  base_url=soar_base_url,
815
861
  )
816
- self.soar_client.update_client(soar_auth, asset_id)
862
+ self.soar_client.update_client(soar_auth, str(asset_id))
817
863
 
818
864
  normalized_query = {}
819
865
  for key, value in query.items():
@@ -829,6 +875,7 @@ class App:
829
875
 
830
876
  self.actions_manager.override_app_dir(self.app_root)
831
877
  self.actions_manager._load_app_json()
878
+ self._load_webhook_state(str(asset_id))
832
879
  request = WebhookRequest(
833
880
  method=method,
834
881
  headers=headers,
@@ -846,4 +893,5 @@ class App:
846
893
  raise TypeError(
847
894
  f"Webhook handler must return a WebhookResponse, got {type(response)}"
848
895
  )
896
+ self._save_webhook_state(str(asset_id))
849
897
  return response.model_dump()