splunkctl 0.13.0__tar.gz → 0.15.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 (197) hide show
  1. splunkctl-0.15.0/PKG-INFO +111 -0
  2. splunkctl-0.15.0/README.md +67 -0
  3. splunkctl-0.15.0/docs/guides/alerts.md +98 -0
  4. splunkctl-0.15.0/docs/guides/apps.md +94 -0
  5. splunkctl-0.15.0/docs/guides/audit.md +92 -0
  6. splunkctl-0.15.0/docs/guides/auth.md +96 -0
  7. splunkctl-0.15.0/docs/guides/conf.md +105 -0
  8. splunkctl-0.15.0/docs/guides/configure.md +156 -0
  9. splunkctl-0.15.0/docs/guides/dashboards.md +101 -0
  10. splunkctl-0.15.0/docs/guides/datamodels.md +98 -0
  11. splunkctl-0.15.0/docs/guides/doctor.md +88 -0
  12. splunkctl-0.15.0/docs/guides/es-detections.md +98 -0
  13. splunkctl-0.15.0/docs/guides/es.md +101 -0
  14. splunkctl-0.15.0/docs/guides/exit-codes.md +46 -0
  15. splunkctl-0.15.0/docs/guides/hec.md +113 -0
  16. splunkctl-0.15.0/docs/guides/indexes.md +117 -0
  17. splunkctl-0.15.0/docs/guides/inputs.md +109 -0
  18. splunkctl-0.15.0/docs/guides/install.md +101 -0
  19. splunkctl-0.15.0/docs/guides/keycloak-lab.md +75 -0
  20. splunkctl-0.15.0/docs/guides/knowledge.md +97 -0
  21. splunkctl-0.15.0/docs/guides/kvstore.md +139 -0
  22. splunkctl-0.15.0/docs/guides/lookups.md +115 -0
  23. splunkctl-0.15.0/docs/guides/mcp.md +184 -0
  24. splunkctl-0.15.0/docs/guides/parsers.md +144 -0
  25. splunkctl-0.15.0/docs/guides/rules.md +227 -0
  26. splunkctl-0.15.0/docs/guides/search.md +135 -0
  27. splunkctl-0.15.0/docs/guides/server.md +159 -0
  28. splunkctl-0.15.0/docs/guides/soar-actions.md +133 -0
  29. splunkctl-0.15.0/docs/guides/soar-admin.md +126 -0
  30. splunkctl-0.15.0/docs/guides/soar-approvals.md +82 -0
  31. splunkctl-0.15.0/docs/guides/soar-apps.md +76 -0
  32. splunkctl-0.15.0/docs/guides/soar-assets.md +104 -0
  33. splunkctl-0.15.0/docs/guides/soar-automation.md +8 -0
  34. splunkctl-0.15.0/docs/guides/soar-cases.md +141 -0
  35. splunkctl-0.15.0/docs/guides/soar-functions.md +96 -0
  36. splunkctl-0.15.0/docs/guides/soar-incidents.md +186 -0
  37. splunkctl-0.15.0/docs/guides/soar-indicators.md +119 -0
  38. splunkctl-0.15.0/docs/guides/soar-ingest.md +144 -0
  39. splunkctl-0.15.0/docs/guides/soar-lists.md +135 -0
  40. splunkctl-0.15.0/docs/guides/soar-playbooks.md +171 -0
  41. splunkctl-0.15.0/docs/guides/soar.md +128 -0
  42. splunkctl-0.15.0/docs/guides/splunk-cli.md +42 -0
  43. splunkctl-0.15.0/docs/guides/state.md +197 -0
  44. splunkctl-0.15.0/docs/guides/users.md +137 -0
  45. {splunkctl-0.13.0 → splunkctl-0.15.0}/pyproject.toml +7 -4
  46. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/__init__.py +1 -1
  47. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/client.py +28 -4
  48. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/auth.py +2 -2
  49. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/commands_meta.py +21 -10
  50. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/config_cmd.py +16 -8
  51. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/dashboards.py +10 -10
  52. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/docs_cmd.py +69 -16
  53. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/doctor.py +56 -3
  54. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/hec.py +8 -8
  55. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/lookups.py +9 -7
  56. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/search.py +7 -0
  57. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/_client.py +3 -3
  58. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/_ingest_helpers.py +3 -0
  59. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/artifacts.py +6 -2
  60. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/assets.py +21 -3
  61. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/functions.py +2 -1
  62. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/playbooks.py +2 -1
  63. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_io_blobs.py +6 -8
  64. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_io_soar_assets.py +10 -6
  65. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/config.py +70 -12
  66. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/errors.py +5 -0
  67. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/guard.py +2 -2
  68. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/main.py +29 -3
  69. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/dynamic_server.py +9 -1
  70. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/resources.py +2 -0
  71. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/runner.py +3 -1
  72. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/output.py +2 -1
  73. splunkctl-0.15.0/splunkctl/rest_adapters.py +269 -0
  74. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/soar/client.py +1 -1
  75. splunkctl-0.15.0/splunkctl/spl_safety.py +64 -0
  76. splunkctl-0.15.0/splunkctl.egg-info/PKG-INFO +111 -0
  77. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl.egg-info/SOURCES.txt +6 -0
  78. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl.egg-info/entry_points.txt +1 -0
  79. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl.egg-info/requires.txt +1 -1
  80. splunkctl-0.13.0/PKG-INFO +0 -274
  81. splunkctl-0.13.0/README.md +0 -232
  82. splunkctl-0.13.0/docs/guides/alerts.md +0 -79
  83. splunkctl-0.13.0/docs/guides/apps.md +0 -65
  84. splunkctl-0.13.0/docs/guides/audit.md +0 -125
  85. splunkctl-0.13.0/docs/guides/auth.md +0 -61
  86. splunkctl-0.13.0/docs/guides/conf.md +0 -84
  87. splunkctl-0.13.0/docs/guides/configure.md +0 -120
  88. splunkctl-0.13.0/docs/guides/dashboards.md +0 -17
  89. splunkctl-0.13.0/docs/guides/datamodels.md +0 -164
  90. splunkctl-0.13.0/docs/guides/doctor.md +0 -70
  91. splunkctl-0.13.0/docs/guides/es.md +0 -236
  92. splunkctl-0.13.0/docs/guides/exit-codes.md +0 -44
  93. splunkctl-0.13.0/docs/guides/hec.md +0 -59
  94. splunkctl-0.13.0/docs/guides/indexes.md +0 -76
  95. splunkctl-0.13.0/docs/guides/inputs.md +0 -80
  96. splunkctl-0.13.0/docs/guides/install.md +0 -55
  97. splunkctl-0.13.0/docs/guides/keycloak-lab.md +0 -20
  98. splunkctl-0.13.0/docs/guides/knowledge.md +0 -113
  99. splunkctl-0.13.0/docs/guides/kvstore.md +0 -125
  100. splunkctl-0.13.0/docs/guides/lookups.md +0 -127
  101. splunkctl-0.13.0/docs/guides/mcp.md +0 -173
  102. splunkctl-0.13.0/docs/guides/parsers.md +0 -67
  103. splunkctl-0.13.0/docs/guides/rules.md +0 -183
  104. splunkctl-0.13.0/docs/guides/search.md +0 -144
  105. splunkctl-0.13.0/docs/guides/server.md +0 -257
  106. splunkctl-0.13.0/docs/guides/soar-actions.md +0 -130
  107. splunkctl-0.13.0/docs/guides/soar-admin.md +0 -120
  108. splunkctl-0.13.0/docs/guides/soar-approvals.md +0 -99
  109. splunkctl-0.13.0/docs/guides/soar-apps.md +0 -56
  110. splunkctl-0.13.0/docs/guides/soar-automation.md +0 -132
  111. splunkctl-0.13.0/docs/guides/soar-cases.md +0 -178
  112. splunkctl-0.13.0/docs/guides/soar-functions.md +0 -94
  113. splunkctl-0.13.0/docs/guides/soar-indicators.md +0 -123
  114. splunkctl-0.13.0/docs/guides/soar-ingest.md +0 -161
  115. splunkctl-0.13.0/docs/guides/soar-lists.md +0 -110
  116. splunkctl-0.13.0/docs/guides/soar-playbooks.md +0 -267
  117. splunkctl-0.13.0/docs/guides/soar.md +0 -440
  118. splunkctl-0.13.0/docs/guides/state.md +0 -270
  119. splunkctl-0.13.0/docs/guides/users.md +0 -86
  120. splunkctl-0.13.0/splunkctl.egg-info/PKG-INFO +0 -274
  121. {splunkctl-0.13.0 → splunkctl-0.15.0}/LICENSE +0 -0
  122. {splunkctl-0.13.0 → splunkctl-0.15.0}/MANIFEST.in +0 -0
  123. {splunkctl-0.13.0 → splunkctl-0.15.0}/setup.cfg +0 -0
  124. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/__main__.py +0 -0
  125. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/auth/__init__.py +0 -0
  126. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/auth/adapters.py +0 -0
  127. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/auth/broker.py +0 -0
  128. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/auth/detector.py +0 -0
  129. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/auth/session.py +0 -0
  130. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/__init__.py +0 -0
  131. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/alerts.py +0 -0
  132. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/apps.py +0 -0
  133. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/audit.py +0 -0
  134. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/audit_parse.py +0 -0
  135. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/common.py +0 -0
  136. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/conf.py +0 -0
  137. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/conf_ops.py +0 -0
  138. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/datamodels.py +0 -0
  139. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/es.py +0 -0
  140. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/es_threat_intel.py +0 -0
  141. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/indexes.py +0 -0
  142. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/info.py +0 -0
  143. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/inputs.py +0 -0
  144. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/knowledge.py +0 -0
  145. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/kvstore.py +0 -0
  146. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/lookups_wiring.py +0 -0
  147. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/mcp_cmd.py +0 -0
  148. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/parsers.py +0 -0
  149. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/parsers_io.py +0 -0
  150. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/rules.py +0 -0
  151. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/rules_io.py +0 -0
  152. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/rules_schedule.py +0 -0
  153. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server.py +0 -0
  154. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server_auth.py +0 -0
  155. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server_deployment.py +0 -0
  156. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server_tokens.py +0 -0
  157. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server_topology.py +0 -0
  158. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/server_workloads.py +0 -0
  159. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/__init__.py +0 -0
  160. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/actions.py +0 -0
  161. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/admin.py +0 -0
  162. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/admin_roles_audit.py +0 -0
  163. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/admin_views.py +0 -0
  164. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/approvals.py +0 -0
  165. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/apps.py +0 -0
  166. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/cases.py +0 -0
  167. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/containers.py +0 -0
  168. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/containers_assign.py +0 -0
  169. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/containers_write.py +0 -0
  170. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/indicators.py +0 -0
  171. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/ingest.py +0 -0
  172. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/lists.py +0 -0
  173. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/notes.py +0 -0
  174. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/playbook_runs.py +0 -0
  175. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/playbooks_delete.py +0 -0
  176. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/search.py +0 -0
  177. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/system.py +0 -0
  178. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/vault.py +0 -0
  179. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/soar/workbook_templates.py +0 -0
  180. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state.py +0 -0
  181. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_io.py +0 -0
  182. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_io_confs.py +0 -0
  183. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_io_soar.py +0 -0
  184. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/state_types.py +0 -0
  185. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/commands/users.py +0 -0
  186. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/__init__.py +0 -0
  187. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/output_cap.py +0 -0
  188. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/prompts.py +0 -0
  189. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/server.py +0 -0
  190. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/tools.py +0 -0
  191. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/mcp/transport.py +0 -0
  192. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/py.typed +0 -0
  193. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/soar/__init__.py +0 -0
  194. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/soar/cimcef.py +0 -0
  195. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl/soar/web.py +0 -0
  196. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl.egg-info/dependency_links.txt +0 -0
  197. {splunkctl-0.13.0 → splunkctl-0.15.0}/splunkctl.egg-info/top_level.txt +0 -0
