splunkctl 0.11.2__tar.gz → 0.13.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 (151) hide show
  1. {splunkctl-0.11.2 → splunkctl-0.13.0}/MANIFEST.in +1 -0
  2. {splunkctl-0.11.2/splunkctl.egg-info → splunkctl-0.13.0}/PKG-INFO +6 -2
  3. {splunkctl-0.11.2 → splunkctl-0.13.0}/README.md +2 -0
  4. splunkctl-0.13.0/docs/guides/alerts.md +79 -0
  5. splunkctl-0.13.0/docs/guides/apps.md +65 -0
  6. splunkctl-0.13.0/docs/guides/audit.md +125 -0
  7. splunkctl-0.13.0/docs/guides/auth.md +61 -0
  8. splunkctl-0.13.0/docs/guides/conf.md +84 -0
  9. splunkctl-0.13.0/docs/guides/configure.md +120 -0
  10. splunkctl-0.13.0/docs/guides/dashboards.md +17 -0
  11. splunkctl-0.13.0/docs/guides/datamodels.md +164 -0
  12. splunkctl-0.13.0/docs/guides/doctor.md +70 -0
  13. splunkctl-0.13.0/docs/guides/es.md +236 -0
  14. splunkctl-0.13.0/docs/guides/exit-codes.md +44 -0
  15. splunkctl-0.13.0/docs/guides/hec.md +59 -0
  16. splunkctl-0.13.0/docs/guides/indexes.md +76 -0
  17. splunkctl-0.13.0/docs/guides/inputs.md +80 -0
  18. splunkctl-0.13.0/docs/guides/install.md +55 -0
  19. splunkctl-0.13.0/docs/guides/keycloak-lab.md +20 -0
  20. splunkctl-0.13.0/docs/guides/knowledge.md +113 -0
  21. splunkctl-0.13.0/docs/guides/kvstore.md +125 -0
  22. splunkctl-0.13.0/docs/guides/lookups.md +127 -0
  23. splunkctl-0.13.0/docs/guides/mcp.md +173 -0
  24. splunkctl-0.13.0/docs/guides/parsers.md +67 -0
  25. splunkctl-0.13.0/docs/guides/rules.md +183 -0
  26. splunkctl-0.13.0/docs/guides/search.md +144 -0
  27. splunkctl-0.13.0/docs/guides/server.md +257 -0
  28. splunkctl-0.13.0/docs/guides/soar-actions.md +130 -0
  29. splunkctl-0.13.0/docs/guides/soar-admin.md +120 -0
  30. splunkctl-0.13.0/docs/guides/soar-approvals.md +99 -0
  31. splunkctl-0.13.0/docs/guides/soar-apps.md +56 -0
  32. splunkctl-0.13.0/docs/guides/soar-automation.md +132 -0
  33. splunkctl-0.13.0/docs/guides/soar-cases.md +178 -0
  34. splunkctl-0.13.0/docs/guides/soar-functions.md +94 -0
  35. splunkctl-0.13.0/docs/guides/soar-indicators.md +123 -0
  36. splunkctl-0.13.0/docs/guides/soar-ingest.md +161 -0
  37. splunkctl-0.13.0/docs/guides/soar-lists.md +110 -0
  38. splunkctl-0.13.0/docs/guides/soar-playbooks.md +267 -0
  39. splunkctl-0.13.0/docs/guides/soar.md +440 -0
  40. splunkctl-0.13.0/docs/guides/state.md +270 -0
  41. splunkctl-0.13.0/docs/guides/users.md +86 -0
  42. {splunkctl-0.11.2 → splunkctl-0.13.0}/pyproject.toml +7 -1
  43. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/__init__.py +1 -1
  44. splunkctl-0.13.0/splunkctl/auth/__init__.py +1 -0
  45. splunkctl-0.13.0/splunkctl/auth/adapters.py +151 -0
  46. splunkctl-0.13.0/splunkctl/auth/broker.py +115 -0
  47. splunkctl-0.13.0/splunkctl/auth/detector.py +120 -0
  48. splunkctl-0.13.0/splunkctl/auth/session.py +204 -0
  49. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/client.py +62 -5
  50. splunkctl-0.13.0/splunkctl/commands/auth.py +198 -0
  51. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/config_cmd.py +107 -7
  52. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/mcp_cmd.py +8 -5
  53. splunkctl-0.13.0/splunkctl/commands/soar/_client.py +81 -0
  54. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/errors.py +7 -0
  55. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/main.py +2 -0
  56. splunkctl-0.13.0/splunkctl/mcp/dynamic_server.py +132 -0
  57. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/prompts.py +8 -4
  58. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/resources.py +20 -3
  59. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/runner.py +0 -64
  60. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/server.py +38 -59
  61. splunkctl-0.13.0/splunkctl/mcp/transport.py +18 -0
  62. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/soar/client.py +11 -0
  63. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/soar/web.py +11 -0
  64. {splunkctl-0.11.2 → splunkctl-0.13.0/splunkctl.egg-info}/PKG-INFO +6 -2
  65. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl.egg-info/SOURCES.txt +46 -0
  66. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl.egg-info/requires.txt +4 -1
  67. splunkctl-0.11.2/splunkctl/commands/soar/_client.py +0 -44
  68. {splunkctl-0.11.2 → splunkctl-0.13.0}/LICENSE +0 -0
  69. {splunkctl-0.11.2 → splunkctl-0.13.0}/setup.cfg +0 -0
  70. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/__main__.py +0 -0
  71. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/__init__.py +0 -0
  72. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/alerts.py +0 -0
  73. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/apps.py +0 -0
  74. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/audit.py +0 -0
  75. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/audit_parse.py +0 -0
  76. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/commands_meta.py +0 -0
  77. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/common.py +0 -0
  78. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/conf.py +0 -0
  79. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/conf_ops.py +0 -0
  80. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/dashboards.py +0 -0
  81. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/datamodels.py +0 -0
  82. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/docs_cmd.py +0 -0
  83. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/doctor.py +0 -0
  84. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/es.py +0 -0
  85. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/es_threat_intel.py +0 -0
  86. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/hec.py +0 -0
  87. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/indexes.py +0 -0
  88. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/info.py +0 -0
  89. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/inputs.py +0 -0
  90. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/knowledge.py +0 -0
  91. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/kvstore.py +0 -0
  92. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/lookups.py +0 -0
  93. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/lookups_wiring.py +0 -0
  94. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/parsers.py +0 -0
  95. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/parsers_io.py +0 -0
  96. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/rules.py +0 -0
  97. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/rules_io.py +0 -0
  98. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/rules_schedule.py +0 -0
  99. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/search.py +0 -0
  100. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server.py +0 -0
  101. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server_auth.py +0 -0
  102. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server_deployment.py +0 -0
  103. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server_tokens.py +0 -0
  104. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server_topology.py +0 -0
  105. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/server_workloads.py +0 -0
  106. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/__init__.py +0 -0
  107. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/_ingest_helpers.py +0 -0
  108. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/actions.py +0 -0
  109. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/admin.py +0 -0
  110. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/admin_roles_audit.py +0 -0
  111. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/admin_views.py +0 -0
  112. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/approvals.py +0 -0
  113. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/apps.py +0 -0
  114. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/artifacts.py +0 -0
  115. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/assets.py +0 -0
  116. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/cases.py +0 -0
  117. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/containers.py +0 -0
  118. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/containers_assign.py +0 -0
  119. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/containers_write.py +0 -0
  120. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/functions.py +0 -0
  121. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/indicators.py +0 -0
  122. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/ingest.py +0 -0
  123. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/lists.py +0 -0
  124. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/notes.py +0 -0
  125. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/playbook_runs.py +0 -0
  126. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/playbooks.py +0 -0
  127. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/playbooks_delete.py +0 -0
  128. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/search.py +0 -0
  129. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/system.py +0 -0
  130. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/vault.py +0 -0
  131. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/soar/workbook_templates.py +0 -0
  132. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state.py +0 -0
  133. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_io.py +0 -0
  134. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_io_blobs.py +0 -0
  135. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_io_confs.py +0 -0
  136. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_io_soar.py +0 -0
  137. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_io_soar_assets.py +0 -0
  138. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/state_types.py +0 -0
  139. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/commands/users.py +0 -0
  140. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/config.py +0 -0
  141. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/guard.py +0 -0
  142. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/__init__.py +0 -0
  143. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/output_cap.py +0 -0
  144. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/mcp/tools.py +0 -0
  145. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/output.py +0 -0
  146. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/py.typed +0 -0
  147. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/soar/__init__.py +0 -0
  148. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl/soar/cimcef.py +0 -0
  149. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl.egg-info/dependency_links.txt +0 -0
  150. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl.egg-info/entry_points.txt +0 -0
  151. {splunkctl-0.11.2 → splunkctl-0.13.0}/splunkctl.egg-info/top_level.txt +0 -0
