splunkctl 0.11.0__tar.gz → 0.11.2__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.11.2/MANIFEST.in +5 -0
- splunkctl-0.11.2/PKG-INFO +270 -0
- splunkctl-0.11.2/README.md +230 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/pyproject.toml +5 -3
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/__init__.py +1 -1
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/playbooks.py +3 -0
- splunkctl-0.11.2/splunkctl/soar/__init__.py +0 -0
- splunkctl-0.11.2/splunkctl.egg-info/PKG-INFO +270 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl.egg-info/SOURCES.txt +3 -9
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl.egg-info/requires.txt +1 -1
- splunkctl-0.11.0/PKG-INFO +0 -279
- splunkctl-0.11.0/README.md +0 -241
- splunkctl-0.11.0/splunkctl.egg-info/PKG-INFO +0 -279
- splunkctl-0.11.0/tests/test_client.py +0 -290
- splunkctl-0.11.0/tests/test_client_errors.py +0 -249
- splunkctl-0.11.0/tests/test_config.py +0 -500
- splunkctl-0.11.0/tests/test_guard.py +0 -226
- splunkctl-0.11.0/tests/test_main_errors.py +0 -167
- splunkctl-0.11.0/tests/test_main_hoisting.py +0 -82
- splunkctl-0.11.0/tests/test_output.py +0 -370
- splunkctl-0.11.0/tests/test_version.py +0 -7
- {splunkctl-0.11.0 → splunkctl-0.11.2}/LICENSE +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/setup.cfg +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/__main__.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/client.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/__init__.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/alerts.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/apps.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/audit.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/audit_parse.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/commands_meta.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/common.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/conf.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/conf_ops.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/config_cmd.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/dashboards.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/datamodels.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/docs_cmd.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/doctor.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/es.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/es_threat_intel.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/hec.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/indexes.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/info.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/inputs.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/knowledge.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/kvstore.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/lookups.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/lookups_wiring.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/mcp_cmd.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/parsers.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/parsers_io.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/rules.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/rules_io.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/rules_schedule.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/search.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server_auth.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server_deployment.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server_tokens.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server_topology.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/server_workloads.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/__init__.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/_client.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/_ingest_helpers.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/actions.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/admin.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/admin_roles_audit.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/admin_views.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/approvals.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/apps.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/artifacts.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/assets.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/cases.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/containers.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/containers_assign.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/containers_write.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/functions.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/indicators.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/ingest.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/lists.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/notes.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/playbook_runs.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/playbooks_delete.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/search.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/system.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/vault.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/soar/workbook_templates.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_io.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_io_blobs.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_io_confs.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_io_soar.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_io_soar_assets.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/state_types.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/commands/users.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/config.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/errors.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/guard.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/main.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/__init__.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/output_cap.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/prompts.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/resources.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/runner.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/server.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/mcp/tools.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/output.py +0 -0
- /splunkctl-0.11.0/splunkctl/soar/__init__.py → /splunkctl-0.11.2/splunkctl/py.typed +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/soar/cimcef.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/soar/client.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl/soar/web.py +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl.egg-info/dependency_links.txt +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl.egg-info/entry_points.txt +0 -0
- {splunkctl-0.11.0 → splunkctl-0.11.2}/splunkctl.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: splunkctl
|
|
3
|
+
Version: 0.11.2
|
|
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<2,>=1.28.1
|
|
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
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
<div align="center">
|
|
42
|
+
|
|
43
|
+
<a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl — operate Splunk Enterprise and Splunk SOAR as code" width="600"></a>
|
|
44
|
+
|
|
45
|
+
# splunkctl
|
|
46
|
+
|
|
47
|
+
[](https://pypi.org/project/splunkctl/)
|
|
48
|
+
[](https://pypi.org/project/splunkctl/)
|
|
49
|
+
[](https://github.com/dannyota/splunkctl/actions/workflows/ci.yml)
|
|
50
|
+
[](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
51
|
+
|
|
52
|
+
**Operate Splunk Enterprise and Splunk SOAR as code with a safety-first CLI and MCP server for humans and AI agents.**
|
|
53
|
+
|
|
54
|
+
[Documentation](https://splunkctl.danny.vn) · [Command catalog](https://github.com/dannyota/splunkctl/blob/master/docs/design/catalog.md) · [Releases](https://github.com/dannyota/splunkctl/releases)
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
`splunkctl` is an open-source Python CLI and
|
|
61
|
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for
|
|
62
|
+
remote Splunk Enterprise and Splunk SOAR instances. Use it interactively,
|
|
63
|
+
script its stable JSON output, or give an MCP client access to the same command
|
|
64
|
+
surface.
|
|
65
|
+
|
|
66
|
+
- **Manage Splunk Enterprise** — searches, detection rules, alerts, indexes,
|
|
67
|
+
inputs, lookups, parsers, dashboards, apps, users, topology, audit, and
|
|
68
|
+
Enterprise Security workflows.
|
|
69
|
+
- **Operate Splunk SOAR** — containers, artifacts, playbooks, actions, cases,
|
|
70
|
+
approvals, assets, vault files, custom lists, administration, and SIEM-to-SOAR
|
|
71
|
+
ingest.
|
|
72
|
+
- **Keep configuration as code** — pull live state, review structured drift,
|
|
73
|
+
and push approved changes with change-evidence reports.
|
|
74
|
+
- **Automate safely** — mutations preview by default, machine output is
|
|
75
|
+
structured, errors are typed, and every target profile and host is shown.
|
|
76
|
+
|
|
77
|
+
> **Every mutation is a dry run by default.** Nothing changes until you pass
|
|
78
|
+
> `--yes`. Review the target and proposed change before applying it.
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
python -m pip install splunkctl
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Python 3.13 or newer is required. Core commands work with the upstream Splunk
|
|
87
|
+
SDK installed from PyPI.
|
|
88
|
+
|
|
89
|
+
Dashboard, lookup-file, and HTTP Event Collector (HEC) token commands use
|
|
90
|
+
entity classes provided by the optional `splunkctl` SDK fork:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
See the [installation guide](https://splunkctl.danny.vn/#/guides/install) for
|
|
97
|
+
environment-specific setup.
|
|
98
|
+
|
|
99
|
+
## Quickstart
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Configure and verify Splunk Enterprise
|
|
103
|
+
splunkctl config init
|
|
104
|
+
splunkctl doctor
|
|
105
|
+
|
|
106
|
+
# Read live state
|
|
107
|
+
splunkctl info
|
|
108
|
+
splunkctl search run 'index=main | head 10'
|
|
109
|
+
splunkctl rules list --json
|
|
110
|
+
|
|
111
|
+
# Preview a change; add --yes only after reviewing it
|
|
112
|
+
splunkctl rules disable 'My Rule'
|
|
113
|
+
|
|
114
|
+
# Add and verify Splunk SOAR when needed
|
|
115
|
+
splunkctl config init --soar
|
|
116
|
+
splunkctl soar test
|
|
117
|
+
splunkctl soar containers list
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use named profiles for separate development, UAT, and production instances:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
splunkctl config init --profile uat
|
|
124
|
+
splunkctl --profile uat doctor
|
|
125
|
+
splunkctl --profile uat rules list
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Core workflows
|
|
129
|
+
|
|
130
|
+
### Configuration as code
|
|
131
|
+
|
|
132
|
+
The `state` engine covers rules, parsers, macros, lookups, and selected SOAR
|
|
133
|
+
objects. Dashboards support pull and diff. Push never deletes remote objects.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
splunkctl state pull --dir config/
|
|
137
|
+
# Edit the exported files in version control.
|
|
138
|
+
splunkctl state diff --dir config/
|
|
139
|
+
splunkctl state push --dir config/ --report change-report.json
|
|
140
|
+
splunkctl state push --dir config/ --report change-report.json --yes
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The report records before-and-after state and whether the change was applied,
|
|
144
|
+
so it can be attached to a change ticket.
|
|
145
|
+
|
|
146
|
+
### Detection and SIEM operations
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
splunkctl rules export --path rules.yaml
|
|
150
|
+
splunkctl rules import --path rules.yaml
|
|
151
|
+
splunkctl datamodels acceleration
|
|
152
|
+
splunkctl es notables list --status new --json
|
|
153
|
+
splunkctl audit rbac --format csv --out rbac.csv
|
|
154
|
+
splunkctl server cluster
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Enterprise Security commands detect whether the required app is available and
|
|
158
|
+
return a clear error when it is not.
|
|
159
|
+
|
|
160
|
+
### Splunk SOAR operations
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
splunkctl soar containers list --severity high
|
|
164
|
+
splunkctl soar playbooks export my_playbook --unpack --out playbooks/
|
|
165
|
+
splunkctl soar playbooks run my_playbook --container 42 --wait
|
|
166
|
+
splunkctl soar actions run --action geolocate_ip --asset maxmind \
|
|
167
|
+
--container 42 --param ip=203.0.113.10 --wait
|
|
168
|
+
splunkctl soar ingest --spl 'index=notable' --label events
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
SOAR commands use the same profiles, dry-run guard, output formats, and error
|
|
172
|
+
contract as the Splunk Enterprise commands.
|
|
173
|
+
|
|
174
|
+
### MCP for AI agents
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
splunkctl mcp install
|
|
178
|
+
splunkctl mcp serve
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
The built-in MCP server generates typed tools from the CLI command tree and
|
|
182
|
+
uses progressive discovery: clients start with a small set of meta-tools, then
|
|
183
|
+
focus on the command groups needed for the task. Guarded tools require an
|
|
184
|
+
explicit `yes=true` before they can mutate a remote instance.
|
|
185
|
+
|
|
186
|
+
See the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp) for stdio and
|
|
187
|
+
streamable HTTP configuration.
|
|
188
|
+
|
|
189
|
+
## Command groups
|
|
190
|
+
|
|
191
|
+
| Group | Purpose |
|
|
192
|
+
|---|---|
|
|
193
|
+
| `doctor` | Check connection, authentication, health, and permissions |
|
|
194
|
+
| `config` | Configure profiles and test connectivity |
|
|
195
|
+
| `info` | Show server version, operating system, and license details |
|
|
196
|
+
| `search` | Run, export, upload, and manage search jobs |
|
|
197
|
+
| `rules` | Manage detection rules and YAML import/export |
|
|
198
|
+
| `alerts` | Inspect fired alerts and manage suppression |
|
|
199
|
+
| `dashboards` | Manage Classic and Studio dashboards |
|
|
200
|
+
| `indexes` | Manage indexes |
|
|
201
|
+
| `inputs` | Manage monitor, TCP, UDP, script, and HTTP inputs |
|
|
202
|
+
| `lookups` | Manage lookup files, definitions, and automatic wiring |
|
|
203
|
+
| `hec` | Manage HEC tokens, settings, and events |
|
|
204
|
+
| `parsers` | Manage source types, props, transforms, and YAML state |
|
|
205
|
+
| `apps` | Install, update, reload, and uninstall apps |
|
|
206
|
+
| `users` | Manage users and roles |
|
|
207
|
+
| `server` | Inspect health, topology, deployment, auth, tokens, and workloads |
|
|
208
|
+
| `es` | Triage notables and manage correlations and threat intelligence |
|
|
209
|
+
| `audit` | Review changes and generate role-based access control attestations |
|
|
210
|
+
| `kvstore` | Manage KV Store collections and documents |
|
|
211
|
+
| `conf` | Edit any Splunk configuration file and stanza |
|
|
212
|
+
| `macros`, `eventtypes`, `tags` | Manage search knowledge objects |
|
|
213
|
+
| `datamodels` | Inspect definitions and acceleration health |
|
|
214
|
+
| `state` | Pull, diff, and push configuration state |
|
|
215
|
+
| `soar` | Operate Splunk SOAR and run SIEM-to-SOAR workflows |
|
|
216
|
+
| `commands` | Emit the machine-readable command tree |
|
|
217
|
+
| `completion` | Generate shell completion for Bash, Zsh, or Fish |
|
|
218
|
+
| `mcp` | Install and run the MCP server |
|
|
219
|
+
|
|
220
|
+
Run `splunkctl COMMAND --help` for local help, or use the
|
|
221
|
+
[generated command reference](https://splunkctl.danny.vn/#/commands/).
|
|
222
|
+
|
|
223
|
+
## Output and safety contracts
|
|
224
|
+
|
|
225
|
+
Global flags work before or after subcommands:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
--json Force JSON output
|
|
229
|
+
--format FMT Select table, json, csv, or jsonl
|
|
230
|
+
--fields f1,f2 Select output fields
|
|
231
|
+
--out FILE Write output to a file
|
|
232
|
+
--yes, -y Apply a mutation after previewing it
|
|
233
|
+
--timeout N Set the request timeout in seconds
|
|
234
|
+
--watch N Repeat a read-only command every N seconds
|
|
235
|
+
--config FILE Use a specific configuration file
|
|
236
|
+
--profile NAME Select a named profile
|
|
237
|
+
--debug Log HTTP requests and responses
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Under JSON output, failures emit one JSON object on standard error with a
|
|
241
|
+
stable error kind:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{"error": {"kind": "not_found", "http_status": 404, "message": "..."}}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Kinds include `auth`, `permission`, `not_found`, `conflict`, `http`,
|
|
248
|
+
`connection`, `timeout`, and `error`. List commands share uniform filtering and
|
|
249
|
+
paging flags where the remote API supports them.
|
|
250
|
+
|
|
251
|
+
Every guarded operation identifies its target before it runs:
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
$ splunkctl --profile uat rules delete 'My Rule'
|
|
255
|
+
[DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
|
|
256
|
+
Pass --yes to apply.
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Development
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
git clone https://github.com/dannyota/splunkctl
|
|
263
|
+
cd splunkctl
|
|
264
|
+
python -m pip install -e '.[dev]'
|
|
265
|
+
python -m pytest
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
[Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<a href="https://splunkctl.danny.vn"><img src="https://raw.githubusercontent.com/dannyota/splunkctl/master/docs/assets/banner.svg" alt="splunkctl — operate Splunk Enterprise and Splunk SOAR as code" width="600"></a>
|
|
4
|
+
|
|
5
|
+
# splunkctl
|
|
6
|
+
|
|
7
|
+
[](https://pypi.org/project/splunkctl/)
|
|
8
|
+
[](https://pypi.org/project/splunkctl/)
|
|
9
|
+
[](https://github.com/dannyota/splunkctl/actions/workflows/ci.yml)
|
|
10
|
+
[](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
11
|
+
|
|
12
|
+
**Operate Splunk Enterprise and Splunk SOAR as code with a safety-first CLI and MCP server for humans and AI agents.**
|
|
13
|
+
|
|
14
|
+
[Documentation](https://splunkctl.danny.vn) · [Command catalog](https://github.com/dannyota/splunkctl/blob/master/docs/design/catalog.md) · [Releases](https://github.com/dannyota/splunkctl/releases)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
`splunkctl` is an open-source Python CLI and
|
|
21
|
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for
|
|
22
|
+
remote Splunk Enterprise and Splunk SOAR instances. Use it interactively,
|
|
23
|
+
script its stable JSON output, or give an MCP client access to the same command
|
|
24
|
+
surface.
|
|
25
|
+
|
|
26
|
+
- **Manage Splunk Enterprise** — searches, detection rules, alerts, indexes,
|
|
27
|
+
inputs, lookups, parsers, dashboards, apps, users, topology, audit, and
|
|
28
|
+
Enterprise Security workflows.
|
|
29
|
+
- **Operate Splunk SOAR** — containers, artifacts, playbooks, actions, cases,
|
|
30
|
+
approvals, assets, vault files, custom lists, administration, and SIEM-to-SOAR
|
|
31
|
+
ingest.
|
|
32
|
+
- **Keep configuration as code** — pull live state, review structured drift,
|
|
33
|
+
and push approved changes with change-evidence reports.
|
|
34
|
+
- **Automate safely** — mutations preview by default, machine output is
|
|
35
|
+
structured, errors are typed, and every target profile and host is shown.
|
|
36
|
+
|
|
37
|
+
> **Every mutation is a dry run by default.** Nothing changes until you pass
|
|
38
|
+
> `--yes`. Review the target and proposed change before applying it.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python -m pip install splunkctl
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Python 3.13 or newer is required. Core commands work with the upstream Splunk
|
|
47
|
+
SDK installed from PyPI.
|
|
48
|
+
|
|
49
|
+
Dashboard, lookup-file, and HTTP Event Collector (HEC) token commands use
|
|
50
|
+
entity classes provided by the optional `splunkctl` SDK fork:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python -m pip install git+https://github.com/dannyota/splunk-sdk-python@splunkctl
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
See the [installation guide](https://splunkctl.danny.vn/#/guides/install) for
|
|
57
|
+
environment-specific setup.
|
|
58
|
+
|
|
59
|
+
## Quickstart
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Configure and verify Splunk Enterprise
|
|
63
|
+
splunkctl config init
|
|
64
|
+
splunkctl doctor
|
|
65
|
+
|
|
66
|
+
# Read live state
|
|
67
|
+
splunkctl info
|
|
68
|
+
splunkctl search run 'index=main | head 10'
|
|
69
|
+
splunkctl rules list --json
|
|
70
|
+
|
|
71
|
+
# Preview a change; add --yes only after reviewing it
|
|
72
|
+
splunkctl rules disable 'My Rule'
|
|
73
|
+
|
|
74
|
+
# Add and verify Splunk SOAR when needed
|
|
75
|
+
splunkctl config init --soar
|
|
76
|
+
splunkctl soar test
|
|
77
|
+
splunkctl soar containers list
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use named profiles for separate development, UAT, and production instances:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
splunkctl config init --profile uat
|
|
84
|
+
splunkctl --profile uat doctor
|
|
85
|
+
splunkctl --profile uat rules list
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Core workflows
|
|
89
|
+
|
|
90
|
+
### Configuration as code
|
|
91
|
+
|
|
92
|
+
The `state` engine covers rules, parsers, macros, lookups, and selected SOAR
|
|
93
|
+
objects. Dashboards support pull and diff. Push never deletes remote objects.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
splunkctl state pull --dir config/
|
|
97
|
+
# Edit the exported files in version control.
|
|
98
|
+
splunkctl state diff --dir config/
|
|
99
|
+
splunkctl state push --dir config/ --report change-report.json
|
|
100
|
+
splunkctl state push --dir config/ --report change-report.json --yes
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The report records before-and-after state and whether the change was applied,
|
|
104
|
+
so it can be attached to a change ticket.
|
|
105
|
+
|
|
106
|
+
### Detection and SIEM operations
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
splunkctl rules export --path rules.yaml
|
|
110
|
+
splunkctl rules import --path rules.yaml
|
|
111
|
+
splunkctl datamodels acceleration
|
|
112
|
+
splunkctl es notables list --status new --json
|
|
113
|
+
splunkctl audit rbac --format csv --out rbac.csv
|
|
114
|
+
splunkctl server cluster
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Enterprise Security commands detect whether the required app is available and
|
|
118
|
+
return a clear error when it is not.
|
|
119
|
+
|
|
120
|
+
### Splunk SOAR operations
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
splunkctl soar containers list --severity high
|
|
124
|
+
splunkctl soar playbooks export my_playbook --unpack --out playbooks/
|
|
125
|
+
splunkctl soar playbooks run my_playbook --container 42 --wait
|
|
126
|
+
splunkctl soar actions run --action geolocate_ip --asset maxmind \
|
|
127
|
+
--container 42 --param ip=203.0.113.10 --wait
|
|
128
|
+
splunkctl soar ingest --spl 'index=notable' --label events
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
SOAR commands use the same profiles, dry-run guard, output formats, and error
|
|
132
|
+
contract as the Splunk Enterprise commands.
|
|
133
|
+
|
|
134
|
+
### MCP for AI agents
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
splunkctl mcp install
|
|
138
|
+
splunkctl mcp serve
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The built-in MCP server generates typed tools from the CLI command tree and
|
|
142
|
+
uses progressive discovery: clients start with a small set of meta-tools, then
|
|
143
|
+
focus on the command groups needed for the task. Guarded tools require an
|
|
144
|
+
explicit `yes=true` before they can mutate a remote instance.
|
|
145
|
+
|
|
146
|
+
See the [MCP guide](https://splunkctl.danny.vn/#/guides/mcp) for stdio and
|
|
147
|
+
streamable HTTP configuration.
|
|
148
|
+
|
|
149
|
+
## Command groups
|
|
150
|
+
|
|
151
|
+
| Group | Purpose |
|
|
152
|
+
|---|---|
|
|
153
|
+
| `doctor` | Check connection, authentication, health, and permissions |
|
|
154
|
+
| `config` | Configure profiles and test connectivity |
|
|
155
|
+
| `info` | Show server version, operating system, and license details |
|
|
156
|
+
| `search` | Run, export, upload, and manage search jobs |
|
|
157
|
+
| `rules` | Manage detection rules and YAML import/export |
|
|
158
|
+
| `alerts` | Inspect fired alerts and manage suppression |
|
|
159
|
+
| `dashboards` | Manage Classic and Studio dashboards |
|
|
160
|
+
| `indexes` | Manage indexes |
|
|
161
|
+
| `inputs` | Manage monitor, TCP, UDP, script, and HTTP inputs |
|
|
162
|
+
| `lookups` | Manage lookup files, definitions, and automatic wiring |
|
|
163
|
+
| `hec` | Manage HEC tokens, settings, and events |
|
|
164
|
+
| `parsers` | Manage source types, props, transforms, and YAML state |
|
|
165
|
+
| `apps` | Install, update, reload, and uninstall apps |
|
|
166
|
+
| `users` | Manage users and roles |
|
|
167
|
+
| `server` | Inspect health, topology, deployment, auth, tokens, and workloads |
|
|
168
|
+
| `es` | Triage notables and manage correlations and threat intelligence |
|
|
169
|
+
| `audit` | Review changes and generate role-based access control attestations |
|
|
170
|
+
| `kvstore` | Manage KV Store collections and documents |
|
|
171
|
+
| `conf` | Edit any Splunk configuration file and stanza |
|
|
172
|
+
| `macros`, `eventtypes`, `tags` | Manage search knowledge objects |
|
|
173
|
+
| `datamodels` | Inspect definitions and acceleration health |
|
|
174
|
+
| `state` | Pull, diff, and push configuration state |
|
|
175
|
+
| `soar` | Operate Splunk SOAR and run SIEM-to-SOAR workflows |
|
|
176
|
+
| `commands` | Emit the machine-readable command tree |
|
|
177
|
+
| `completion` | Generate shell completion for Bash, Zsh, or Fish |
|
|
178
|
+
| `mcp` | Install and run the MCP server |
|
|
179
|
+
|
|
180
|
+
Run `splunkctl COMMAND --help` for local help, or use the
|
|
181
|
+
[generated command reference](https://splunkctl.danny.vn/#/commands/).
|
|
182
|
+
|
|
183
|
+
## Output and safety contracts
|
|
184
|
+
|
|
185
|
+
Global flags work before or after subcommands:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
--json Force JSON output
|
|
189
|
+
--format FMT Select table, json, csv, or jsonl
|
|
190
|
+
--fields f1,f2 Select output fields
|
|
191
|
+
--out FILE Write output to a file
|
|
192
|
+
--yes, -y Apply a mutation after previewing it
|
|
193
|
+
--timeout N Set the request timeout in seconds
|
|
194
|
+
--watch N Repeat a read-only command every N seconds
|
|
195
|
+
--config FILE Use a specific configuration file
|
|
196
|
+
--profile NAME Select a named profile
|
|
197
|
+
--debug Log HTTP requests and responses
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Under JSON output, failures emit one JSON object on standard error with a
|
|
201
|
+
stable error kind:
|
|
202
|
+
|
|
203
|
+
```json
|
|
204
|
+
{"error": {"kind": "not_found", "http_status": 404, "message": "..."}}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Kinds include `auth`, `permission`, `not_found`, `conflict`, `http`,
|
|
208
|
+
`connection`, `timeout`, and `error`. List commands share uniform filtering and
|
|
209
|
+
paging flags where the remote API supports them.
|
|
210
|
+
|
|
211
|
+
Every guarded operation identifies its target before it runs:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
$ splunkctl --profile uat rules delete 'My Rule'
|
|
215
|
+
[DRY RUN] Delete saved search 'My Rule' (profile: uat @ uat.splunk.internal:8089)
|
|
216
|
+
Pass --yes to apply.
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Development
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
git clone https://github.com/dannyota/splunkctl
|
|
223
|
+
cd splunkctl
|
|
224
|
+
python -m pip install -e '.[dev]'
|
|
225
|
+
python -m pytest
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
[Apache-2.0](https://github.com/dannyota/splunkctl/blob/master/LICENSE)
|
|
@@ -13,7 +13,7 @@ license-files = ["LICENSE"]
|
|
|
13
13
|
authors = [{ name = "dannyota" }]
|
|
14
14
|
keywords = ["splunk", "mcp", "model-context-protocol", "siem", "soar", "security", "cli", "detection", "spl"]
|
|
15
15
|
classifiers = [
|
|
16
|
-
"Development Status ::
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
17
|
"Environment :: Console",
|
|
18
18
|
"Intended Audience :: System Administrators",
|
|
19
19
|
"Operating System :: OS Independent",
|
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
|
29
29
|
"tabulate>=0.9",
|
|
30
30
|
"requests>=2.32",
|
|
31
31
|
"defusedxml>=0.7",
|
|
32
|
-
"mcp>=1.
|
|
32
|
+
"mcp>=1.28.1,<2",
|
|
33
33
|
]
|
|
34
34
|
|
|
35
35
|
[project.optional-dependencies]
|
|
@@ -48,8 +48,10 @@ splunkctl = "splunkctl.main:cli"
|
|
|
48
48
|
|
|
49
49
|
[project.urls]
|
|
50
50
|
Homepage = "https://github.com/dannyota/splunkctl"
|
|
51
|
+
Documentation = "https://splunkctl.danny.vn"
|
|
51
52
|
Repository = "https://github.com/dannyota/splunkctl"
|
|
52
53
|
Issues = "https://github.com/dannyota/splunkctl/issues"
|
|
54
|
+
Changelog = "https://github.com/dannyota/splunkctl/blob/master/CHANGELOG.md"
|
|
53
55
|
|
|
54
56
|
# Auto-discover subpackages — a hardcoded list silently dropped
|
|
55
57
|
# splunkctl.commands.soar from every wheel (v0.7.0–v0.10.0).
|
|
@@ -60,7 +62,7 @@ include = ["splunkctl*"]
|
|
|
60
62
|
version = { attr = "splunkctl.__version__" }
|
|
61
63
|
|
|
62
64
|
[tool.setuptools.package-data]
|
|
63
|
-
"splunkctl
|
|
65
|
+
"splunkctl" = ["py.typed"]
|
|
64
66
|
|
|
65
67
|
# --- Ruff (lint + format) ---
|
|
66
68
|
|
|
@@ -328,6 +328,9 @@ def _unpack_tgz(tgz_bytes: bytes, out_dir: str | None, ctx: click.Context) -> No
|
|
|
328
328
|
"""Extract a playbook tgz to *out_dir* (or cwd)."""
|
|
329
329
|
dest = Path(out_dir) if out_dir else Path.cwd()
|
|
330
330
|
try:
|
|
331
|
+
# filter="data" rejects path traversal, absolute paths, and
|
|
332
|
+
# symlink escapes (PEP 706).
|
|
333
|
+
# nosemgrep
|
|
331
334
|
with tarfile.open(fileobj=io.BytesIO(tgz_bytes), mode="r:gz") as tar:
|
|
332
335
|
tar.extractall(path=dest, filter="data")
|
|
333
336
|
except (tarfile.TarError, OSError) as exc:
|
|
File without changes
|