@@ -0,0 +1,111 @@
1
+ Metadata-Version: 2.4
2
+ Name: splunkctl
3
+ Version: 0.15.0
4
+ Summary: Open-source MCP server and CLI for Splunk Enterprise SIEM and Splunk SOAR.
5
+ Author: dannyota
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/dannyota/splunkctl
8
+ Project-URL: Documentation, https://splunkctl.danny.vn
9
+ Project-URL: Repository, https://github.com/dannyota/splunkctl
10
+ Project-URL: Issues, https://github.com/dannyota/splunkctl/issues
11
+ Project-URL: Changelog, https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md
12
+ Keywords: splunk,mcp,model-context-protocol,siem,soar,security,cli,detection,spl
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Requires-Python: >=3.12
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: splunk-sdk>=2.0
27
+ Requires-Dist: click>=8.2
28
+ Requires-Dist: pyyaml>=6.0
29
+ Requires-Dist: tabulate>=0.9
30
+ Requires-Dist: requests>=2.32
31
+ Requires-Dist: defusedxml>=0.7
32
+ Requires-Dist: mcp<3,>=2.3
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=8.0; extra == "dev"
35
+ Requires-Dist: ruff>=0.6; extra == "dev"
36
+ Requires-Dist: mypy>=1.11; extra == "dev"
37
+ Requires-Dist: types-requests; extra == "dev"
38
+ Requires-Dist: types-PyYAML; extra == "dev"
39
+ Requires-Dist: types-tabulate; extra == "dev"
40
+ Requires-Dist: types-defusedxml; extra == "dev"
41
+ Provides-Extra: browser
42
+ Requires-Dist: playwright>=1.45; extra == "browser"
43
+ Dynamic: license-file
44
+
45
+ # splunkctl
46
+
47
+ <a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl: CLI and MCP server for Splunk Enterprise, Enterprise Security, and SOAR" width="600"></a>
48
+
49
+ Operate Splunk Enterprise, Enterprise Security, and Splunk SOAR from a terminal, or give an AI agent the same commands through MCP.
50
+
51
+ Requires Python 3.12+ and credentials for your Splunk instance.
52
+
53
+ ## Quickstart
54
+
55
+ ```bash
56
+ python -m pip install splunkctl
57
+ splunkctl config init
58
+ splunkctl doctor
59
+ ```
60
+
61
+ [Documentation](https://splunkctl.danny.vn) · [Installation requirements](https://splunkctl.danny.vn/#/guides/install)
62
+
63
+ ## Tasks
64
+
65
+ - Investigate: run SPL, read fired alerts, and triage Enterprise Security notables. [Search](https://splunkctl.danny.vn/#/guides/search), [Triage notables](https://splunkctl.danny.vn/#/guides/es)
66
+ - Deploy detections: export saved searches to YAML, review the diff, and import them on another instance. [Manage detection rules](https://splunkctl.danny.vn/#/guides/rules)
67
+ - Respond with SOAR: work containers, artifacts, vault files, notes, and playbook runs. [Work SOAR incidents](https://splunkctl.danny.vn/#/guides/soar-incidents)
68
+ - Review configuration drift: pull live state, diff it against version control, and push approved changes with a change report. [Manage configuration as code](https://splunkctl.danny.vn/#/guides/state)
69
+
70
+ ## Safety
71
+
72
+ Every command that changes a remote Splunk or SOAR instance is guarded. Without `--yes` it prints a preview and exits without changing anything; some previews read the current state first to show a diff. The preview names the target host, and the active profile for Splunk Enterprise, so a change aimed at production is visible before it happens:
73
+
74
+ ```text
75
+ $ splunkctl --profile uat rules delete 'My Rule'
76
+ [DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
77
+ Pass --yes to apply.
78
+ ```
79
+
80
+ Add `--yes` to apply. `splunkctl state push --report FILE` writes a change report with the before and after state for each object, which you can attach to a change ticket.
81
+
82
+ Local configuration writes are not guarded: `splunkctl config init`, `splunkctl config use`, `splunkctl auth login`, and `splunkctl mcp install` write to your own machine immediately.
83
+
84
+ ## Agent access
85
+
86
+ The MCP server exposes the command tree to Claude Code, Claude Desktop, Cursor, or any other MCP client. Setup, transports, and the progressive tool-loading model are in the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp).
87
+
88
+ ```bash
89
+ splunkctl mcp install # register the server in ./.mcp.json
90
+ splunkctl commands --json # machine-readable command tree
91
+ ```
92
+
93
+ Guarded tools keep the same contract as the CLI: a call previews until the agent passes `yes=true` explicitly.
94
+
95
+ ## Requirements and limitations
96
+
97
+ - Python 3.12 or newer.
98
+ - A Splunk account with REST API access on port 8089 (or your configured port). Each command needs the Splunk capability or SOAR permission its action requires; `splunkctl doctor` reports which checks pass for the active profile.
99
+ - Enterprise Security commands (`splunkctl es ...`) check for the `SplunkEnterpriseSecuritySuite` app and exit 1 with a `not_found` error when it is not installed.
100
+ - Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
101
+
102
+ ## Project and support
103
+
104
+ splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
105
+
106
+ Splunk Inc. publishes an unrelated Go CLI with the same executable name, [`splunk/splunkctl`](https://github.com/splunk/splunkctl). This package also installs `splunkctl-py` and leaves a Splunk-format config file untouched, so both tools can be installed together; see [Relationship to Splunk's splunkctl](https://splunkctl.danny.vn/#/guides/splunk-cli).
107
+
108
+ - [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
109
+ - [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
110
+ - [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
111
+ - License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
@@ -0,0 +1,67 @@
1
+ # splunkctl
2
+
3
+ <a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl: CLI and MCP server for Splunk Enterprise, Enterprise Security, and SOAR" width="600"></a>
4
+
5
+ Operate Splunk Enterprise, Enterprise Security, and Splunk SOAR from a terminal, or give an AI agent the same commands through MCP.
6
+
7
+ Requires Python 3.12+ and credentials for your Splunk instance.
8
+
9
+ ## Quickstart
10
+
11
+ ```bash
12
+ python -m pip install splunkctl
13
+ splunkctl config init
14
+ splunkctl doctor
15
+ ```
16
+
17
+ [Documentation](https://splunkctl.danny.vn) · [Installation requirements](https://splunkctl.danny.vn/#/guides/install)
18
+
19
+ ## Tasks
20
+
21
+ - Investigate: run SPL, read fired alerts, and triage Enterprise Security notables. [Search](https://splunkctl.danny.vn/#/guides/search), [Triage notables](https://splunkctl.danny.vn/#/guides/es)
22
+ - Deploy detections: export saved searches to YAML, review the diff, and import them on another instance. [Manage detection rules](https://splunkctl.danny.vn/#/guides/rules)
23
+ - Respond with SOAR: work containers, artifacts, vault files, notes, and playbook runs. [Work SOAR incidents](https://splunkctl.danny.vn/#/guides/soar-incidents)
24
+ - Review configuration drift: pull live state, diff it against version control, and push approved changes with a change report. [Manage configuration as code](https://splunkctl.danny.vn/#/guides/state)
25
+
26
+ ## Safety
27
+
28
+ Every command that changes a remote Splunk or SOAR instance is guarded. Without `--yes` it prints a preview and exits without changing anything; some previews read the current state first to show a diff. The preview names the target host, and the active profile for Splunk Enterprise, so a change aimed at production is visible before it happens:
29
+
30
+ ```text
31
+ $ splunkctl --profile uat rules delete 'My Rule'
32
+ [DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
33
+ Pass --yes to apply.
34
+ ```
35
+
36
+ Add `--yes` to apply. `splunkctl state push --report FILE` writes a change report with the before and after state for each object, which you can attach to a change ticket.
37
+
38
+ Local configuration writes are not guarded: `splunkctl config init`, `splunkctl config use`, `splunkctl auth login`, and `splunkctl mcp install` write to your own machine immediately.
39
+
40
+ ## Agent access
41
+
42
+ The MCP server exposes the command tree to Claude Code, Claude Desktop, Cursor, or any other MCP client. Setup, transports, and the progressive tool-loading model are in the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp).
43
+
44
+ ```bash
45
+ splunkctl mcp install # register the server in ./.mcp.json
46
+ splunkctl commands --json # machine-readable command tree
47
+ ```
48
+
49
+ Guarded tools keep the same contract as the CLI: a call previews until the agent passes `yes=true` explicitly.
50
+
51
+ ## Requirements and limitations
52
+
53
+ - Python 3.12 or newer.
54
+ - A Splunk account with REST API access on port 8089 (or your configured port). Each command needs the Splunk capability or SOAR permission its action requires; `splunkctl doctor` reports which checks pass for the active profile.
55
+ - Enterprise Security commands (`splunkctl es ...`) check for the `SplunkEnterpriseSecuritySuite` app and exit 1 with a `not_found` error when it is not installed.
56
+ - Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
57
+
58
+ ## Project and support
59
+
60
+ splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
61
+
62
+ Splunk Inc. publishes an unrelated Go CLI with the same executable name, [`splunk/splunkctl`](https://github.com/splunk/splunkctl). This package also installs `splunkctl-py` and leaves a Splunk-format config file untouched, so both tools can be installed together; see [Relationship to Splunk's splunkctl](https://splunkctl.danny.vn/#/guides/splunk-cli).
63
+
64
+ - [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
65
+ - [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
66
+ - [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
67
+ - License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
@@ -0,0 +1,98 @@
1
+ <!-- summary: Review fired alerts, inspect alert actions, and manage alert suppression on a Splunk instance from the terminal. -->
2
+
3
+ # Review fired alerts
4
+
5
+ When to use: an incident is under way and you need to see which rules fired, when, and at what severity; a maintenance window is coming and noisy rules must be throttled before they flood the on-call channel; or an auditor asks which alerts fired and which were suppressed.
6
+
7
+ ## Prerequisites
8
+
9
+ - A profile that passes `splunkctl doctor` (see [Configure](configure.md)).
10
+ - Read access to fired alerts for `list`, `get`, and `actions`.
11
+ - Write access to the saved search that owns the rule for `suppress` and `unsuppress`.
12
+
13
+ ## Synopsis
14
+
15
+ ```text
16
+ splunkctl alerts list [--filter SUBSTRING] [--limit N] [--offset N]
17
+ splunkctl alerts get <NAME>
18
+ splunkctl alerts actions
19
+ splunkctl alerts suppress <NAME> [--duration SECONDS] [--yes]
20
+ splunkctl alerts unsuppress <NAME> [--yes]
21
+ ```
22
+
23
+ `NAME` is the rule's saved search name, matched exactly and case-sensitively.
24
+
25
+ ## Workflow
26
+
27
+ ### Triage during an incident
28
+
29
+ ```bash
30
+ splunkctl alerts list
31
+ splunkctl alerts list --filter brute
32
+ splunkctl alerts get 'Brute Force Login Attempts'
33
+ ```
34
+
35
+ Expected result: one row per firing with `rule`, `triggered`, `severity`, `sid`, and `actions`. `--filter` matches the rule name; `--limit` and `--offset` page the firing rows client side, so a row is one firing, not one rule. `get` prints every firing of one rule and the firing count.
36
+
37
+ ### Check alert action types
38
+
39
+ ```bash
40
+ splunkctl alerts actions
41
+ ```
42
+
43
+ Expected result: the action types (email, webhook, script, and app-provided actions) configured on the instance. Check this before creating or changing saved searches that fire alerts.
44
+
45
+ ### Suppress during a maintenance window
46
+
47
+ > **Safety:** Target is the Splunk host in the active profile. Impact: `alert.suppress=1` and `alert.suppress.period=<SECONDS>s` are written to the rule's saved search, so repeat firings are throttled for that window. Preview with `splunkctl alerts suppress 'Brute Force Login Attempts' --duration 7200`, apply by adding `--yes`, and verify with `splunkctl conf get savedsearches 'Brute Force Login Attempts' --key alert.suppress`.
48
+
49
+ ```bash
50
+ splunkctl alerts suppress 'Brute Force Login Attempts' --duration 7200
51
+ splunkctl alerts suppress 'Brute Force Login Attempts' --duration 7200 --yes
52
+ ```
53
+
54
+ Expected result: the preview prints `[DRY RUN] Throttle alerts for rule (profile: NAME @ HOST:8089)` and the settings it will write; the apply prints `Throttled 'Brute Force Login Attempts' for 7200s.`. `--duration` is in seconds and defaults to 3600. Splunk's fired-alerts endpoint cannot be edited; throttling is a property of the underlying saved search.
55
+
56
+ Suppress several rules during a planned outage:
57
+
58
+ ```bash
59
+ for rule in 'Brute Force Login Attempts' 'Failed VPN Auth' 'DNS Exfil'; do
60
+ splunkctl alerts suppress "$rule" --duration 14400 --yes
61
+ done
62
+ ```
63
+
64
+ ### Remove suppression after the window
65
+
66
+ > **Safety:** Target is the Splunk host in the active profile. Impact: `alert.suppress=0` is written to the rule's saved search and it alerts normally again. Preview with `splunkctl alerts unsuppress 'Brute Force Login Attempts'`, apply by adding `--yes`, and verify with `splunkctl conf get savedsearches 'Brute Force Login Attempts' --key alert.suppress`.
67
+
68
+ ```bash
69
+ splunkctl alerts unsuppress 'Brute Force Login Attempts'
70
+ splunkctl alerts unsuppress 'Brute Force Login Attempts' --yes
71
+ ```
72
+
73
+ Expected result: `Removed throttling from 'Brute Force Login Attempts'.`. The throttle setting stays on the saved search until you remove it; it does not expire on its own.
74
+
75
+ ### Produce JSON for scripts and agents
76
+
77
+ ```bash
78
+ splunkctl alerts list --json
79
+ splunkctl alerts list --json | jq '.[] | select((.severity | tonumber) >= 5)'
80
+ splunkctl alerts get 'Brute Force Login Attempts' --json > alert_detail.json
81
+ ```
82
+
83
+ Expected result: a JSON array of firing rows, suitable for `jq`, an agent, or audit evidence. `--format table|json|csv|jsonl` picks another output format. An agent can consume the JSON directly to correlate fired alerts with a change calendar or file tickets for high-severity triggers.
84
+
85
+ ## Troubleshooting
86
+
87
+ - `not_found` from `alerts get`: the name must match the rule exactly; run `splunkctl alerts list --filter <text>` to find the spelling.
88
+ - `not_found` from `suppress` or `unsuppress`: no saved search with that name is visible to your account; check `splunkctl rules list --filter <text>`.
89
+ - `permission` from `suppress` or `unsuppress`: your role cannot edit the saved search in its owning app.
90
+ - `No fired alerts.`: nothing has fired within Splunk's fired-alert retention; this is not an error.
91
+ - A rule keeps firing after `suppress --yes`: throttling suppresses repeat firings for the period after a trigger; it does not disable the search. Disable the rule itself with the commands in [Manage detection rules](rules.md).
92
+
93
+ ## See also
94
+
95
+ - [Manage detection rules](rules.md)
96
+ - [Triage ES notables](es.md)
97
+ - [Edit any conf file](conf.md)
98
+ - [Command reference: alerts](../commands/alerts.md)
@@ -0,0 +1,94 @@
1
+ <!-- summary: Install, update, reload, and uninstall Splunk apps from local packages with a preview before every change. -->
2
+
3
+ # Manage apps
4
+
5
+ When to use: you need to deploy or upgrade a Technology Add-on, a content pack such as Enterprise Security content, or a custom detection app on a remote instance, disable an app during an incident, or audit what is installed, without SSH or the Web UI.
6
+
7
+ ## Prerequisites
8
+
9
+ - A profile that passes `splunkctl doctor`, including the `Web UI reachable` check: `install` uploads the package through the Splunk Web UI handler.
10
+ - An account allowed to install and edit apps (for example the `admin` role).
11
+ - For `install`: a local `.spl` or `.tar.gz` package.
12
+
13
+ ## Synopsis
14
+
15
+ ```text
16
+ splunkctl apps list [--filter SUBSTRING] [--limit N] [--offset N]
17
+ splunkctl apps get <NAME>
18
+ splunkctl apps install --path <PACKAGE.spl|PACKAGE.tar.gz> [--force] [--yes]
19
+ splunkctl apps update <NAME> [--enabled|--disabled] [--visible|--hidden] [--yes]
20
+ splunkctl apps uninstall <NAME> [--yes]
21
+ splunkctl apps reload [--yes]
22
+ ```
23
+
24
+ ## Workflow
25
+
26
+ ### List and inspect
27
+
28
+ ```bash
29
+ splunkctl apps list
30
+ splunkctl apps list --filter TA-
31
+ splunkctl apps get SplunkForwarder
32
+ splunkctl apps list --json | jq '.[] | {name, version, disabled}'
33
+ ```
34
+
35
+ Expected result: one row per installed app; `get` prints the app's full settings. `--filter`, `--limit`, and `--offset` apply client side.
36
+
37
+ ### Install or upgrade from a local package
38
+
39
+ > **Safety:** Target is the Splunk host in the active profile. Impact: the package is uploaded through Splunk Web and installed; with `--force` an existing app of the same name is overwritten. Preview with `splunkctl apps install --path ./Splunk_TA_windows-8.9.0.spl`, apply by adding `--yes`, and verify with `splunkctl apps get Splunk_TA_windows`.
40
+
41
+ ```bash
42
+ splunkctl apps install --path ./Splunk_TA_windows-8.9.0.spl
43
+ splunkctl apps install --path ./Splunk_TA_windows-8.9.0.spl --yes
44
+ splunkctl apps install --path ./DA-ESS-ContentUpdate-4.29.0.spl --force --yes
45
+ ```
46
+
47
+ Expected result: the app appears in `splunkctl apps list`. The upload goes from your machine to the Splunk Web UI handler, so no SSH, SCP, or server filesystem access is needed. `--force` is required when the app already exists on the instance (reinstall or upgrade). An install may still need a Splunk restart to activate new modular inputs or scripted lookups; the CLI does not restart Splunk.
48
+
49
+ ### Disable an app during an incident
50
+
51
+ > **Safety:** Target is the Splunk host in the active profile. Impact: the app's scheduled searches and knowledge objects stop running until re-enabled. Preview with `splunkctl apps update SplunkEnterpriseSecuritySuite --disabled`, apply by adding `--yes`, and verify with `splunkctl apps get SplunkEnterpriseSecuritySuite --json` (check `disabled`).
52
+
53
+ ```bash
54
+ splunkctl apps update SplunkEnterpriseSecuritySuite --disabled
55
+ splunkctl apps update SplunkEnterpriseSecuritySuite --disabled --yes
56
+ splunkctl apps update SplunkEnterpriseSecuritySuite --enabled --yes
57
+ splunkctl apps update my_app --enabled --visible --yes
58
+ splunkctl apps update my_app --disabled --hidden --yes
59
+ ```
60
+
61
+ Expected result: `Updated app 'NAME'.`. `--visible` and `--hidden` control whether the app shows in the Splunk Web app menu; at least one of the four flags is required.
62
+
63
+ ### Uninstall an app
64
+
65
+ > **Safety:** Target is the Splunk host in the active profile. Impact: the app and its configuration are removed from the instance. Preview with `splunkctl apps uninstall my_app`, apply by adding `--yes`, and verify with `splunkctl apps list --filter my_app`.
66
+
67
+ ```bash
68
+ splunkctl apps uninstall my_app
69
+ splunkctl apps uninstall my_app --yes
70
+ ```
71
+
72
+ ### Reload all apps after a bulk change
73
+
74
+ > **Safety:** Target is the Splunk host in the active profile. Impact: every app's configuration is re-read by splunkd. Preview with `splunkctl apps reload`, apply with `splunkctl apps reload --yes`, and verify with `splunkctl apps list`.
75
+
76
+ ```bash
77
+ splunkctl apps reload --yes
78
+ ```
79
+
80
+ ## Troubleshooting
81
+
82
+ - `not_found` from `get`, `update`, or `uninstall`: the app id (directory name) differs from its label; find it with `splunkctl apps list --filter <text>`.
83
+ - `App install failed` or a `web` error: Splunk Web is not reachable from this machine; run `splunkctl doctor` and check `Web UI reachable`.
84
+ - Install fails because the app already exists: add `--force`.
85
+ - `No settings specified`: `update` needs `--enabled`, `--disabled`, `--visible`, or `--hidden`.
86
+ - `permission` on `update` or `uninstall`: the account lacks app administration rights; use an `admin` account.
87
+ - New inputs or lookups from an installed app do not run: restart Splunk from the server; the CLI does not restart it.
88
+
89
+ ## See also
90
+
91
+ - [Diagnose a connection](doctor.md)
92
+ - [Manage detection rules](rules.md)
93
+ - [Manage configuration as code](state.md)
94
+ - [Command reference: apps](../commands/apps.md)
@@ -0,0 +1,92 @@
1
+ <!-- summary: Produce change-audit and role-based access control attestation reports from Splunk for regulators and reviewers. -->
2
+
3
+ # Audit changes and attest RBAC
4
+
5
+ When to use: a regulator or reviewer asks who changed a saved search, role, or index and when (`audit changes`), or who holds which capabilities and index access for periodic access recertification (`audit rbac`). Both commands are read-only: no guard, no `--yes`.
6
+
7
+ ## Prerequisites
8
+
9
+ - A profile that passes `splunkctl doctor` (see [Configure](configure.md)).
10
+ - For `changes`: search access to `index=_audit` (the `admin` role has it by default).
11
+ - For `rbac`: read access to users and roles (`edit_user` and `edit_roles`, or an `admin` account).
12
+
13
+ ## Synopsis
14
+
15
+ ```text
16
+ splunkctl audit changes [--since TIME] [--until TIME] [--user USER] [--action SUBSTRING] [--object-type TYPE] [--limit N]
17
+ splunkctl audit rbac [--roles-only] [--format csv] [--out FILE]
18
+ ```
19
+
20
+ ## Workflow
21
+
22
+ ### Pull the change log for a window
23
+
24
+ ```bash
25
+ splunkctl audit changes
26
+ splunkctl audit changes --since -7d --until -1d
27
+ splunkctl audit changes --limit 2000 --json
28
+ ```
29
+
30
+ Expected result: one row per `_audit` event, newest first, with exactly six keys in this order: `time`, `user`, `action`, `object`, `object_type`, `app`. The default window is the last 24 hours (`--since -24h`, `--until now`) and the display cap is 500 rows. Splunk mixes two incompatible event shapes in `_audit`; this command normalizes both:
31
+
32
+ | Sourcetype | Shape | Mapping |
33
+ |---|---|---|
34
+ | `audittrail` (legacy) | `Audit:[timestamp=..., user=..., action=..., <tail>]` plain text | `user` and `action` parsed directly; `object` only when the line carries a literal `object="..."` marker (common on capability checks like `edit_user` and `edit_roles`); `object_type` always empty, the legacy format has no per-action type field; `app` from `app="..."` or unquoted `app=...` when present |
35
+ | `audittrailv2` (structured) | one JSON object per line | `user` = `actor.name`; `action` = top-level `action`; `object` = `data.name`; `object_type` = `data.type`; `app` = `data.ownership.app` or `data.attributes.app` |
36
+
37
+ `time` always comes from Splunk's indexed `_time`, not a re-parse of either embedded timestamp, so every row has one consistent, sortable value. Real `audittrailv2` events have no `data.object` or `data.object_type` key; `data.name` and `data.type` are the nearest equivalents and are present on object and system category events (config changes). Action, authn, and check category events (ad-hoc searches, logins, capability grants) carry `data.type` sometimes but rarely `data.name`, so `object` stays empty for them, which is correct: they are not changes to a named object. An event matching neither shape is never dropped; it comes back as `action: "unparsed"` with the full raw line in `object`, so evidence stays complete for formats the parser does not know yet.
38
+
39
+ ### Filter by user, action, or object type
40
+
41
+ ```bash
42
+ splunkctl audit changes --user jdoe
43
+ splunkctl audit changes --action edit
44
+ splunkctl audit changes --object-type saved_search
45
+ splunkctl audit changes --since -30d --user svc_deploy --action edit --format csv --out changes.csv
46
+ ```
47
+
48
+ Expected result: only matching rows. `--user` and `--object-type` are case-insensitive exact matches; `--action` is a case-insensitive substring match. Filters run client side on the normalized rows after the fetch, and `--limit` applies after filtering. The raw fetch is unbounded (`count=0`) within the `--since` and `--until` window, so a filter never misses a match because of an arbitrary raw-fetch cutoff. A very wide `--since` over a large `_audit` index fetches every event in that range before limiting, which can be slow; narrow `--since` when you can.
49
+
50
+ ### Confirm no flag value reaches the SPL
51
+
52
+ ```bash
53
+ splunkctl --debug audit changes --user 'x" | delete' --action 'y | outputlookup evil.csv'
54
+ ```
55
+
56
+ Expected result: the debug log shows `POST .../search/v2/jobs/ (body: {'search': 'search index=_audit', ...})`. The dispatched search is always the constant `search index=_audit`; `--since` and `--until` go through the job's `earliest_time` and `latest_time` arguments, and the other flags filter rows client side. No flag value, however adversarial, is composed into the SPL string.
57
+
58
+ ### Export an RBAC recertification report
59
+
60
+ ```bash
61
+ splunkctl audit rbac
62
+ splunkctl audit rbac --format csv --out recert-2026-07.csv
63
+ ```
64
+
65
+ Expected result: one row per user with `user`, `email`, `roles` (direct roles, semicolon-joined), `capabilities`, and `srch_indexes_allowed`. The last two are aggregated across the user's direct roles and the full transitive closure of their imported roles, deduplicated, sorted, and semicolon-joined. Example: role `soc_analyst` imports `power`, which imports `user`; a `soc_analyst` user's effective `capabilities` is the union of all three roles' own capabilities. This is what a role with zero capabilities of its own needs (Splunk's built-in `splunk-system-role` only imports `admin`) to show its real effective grant instead of an empty cell. `rbac` reads roles and users through the SDK only; it dispatches no search.
66
+
67
+ ### Attest per role instead of per user
68
+
69
+ ```bash
70
+ splunkctl audit rbac --roles-only
71
+ splunkctl audit rbac --roles-only --format csv --out roles-2026-07.csv
72
+ ```
73
+
74
+ Expected result: one row per role with `role`, `imported_roles` (direct only), `capabilities`, and `srch_indexes_allowed`, the last two aggregated the same transitive way, rooted at that role.
75
+
76
+ Multi-value fields (`roles`, `capabilities`, `srch_indexes_allowed`, `imported_roles`) join with `;`, never a newline. Splunk role, capability, and index names cannot contain a semicolon, so the join is lossless and never produces an embedded newline inside a CSV cell; `--format csv` output round-trips through Python's `csv` module.
77
+
78
+ ## Troubleshooting
79
+
80
+ - `permission` or an empty result from `changes`: your role cannot search `index=_audit`; use an `admin` account or add `_audit` to the role's allowed indexes.
81
+ - `timeout` on `changes`: the window is too wide; narrow `--since` or raise the global `--timeout`.
82
+ - Rows show `action: "unparsed"`: the event matched neither audit shape; the raw line is in `object`, so the evidence is still complete.
83
+ - `object_type` is empty on every row: the instance writes only the legacy `audittrail` shape, which has no type field; filter on `--action` instead.
84
+ - `permission` from `rbac`: the account cannot list users or roles; it needs `edit_user` and `edit_roles` or an `admin` role.
85
+ - Fewer rows than expected: `--limit` defaults to 500 after filtering; raise it.
86
+
87
+ ## See also
88
+
89
+ - [Manage users and roles](users.md)
90
+ - [Run searches](search.md)
91
+ - [Exit codes](exit-codes.md)
92
+ - [Command reference: audit](../commands/audit.md)
@@ -0,0 +1,96 @@
1
+ <!-- summary: Complete Splunk and SOAR SAML single sign-on, including a second factor, in a browser and reuse the session from every splunkctl command. -->
2
+
3
+ # Log in through browser SAML
4
+
5
+ When to use: your Splunk or SOAR instance authenticates through a SAML identity provider (with or without a second factor), so a username and password or a token cannot be stored in the profile, and you want every splunkctl command to reuse one browser login until it expires.
6
+
7
+ ## Prerequisites
8
+
9
+ - splunkctl with the browser extra and Chromium:
10
+
11
+ ```bash
12
+ python -m pip install 'splunkctl[browser]'
13
+ python -m playwright install chromium
14
+ ```
15
+
16
+ Configuration succeeds without them; `splunkctl auth login` prints these commands when they are missing.
17
+
18
+ - A machine with a display: login opens a headed Chromium window. The browser handles the identity provider; splunkctl never reads or stores TOTP secrets or codes.
19
+ - A profile in browser mode (`auth_mode: browser` with a `web_url`), written by `config init` as shown below.
20
+ - Not supported: reading or storing TOTP secrets, native Splunk Duo or RSA flows, OpenID Connect or OAuth, logging in to both products in one command, and a local splunkctl callback redirect.
21
+
22
+ ## Synopsis
23
+
24
+ ```text
25
+ splunkctl config init --web-url <https://splunk.example.com:8000> [--profile NAME] [--auth-mode auto|browser]
26
+ splunkctl config init --soar --web-url <https://soar.example.com> [--sso-url URL] [--profile NAME]
27
+ splunkctl auth login --target <siem|soar>
28
+ splunkctl auth status [--target siem|soar|both]
29
+ splunkctl auth logout [--target siem|soar|both]
30
+ ```
31
+
32
+ ## Workflow
33
+
34
+ ### Detect SAML during setup
35
+
36
+ ```bash
37
+ splunkctl config init --web-url https://splunk.example.com:8000
38
+ splunkctl config init --soar --web-url https://soar.example.com --sso-url 'https://soar.example.com/saml2/login?idp=okta&next=/'
39
+ ```
40
+
41
+ Expected result: `config init` probes the product's public login route. When it sees a redirect to an external identity provider it records `auth_mode: browser` and stores the product `web_url` in the profile. SAML detection runs only when `--web-url` is given. Pass `--auth-mode browser` to force browser mode without probing. For SOAR, pass `--sso-url` because SOAR's `/login` route is local-only.
42
+
43
+ ### Log in
44
+
45
+ ```bash
46
+ splunkctl auth login --target siem
47
+ splunkctl auth login --target soar
48
+ ```
49
+
50
+ Expected result: Chromium opens at the product login route; you complete the identity provider prompts, including any TOTP code; splunkctl extracts only the product session (the Splunk `splunkd_<port>` cookie, or the SOAR `sessionid` and `csrftoken` cookies), proves it against the product API, and prints `siem session stored (profile 'NAME').`. `login` requires exactly one target because two back-to-back browser flows are easy to confuse.
51
+
52
+ ### Check the session
53
+
54
+ ```bash
55
+ splunkctl auth status
56
+ splunkctl auth status --target siem
57
+ ```
58
+
59
+ Expected result: one row per target with `status` set to `missing`, `valid`, `expired`, or `unreachable`. Without `--target`, only targets configured for browser mode are checked; if none are, it prints `No browser-authenticated targets configured.`.
60
+
61
+ ### Use the session from normal commands
62
+
63
+ ```bash
64
+ splunkctl search oneshot 'index=_internal | head 5'
65
+ splunkctl soar test
66
+ ```
67
+
68
+ Expected result: commands reuse the cached session whenever the active profile selects browser mode. A missing or expired session never opens a browser; the command fails with the exact `splunkctl auth login --target ...` instruction to run instead.
69
+
70
+ ### Log out
71
+
72
+ ```bash
73
+ splunkctl auth logout --target siem
74
+ splunkctl auth logout --target both
75
+ ```
76
+
77
+ Expected result: a best-effort remote logout, then `Logout complete.`. The local session is always removed, even if the remote endpoint refuses; a refused remote logout prints a warning.
78
+
79
+ Sessions live under `~/.splunkctl/sessions/<profile>/<target>.json` with directory mode `0700` and file mode `0600`. A record holds only the target, profile, product origin, product session values, and validation timestamps. It never stores passwords, Playwright storage state, identity-provider cookies, or TOTP secrets, and session values are redacted from all output.
80
+
81
+ ## Troubleshooting
82
+
83
+ - `usage` error `siem is configured for token authentication, not browser login`: the profile has `auth_mode: token` or `password`; rerun `splunkctl config init --web-url URL` so SAML is detected, or pass `--auth-mode browser`.
84
+ - `login` prints `pip install` and `playwright install` commands: the browser extra is missing; run them and retry.
85
+ - `auth` error `login finished but the product session was rejected`: the browser ended on a different origin than `web_url`, or the identity provider flow did not complete; check `web_url` with `splunkctl config show` and log in again.
86
+ - `connection` error `SIEM is unreachable while checking the browser session`: the product API is down or blocked; fix connectivity with [Diagnose a connection](doctor.md).
87
+ - A command reports the session is missing or expired: run the `splunkctl auth login --target ...` command it prints; commands never open a browser on their own.
88
+ - `remote logout failed; clearing local session`: the product refused the logout call; the local file is still removed and a new `login` is required.
89
+
90
+ ## See also
91
+
92
+ - [Configure](configure.md)
93
+ - [Install](install.md)
94
+ - [Set up and check SOAR](soar.md)
95
+ - [Contributor lab: Keycloak SAML](keycloak-lab.md)
96
+ - [Command reference: auth](../commands/auth.md)