@@ -3,3 +3,4 @@ prune docs
3
3
  prune samples
4
4
  prune scripts
5
5
  prune installers
6
+ graft docs/guides
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: splunkctl
3
- Version: 0.11.2
3
+ Version: 0.13.0
4
4
  Summary: Open-source MCP server and CLI for Splunk Enterprise SIEM and Splunk SOAR.
5
5
  Author: dannyota
6
6
  License-Expression: Apache-2.0
@@ -27,7 +27,7 @@ Requires-Dist: pyyaml>=6.0
27
27
  Requires-Dist: tabulate>=0.9
28
28
  Requires-Dist: requests>=2.32
29
29
  Requires-Dist: defusedxml>=0.7
30
- Requires-Dist: mcp<2,>=1.28.1
30
+ Requires-Dist: mcp<3,>=2
31
31
  Provides-Extra: dev
32
32
  Requires-Dist: pytest>=8.0; extra == "dev"
33
33
  Requires-Dist: ruff>=0.6; extra == "dev"
@@ -36,6 +36,8 @@ Requires-Dist: types-requests; extra == "dev"
36
36
  Requires-Dist: types-PyYAML; extra == "dev"
37
37
  Requires-Dist: types-tabulate; extra == "dev"
38
38
  Requires-Dist: types-defusedxml; extra == "dev"
