splunkctl 0.12.0__tar.gz → 0.14.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.
- splunkctl-0.14.0/PKG-INFO +115 -0
- splunkctl-0.14.0/README.md +73 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/alerts.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/apps.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/audit.md +16 -14
- splunkctl-0.14.0/docs/guides/auth.md +63 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/conf.md +7 -5
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/configure.md +42 -12
- splunkctl-0.14.0/docs/guides/dashboards.md +108 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/datamodels.md +28 -26
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/doctor.md +5 -8
- splunkctl-0.14.0/docs/guides/es-detections.md +98 -0
- splunkctl-0.14.0/docs/guides/es.md +101 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/exit-codes.md +3 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/hec.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/indexes.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/inputs.md +3 -1
- splunkctl-0.14.0/docs/guides/install.md +108 -0
- splunkctl-0.14.0/docs/guides/keycloak-lab.md +75 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/knowledge.md +12 -10
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/kvstore.md +19 -17
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/lookups.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/mcp.md +12 -10
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/parsers.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/rules.md +7 -5
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/search.md +6 -2
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/server.md +4 -2
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-actions.md +5 -3
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-admin.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-approvals.md +3 -1
- splunkctl-0.14.0/docs/guides/soar-apps.md +76 -0
- splunkctl-0.14.0/docs/guides/soar-assets.md +104 -0
- splunkctl-0.14.0/docs/guides/soar-automation.md +8 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-cases.md +4 -2
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-functions.md +3 -1
- splunkctl-0.14.0/docs/guides/soar-incidents.md +186 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-indicators.md +5 -3
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-ingest.md +15 -13
- splunkctl-0.14.0/docs/guides/soar-lists.md +135 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/soar-playbooks.md +9 -7
- splunkctl-0.14.0/docs/guides/soar.md +128 -0
- splunkctl-0.14.0/docs/guides/splunk-cli.md +42 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/state.md +7 -5
- {splunkctl-0.12.0 → splunkctl-0.14.0}/docs/guides/users.md +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/pyproject.toml +5 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/__init__.py +1 -1
- splunkctl-0.14.0/splunkctl/auth/__init__.py +1 -0
- splunkctl-0.14.0/splunkctl/auth/adapters.py +151 -0
- splunkctl-0.14.0/splunkctl/auth/broker.py +115 -0
- splunkctl-0.14.0/splunkctl/auth/detector.py +120 -0
- splunkctl-0.14.0/splunkctl/auth/session.py +204 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/client.py +66 -9
- splunkctl-0.14.0/splunkctl/commands/auth.py +198 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/commands_meta.py +21 -10
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/config_cmd.py +122 -14
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/docs_cmd.py +65 -15
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/doctor.py +49 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/hec.py +1 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/search.py +7 -0
- splunkctl-0.14.0/splunkctl/commands/soar/_client.py +81 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/_ingest_helpers.py +3 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/artifacts.py +6 -2
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/assets.py +21 -3
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/functions.py +2 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbooks.py +2 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_soar_assets.py +10 -6
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/config.py +70 -12
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/errors.py +12 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/guard.py +2 -2
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/main.py +31 -3
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/dynamic_server.py +9 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/resources.py +2 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/runner.py +3 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/output.py +2 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/client.py +12 -1
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/web.py +11 -0
- splunkctl-0.14.0/splunkctl/spl_safety.py +64 -0
- splunkctl-0.14.0/splunkctl.egg-info/PKG-INFO +115 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/SOURCES.txt +13 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/entry_points.txt +1 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/requires.txt +4 -1
- splunkctl-0.12.0/PKG-INFO +0 -270
- splunkctl-0.12.0/README.md +0 -230
- splunkctl-0.12.0/docs/guides/dashboards.md +0 -17
- splunkctl-0.12.0/docs/guides/es.md +0 -236
- splunkctl-0.12.0/docs/guides/install.md +0 -55
- splunkctl-0.12.0/docs/guides/soar-apps.md +0 -56
- splunkctl-0.12.0/docs/guides/soar-automation.md +0 -132
- splunkctl-0.12.0/docs/guides/soar-lists.md +0 -110
- splunkctl-0.12.0/docs/guides/soar.md +0 -440
- splunkctl-0.12.0/splunkctl/commands/soar/_client.py +0 -44
- splunkctl-0.12.0/splunkctl.egg-info/PKG-INFO +0 -270
- {splunkctl-0.12.0 → splunkctl-0.14.0}/LICENSE +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/MANIFEST.in +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/setup.cfg +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/__main__.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/__init__.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/alerts.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/apps.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/audit.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/audit_parse.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/common.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/conf.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/conf_ops.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/dashboards.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/datamodels.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/es.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/es_threat_intel.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/indexes.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/info.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/inputs.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/knowledge.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/kvstore.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/lookups.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/lookups_wiring.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/mcp_cmd.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/parsers.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/parsers_io.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules_io.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/rules_schedule.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_auth.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_deployment.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_tokens.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_topology.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/server_workloads.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/__init__.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/actions.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin_roles_audit.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/admin_views.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/approvals.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/apps.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/cases.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers_assign.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/containers_write.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/indicators.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/ingest.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/lists.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/notes.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbook_runs.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/playbooks_delete.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/search.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/system.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/vault.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/soar/workbook_templates.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_blobs.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_confs.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_io_soar.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/state_types.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/commands/users.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/__init__.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/output_cap.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/prompts.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/server.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/tools.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/mcp/transport.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/py.typed +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/__init__.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl/soar/cimcef.py +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/dependency_links.txt +0 -0
- {splunkctl-0.12.0 → splunkctl-0.14.0}/splunkctl.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: splunkctl
|
|
3
|
+
Version: 0.14.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.13
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Topic :: System :: Systems Administration
|
|
21
|
+
Requires-Python: >=3.13
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: splunk-sdk>=2.0
|
|
25
|
+
Requires-Dist: click>=8.2
|
|
26
|
+
Requires-Dist: pyyaml>=6.0
|
|
27
|
+
Requires-Dist: tabulate>=0.9
|
|
28
|
+
Requires-Dist: requests>=2.32
|
|
29
|
+
Requires-Dist: defusedxml>=0.7
|
|
30
|
+
Requires-Dist: mcp<3,>=2.3
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy>=1.11; extra == "dev"
|
|
35
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
36
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
37
|
+
Requires-Dist: types-tabulate; extra == "dev"
|
|
38
|
+
Requires-Dist: types-defusedxml; extra == "dev"
|
|
39
|
+
Provides-Extra: browser
|
|
40
|
+
Requires-Dist: playwright>=1.45; extra == "browser"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# splunkctl
|
|
44
|
+
|
|
45
|
+
<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>
|
|
46
|
+
|
|
47
|
+
Operate Splunk Enterprise, Enterprise Security, and Splunk SOAR from a terminal, or give an AI agent the same commands through MCP.
|
|
48
|
+
|
|
49
|
+
Requires Python 3.13+ and credentials for your Splunk instance.
|
|
50
|
+
|
|
51
|
+
## Quickstart
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
python -m pip install splunkctl
|
|
55
|
+
splunkctl config init
|
|
56
|
+
splunkctl doctor
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
[Documentation](https://splunkctl.danny.vn) · [Installation requirements](https://splunkctl.danny.vn/#/guides/install)
|
|
60
|
+
|
|
61
|
+
## Tasks
|
|
62
|
+
|
|
63
|
+
- 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)
|
|
64
|
+
- 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)
|
|
65
|
+
- Respond with SOAR: work containers, artifacts, vault files, notes, and playbook runs. [Work SOAR incidents](https://splunkctl.danny.vn/#/guides/soar-incidents)
|
|
66
|
+
- 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)
|
|
67
|
+
|
|
68
|
+
## Safety
|
|
69
|
+
|
|
70
|
+
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:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
$ splunkctl --profile uat rules delete 'My Rule'
|
|
74
|
+
[DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
|
|
75
|
+
Pass --yes to apply.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
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.
|
|
81
|
+
|
|
82
|
+
## Agent access
|
|
83
|
+
|
|
84
|
+
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).
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
splunkctl mcp install # register the server in ./.mcp.json
|
|
88
|
+
splunkctl commands --json # machine-readable command tree
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Guarded tools keep the same contract as the CLI: a call previews until the agent passes `yes=true` explicitly.
|
|
92
|
+
|
|
93
|
+
## Requirements and limitations
|
|
94
|
+
|
|
95
|
+
- Python 3.13 or newer.
|
|
96
|
+
- 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.
|
|
97
|
+
- Enterprise Security commands (`splunkctl es ...`) check for the `SplunkEnterpriseSecuritySuite` app and exit 1 with a `not_found` error when it is not installed.
|
|
98
|
+
- Dashboard, lookup file, and HEC token commands use entity classes from an optional SDK fork. Install it with:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
|
|
105
|
+
|
|
106
|
+
## Project and support
|
|
107
|
+
|
|
108
|
+
splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
|
|
109
|
+
|
|
110
|
+
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).
|
|
111
|
+
|
|
112
|
+
- [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
|
|
113
|
+
- [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
|
|
114
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
|
|
115
|
+
- License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
@@ -0,0 +1,73 @@
|
|
|
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.13+ 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.13 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
|
+
- Dashboard, lookup file, and HEC token commands use entity classes from an optional SDK fork. Install it with:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Browser SAML login needs the `browser` extra: `python -m pip install 'splunkctl[browser]'`.
|
|
63
|
+
|
|
64
|
+
## Project and support
|
|
65
|
+
|
|
66
|
+
splunkctl is an independent community project. It is not affiliated with or endorsed by Splunk Inc.
|
|
67
|
+
|
|
68
|
+
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).
|
|
69
|
+
|
|
70
|
+
- [Releases](https://github.com/dannyota/splunkctl/releases) and [changelog](https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md)
|
|
71
|
+
- [Issues](https://github.com/dannyota/splunkctl/issues) for bugs and feature requests; see [SECURITY.md](SECURITY.md) for vulnerabilities
|
|
72
|
+
- [CONTRIBUTING.md](CONTRIBUTING.md) for development setup
|
|
73
|
+
- License: [Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- summary: Review fired alerts, inspect alert actions, and manage alert suppression on a Splunk instance from the terminal. -->
|
|
2
|
+
|
|
3
|
+
# Review fired alerts
|
|
2
4
|
|
|
3
5
|
Fired alerts are the SOC's incoming work queue. During an incident, you
|
|
4
6
|
need to see what triggered, when, and at what severity. During planned
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- summary: Install, update, reload, and uninstall Splunk apps from local packages with a preview before every change. -->
|
|
2
|
+
|
|
3
|
+
# Manage apps
|
|
2
4
|
|
|
3
5
|
Splunk's detection and enrichment capabilities live in apps --
|
|
4
6
|
Technology Add-ons (TAs) for data normalization, security content packs
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
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
|
|
2
4
|
|
|
3
5
|
Regulator-facing evidence for bank SOC operations: who changed what
|
|
4
6
|
(`audit changes`) and who can do what (`audit rbac`). Both commands are
|
|
5
|
-
**read-only
|
|
7
|
+
**read-only**, no `guard`, no `--yes` needed.
|
|
6
8
|
|
|
7
9
|
## Why this matters
|
|
8
10
|
|
|
@@ -10,7 +12,7 @@ Banks carry regulator obligations for change-management evidence ("who
|
|
|
10
12
|
changed this saved search / role / index, and when") and periodic access
|
|
11
13
|
recertification ("who has which capabilities, and why"). Today an agent
|
|
12
14
|
would have to hand-write `index=_audit` SPL and know that Splunk mixes
|
|
13
|
-
**two incompatible event shapes** in that one index
|
|
15
|
+
**two incompatible event shapes** in that one index, this group
|
|
14
16
|
normalizes both into one schema and joins the RBAC graph so neither
|
|
15
17
|
requires bespoke SPL per engagement.
|
|
16
18
|
|
|
@@ -37,11 +39,11 @@ sourcetypes and this command normalizes both:
|
|
|
37
39
|
|
|
38
40
|
| Sourcetype | Shape | Mapping |
|
|
39
41
|
|---|---|---|
|
|
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
|
|
42
|
+
| `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
43
|
| `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
44
|
|
|
43
45
|
`time` always comes from Splunk's own indexed `_time` (not a re-parse of
|
|
44
|
-
either embedded timestamp format)
|
|
46
|
+
either embedded timestamp format), it's present on every event
|
|
45
47
|
regardless of shape and gives one consistent, sortable value.
|
|
46
48
|
|
|
47
49
|
There is no literal `data.object`/`data.object_type` key on real
|
|
@@ -49,20 +51,20 @@ There is no literal `data.object`/`data.object_type` key on real
|
|
|
49
51
|
equivalents and confirmed present for object/system-category events
|
|
50
52
|
(config changes). Action/authn/check-category events (ad-hoc searches,
|
|
51
53
|
logins, capability grants) carry `data.type` sometimes but rarely
|
|
52
|
-
`data.name
|
|
54
|
+
`data.name`, `object` stays empty for those, which is correct: they
|
|
53
55
|
aren't changes to a named object.
|
|
54
56
|
|
|
55
|
-
An event matching neither shape is **never dropped
|
|
57
|
+
An event matching neither shape is **never dropped**, it comes back as
|
|
56
58
|
`action: "unparsed"` with the full raw line in `object`, so evidence
|
|
57
59
|
stays complete even for audit-log formats this parser doesn't yet know.
|
|
58
60
|
|
|
59
61
|
## `audit changes`: SPL safety
|
|
60
62
|
|
|
61
|
-
The dispatched search is always the constant `search index=_audit
|
|
63
|
+
The dispatched search is always the constant `search index=_audit`,
|
|
62
64
|
nothing else, ever. `--since`/`--until` go through the oneshot job's
|
|
63
65
|
`earliest_time`/`latest_time` kwargs (not string-composed), and
|
|
64
66
|
`--user`/`--action`/`--object-type` filter the already-normalized rows
|
|
65
|
-
**client-side**, after the fetch. No flag value
|
|
67
|
+
**client-side**, after the fetch. No flag value, however adversarial,
|
|
66
68
|
reaches the SPL string. Verified live with `--debug`:
|
|
67
69
|
|
|
68
70
|
```bash
|
|
@@ -72,7 +74,7 @@ POST .../search/v2/jobs/ (body: {'search': 'search index=_audit', ...})
|
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
`--limit` (default 500) applies **after** filtering, not to the raw
|
|
75
|
-
fetch
|
|
77
|
+
fetch, the raw fetch itself is unbounded (`count=0`) within the
|
|
76
78
|
`--since`/`--until` window, so a `--user`/`--action` filter never misses
|
|
77
79
|
a match just because it fell outside an arbitrary raw-fetch cutoff.
|
|
78
80
|
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.
|
|
@@ -83,7 +85,7 @@ A very wide `--since` over a large `_audit` index may fetch all events in that r
|
|
|
83
85
|
One row per user by default: `user`, `email`, `roles` (direct roles,
|
|
84
86
|
semicolon-joined), `capabilities`, `srch_indexes_allowed`. The last two
|
|
85
87
|
are aggregated across the user's direct roles **and the full transitive
|
|
86
|
-
closure of their imported roles
|
|
88
|
+
closure of their imported roles**, deduplicated, sorted, and
|
|
87
89
|
semicolon-joined. `--roles-only` flips to one row per role instead:
|
|
88
90
|
`role`, `imported_roles` (direct only), `capabilities`,
|
|
89
91
|
`srch_indexes_allowed` (both aggregated the same transitive way, rooted
|
|
@@ -91,14 +93,14 @@ at that role).
|
|
|
91
93
|
|
|
92
94
|
Example: role `soc_analyst` imports `power`, which imports `user`. A
|
|
93
95
|
`soc_analyst` user's effective `capabilities` is the union of all three
|
|
94
|
-
roles' own capabilities
|
|
96
|
+
roles' own capabilities, this is what a role with zero capabilities of
|
|
95
97
|
its own (e.g. Splunk's built-in `splunk-system-role`, which only imports
|
|
96
98
|
`admin`) needs to show its real effective grant, not an empty cell.
|
|
97
99
|
|
|
98
100
|
## CSV round-trip safety
|
|
99
101
|
|
|
100
102
|
Multi-value fields (`roles`, `capabilities`, `srch_indexes_allowed`,
|
|
101
|
-
`imported_roles`) join with `;`, never `\n
|
|
103
|
+
`imported_roles`) join with `;`, never `\n`, Splunk role/capability/index
|
|
102
104
|
names can't contain a semicolon, so this is a safe, lossless join that
|
|
103
105
|
never produces an embedded newline inside a CSV cell. `--format csv`
|
|
104
106
|
output round-trips cleanly through Python's `csv` module.
|
|
@@ -121,5 +123,5 @@ output round-trips cleanly through Python's `csv` module.
|
|
|
121
123
|
(`svc.jobs.oneshot`); the event-shape parsers live in a sibling module,
|
|
122
124
|
`splunkctl/commands/audit_parse.py`, kept separate from the click
|
|
123
125
|
commands since they're pure functions with their own fixture-driven test
|
|
124
|
-
suite. `rbac` is SDK reads only (`svc.roles`, `svc.users`)
|
|
126
|
+
suite. `rbac` is SDK reads only (`svc.roles`, `svc.users`), no oneshot
|
|
125
127
|
search involved.
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
splunkctl can complete Splunk SAML single sign-on (including a second factor)
|
|
6
|
+
in a headed Chromium window and then reuse the resulting product session until
|
|
7
|
+
it expires. The browser handles the identity provider; splunkctl never reads or
|
|
8
|
+
stores TOTP secrets or codes.
|
|
9
|
+
|
|
10
|
+
## How it works
|
|
11
|
+
|
|
12
|
+
1. `splunkctl config init --web-url https://splunk.example.com` probes the public login route. When it sees a
|
|
13
|
+
redirect to an external identity provider, it records `auth_mode: browser`
|
|
14
|
+
and stores the product `web_url`.
|
|
15
|
+
2. `splunkctl auth login --target <siem|soar>` opens Chromium at the product
|
|
16
|
+
login route. You complete the IdP prompts, including any TOTP code.
|
|
17
|
+
3. splunkctl extracts only the product session (Splunk `splunkd_<port>` cookie,
|
|
18
|
+
or SOAR `sessionid` + `csrftoken`) and proves it against the product API.
|
|
19
|
+
4. Normal commands reuse the cached session whenever the active profile selects
|
|
20
|
+
browser mode. A missing or expired session never opens a browser; the command
|
|
21
|
+
prints the exact login instruction instead.
|
|
22
|
+
|
|
23
|
+
## Commands
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
splunkctl auth login --target siem
|
|
27
|
+
splunkctl auth login --target soar
|
|
28
|
+
splunkctl auth status [--target siem|soar|both]
|
|
29
|
+
splunkctl auth logout [--target siem|soar|both]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`login` requires exactly one target; two back-to-back browser flows are easy to
|
|
33
|
+
confuse. `status` reports `missing`, `valid`, `expired`, or `unreachable`.
|
|
34
|
+
`logout` always removes the local session, even if the remote endpoint refuses.
|
|
35
|
+
|
|
36
|
+
## Optional dependency
|
|
37
|
+
|
|
38
|
+
Browser login needs Playwright and Chromium:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install 'splunkctl[browser]'
|
|
42
|
+
python -m playwright install chromium
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Configuration still succeeds without them. `splunkctl auth login` prints the
|
|
46
|
+
exact commands when they are missing.
|
|
47
|
+
|
|
48
|
+
## Session storage and security
|
|
49
|
+
|
|
50
|
+
Sessions are stored under `~/.splunkctl/sessions/<profile>/<target>.json` with
|
|
51
|
+
directory mode `0700` and file mode `0600`. A record holds only the target,
|
|
52
|
+
profile, product origin, product session values, and validation timestamps. It
|
|
53
|
+
never stores passwords, Playwright storage state, identity-provider cookies, or
|
|
54
|
+
TOTP secrets. Session values are redacted from all output.
|
|
55
|
+
|
|
56
|
+
## What is and is not supported
|
|
57
|
+
|
|
58
|
+
Supported: SAML browser login for SIEM and SOAR, one target per login, session
|
|
59
|
+
status and logout, automatic SAML detection, and a reusable Keycloak lab.
|
|
60
|
+
|
|
61
|
+
Not supported in this release: reading or storing TOTP secrets, native Splunk
|
|
62
|
+
Duo or RSA flows, OpenID Connect or OAuth, logging in to both products in one
|
|
63
|
+
command, and a local splunkctl callback redirect.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
<!-- summary: Read and edit any Splunk configuration file and stanza over the REST confs API when no dedicated command group covers it. -->
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# Edit any conf file
|
|
4
|
+
|
|
5
|
+
Generic conf file/stanza editor over the REST `confs` API, the escape
|
|
4
6
|
hatch for any Splunk conf file that doesn't have a dedicated command
|
|
5
7
|
group yet: `macros`, `eventtypes`, `tags`, `limits`, `authorize`,
|
|
6
8
|
`server`, `web`, and everything else under `$SPLUNK_HOME/etc/*/local`.
|
|
@@ -14,7 +16,7 @@ and calculated fields live in `props.conf` alongside sourcetypes.
|
|
|
14
16
|
every other conf file the same way, so nothing detection-relevant is
|
|
15
17
|
locked out of code review or CI.
|
|
16
18
|
|
|
17
|
-
There is **no blocklist
|
|
19
|
+
There is **no blocklist**, `conf` can edit `authorize.conf`,
|
|
18
20
|
`server.conf`, and `web.conf` just as readily as `macros.conf`. The
|
|
19
21
|
dry-run guard and `--yes` are the only safety net: every `set`/`unset`/
|
|
20
22
|
`reload` preview names the exact file and stanza before it touches
|
|
@@ -54,7 +56,7 @@ splunkctl conf get eventtypes authentication --json | jq .
|
|
|
54
56
|
|
|
55
57
|
### Review a stanza change before applying
|
|
56
58
|
|
|
57
|
-
`conf set` always previews a field-level diff
|
|
59
|
+
`conf set` always previews a field-level diff, old value on the left,
|
|
58
60
|
new value on the right, `add` for a brand-new key:
|
|
59
61
|
|
|
60
62
|
```bash
|
|
@@ -71,7 +73,7 @@ splunkctl conf files --filter tag
|
|
|
71
73
|
|
|
72
74
|
## Tips
|
|
73
75
|
|
|
74
|
-
- `conf set` creates the stanza if it doesn't exist yet
|
|
76
|
+
- `conf set` creates the stanza if it doesn't exist yet, there's no
|
|
75
77
|
separate create step.
|
|
76
78
|
- The REST API has no true per-key delete; `conf unset` sets keys to
|
|
77
79
|
the empty string (same mechanism `parsers unset` uses). To fully
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<!-- summary: Set up splunkctl profiles for development, UAT, and production, and override them with environment variables or flags. -->
|
|
2
|
+
|
|
1
3
|
# Configure
|
|
2
4
|
|
|
3
5
|
## Interactive setup
|
|
@@ -6,8 +8,10 @@
|
|
|
6
8
|
splunkctl config init
|
|
7
9
|
```
|
|
8
10
|
|
|
9
|
-
Prompts for host, port,
|
|
10
|
-
|
|
11
|
+
Prompts for host, port, username, password, and TLS verification, then writes
|
|
12
|
+
`~/.splunkctl/config.yaml` with `0600` permissions. SAML detection runs only
|
|
13
|
+
when `--web-url URL` is supplied. Run `splunkctl config test` to check
|
|
14
|
+
connectivity and authentication after setup.
|
|
11
15
|
|
|
12
16
|
## Config file
|
|
13
17
|
|
|
@@ -27,7 +31,7 @@ owner: "nobody" # default owner context
|
|
|
27
31
|
|
|
28
32
|
**TLS verification is on by default.** Production instances with valid
|
|
29
33
|
certificates work out of the box. For lab/dev instances with self-signed
|
|
30
|
-
certs, set `verify: false` explicitly in the profile
|
|
34
|
+
certs, set `verify: false` explicitly in the profile, `config init` asks
|
|
31
35
|
during setup (default: yes).
|
|
32
36
|
|
|
33
37
|
## Profiles (dev/UAT/prod)
|
|
@@ -62,8 +66,8 @@ splunkctl --profile prod rules list # override for a single invocation
|
|
|
62
66
|
pointer > `default`.
|
|
63
67
|
|
|
64
68
|
**Legacy files keep working.** A plain flat file (no `profiles:` key) is
|
|
65
|
-
treated as an implicit profile named `default
|
|
66
|
-
`config init` writes that flat shape
|
|
69
|
+
treated as an implicit profile named `default`, nothing to migrate. Bare
|
|
70
|
+
`config init` writes that flat shape, unless the destination file already
|
|
67
71
|
has a `profiles:` key, in which case it folds the new values into
|
|
68
72
|
`profiles.default` instead, leaving sibling profiles and `current`
|
|
69
73
|
untouched (bare `config init` never clobbers an existing multi-profile
|
|
@@ -73,8 +77,8 @@ keys move under `profiles.default`, the new named profile is added
|
|
|
73
77
|
alongside it, and file permissions stay `0600`.
|
|
74
78
|
|
|
75
79
|
**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)
|
|
80
|
+
which instance is about to be mutated,
|
|
81
|
+
`[DRY RUN] ... (profile: uat @ uat.splunk.internal:8089)`, so switching
|
|
78
82
|
between dev/UAT/prod never happens silently. The banner is built from local
|
|
79
83
|
config only; it never opens a connection.
|
|
80
84
|
|
|
@@ -88,14 +92,40 @@ config only; it never opens a connection.
|
|
|
88
92
|
| `SPLUNK_USER` | `username` |
|
|
89
93
|
| `SPLUNK_PASS` | `password` |
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
override the flat config today.
|
|
95
|
+
Environment variables override fields in the selected profile.
|
|
93
96
|
|
|
94
97
|
## Resolution priority
|
|
95
98
|
|
|
96
|
-
1.
|
|
97
|
-
2.
|
|
98
|
-
3.
|
|
99
|
+
1. Environment variables
|
|
100
|
+
2. Selected profile
|
|
101
|
+
3. Built-in defaults
|
|
102
|
+
|
|
103
|
+
`--profile` and `--config` are the only root options that select configuration.
|
|
104
|
+
|
|
105
|
+
## Coexistence with Splunk's splunkctl
|
|
106
|
+
|
|
107
|
+
Splunk's own Go CLI, [`splunk/splunkctl`](https://github.com/splunk/splunkctl),
|
|
108
|
+
also writes `~/.splunkctl/config.yaml`, as a flat file with `host` (a full
|
|
109
|
+
URL) and `token`. This tool never rewrites that file.
|
|
110
|
+
|
|
111
|
+
- When `~/.splunkctl/config.yaml` is in Splunk's format and no `--config`
|
|
112
|
+
is given, this tool reads and writes `~/.splunkctl/profiles.yaml`
|
|
113
|
+
instead and prints one notice on standard error:
|
|
114
|
+
`Splunk-format config at ~/.splunkctl/config.yaml; using ~/.splunkctl/profiles.yaml`.
|
|
115
|
+
- `splunkctl config init` writes to the same fallback file, so a single
|
|
116
|
+
`config init` is enough on a host that already has Splunk's tool.
|
|
117
|
+
- An explicit `--config FILE` is never redirected. If that file is in
|
|
118
|
+
Splunk's format, the command fails with
|
|
119
|
+
`Splunk-format config at FILE: this is a flat host/token file written by Splunk's splunkctl. Pass a profiles file with --config, or create one with: splunkctl config init --path FILE`
|
|
120
|
+
- `splunkctl doctor` reports the config file in use as its first check.
|
|
121
|
+
- A hand-written file of this tool's own legacy flat format that contains
|
|
122
|
+
only `host` and `token` is indistinguishable from Splunk's format and is
|
|
123
|
+
treated the same way. Add `port` or `scheme`, or run `config init`, to
|
|
124
|
+
keep using it.
|
|
125
|
+
|
|
126
|
+
Both tools install an executable named `splunkctl`. This package also
|
|
127
|
+
installs `splunkctl-py`, which runs the same CLI, for hosts where Splunk's
|
|
128
|
+
binary comes first on `PATH`.
|
|
99
129
|
|
|
100
130
|
## Watch mode
|
|
101
131
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!-- summary: Export Splunk dashboards to files, keep them in version control, and create, update, share, or delete them with a preview before every change. -->
|
|
2
|
+
|
|
3
|
+
# Manage dashboards
|
|
4
|
+
|
|
5
|
+
When to use: you want dashboard XML or Studio JSON in version control, need to copy a dashboard between instances, or must change who can see one.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- The optional SDK fork, because dashboard commands use its `Dashboard` entity classes:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- A Splunk account with write access to the target app (for example the `admin` or `power` role in `search`).
|
|
16
|
+
|
|
17
|
+
## Synopsis
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
splunkctl dashboards list [--app APP] [--all] [--filter SUBSTRING] [--limit N] [--offset N]
|
|
21
|
+
splunkctl dashboards get <NAME> [--app APP] [--definition]
|
|
22
|
+
splunkctl dashboards export [NAME] [--app APP] [--out FILE] [--definition] [--all --dir DIR]
|
|
23
|
+
splunkctl dashboards create --name <NAME> --file <FILE> [--app APP] [--type classic|studio|auto] [--sharing user|app|global] [--yes]
|
|
24
|
+
splunkctl dashboards update <NAME> --file <FILE> [--app APP] [--type classic|studio|auto] [--yes]
|
|
25
|
+
splunkctl dashboards share <NAME> --sharing <user|app|global> [--owner USER] [--app APP] [--yes]
|
|
26
|
+
splunkctl dashboards delete <NAME> [--app APP] [--yes]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`--app` defaults to `search` for the mutation commands.
|
|
30
|
+
|
|
31
|
+
## Workflow
|
|
32
|
+
|
|
33
|
+
### List and inspect
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
splunkctl dashboards list
|
|
37
|
+
splunkctl dashboards list --app search --filter soc
|
|
38
|
+
splunkctl dashboards get soc_overview --app search
|
|
39
|
+
splunkctl dashboards get soc_studio --definition
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`list` shows dashboards only; add `--all` to include other views. `--filter`, `--limit`, and `--offset` apply client side after the app and type filters. `get` prints the XML source; `--definition` extracts the Studio JSON and errors on a Classic dashboard.
|
|
43
|
+
|
|
44
|
+
### Export to files
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
splunkctl dashboards export soc_overview --out dashboards/soc_overview.xml
|
|
48
|
+
splunkctl dashboards export soc_studio --definition --out dashboards/soc_studio.json
|
|
49
|
+
splunkctl dashboards export --all --dir dashboards/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Expected result: one file per dashboard, ready to commit. `--out` overwrites without prompting.
|
|
53
|
+
|
|
54
|
+
### Create a dashboard from a file
|
|
55
|
+
|
|
56
|
+
> **Safety:** Target is the Splunk host and app in the active profile (`--app`, default `search`). Impact: a new dashboard appears in that app. Preview with `splunkctl dashboards create --name new_dash --file dash.xml --app search`, apply by adding `--yes`, and verify with `splunkctl dashboards get new_dash --app search`.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
splunkctl dashboards create --name new_dash --file dash.xml --app search
|
|
60
|
+
splunkctl dashboards create --name new_dash --file dash.xml --app search --yes
|
|
61
|
+
splunkctl dashboards create --name new_dash --file dash.json --type studio --sharing app --yes
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`--type auto` (the default) detects Classic XML or Studio JSON from the file.
|
|
65
|
+
|
|
66
|
+
### Update a dashboard
|
|
67
|
+
|
|
68
|
+
> **Safety:** Target is the Splunk host and app in the active profile. Impact: the dashboard source is replaced with the file's content. Preview with `splunkctl dashboards update soc_overview --file updated.xml`, apply by adding `--yes`, and verify with `splunkctl dashboards get soc_overview`.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
splunkctl dashboards update soc_overview --file updated.xml --app search
|
|
72
|
+
splunkctl dashboards update soc_overview --file updated.xml --app search --yes
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Export first so you can restore the previous version if needed.
|
|
76
|
+
|
|
77
|
+
### Change sharing
|
|
78
|
+
|
|
79
|
+
> **Safety:** Target is the Splunk host and app in the active profile. Impact: who can see the dashboard changes; `global` makes it visible from every app. Preview with `splunkctl dashboards share soc_overview --sharing app`, apply by adding `--yes`, and verify with `splunkctl dashboards list --filter soc_overview --json` (check `sharing`).
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
splunkctl dashboards share soc_overview --sharing app --yes
|
|
83
|
+
splunkctl dashboards share soc_overview --sharing global --owner admin --yes
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Delete a dashboard
|
|
87
|
+
|
|
88
|
+
> **Safety:** Target is the Splunk host and app in the active profile. Impact: the dashboard is removed and cannot be recovered except from an export. Preview with `splunkctl dashboards delete old_dash --app search`, apply by adding `--yes`, and verify with `splunkctl dashboards list --app search --filter old_dash`.
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
splunkctl dashboards export old_dash --out backup/old_dash.xml
|
|
92
|
+
splunkctl dashboards delete old_dash --app search
|
|
93
|
+
splunkctl dashboards delete old_dash --app search --yes
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Troubleshooting
|
|
97
|
+
|
|
98
|
+
- `ImportError` or a message about missing `Dashboard` classes: install the SDK fork listed under Prerequisites.
|
|
99
|
+
- `not_found` on `get` or `update`: pass `--app`; the dashboard may live outside `search`.
|
|
100
|
+
- `--definition` errors: the dashboard is Classic XML, not Studio.
|
|
101
|
+
- `permission` on create or share: the account lacks write access to the app, or `global` sharing needs the `admin_all_objects` capability.
|
|
102
|
+
|
|
103
|
+
## See also
|
|
104
|
+
|
|
105
|
+
- [Manage configuration as code](state.md), which pulls and diffs dashboards
|
|
106
|
+
- [Run searches](search.md)
|
|
107
|
+
- [Install](install.md)
|
|
108
|
+
- [Command reference: dashboards](../commands/dashboards.md)
|