holmesgpt 0.13.0__py3-none-any.whl → 0.13.1__py3-none-any.whl
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.
Potentially problematic release.
This version of holmesgpt might be problematic. Click here for more details.
- holmes/__init__.py +1 -1
- holmes/common/env_vars.py +4 -0
- holmes/core/llm.py +3 -1
- holmes/core/tool_calling_llm.py +112 -11
- holmes/core/toolset_manager.py +1 -5
- holmes/core/tracing.py +1 -1
- holmes/main.py +7 -1
- holmes/plugins/prompts/_fetch_logs.jinja2 +4 -0
- holmes/plugins/runbooks/CLAUDE.md +85 -0
- holmes/plugins/runbooks/README.md +24 -0
- holmes/plugins/toolsets/bash/argocd/__init__.py +65 -0
- holmes/plugins/toolsets/bash/argocd/constants.py +120 -0
- holmes/plugins/toolsets/bash/aws/__init__.py +66 -0
- holmes/plugins/toolsets/bash/aws/constants.py +529 -0
- holmes/plugins/toolsets/bash/azure/__init__.py +56 -0
- holmes/plugins/toolsets/bash/azure/constants.py +339 -0
- holmes/plugins/toolsets/bash/bash_instructions.jinja2 +6 -7
- holmes/plugins/toolsets/bash/bash_toolset.py +47 -13
- holmes/plugins/toolsets/bash/common/bash_command.py +131 -0
- holmes/plugins/toolsets/bash/common/stringify.py +14 -1
- holmes/plugins/toolsets/bash/common/validators.py +91 -0
- holmes/plugins/toolsets/bash/docker/__init__.py +59 -0
- holmes/plugins/toolsets/bash/docker/constants.py +255 -0
- holmes/plugins/toolsets/bash/helm/__init__.py +61 -0
- holmes/plugins/toolsets/bash/helm/constants.py +92 -0
- holmes/plugins/toolsets/bash/kubectl/__init__.py +80 -79
- holmes/plugins/toolsets/bash/kubectl/constants.py +0 -14
- holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +38 -56
- holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +28 -76
- holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +39 -99
- holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +34 -15
- holmes/plugins/toolsets/bash/kubectl/kubectl_run.py +1 -1
- holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +38 -77
- holmes/plugins/toolsets/bash/parse_command.py +106 -32
- holmes/plugins/toolsets/bash/utilities/__init__.py +0 -0
- holmes/plugins/toolsets/bash/utilities/base64_util.py +12 -0
- holmes/plugins/toolsets/bash/utilities/cut.py +12 -0
- holmes/plugins/toolsets/bash/utilities/grep/__init__.py +10 -0
- holmes/plugins/toolsets/bash/utilities/head.py +12 -0
- holmes/plugins/toolsets/bash/utilities/jq.py +79 -0
- holmes/plugins/toolsets/bash/utilities/sed.py +164 -0
- holmes/plugins/toolsets/bash/utilities/sort.py +15 -0
- holmes/plugins/toolsets/bash/utilities/tail.py +12 -0
- holmes/plugins/toolsets/bash/utilities/tr.py +57 -0
- holmes/plugins/toolsets/bash/utilities/uniq.py +12 -0
- holmes/plugins/toolsets/bash/utilities/wc.py +12 -0
- holmes/plugins/toolsets/prometheus/prometheus.py +42 -12
- holmes/utils/console/logging.py +6 -1
- {holmesgpt-0.13.0.dist-info → holmesgpt-0.13.1.dist-info}/METADATA +1 -1
- {holmesgpt-0.13.0.dist-info → holmesgpt-0.13.1.dist-info}/RECORD +53 -30
- holmes/plugins/toolsets/bash/grep/__init__.py +0 -52
- {holmesgpt-0.13.0.dist-info → holmesgpt-0.13.1.dist-info}/LICENSE.txt +0 -0
- {holmesgpt-0.13.0.dist-info → holmesgpt-0.13.1.dist-info}/WHEEL +0 -0
- {holmesgpt-0.13.0.dist-info → holmesgpt-0.13.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import fnmatch
|
|
2
3
|
import re
|
|
3
4
|
from typing import Union
|
|
4
5
|
|
|
@@ -22,3 +23,93 @@ def whitelist_validator(field_name: str, whitelisted_values: set[str]):
|
|
|
22
23
|
return value
|
|
23
24
|
|
|
24
25
|
return validate_value
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def validate_command_and_operations(
|
|
29
|
+
command: str,
|
|
30
|
+
options: list[str],
|
|
31
|
+
allowed_commands: dict[str, dict],
|
|
32
|
+
denied_commands: dict[str, dict],
|
|
33
|
+
) -> None:
|
|
34
|
+
"""Validate that the command and operation combination is safe, with wildcard support."""
|
|
35
|
+
|
|
36
|
+
# Check denied commands first (including wildcards)
|
|
37
|
+
_check_denied_command_with_wildcards(
|
|
38
|
+
command=command, options=options, denied_commands=denied_commands
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Check allowed commands (including wildcards)
|
|
42
|
+
_check_allowed_command_with_wildcards(
|
|
43
|
+
command=command, options=options, allowed_commands=allowed_commands
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _check_options_against_denied_commands(
|
|
48
|
+
command: str, options: list[str], denied_commands: dict
|
|
49
|
+
):
|
|
50
|
+
for idx, option in enumerate(options):
|
|
51
|
+
new_command = command + " " + option
|
|
52
|
+
for potential_command, children in denied_commands.items():
|
|
53
|
+
option_does_match = fnmatch.fnmatchcase(option, potential_command)
|
|
54
|
+
if option_does_match and children == {}:
|
|
55
|
+
raise ValueError(f"Command is blocked: {new_command}")
|
|
56
|
+
elif option_does_match:
|
|
57
|
+
_check_options_against_denied_commands(
|
|
58
|
+
command=new_command,
|
|
59
|
+
options=options[idx + 1 :],
|
|
60
|
+
denied_commands=children,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _check_denied_command_with_wildcards(
|
|
65
|
+
command: str, options: list[str], denied_commands: dict[str, dict]
|
|
66
|
+
) -> None:
|
|
67
|
+
# Check exact command match first
|
|
68
|
+
for potential_command, children in denied_commands.items():
|
|
69
|
+
command_does_match = fnmatch.fnmatchcase(command, potential_command)
|
|
70
|
+
if command_does_match and children == {}:
|
|
71
|
+
raise ValueError(f"Command is blocked: {command}")
|
|
72
|
+
elif command_does_match:
|
|
73
|
+
_check_options_against_denied_commands(
|
|
74
|
+
command=command, options=options, denied_commands=children
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _do_options_match_an_allowed_command(
|
|
79
|
+
command: str, options: list[str], allowed_commands: dict
|
|
80
|
+
) -> bool:
|
|
81
|
+
for idx, option in enumerate(options):
|
|
82
|
+
new_command = command + " " + option
|
|
83
|
+
for potential_command, children in allowed_commands.items():
|
|
84
|
+
option_does_match = fnmatch.fnmatchcase(option, potential_command)
|
|
85
|
+
if option_does_match and children == {}:
|
|
86
|
+
return True
|
|
87
|
+
elif option_does_match:
|
|
88
|
+
is_allowed = _do_options_match_an_allowed_command(
|
|
89
|
+
command=new_command,
|
|
90
|
+
options=options[idx + 1 :],
|
|
91
|
+
allowed_commands=children,
|
|
92
|
+
)
|
|
93
|
+
if is_allowed:
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _check_allowed_command_with_wildcards(
|
|
100
|
+
command: str, options: list[str], allowed_commands: dict[str, dict]
|
|
101
|
+
):
|
|
102
|
+
for potential_command, children in allowed_commands.items():
|
|
103
|
+
cursor_does_match = fnmatch.fnmatchcase(command, potential_command)
|
|
104
|
+
if cursor_does_match and children == {}:
|
|
105
|
+
return
|
|
106
|
+
elif cursor_does_match:
|
|
107
|
+
is_allowed = _do_options_match_an_allowed_command(
|
|
108
|
+
command=command, options=options, allowed_commands=children
|
|
109
|
+
)
|
|
110
|
+
if is_allowed:
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
raise ValueError(
|
|
114
|
+
f"Command is not in the allowlist: {command + ' ' + ' '.join(options)}"
|
|
115
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
|
|
5
|
+
from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
|
|
6
|
+
from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
|
|
7
|
+
from holmes.plugins.toolsets.bash.common.validators import (
|
|
8
|
+
validate_command_and_operations,
|
|
9
|
+
)
|
|
10
|
+
from holmes.plugins.toolsets.bash.docker.constants import (
|
|
11
|
+
ALLOWED_DOCKER_COMMANDS,
|
|
12
|
+
DENIED_DOCKER_COMMANDS,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DockerCommand(BashCommand):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__("docker")
|
|
19
|
+
|
|
20
|
+
def add_parser(self, parent_parser: Any):
|
|
21
|
+
docker_parser = parent_parser.add_parser(
|
|
22
|
+
"docker",
|
|
23
|
+
help="Docker Command Line Interface",
|
|
24
|
+
exit_on_error=False,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
docker_parser.add_argument(
|
|
28
|
+
"command",
|
|
29
|
+
help="Docker command (e.g., ps, images, inspect)",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
docker_parser.add_argument(
|
|
33
|
+
"options",
|
|
34
|
+
nargs=argparse.REMAINDER,
|
|
35
|
+
default=[],
|
|
36
|
+
help="Docker CLI subcommands, operations, and options",
|
|
37
|
+
)
|
|
38
|
+
return docker_parser
|
|
39
|
+
|
|
40
|
+
def validate_command(
|
|
41
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
42
|
+
) -> None:
|
|
43
|
+
if hasattr(command, "options"):
|
|
44
|
+
validate_command_and_operations(
|
|
45
|
+
command=command.command,
|
|
46
|
+
options=command.options,
|
|
47
|
+
allowed_commands=ALLOWED_DOCKER_COMMANDS,
|
|
48
|
+
denied_commands=DENIED_DOCKER_COMMANDS,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def stringify_command(
|
|
52
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
53
|
+
) -> str:
|
|
54
|
+
parts = ["docker", command.command]
|
|
55
|
+
|
|
56
|
+
if hasattr(command, "options") and command.options:
|
|
57
|
+
parts.extend(command.options)
|
|
58
|
+
|
|
59
|
+
return " ".join(escape_shell_args(parts))
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
ALLOWED_DOCKER_COMMANDS: dict[str, dict] = {
|
|
2
|
+
# Container management (read-only)
|
|
3
|
+
"ps": {},
|
|
4
|
+
"container": {
|
|
5
|
+
"ls": {},
|
|
6
|
+
"list": {},
|
|
7
|
+
"inspect": {},
|
|
8
|
+
"logs": {},
|
|
9
|
+
"stats": {},
|
|
10
|
+
"top": {},
|
|
11
|
+
"port": {},
|
|
12
|
+
"diff": {},
|
|
13
|
+
},
|
|
14
|
+
# Image management (read-only)
|
|
15
|
+
"images": {},
|
|
16
|
+
"image": {
|
|
17
|
+
"ls": {},
|
|
18
|
+
"list": {},
|
|
19
|
+
"inspect": {},
|
|
20
|
+
"history": {},
|
|
21
|
+
},
|
|
22
|
+
# System information
|
|
23
|
+
"version": {},
|
|
24
|
+
"info": {},
|
|
25
|
+
"system": {
|
|
26
|
+
"info": {},
|
|
27
|
+
"events": {},
|
|
28
|
+
"df": {},
|
|
29
|
+
},
|
|
30
|
+
# Network inspection
|
|
31
|
+
"network": {
|
|
32
|
+
"ls": {},
|
|
33
|
+
"list": {},
|
|
34
|
+
"inspect": {},
|
|
35
|
+
},
|
|
36
|
+
# Volume inspection
|
|
37
|
+
"volume": {
|
|
38
|
+
"ls": {},
|
|
39
|
+
"list": {},
|
|
40
|
+
"inspect": {},
|
|
41
|
+
},
|
|
42
|
+
# Registry operations (read-only)
|
|
43
|
+
"search": {},
|
|
44
|
+
# Plugin inspection
|
|
45
|
+
"plugin": {
|
|
46
|
+
"ls": {},
|
|
47
|
+
"list": {},
|
|
48
|
+
"inspect": {},
|
|
49
|
+
},
|
|
50
|
+
# Node information (Swarm read-only)
|
|
51
|
+
"node": {
|
|
52
|
+
"ls": {},
|
|
53
|
+
"list": {},
|
|
54
|
+
"inspect": {},
|
|
55
|
+
},
|
|
56
|
+
# Service information (Swarm read-only)
|
|
57
|
+
"service": {
|
|
58
|
+
"ls": {},
|
|
59
|
+
"list": {},
|
|
60
|
+
"inspect": {},
|
|
61
|
+
"logs": {},
|
|
62
|
+
"ps": {},
|
|
63
|
+
},
|
|
64
|
+
# Stack information (read-only)
|
|
65
|
+
"stack": {
|
|
66
|
+
"ls": {},
|
|
67
|
+
"list": {},
|
|
68
|
+
"ps": {},
|
|
69
|
+
"services": {},
|
|
70
|
+
},
|
|
71
|
+
# Secret inspection (read-only metadata)
|
|
72
|
+
"secret": {
|
|
73
|
+
"ls": {},
|
|
74
|
+
"list": {},
|
|
75
|
+
"inspect": {},
|
|
76
|
+
},
|
|
77
|
+
# Config inspection (read-only)
|
|
78
|
+
"config": {
|
|
79
|
+
"ls": {},
|
|
80
|
+
"list": {},
|
|
81
|
+
"inspect": {},
|
|
82
|
+
},
|
|
83
|
+
# Context information
|
|
84
|
+
"context": {
|
|
85
|
+
"ls": {},
|
|
86
|
+
"list": {},
|
|
87
|
+
"inspect": {},
|
|
88
|
+
"show": {},
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Blocked Docker operations (state-modifying or dangerous)
|
|
93
|
+
DENIED_DOCKER_COMMANDS: dict[str, dict] = {
|
|
94
|
+
# Container lifecycle operations
|
|
95
|
+
"run": {},
|
|
96
|
+
"create": {},
|
|
97
|
+
"start": {},
|
|
98
|
+
"stop": {},
|
|
99
|
+
"restart": {},
|
|
100
|
+
"pause": {},
|
|
101
|
+
"unpause": {},
|
|
102
|
+
"kill": {},
|
|
103
|
+
"remove": {},
|
|
104
|
+
"rm": {},
|
|
105
|
+
"exec": {},
|
|
106
|
+
"attach": {},
|
|
107
|
+
"cp": {},
|
|
108
|
+
"commit": {},
|
|
109
|
+
"update": {},
|
|
110
|
+
"rename": {},
|
|
111
|
+
"wait": {},
|
|
112
|
+
"container": {
|
|
113
|
+
"create": {},
|
|
114
|
+
"start": {},
|
|
115
|
+
"stop": {},
|
|
116
|
+
"restart": {},
|
|
117
|
+
"pause": {},
|
|
118
|
+
"unpause": {},
|
|
119
|
+
"kill": {},
|
|
120
|
+
"remove": {},
|
|
121
|
+
"rm": {},
|
|
122
|
+
"exec": {},
|
|
123
|
+
"attach": {},
|
|
124
|
+
"cp": {},
|
|
125
|
+
"commit": {},
|
|
126
|
+
"update": {},
|
|
127
|
+
"rename": {},
|
|
128
|
+
"wait": {},
|
|
129
|
+
"prune": {},
|
|
130
|
+
"export": {}, # Can exfiltrate full filesystem
|
|
131
|
+
},
|
|
132
|
+
# Image operations
|
|
133
|
+
"build": {},
|
|
134
|
+
"pull": {},
|
|
135
|
+
"push": {},
|
|
136
|
+
"tag": {},
|
|
137
|
+
"untag": {},
|
|
138
|
+
"rmi": {},
|
|
139
|
+
"load": {},
|
|
140
|
+
"import": {},
|
|
141
|
+
"save": {},
|
|
142
|
+
"image": {
|
|
143
|
+
"build": {},
|
|
144
|
+
"pull": {},
|
|
145
|
+
"push": {},
|
|
146
|
+
"tag": {},
|
|
147
|
+
"untag": {},
|
|
148
|
+
"rm": {},
|
|
149
|
+
"remove": {},
|
|
150
|
+
"load": {},
|
|
151
|
+
"import": {},
|
|
152
|
+
"save": {},
|
|
153
|
+
"prune": {},
|
|
154
|
+
},
|
|
155
|
+
# Network operations
|
|
156
|
+
"network": {
|
|
157
|
+
"create": {},
|
|
158
|
+
"rm": {},
|
|
159
|
+
"remove": {},
|
|
160
|
+
"connect": {},
|
|
161
|
+
"disconnect": {},
|
|
162
|
+
"prune": {},
|
|
163
|
+
},
|
|
164
|
+
# Volume operations
|
|
165
|
+
"volume": {
|
|
166
|
+
"create": {},
|
|
167
|
+
"rm": {},
|
|
168
|
+
"remove": {},
|
|
169
|
+
"prune": {},
|
|
170
|
+
},
|
|
171
|
+
# System operations
|
|
172
|
+
"system": {
|
|
173
|
+
"prune": {},
|
|
174
|
+
},
|
|
175
|
+
# Registry operations
|
|
176
|
+
"login": {},
|
|
177
|
+
"logout": {},
|
|
178
|
+
# Plugin operations
|
|
179
|
+
"plugin": {
|
|
180
|
+
"install": {},
|
|
181
|
+
"enable": {},
|
|
182
|
+
"disable": {},
|
|
183
|
+
"upgrade": {},
|
|
184
|
+
"rm": {},
|
|
185
|
+
"remove": {},
|
|
186
|
+
"push": {},
|
|
187
|
+
"create": {},
|
|
188
|
+
"set": {},
|
|
189
|
+
},
|
|
190
|
+
# Swarm operations
|
|
191
|
+
"swarm": {
|
|
192
|
+
"init": {},
|
|
193
|
+
"join": {},
|
|
194
|
+
"leave": {},
|
|
195
|
+
"update": {},
|
|
196
|
+
"join-token": {},
|
|
197
|
+
"unlock": {},
|
|
198
|
+
"unlock-key": {},
|
|
199
|
+
},
|
|
200
|
+
# Node operations
|
|
201
|
+
"node": {
|
|
202
|
+
"update": {},
|
|
203
|
+
"demote": {},
|
|
204
|
+
"promote": {},
|
|
205
|
+
"rm": {},
|
|
206
|
+
"remove": {},
|
|
207
|
+
},
|
|
208
|
+
# Service operations
|
|
209
|
+
"service": {
|
|
210
|
+
"create": {},
|
|
211
|
+
"update": {},
|
|
212
|
+
"scale": {},
|
|
213
|
+
"rm": {},
|
|
214
|
+
"remove": {},
|
|
215
|
+
"rollback": {},
|
|
216
|
+
},
|
|
217
|
+
# Stack operations
|
|
218
|
+
"stack": {
|
|
219
|
+
"deploy": {},
|
|
220
|
+
"rm": {},
|
|
221
|
+
"remove": {},
|
|
222
|
+
},
|
|
223
|
+
# Secret operations
|
|
224
|
+
"secret": {
|
|
225
|
+
"create": {},
|
|
226
|
+
"rm": {},
|
|
227
|
+
"remove": {},
|
|
228
|
+
},
|
|
229
|
+
# Config operations
|
|
230
|
+
"config": {
|
|
231
|
+
"create": {},
|
|
232
|
+
"rm": {},
|
|
233
|
+
"remove": {},
|
|
234
|
+
},
|
|
235
|
+
# Context operations
|
|
236
|
+
"context": {
|
|
237
|
+
"create": {},
|
|
238
|
+
"rm": {},
|
|
239
|
+
"remove": {},
|
|
240
|
+
"update": {},
|
|
241
|
+
"use": {},
|
|
242
|
+
"export": {},
|
|
243
|
+
"import": {},
|
|
244
|
+
},
|
|
245
|
+
# Checkpoint operations
|
|
246
|
+
"checkpoint": {},
|
|
247
|
+
# Buildx operations
|
|
248
|
+
"buildx": {},
|
|
249
|
+
# Compose operations
|
|
250
|
+
"compose": {},
|
|
251
|
+
# Trust operations
|
|
252
|
+
"trust": {},
|
|
253
|
+
# Manifest operations
|
|
254
|
+
"manifest": {},
|
|
255
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
|
|
5
|
+
from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
|
|
6
|
+
from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
|
|
7
|
+
from holmes.plugins.toolsets.bash.common.validators import (
|
|
8
|
+
validate_command_and_operations,
|
|
9
|
+
)
|
|
10
|
+
from holmes.plugins.toolsets.bash.helm.constants import (
|
|
11
|
+
ALLOWED_HELM_COMMANDS,
|
|
12
|
+
DENIED_HELM_COMMANDS,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class HelmCommand(BashCommand):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__("helm")
|
|
19
|
+
|
|
20
|
+
def add_parser(self, parent_parser: Any):
|
|
21
|
+
"""Create Helm CLI parser with safe command validation."""
|
|
22
|
+
helm_parser = parent_parser.add_parser(
|
|
23
|
+
"helm", help="Helm Package Manager for Kubernetes", exit_on_error=False
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Add command subparser
|
|
27
|
+
helm_parser.add_argument(
|
|
28
|
+
"command", help="Helm command (e.g., list, get, status, show)"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Capture remaining arguments
|
|
32
|
+
helm_parser.add_argument(
|
|
33
|
+
"options",
|
|
34
|
+
nargs=argparse.REMAINDER,
|
|
35
|
+
default=[],
|
|
36
|
+
help="Helm CLI subcommands, operations, and options",
|
|
37
|
+
)
|
|
38
|
+
return helm_parser
|
|
39
|
+
|
|
40
|
+
def validate_command(
|
|
41
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
42
|
+
) -> None:
|
|
43
|
+
if hasattr(command, "options"):
|
|
44
|
+
validate_command_and_operations(
|
|
45
|
+
command=command.command,
|
|
46
|
+
options=command.options,
|
|
47
|
+
allowed_commands=ALLOWED_HELM_COMMANDS,
|
|
48
|
+
denied_commands=DENIED_HELM_COMMANDS,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def stringify_command(
|
|
52
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
53
|
+
) -> str:
|
|
54
|
+
"""Convert parsed Helm command back to safe command string."""
|
|
55
|
+
# Build command parts
|
|
56
|
+
parts = ["helm", command.command]
|
|
57
|
+
|
|
58
|
+
if hasattr(command, "options") and command.options:
|
|
59
|
+
parts.extend(command.options)
|
|
60
|
+
|
|
61
|
+
return " ".join(escape_shell_args(parts))
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
ALLOWED_HELM_COMMANDS: dict[str, dict] = {
|
|
2
|
+
# Release management (read-only)
|
|
3
|
+
"list": {},
|
|
4
|
+
"ls": {},
|
|
5
|
+
"get": {
|
|
6
|
+
"all": {},
|
|
7
|
+
"hooks": {},
|
|
8
|
+
"manifest": {},
|
|
9
|
+
"notes": {},
|
|
10
|
+
"values": {},
|
|
11
|
+
"metadata": {},
|
|
12
|
+
},
|
|
13
|
+
"status": {},
|
|
14
|
+
"history": {},
|
|
15
|
+
"diff": {
|
|
16
|
+
"upgrade": {},
|
|
17
|
+
"rollback": {},
|
|
18
|
+
"revision": {},
|
|
19
|
+
"release": {},
|
|
20
|
+
"version": {},
|
|
21
|
+
},
|
|
22
|
+
# Chart operations (read-only)
|
|
23
|
+
"show": {
|
|
24
|
+
"all": {},
|
|
25
|
+
"chart": {},
|
|
26
|
+
"readme": {},
|
|
27
|
+
"values": {},
|
|
28
|
+
"crds": {},
|
|
29
|
+
},
|
|
30
|
+
"inspect": {},
|
|
31
|
+
"search": {
|
|
32
|
+
"repo": {},
|
|
33
|
+
},
|
|
34
|
+
"lint": {},
|
|
35
|
+
"verify": {},
|
|
36
|
+
"dependency": {"list": {}},
|
|
37
|
+
# Repository operations (read-only)
|
|
38
|
+
"repo": {"list": {}},
|
|
39
|
+
# Help and information
|
|
40
|
+
"help": {},
|
|
41
|
+
"version": {},
|
|
42
|
+
# Plugin operations (read-only)
|
|
43
|
+
"plugin": {
|
|
44
|
+
"list": {},
|
|
45
|
+
},
|
|
46
|
+
# Completion
|
|
47
|
+
"completion": {},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
# Blocked Helm operations (state-modifying or dangerous)
|
|
51
|
+
DENIED_HELM_COMMANDS: dict[str, dict] = {
|
|
52
|
+
# Release lifecycle operations
|
|
53
|
+
"install": {},
|
|
54
|
+
"upgrade": {},
|
|
55
|
+
"uninstall": {},
|
|
56
|
+
"delete": {},
|
|
57
|
+
"rollback": {},
|
|
58
|
+
"test": {},
|
|
59
|
+
# Repository management
|
|
60
|
+
"repo": {
|
|
61
|
+
"add": {},
|
|
62
|
+
"remove": {},
|
|
63
|
+
"rm": {},
|
|
64
|
+
"update": {},
|
|
65
|
+
"index": {},
|
|
66
|
+
},
|
|
67
|
+
# Chart packaging and publishing
|
|
68
|
+
"create": {},
|
|
69
|
+
"package": {},
|
|
70
|
+
"push": {},
|
|
71
|
+
"pull": {},
|
|
72
|
+
"fetch": {},
|
|
73
|
+
"dependency": {
|
|
74
|
+
"update": {},
|
|
75
|
+
"build": {},
|
|
76
|
+
},
|
|
77
|
+
# Plugin management
|
|
78
|
+
"plugin": {
|
|
79
|
+
"install": {},
|
|
80
|
+
"uninstall": {},
|
|
81
|
+
"update": {},
|
|
82
|
+
},
|
|
83
|
+
# Registry operations
|
|
84
|
+
"registry": {},
|
|
85
|
+
# Environment modification
|
|
86
|
+
"env": {},
|
|
87
|
+
# Configuration modification
|
|
88
|
+
"config": {},
|
|
89
|
+
# Mapkubeapis operations
|
|
90
|
+
"mapkubeapis": {},
|
|
91
|
+
"template": {},
|
|
92
|
+
}
|