39
+ Provides-Extra: browser
40
+ Requires-Dist: playwright>=1.45; extra == "browser"
39
41
  Dynamic: license-file
40
42
 
41
43
  <div align="center">
@@ -114,6 +116,7 @@ splunkctl rules disable 'My Rule'
114
116
  # Add and verify Splunk SOAR when needed
115
117
  splunkctl config init --soar
116
118
  splunkctl soar test
119
+ splunkctl auth login --target siem # browser SAML/MFA login
117
120
  splunkctl soar containers list
118
121
  ```
119
122
 
@@ -192,6 +195,7 @@ streamable HTTP configuration.
192
195
  |---|---|
193
196
  | `doctor` | Check connection, authentication, health, and permissions |
194
197
  | `config` | Configure profiles and test connectivity |
198
+ | `auth` | Browser SAML login, session status, and logout |
195
199
  | `info` | Show server version, operating system, and license details |
196
200
  | `search` | Run, export, upload, and manage search jobs |
197
201
  | `rules` | Manage detection rules and YAML import/export |
@@ -74,6 +74,7 @@ splunkctl rules disable 'My Rule'
74
74
  # Add and verify Splunk SOAR when needed
75
75
  splunkctl config init --soar
76
76
  splunkctl soar test
77
+ splunkctl auth login --target siem # browser SAML/MFA login
77
78
  splunkctl soar containers list
78
79
  ```
79
80
 
@@ -152,6 +153,7 @@ streamable HTTP configuration.
152
153
  |---|---|
153
154
  | `doctor` | Check connection, authentication, health, and permissions |
154
155
  | `config` | Configure profiles and test connectivity |
156
+ | `auth` | Browser SAML login, session status, and logout |
155
157
  | `info` | Show server version, operating system, and license details |
156
158
  | `search` | Run, export, upload, and manage search jobs |
157
159
  | `rules` | Manage detection rules and YAML import/export |
@@ -0,0 +1,79 @@
1
+ # Alerts
2
+
3
+ Fired alerts are the SOC's incoming work queue. During an incident, you
4
+ need to see what triggered, when, and at what severity. During planned
5
+ maintenance, you need to suppress noisy rules before they flood the
6
+ on-call channel. After the fact, auditors ask which alerts fired and
7
+ which were suppressed. These commands cover all three workflows.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ splunkctl alerts list # list fired alerts
13
+ splunkctl alerts get 'Alert Name' # details for one alert group
14
+ splunkctl alerts actions # list alert action types
15
+ splunkctl alerts suppress 'Alert Name' \
16
+ --duration 7200 --yes # suppress for 2 hours
17
+ ```
18
+
19
+ ## Triage during an incident
20
+
21
+ List all currently fired alerts to see what the environment is telling you.
22
+ Output includes name, trigger count, triggered time, and severity.
23
+
24
+ ```bash
25
+ splunkctl alerts list
26
+ splunkctl alerts get 'Brute Force Login Attempts'
27
+ ```
28
+
29
+ ## Check alert action types
30
+
31
+ See which action types (email, webhook, script, etc.) are configured on
32
+ the instance. Useful before creating or modifying saved searches that
33
+ fire alerts.
34
+
35
+ ```bash
36
+ splunkctl alerts actions
37
+ ```
38
+
39
+ ## Suppress during a maintenance window
40
+
41
+ Suppression is guarded -- dry-run by default. The first command below
42
+ previews the change; the second applies it. Duration is in seconds.
43
+
44
+ ```bash
45
+ splunkctl alerts suppress 'Brute Force Login Attempts' --duration 7200
46
+ splunkctl alerts suppress 'Brute Force Login Attempts' --duration 7200 --yes
47
+ ```
48
+
49
+ Suppress multiple alerts in a loop during a planned outage:
50
+
51
+ ```bash
52
+ for rule in 'Brute Force Login Attempts' 'Failed VPN Auth' 'DNS Exfil'; do
53
+ splunkctl alerts suppress "$rule" --duration 14400 --yes
54
+ done
55
+ ```
56
+
57
+ ## JSON output for scripts and agents
58
+
59
+ Pass `--json` to get structured output suitable for piping into `jq`,
60
+ feeding into an LLM agent, or storing as audit evidence.
61
+
62
+ ```bash
63
+ splunkctl alerts list --json # all fired alerts
64
+ splunkctl alerts list --json | jq '.[] | select(.severity >= 6)'
65
+ splunkctl alerts get 'Brute Force Login Attempts' --json > alert_detail.json
66
+ ```
67
+
68
+ An LLM agent can consume the JSON directly to decide next steps --
69
+ for example, correlating fired alerts with a change window calendar
70
+ or auto-filing tickets for high-severity triggers.
71
+
72
+ ## Options
73
+
74
+ | Flag | Applies to | Description |
75
+ |------|-----------|-------------|
76
+ | `--duration` | `suppress` | Suppression length in seconds (default 3600) |
77
+ | `--json` | all | Force JSON output regardless of TTY |
78
+ | `--format` | all | Output format: `table`, `json`, `csv`, `jsonl` |
79
+ | `--yes` | `suppress` | Apply the mutation (skip dry-run preview) |
@@ -0,0 +1,65 @@
1
+ # Apps
2
+
3
+ Splunk's detection and enrichment capabilities live in apps --
4
+ Technology Add-ons (TAs) for data normalization, security content packs
5
+ like Splunk Enterprise Security, and custom apps with org-specific
6
+ detections. Managing these remotely lets you deploy, update, and audit
7
+ apps across instances without SSH or manual Web UI clicks.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ splunkctl apps list # list installed apps
13
+ splunkctl apps get SplunkForwarder # get app details
14
+ splunkctl apps install --path ./app.spl --yes # install from local file
15
+ splunkctl apps install --path ./app.tar.gz \
16
+ --force --yes # force overwrite
17
+ splunkctl apps uninstall my_app --yes # uninstall
18
+ splunkctl apps update my_app --enabled \
19
+ --visible --yes # enable + show
20
+ splunkctl apps update my_app --disabled \
21
+ --hidden --yes # disable + hide
22
+ splunkctl apps reload --yes # reload all apps
23
+ ```
24
+
25
+ ## Remote install
26
+
27
+ `apps install --path` uploads a local `.spl` or `.tar.gz` package to
28
+ the remote Splunk instance via the Web UI handler. No SSH, no SCP, no
29
+ server filesystem access needed -- push from your laptop to any
30
+ reachable instance.
31
+
32
+ Use `--force` to overwrite an existing app of the same name.
33
+
34
+ ## Practical examples
35
+
36
+ ```bash
37
+ # Deploy a TA for Windows event log normalization
38
+ splunkctl apps install \
39
+ --path ./Splunk_TA_windows-8.9.0.spl --yes
40
+
41
+ # Upgrade a security content pack (force overwrite)
42
+ splunkctl apps install \
43
+ --path ./DA-ESS-ContentUpdate-4.29.0.spl --force --yes
44
+
45
+ # Disable an app during an incident (stop its scheduled searches)
46
+ splunkctl apps update SplunkEnterpriseSecuritySuite \
47
+ --disabled --yes
48
+
49
+ # Re-enable after the incident
50
+ splunkctl apps update SplunkEnterpriseSecuritySuite \
51
+ --enabled --yes
52
+
53
+ # Audit installed apps -- pipe JSON to jq for scripting
54
+ splunkctl apps list --json | jq '.[] | {name, version, disabled}'
55
+
56
+ # Reload all app configs after a bulk change
57
+ splunkctl apps reload --yes
58
+ ```
59
+
60
+ ## Notes
61
+
62
+ - App install may require a Splunk restart to activate new modular
63
+ inputs or scripted lookups. The CLI does not restart automatically.
64
+ - `--force` is required when reinstalling or upgrading an app that
65
+ already exists on the instance.
@@ -0,0 +1,125 @@
1
+ # Change audit & RBAC attestation
2
+
3
+ Regulator-facing evidence for bank SOC operations: who changed what
4
+ (`audit changes`) and who can do what (`audit rbac`). Both commands are
5
+ **read-only** — no `guard`, no `--yes` needed.
6
+
7
+ ## Why this matters
8
+
9
+ Banks carry regulator obligations for change-management evidence ("who
10
+ changed this saved search / role / index, and when") and periodic access
11
+ recertification ("who has which capabilities, and why"). Today an agent
12
+ would have to hand-write `index=_audit` SPL and know that Splunk mixes
13
+ **two incompatible event shapes** in that one index — this group
14
+ normalizes both into one schema and joins the RBAC graph so neither
15
+ requires bespoke SPL per engagement.
16
+
17
+ ## Commands
18
+
19
+ ```bash
20
+ splunkctl audit changes # last 24h, up to 500
21
+ splunkctl audit changes --since -7d --until -1d # explicit window
22
+ splunkctl audit changes --user jdoe # exact-match user
23
+ splunkctl audit changes --action edit # substring-match action
24
+ splunkctl audit changes --object-type saved_search # exact-match object type
25
+ splunkctl audit changes --limit 2000 --json # raise the display cap
26
+
27
+ splunkctl audit rbac # one row per user
28
+ splunkctl audit rbac --format csv --out recert-2026-07.csv # recertification export
29
+ splunkctl audit rbac --roles-only # one row per role
30
+ ```
31
+
32
+ ## `audit changes`: normalized schema
33
+
34
+ Every row has exactly six keys, in this order: `time`, `user`, `action`,
35
+ `object`, `object_type`, `app`. Splunk's `_audit` index mixes two
36
+ sourcetypes and this command normalizes both:
37
+
38
+ | Sourcetype | Shape | Mapping |
39
+ |---|---|---|
40
+ | `audittrail` (legacy) | `Audit:[timestamp=..., user=..., action=..., <tail>]` plain text | `user`/`action` parsed directly; `object` only when the line carries a literal `object="..."` marker (common on capability checks like `edit_user`/`edit_roles`); `object_type` is always empty — the legacy format has no per-action type field; `app` from `app="..."` or unquoted `app=...`, when present |
41
+ | `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` |
42
+
43
+ `time` always comes from Splunk's own indexed `_time` (not a re-parse of
44
+ either embedded timestamp format) — it's present on every event
45
+ regardless of shape and gives one consistent, sortable value.
46
+
47
+ There is no literal `data.object`/`data.object_type` key on real
48
+ `audittrailv2` events; `data.name`/`data.type` are the nearest
49
+ equivalents and confirmed present for object/system-category events
50
+ (config changes). Action/authn/check-category events (ad-hoc searches,
51
+ logins, capability grants) carry `data.type` sometimes but rarely
52
+ `data.name` — `object` stays empty for those, which is correct: they
53
+ aren't changes to a named object.
54
+
55
+ An event matching neither shape is **never dropped** — it comes back as
56
+ `action: "unparsed"` with the full raw line in `object`, so evidence
57
+ stays complete even for audit-log formats this parser doesn't yet know.
58
+
59
+ ## `audit changes`: SPL safety
60
+
61
+ The dispatched search is always the constant `search index=_audit` —
62
+ nothing else, ever. `--since`/`--until` go through the oneshot job's
63
+ `earliest_time`/`latest_time` kwargs (not string-composed), and
64
+ `--user`/`--action`/`--object-type` filter the already-normalized rows
65
+ **client-side**, after the fetch. No flag value — however adversarial —
66
+ reaches the SPL string. Verified live with `--debug`:
67
+
68
+ ```bash
69
+ $ splunkctl --debug audit changes --user 'x" | delete' --action 'y | outputlookup evil.csv'
70
+ ...
71
+ POST .../search/v2/jobs/ (body: {'search': 'search index=_audit', ...})
72
+ ```
73
+
74
+ `--limit` (default 500) applies **after** filtering, not to the raw
75
+ fetch — the raw fetch itself is unbounded (`count=0`) within the
76
+ `--since`/`--until` window, so a `--user`/`--action` filter never misses
77
+ a match just because it fell outside an arbitrary raw-fetch cutoff.
78
+ A very wide `--since` over a large `_audit` index may fetch all events in that range before limiting, which can be slow; narrow `--since` when possible.
79
+ `--user`/`--object-type` are case-insensitive exact match; `--action` is case-insensitive substring match.
80
+
81
+ ## `audit rbac`: aggregation
82
+
83
+ One row per user by default: `user`, `email`, `roles` (direct roles,
84
+ semicolon-joined), `capabilities`, `srch_indexes_allowed`. The last two
85
+ are aggregated across the user's direct roles **and the full transitive
86
+ closure of their imported roles** — deduplicated, sorted, and
87
+ semicolon-joined. `--roles-only` flips to one row per role instead:
88
+ `role`, `imported_roles` (direct only), `capabilities`,
89
+ `srch_indexes_allowed` (both aggregated the same transitive way, rooted
90
+ at that role).
91
+
92
+ Example: role `soc_analyst` imports `power`, which imports `user`. A
93
+ `soc_analyst` user's effective `capabilities` is the union of all three
94
+ roles' own capabilities — this is what a role with zero capabilities of
95
+ its own (e.g. Splunk's built-in `splunk-system-role`, which only imports
96
+ `admin`) needs to show its real effective grant, not an empty cell.
97
+
98
+ ## CSV round-trip safety
99
+
100
+ Multi-value fields (`roles`, `capabilities`, `srch_indexes_allowed`,
101
+ `imported_roles`) join with `;`, never `\n` — Splunk role/capability/index
102
+ names can't contain a semicolon, so this is a safe, lossless join that
103
+ never produces an embedded newline inside a CSV cell. `--format csv`
104
+ output round-trips cleanly through Python's `csv` module.
105
+
106
+ ## Options
107
+
108
+ | Flag | Applies to | Description |
109
+ |------|-----------|--------------|
110
+ | `--since` | `changes` | Earliest time (default `-24h`) |
111
+ | `--until` | `changes` | Latest time (default `now`) |
112
+ | `--user` | `changes` | Filter by user, case-insensitive exact match |
113
+ | `--action` | `changes` | Filter by action, case-insensitive substring match |
114
+ | `--object-type` | `changes` | Filter by object type, case-insensitive exact match |
115
+ | `--limit` | `changes` | Max results after client-side filtering (default 500) |
116
+ | `--roles-only` | `rbac` | One row per role instead of per user |
117
+
118
+ ## Implementation notes
119
+
120
+ `changes` runs over the existing oneshot-search infrastructure
121
+ (`svc.jobs.oneshot`); the event-shape parsers live in a sibling module,
122
+ `splunkctl/commands/audit_parse.py`, kept separate from the click
123
+ commands since they're pure functions with their own fixture-driven test
124
+ suite. `rbac` is SDK reads only (`svc.roles`, `svc.users`) — no oneshot
125
+ search involved.
@@ -0,0 +1,61 @@
1
+ # Browser SAML authentication
2
+
3
+ splunkctl can complete Splunk SAML single sign-on (including a second factor)
4
+ in a headed Chromium window and then reuse the resulting product session until
5
+ it expires. The browser handles the identity provider; splunkctl never reads or
6
+ stores TOTP secrets or codes.
7
+
8
+ ## How it works
9
+
10
+ 1. `splunkctl config init` probes the public login route. When it sees a
11
+ redirect to an external identity provider, it records `auth_mode: browser`
12
+ and stores the product `web_url`.
13
+ 2. `splunkctl auth login --target <siem|soar>` opens Chromium at the product
14
+ login route. You complete the IdP prompts, including any TOTP code.
15
+ 3. splunkctl extracts only the product session (Splunk `splunkd_<port>` cookie,
16
+ or SOAR `sessionid` + `csrftoken`) and proves it against the product API.
17
+ 4. Normal commands reuse the cached session whenever the active profile selects
18
+ browser mode. A missing or expired session never opens a browser; the command
19
+ prints the exact login instruction instead.
20
+
21
+ ## Commands
22
+
23
+ ```text
24
+ splunkctl auth login --target siem
25
+ splunkctl auth login --target soar
26
+ splunkctl auth status [--target siem|soar|both]
27
+ splunkctl auth logout [--target siem|soar|both]
28
+ ```
29
+
30
+ `login` requires exactly one target; two back-to-back browser flows are easy to
31
+ confuse. `status` reports `missing`, `valid`, `expired`, or `unreachable`.
32
+ `logout` always removes the local session, even if the remote endpoint refuses.
33
+
34
+ ## Optional dependency
35
+
36
+ Browser login needs Playwright and Chromium:
37
+
38
+ ```bash
39
+ pip install 'splunkctl[browser]'
40
+ python -m playwright install chromium
41
+ ```
42
+
43
+ Configuration still succeeds without them. `splunkctl auth login` prints the
44
+ exact commands when they are missing.
45
+
46
+ ## Session storage and security
47
+
48
+ Sessions are stored under `~/.splunkctl/sessions/<profile>/<target>.json` with
49
+ directory mode `0700` and file mode `0600`. A record holds only the target,
50
+ profile, product origin, product session values, and validation timestamps. It
51
+ never stores passwords, Playwright storage state, identity-provider cookies, or
52
+ TOTP secrets. Session values are redacted from all output.
53
+
54
+ ## What is and is not supported
55
+
56
+ Supported: SAML browser login for SIEM and SOAR, one target per login, session
57
+ status and logout, automatic SAML detection, and a reusable Keycloak lab.
58
+
59
+ Not supported in this release: reading or storing TOTP secrets, native Splunk
60
+ Duo or RSA flows, OpenID Connect or OAuth, logging in to both products in one
61
+ command, and a local splunkctl callback redirect.
@@ -0,0 +1,84 @@
1
+ # Conf
2
+
3
+ Generic conf file/stanza editor over the REST `confs` API — the escape
4
+ hatch for any Splunk conf file that doesn't have a dedicated command
5
+ group yet: `macros`, `eventtypes`, `tags`, `limits`, `authorize`,
6
+ `server`, `web`, and everything else under `$SPLUNK_HOME/etc/*/local`.
7
+
8
+ ## Why this matters
9
+
10
+ Detections depend on more than saved searches: macros expand reusable
11
+ SPL fragments, eventtypes classify events, tags drive CIM compliance,
12
+ and calculated fields live in `props.conf` alongside sourcetypes.
13
+ `parsers` only reaches `props.conf`/`transforms.conf`; `conf` reaches
14
+ every other conf file the same way, so nothing detection-relevant is
15
+ locked out of code review or CI.
16
+
17
+ There is **no blocklist** — `conf` can edit `authorize.conf`,
18
+ `server.conf`, and `web.conf` just as readily as `macros.conf`. The
19
+ dry-run guard and `--yes` are the only safety net: every `set`/`unset`/
20
+ `reload` preview names the exact file and stanza before it touches
21
+ anything, so review the preview before applying to a sensitive file.
22
+
23
+ ## Commands
24
+
25
+ ```bash
26
+ splunkctl conf files # list conf files
27
+ splunkctl conf list macros # list stanzas in macros.conf
28
+ splunkctl conf list macros --app my_app # scope to one app's stanzas
29
+ splunkctl conf get macros my_macro # full stanza config
30
+ splunkctl conf get macros my_macro --key definition # one key
31
+ splunkctl conf set macros my_macro \
32
+ definition='index=main' --yes # create/update keys
33
+ splunkctl conf unset macros my_macro definition --yes # clear a key
34
+ splunkctl conf reload macros --yes # reload the conf file
35
+ ```
36
+
37
+ ## Recipes
38
+
39
+ ### Add a macro
40
+
41
+ Create a macro and verify it before rollout:
42
+
43
+ ```bash
44
+ splunkctl conf set macros my_macro \
45
+ definition='index=main sourcetype=syslog' --yes
46
+ splunkctl conf get macros my_macro
47
+ ```
48
+
49
+ ### Audit an eventtype
50
+
51
+ ```bash
52
+ splunkctl conf get eventtypes authentication --json | jq .
53
+ ```
54
+
55
+ ### Review a stanza change before applying
56
+
57
+ `conf set` always previews a field-level diff — old value on the left,
58
+ new value on the right, `add` for a brand-new key:
59
+
60
+ ```bash
61
+ splunkctl conf set macros my_macro definition='index=main'
62
+ # [DRY RUN] ...
63
+ # definition: index=old -> index=main
64
+ ```
65
+
66
+ ### List conf files to find the right one
67
+
68
+ ```bash
69
+ splunkctl conf files --filter tag
70
+ ```
71
+
72
+ ## Tips
73
+
74
+ - `conf set` creates the stanza if it doesn't exist yet — there's no
75
+ separate create step.
76
+ - The REST API has no true per-key delete; `conf unset` sets keys to
77
+ the empty string (same mechanism `parsers unset` uses). To fully
78
+ remove a stanza, use the dedicated command group for that conf file
79
+ when one exists (e.g. `parsers delete` for `props.conf`).
80
+ - `--app` on `conf list`/`conf files` matters: the unscoped default
81
+ view can miss app-private stanzas, same as `rules list`/`dashboards
82
+ list`.
83
+ - Reload the conf file after a `set`/`unset` if the change needs to
84
+ take effect immediately (`conf reload <file> --yes`).
@@ -0,0 +1,120 @@
1
+ # Configure
2
+
3
+ ## Interactive setup
4
+
5
+ ```bash
6
+ splunkctl config init
7
+ ```
8
+
9
+ Prompts for host, port, auth method (token or username/password), tests the
10
+ connection, and writes `~/.splunkctl/config.yaml` with `0600` permissions.
11
+
12
+ ## Config file
13
+
14
+ Location: `~/.splunkctl/config.yaml`
15
+
16
+ ```yaml
17
+ host: "localhost"
18
+ port: 8089
19
+ scheme: "https"
20
+ username: "admin"
21
+ password: "" # optional, can use token instead
22
+ token: "" # bearer token (preferred)
23
+ verify: true # TLS cert verification (default: on)
24
+ app: "search" # default app context
25
+ owner: "nobody" # default owner context
26
+ ```
27
+
28
+ **TLS verification is on by default.** Production instances with valid
29
+ certificates work out of the box. For lab/dev instances with self-signed
30
+ certs, set `verify: false` explicitly in the profile — `config init` asks
31
+ during setup (default: yes).
32
+
33
+ ## Profiles (dev/UAT/prod)
34
+
35
+ For more than one Splunk instance, add a `profiles:` map and a `current:`
36
+ pointer instead of the flat keys above:
37
+
38
+ ```yaml
39
+ profiles:
40
+ dev:
41
+ host: "dev.splunk.internal"
42
+ username: "admin"
43
+ password: "devpass"
44
+ uat:
45
+ host: "uat.splunk.internal"
46
+ token: "..."
47
+ prod:
48
+ host: "prod.splunk.internal"
49
+ token: "..."
50
+ current: "uat" # active profile when nothing else selects one
51
+ ```
52
+
53
+ ```bash
54
+ splunkctl config init --profile uat ... # create/update one named profile
55
+ splunkctl config use uat # point 'current' at it (no connectivity test)
56
+ splunkctl config show # active profile (redacted) + other names
57
+ splunkctl config show --profile prod # show a specific profile without switching
58
+ splunkctl --profile prod rules list # override for a single invocation
59
+ ```
60
+
61
+ **Selection precedence**: `--profile <name>` global flag > `current:`
62
+ pointer > `default`.
63
+
64
+ **Legacy files keep working.** A plain flat file (no `profiles:` key) is
65
+ treated as an implicit profile named `default` — nothing to migrate. Bare
66
+ `config init` writes that flat shape — unless the destination file already
67
+ has a `profiles:` key, in which case it folds the new values into
68
+ `profiles.default` instead, leaving sibling profiles and `current`
69
+ untouched (bare `config init` never clobbers an existing multi-profile
70
+ file). The first time you run `config init --profile <name>` against a
71
+ legacy file, it's upgraded to the `profiles:` schema in place: the old flat
72
+ keys move under `profiles.default`, the new named profile is added
73
+ alongside it, and file permissions stay `0600`.
74
+
75
+ **Guard banner.** Every dry-run preview and `--yes` confirmation prints
76
+ which instance is about to be mutated —
77
+ `[DRY RUN] ... (profile: uat @ uat.splunk.internal:8089)` — so switching
78
+ between dev/UAT/prod never happens silently. The banner is built from local
79
+ config only; it never opens a connection.
80
+
81
+ ## Environment variables
82
+
83
+ | Variable | Maps to |
84
+ |---|---|
85
+ | `SPLUNK_HOST` | `host` |
86
+ | `SPLUNK_PORT` | `port` |
87
+ | `SPLUNK_TOKEN` | `token` |
88
+ | `SPLUNK_USER` | `username` |
89
+ | `SPLUNK_PASS` | `password` |
90
+
91
+ Env vars override fields of whichever profile is selected — same as they
92
+ override the flat config today.
93
+
94
+ ## Resolution priority
95
+
96
+ 1. CLI flags (`--host`, `--port`, `--token`)
97
+ 2. Environment variables
98
+ 3. Profile (config file)
99
+
100
+ ## Watch mode
101
+
102
+ Re-run any read-only command at a fixed interval, clearing the screen
103
+ between runs (like `watch(1)` on Linux). Errors are printed in place and
104
+ the loop continues. Press Ctrl-C to stop.
105
+
106
+ ```bash
107
+ splunkctl --watch 5 indexes list # refresh every 5 seconds
108
+ splunkctl --watch 10 server health # poll server health
109
+ splunkctl --watch 3 rules list --filter brute # filtered view
110
+ ```
111
+
112
+ Requires an interactive terminal (TTY). Mutation commands (those guarded
113
+ by `--yes`) are rejected.
114
+
115
+ ## Verify
116
+
117
+ ```bash
118
+ splunkctl config show # display config (secrets redacted)
119
+ splunkctl config test # test connectivity + auth
120
+ ```
@@ -0,0 +1,17 @@
1
+ # Dashboards
2
+
3
+ ## Commands
4
+
5
+ ```bash
6
+ splunkctl dashboards list # list dashboards
7
+ splunkctl dashboards list --app search # filter by app
8
+ splunkctl dashboards get <name> # get definition (XML)
9
+ splunkctl dashboards create --name new_dash --file dash.xml \
10
+ --app search --yes
11
+ splunkctl dashboards update <name> --file updated.xml \
12
+ --app search --yes
13
+ splunkctl dashboards delete <name> --app search --yes
14
+ splunkctl dashboards export <name> --out dash.xml
15
+ ```
16
+
17
+ Uses the `Dashboard`/`Dashboards` entity classes from the SDK fork.