huaweicloud-devkit 1.0.2-next.8 → 1.0.2
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.
- package/.agents/plugins/marketplace.json +1 -1
- package/LICENSE +201 -201
- package/README.md +71 -52
- package/README.zh-CN.md +71 -50
- package/bin/setup.cjs +0 -0
- package/package.json +9 -5
- package/plugins/huaweicloud-core/.claude-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.codex-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.cursor-plugin/plugin.json +2 -2
- package/plugins/huaweicloud-core/.hermes-plugin/plugin.json +30 -0
- package/plugins/huaweicloud-core/.mcp.json +1 -2
- package/plugins/huaweicloud-core/.workbuddy-plugin/plugin.json +2 -3
- package/plugins/huaweicloud-core/hooks/huaweicloud-safety.py +159 -136
- package/plugins/huaweicloud-core/openclaw.plugin.json +20 -0
- package/plugins/huaweicloud-core/skills/huawei-cloud-find-skills/SKILL.md +1 -1
- package/plugins/huaweicloud-core/skills/huawei-sandbox/SKILL.md +67 -20
- package/plugins/huaweicloud-core/skills/huaweicloud-capability-discovery/SKILL.md +11 -0
- package/plugins/huaweicloud-core/skills/huaweicloud-cli-and-auth/SKILL.md +16 -0
- package/plugins/huaweicloud-core/skills/huaweicloud-core/SKILL.md +27 -24
- package/plugins/huaweicloud-core/skills/huaweicloud-core/references/select.md +12 -0
- package/plugins/huaweicloud-core/src/auth/agent-registration.mjs +79 -11
- package/plugins/huaweicloud-core/src/auth/credentials.mjs +65 -0
- package/plugins/huaweicloud-core/src/mcp-server.mjs +31 -4
- package/plugins/huaweicloud-core/src/proxy/proxy-agent.mjs +6 -1
- package/plugins/huaweicloud-core/src/sandbox/hdkitservice-api.mjs +7 -2
- package/plugins/huaweicloud-core/src/sandbox/hwlink-api.mjs +14 -4
- package/plugins/huaweicloud-core/src/sandbox/sandbox-file-server.py +45 -0
- package/plugins/huaweicloud-core/src/sandbox/session-manager.mjs +432 -10
- package/plugins/huaweicloud-core/src/setup-cli.mjs +581 -87
- package/plugins/huaweicloud-core/src/tools.mjs +225 -33
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-exec-client.js +18 -4
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-fair-queue.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-multiplexer.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-packet.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-terminal-channel.js +9 -0
- package/plugins/huaweicloud-core/src/ws-exec/hwlink-tunnel-channel.mjs +267 -0
- package/plugins/huaweicloud-core/src/ws-exec/index.js +3 -0
- package/plugins/huaweicloud-core/src/ws-exec/ws-exec-client.js +9 -5
package/README.zh-CN.md
CHANGED
|
@@ -8,46 +8,32 @@
|
|
|
8
8
|
|
|
9
9
|
帮助 AI 编码助手安全、准确地使用华为云——一站式集成云知识、CLI 工具和安全护栏。
|
|
10
10
|
|
|
11
|
-
支持 OpenCode
|
|
11
|
+
支持 OpenCode、码道(CodeArts Agent)、WorkBuddy、DeepSeek Harness(DSH)、OfficeAce、OpenClaw。
|
|
12
12
|
|
|
13
13
|
## 前置条件
|
|
14
14
|
|
|
15
|
-
- Node.js >=
|
|
15
|
+
- Node.js >= 22
|
|
16
16
|
|
|
17
17
|
## 快速开始
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
npx --yes huaweicloud-devkit install
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
自动安装 DevKit。安装后**重启会话**。
|
|
19
|
+
> 省略 `--target` 时,安装器会自动检测机器上的 agent,检测到多个时**全部安装**。建议始终指定 `--target` 以明确安装目标。
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
npx --yes huaweicloud-devkit doctor # 自检
|
|
29
|
-
npx --yes huaweicloud-devkit status # 查看状态
|
|
30
|
-
npx --yes huaweicloud-devkit update # 更新
|
|
31
|
-
npx --yes huaweicloud-devkit uninstall # 卸载
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### Codex
|
|
21
|
+
### OpenCode
|
|
35
22
|
|
|
36
23
|
```bash
|
|
37
|
-
npx --yes huaweicloud-devkit install --target
|
|
24
|
+
npx --yes huaweicloud-devkit install --target opencode
|
|
38
25
|
```
|
|
39
26
|
|
|
40
|
-
|
|
27
|
+
安装后**重启会话**。
|
|
41
28
|
|
|
42
29
|
```bash
|
|
43
|
-
npx --yes huaweicloud-devkit doctor
|
|
44
|
-
npx --yes huaweicloud-devkit status --target
|
|
45
|
-
npx --yes huaweicloud-devkit update --target
|
|
46
|
-
npx --yes huaweicloud-devkit uninstall --target
|
|
30
|
+
npx --yes huaweicloud-devkit doctor --target opencode
|
|
31
|
+
npx --yes huaweicloud-devkit status --target opencode
|
|
32
|
+
npx --yes huaweicloud-devkit update --target opencode
|
|
33
|
+
npx --yes huaweicloud-devkit uninstall --target opencode
|
|
34
|
+
rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows 路径待确认
|
|
47
35
|
```
|
|
48
36
|
|
|
49
|
-
> **Codex Desktop**(Windows):将 `--target codex` 换成 `--target codex-desktop`,命令相同。
|
|
50
|
-
|
|
51
37
|
### CodeArts Agent(码道)
|
|
52
38
|
|
|
53
39
|
```bash
|
|
@@ -57,16 +43,13 @@ npx --yes huaweicloud-devkit install --target codearts
|
|
|
57
43
|
安装后**重启会话**。
|
|
58
44
|
|
|
59
45
|
```bash
|
|
60
|
-
npx --yes huaweicloud-devkit
|
|
61
|
-
npx --yes huaweicloud-devkit doctor # 自检
|
|
46
|
+
npx --yes huaweicloud-devkit doctor --target codearts
|
|
62
47
|
npx --yes huaweicloud-devkit status --target codearts
|
|
63
48
|
npx --yes huaweicloud-devkit update --target codearts
|
|
64
49
|
npx --yes huaweicloud-devkit uninstall --target codearts
|
|
65
50
|
```
|
|
66
51
|
|
|
67
|
-
> **沙箱模式**:码道默认沙箱模式会阻止 KooCLI 运行。`install-hcloud` 自动检测并给出指引——请在码道外终端安装使用 KooCLI,或在码道设置中关闭沙箱模式(设置 →
|
|
68
|
-
>
|
|
69
|
-
> **认证**:执行 `npx huaweicloud-devkit auth init`,统一配置 KooCLI、OBS 和沙箱接口所需的 AK/SK。
|
|
52
|
+
> **沙箱模式**:码道默认沙箱模式会阻止 KooCLI 运行。`install-hcloud` 自动检测并给出指引——请在码道外终端安装使用 KooCLI,或在码道设置中关闭沙箱模式(设置 → 对话流 → 智能体 终端命令运行模式 → 自动运行)。
|
|
70
53
|
|
|
71
54
|
### WorkBuddy
|
|
72
55
|
|
|
@@ -77,34 +60,28 @@ npx --yes huaweicloud-devkit install --target workbuddy
|
|
|
77
60
|
安装后**重启会话**。
|
|
78
61
|
|
|
79
62
|
```bash
|
|
80
|
-
npx --yes huaweicloud-devkit doctor
|
|
63
|
+
npx --yes huaweicloud-devkit doctor --target workbuddy
|
|
81
64
|
npx --yes huaweicloud-devkit status --target workbuddy
|
|
82
|
-
npx --yes huaweicloud-devkit update --target workbuddy
|
|
65
|
+
npx --yes huaweicloud-devkit update --target workbuddy
|
|
83
66
|
npx --yes huaweicloud-devkit uninstall --target workbuddy
|
|
84
67
|
```
|
|
85
68
|
|
|
86
|
-
> **更新机制**:`update` 按 agent 增量更新,只刷新必要文件、不动你的配置文件。`update --target all` 可一次更新所有已安装的 agent。
|
|
87
|
-
|
|
88
69
|
### DeepSeek Harness(DSH)
|
|
89
70
|
|
|
90
71
|
```bash
|
|
91
72
|
npx --yes huaweicloud-devkit install --target dsh
|
|
92
73
|
```
|
|
93
74
|
|
|
94
|
-
|
|
95
|
-
`$DSH_HOME/huaweicloud-plugins`,并自动维护
|
|
96
|
-
`$DSH_HOME/profiles/web/cordis.patch.yml`。安装后**重启 DSH 会话**。
|
|
75
|
+
安装后**重启 DSH 会话**。
|
|
97
76
|
|
|
98
77
|
```bash
|
|
99
|
-
npx --yes huaweicloud-devkit doctor
|
|
78
|
+
npx --yes huaweicloud-devkit doctor --target dsh
|
|
100
79
|
npx --yes huaweicloud-devkit status --target dsh
|
|
101
80
|
npx --yes huaweicloud-devkit update --target dsh
|
|
102
81
|
npx --yes huaweicloud-devkit uninstall --target dsh
|
|
103
82
|
```
|
|
104
83
|
|
|
105
|
-
> DSH V1 通过 `@deepseek-ai/dsh-mcp-client` 复用现有 MCP Server
|
|
106
|
-
> 如果安装器提示 DSH MCP 客户端未检测到,请按提示执行
|
|
107
|
-
> `npx @deepseek-ai/dsh plugin --profile web add @deepseek-ai/dsh-mcp-client`。
|
|
84
|
+
> DSH V1 通过 `@deepseek-ai/dsh-mcp-client` 复用现有 MCP Server。如果安装器提示客户端未检测到,请执行:`npx @deepseek-ai/dsh plugin --profile web add @deepseek-ai/dsh-mcp-client`。
|
|
108
85
|
|
|
109
86
|
### OfficeAce
|
|
110
87
|
|
|
@@ -115,35 +92,78 @@ npx --yes huaweicloud-devkit install --target officeace
|
|
|
115
92
|
安装后**重启 OfficeAce**。
|
|
116
93
|
|
|
117
94
|
```bash
|
|
118
|
-
npx --yes huaweicloud-devkit doctor
|
|
95
|
+
npx --yes huaweicloud-devkit doctor --target officeace
|
|
119
96
|
npx --yes huaweicloud-devkit status --target officeace
|
|
120
97
|
npx --yes huaweicloud-devkit update --target officeace
|
|
121
98
|
npx --yes huaweicloud-devkit uninstall --target officeace
|
|
122
99
|
```
|
|
123
100
|
|
|
101
|
+
### OpenClaw
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# 推荐方式 (ClawHub)
|
|
105
|
+
openclaw plugins install clawhub:huaweicloud-devkit
|
|
106
|
+
openclaw plugins uninstall huaweicloud-devkit
|
|
107
|
+
openclaw plugins update huaweicloud-devkit
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
安装后**重启 OpenClaw**。如提示安全风险确认,加 `--acknowledge-clawhub-risk`。
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# 或通过 npx
|
|
114
|
+
npx --yes huaweicloud-devkit install --target openclaw
|
|
115
|
+
npx --yes huaweicloud-devkit status --target openclaw
|
|
116
|
+
npx --yes huaweicloud-devkit update --target openclaw
|
|
117
|
+
npx --yes huaweicloud-devkit uninstall --target openclaw
|
|
118
|
+
rm -rf ~/.npm/_npx/ # 仅 Linux/macOS;Windows 路径待确认
|
|
119
|
+
```
|
|
120
|
+
|
|
124
121
|
### 其他 Agent
|
|
125
122
|
|
|
126
|
-
|
|
123
|
+
任何支持 MCP 协议的 Agent,直接使用标准 MCP 配置:
|
|
127
124
|
|
|
128
125
|
```json
|
|
129
126
|
{
|
|
130
|
-
"
|
|
127
|
+
"mcpServers": {
|
|
131
128
|
"huaweicloud-devkit": {
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
"enabled": true
|
|
129
|
+
"command": "npx",
|
|
130
|
+
"args": ["-y", "-p", "huaweicloud-devkit", "huaweicloud-devkit-mcp"]
|
|
135
131
|
}
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
```
|
|
139
135
|
|
|
140
|
-
|
|
136
|
+
无需预安装 — `npx` 自动处理一切。
|
|
137
|
+
|
|
138
|
+
> 项目级 AK/SK 可通过 MCP 配置的 `env` 字段设置 `HW_ACCESS_KEY`/`HW_SECRET_KEY`。
|
|
139
|
+
|
|
140
|
+
### 安装 KooCLI
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
npx --yes huaweicloud-devkit install-hcloud
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 配置凭据
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx --yes huaweicloud-devkit auth init
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
一步同步 AK/SK 到 KooCLI、OBS 和沙箱接口。
|
|
153
|
+
|
|
154
|
+
### 安装所有 Agent
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
npx --yes huaweicloud-devkit install --target all
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 更新所有 Agent
|
|
141
161
|
|
|
142
162
|
```bash
|
|
143
|
-
npx --yes huaweicloud-devkit
|
|
163
|
+
npx --yes huaweicloud-devkit update --target all
|
|
144
164
|
```
|
|
145
165
|
|
|
146
|
-
|
|
166
|
+
`update` 是增量更新——只刷新已安装的文件,不动配置文件。
|
|
147
167
|
|
|
148
168
|
## 功能特性
|
|
149
169
|
|
|
@@ -151,6 +171,7 @@ npx --yes huaweicloud-devkit install
|
|
|
151
171
|
- **安全优先执行** — 所有写操作需用户明确批准;凭证和密钥自动脱敏
|
|
152
172
|
- **执行前风险检查** — 公网暴露、凭证泄露、破坏性操作在执行前即被拦截
|
|
153
173
|
- **区域感知** — 自动发现可用区域,创建资源前检查服务可用性
|
|
174
|
+
- **沙箱(DevStation)** — 临时云端运行环境,部署 Web 应用并即刻获得公网预览地址
|
|
154
175
|
|
|
155
176
|
## 支持的服务
|
|
156
177
|
|
package/bin/setup.cjs
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "huaweicloud-devkit",
|
|
3
|
-
"version": "1.0.2
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Agent toolkit that helps coding agents use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities safely and accurately.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
"integrations/opencode"
|
|
11
11
|
],
|
|
12
12
|
"bin": {
|
|
13
|
-
"huaweicloud-devkit": "./bin/setup.cjs"
|
|
13
|
+
"huaweicloud-devkit": "./bin/setup.cjs",
|
|
14
|
+
"huaweicloud-devkit-mcp": "./plugins/huaweicloud-core/src/mcp-server.mjs"
|
|
14
15
|
},
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
17
|
-
"url": "https://github.com/huaweicloud/
|
|
18
|
+
"url": "https://github.com/huaweicloud/huaweicloud-devkit.git"
|
|
18
19
|
},
|
|
19
20
|
"scripts": {
|
|
20
21
|
"test": "node --test",
|
|
@@ -27,7 +28,10 @@
|
|
|
27
28
|
"pack:verify": "node ./scripts/pack-verify.mjs",
|
|
28
29
|
"postinstall": "node -e \"console.log('\\nHuaweiCloud DevKit installed. Run: npx huaweicloud-devkit install\\n')\""
|
|
29
30
|
},
|
|
30
|
-
"dependencies": {
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"better-sqlite3": "^13.0.3",
|
|
33
|
+
"undici": "^8.10.0"
|
|
34
|
+
},
|
|
31
35
|
"devDependencies": {
|
|
32
36
|
"@eslint/js": "^10.0.1",
|
|
33
37
|
"eslint": "^10.8.1",
|
|
@@ -54,6 +58,6 @@
|
|
|
54
58
|
],
|
|
55
59
|
"license": "Apache-2.0",
|
|
56
60
|
"engines": {
|
|
57
|
-
"node": ">=
|
|
61
|
+
"node": ">=22"
|
|
58
62
|
}
|
|
59
63
|
}
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"mcpServers": "./.mcp.json",
|
|
18
18
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
19
19
|
"skills": "./skills/",
|
|
20
|
-
"version": "1.0.2
|
|
20
|
+
"version": "1.0.2",
|
|
21
21
|
"author": {
|
|
22
22
|
"name": "HuaweiCloud Mate",
|
|
23
23
|
"url": "https://github.com/huaweicloud"
|
|
24
24
|
},
|
|
25
25
|
"hooks": "./hooks/",
|
|
26
|
-
"name": "huaweicloud-
|
|
26
|
+
"name": "huaweicloud-devkit",
|
|
27
27
|
"homepage": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
28
28
|
"repository": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
29
29
|
"license": "Apache-2.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "huaweicloud-
|
|
3
|
-
"version": "1.0.2
|
|
2
|
+
"name": "huaweicloud-devkit",
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "HuaweiCloud Mate",
|
|
@@ -17,13 +17,13 @@
|
|
|
17
17
|
"mcpServers": "./.mcp.json",
|
|
18
18
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
19
19
|
"skills": "./skills/",
|
|
20
|
-
"version": "1.0.2
|
|
20
|
+
"version": "1.0.2",
|
|
21
21
|
"author": {
|
|
22
22
|
"name": "HuaweiCloud Mate",
|
|
23
23
|
"url": "https://github.com/huaweicloud"
|
|
24
24
|
},
|
|
25
25
|
"hooks": "./hooks/",
|
|
26
|
-
"name": "huaweicloud-
|
|
26
|
+
"name": "huaweicloud-devkit",
|
|
27
27
|
"homepage": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
28
28
|
"repository": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
29
29
|
"license": "Apache-2.0",
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "huaweicloud-devkit",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "HuaweiCloud Mate",
|
|
7
|
+
"url": "https://github.com/huaweicloud"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
10
|
+
"repository": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
11
|
+
"license": "Apache-2.0",
|
|
12
|
+
"keywords": ["huaweicloud", "huawei-cloud", "koocli", "hcloud", "agent", "mcp", "api", "sdk", "skills"],
|
|
13
|
+
"skills": "./skills/",
|
|
14
|
+
"mcpServers": "./.mcp.json",
|
|
15
|
+
"interface": {
|
|
16
|
+
"displayName": "HuaweiCloud Devkit",
|
|
17
|
+
"shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
|
|
18
|
+
"longDescription": "HuaweiCloud Devkit helps coding agents choose and use Huawei Cloud Skills, KooCLI, APIs, SDKs, and MCP tools with less context, safer command execution, and more accurate cloud implementation decisions.",
|
|
19
|
+
"developerName": "HuaweiCloud Mate",
|
|
20
|
+
"category": "Cloud",
|
|
21
|
+
"capabilities": ["Read", "Interactive"],
|
|
22
|
+
"websiteURL": "https://github.com/huaweicloud/HuaweiCloud-Devkit",
|
|
23
|
+
"brandColor": "#C7000B",
|
|
24
|
+
"defaultPrompt": [
|
|
25
|
+
"Help me choose the right Huawei Cloud capability.",
|
|
26
|
+
"Check my Huawei Cloud CLI setup safely.",
|
|
27
|
+
"Plan this Huawei Cloud API or SDK task."
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "huaweicloud-
|
|
3
|
-
"version": "1.0.2
|
|
2
|
+
"name": "huaweicloud-devkit",
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Guide coding agents to use Huawei Cloud Skills, KooCLI, APIs, SDKs, and future MCP capabilities with safer execution and less context.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "HuaweiCloud Mate",
|
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
"keywords": ["huaweicloud", "huawei-cloud", "koocli", "hcloud", "agent", "mcp", "api", "sdk", "skills"],
|
|
13
13
|
"skills": "./skills/",
|
|
14
14
|
"mcpServers": "./.mcp.json",
|
|
15
|
-
"hooks": "./hooks/",
|
|
16
15
|
"interface": {
|
|
17
16
|
"displayName": "HuaweiCloud Devkit",
|
|
18
17
|
"shortDescription": "HuaweiCloud Devkit - Huawei Cloud guidance, CLI/API/SDK routing, MCP tools, and safety for coding agents.",
|
|
@@ -1,136 +1,159 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""PreToolUse hook for Huawei Cloud agent safety.
|
|
3
|
-
|
|
4
|
-
Blocks the highest-risk leakage paths before an agent tool runs:
|
|
5
|
-
- reading local Huawei Cloud credential files
|
|
6
|
-
- dumping cloud credential environment variables
|
|
7
|
-
- directly retrieving cloud secret values
|
|
8
|
-
- running unapproved write operations through hcloud
|
|
9
|
-
|
|
10
|
-
The MCP server carries the same policy in Node for platforms that do not support
|
|
11
|
-
plugin hooks.
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import json
|
|
15
|
-
import re
|
|
16
|
-
import sys
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
|
|
19
|
-
DENY_PREFIX = "Huawei Cloud safety hook blocked this action: "
|
|
20
|
-
RULES_PATH = Path(__file__).resolve().parents[1] / "safety" / "rules" / "cloud-risk-rules.json"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
SECRET_READ_RE =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""PreToolUse hook for Huawei Cloud agent safety.
|
|
3
|
+
|
|
4
|
+
Blocks the highest-risk leakage paths before an agent tool runs:
|
|
5
|
+
- reading local Huawei Cloud credential files
|
|
6
|
+
- dumping cloud credential environment variables
|
|
7
|
+
- directly retrieving cloud secret values
|
|
8
|
+
- running unapproved write operations through hcloud
|
|
9
|
+
|
|
10
|
+
The MCP server carries the same policy in Node for platforms that do not support
|
|
11
|
+
plugin hooks.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
DENY_PREFIX = "Huawei Cloud safety hook blocked this action: "
|
|
20
|
+
RULES_PATH = Path(__file__).resolve().parents[1] / "safety" / "rules" / "cloud-risk-rules.json"
|
|
21
|
+
POLICY_PATH = Path(__file__).resolve().parents[1] / "safety" / "policy.json"
|
|
22
|
+
|
|
23
|
+
CONFIG_FILE_RE = None
|
|
24
|
+
SECRET_READ_RE = None
|
|
25
|
+
WRITE_OPERATION_RE = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def load_policy():
|
|
29
|
+
global CONFIG_FILE_RE, SECRET_READ_RE, WRITE_OPERATION_RE
|
|
30
|
+
try:
|
|
31
|
+
with POLICY_PATH.open("r", encoding="utf-8") as file_obj:
|
|
32
|
+
policy = json.load(file_obj)
|
|
33
|
+
cred_patterns = policy.get("credentialFilePatterns", [])
|
|
34
|
+
if cred_patterns:
|
|
35
|
+
CONFIG_FILE_RE = re.compile("|".join(cred_patterns), re.I)
|
|
36
|
+
blocked_secrets = policy.get("blockedSecretOperations", [])
|
|
37
|
+
if blocked_secrets:
|
|
38
|
+
SECRET_READ_RE = re.compile("|".join(re.escape(op) for op in blocked_secrets), re.I)
|
|
39
|
+
write_prefixes = policy.get("writeOperationPrefixes", [])
|
|
40
|
+
if write_prefixes:
|
|
41
|
+
WRITE_OPERATION_RE = re.compile(r"\b(" + "|".join(write_prefixes) + r")\w*", re.I)
|
|
42
|
+
except Exception:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
load_policy()
|
|
47
|
+
|
|
48
|
+
ENV_DUMP_RE = re.compile(
|
|
49
|
+
r"(env|printenv|Get-ChildItem\s+Env:|gci\s+Env:|dir\s+Env:).*(HUAWEICLOUD|HWC_|HCLOUD|OS_)", re.I,
|
|
50
|
+
)
|
|
51
|
+
HCLOUD_RE = re.compile(r"(^|\s)hcloud(\.exe)?\s+", re.I)
|
|
52
|
+
READ_OPERATION_RE = re.compile(r"\b(List|Show|Get|Describe|NovaList|NovaShow)\w*", re.I)
|
|
53
|
+
READ_OPERATION_RE = re.compile(r"\b(List|Show|Get|Describe|NovaList|NovaShow)\w*", re.I)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def deny(reason):
|
|
57
|
+
json.dump(
|
|
58
|
+
{
|
|
59
|
+
"hookSpecificOutput": {
|
|
60
|
+
"hookEventName": "PreToolUse",
|
|
61
|
+
"permissionDecision": "deny",
|
|
62
|
+
"permissionDecisionReason": DENY_PREFIX + reason,
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
sys.stdout,
|
|
66
|
+
)
|
|
67
|
+
sys.exit(0)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def allow():
|
|
71
|
+
sys.exit(0)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def command_text(tool_input):
|
|
75
|
+
if isinstance(tool_input, str):
|
|
76
|
+
return tool_input
|
|
77
|
+
if isinstance(tool_input, dict):
|
|
78
|
+
values = []
|
|
79
|
+
for key in ("command", "cmd", "script", "args", "arguments"):
|
|
80
|
+
value = tool_input.get(key)
|
|
81
|
+
if isinstance(value, list):
|
|
82
|
+
values.append(" ".join(str(item) for item in value))
|
|
83
|
+
elif value is not None:
|
|
84
|
+
values.append(str(value))
|
|
85
|
+
if values:
|
|
86
|
+
return "\n".join(values)
|
|
87
|
+
return json.dumps(tool_input)
|
|
88
|
+
return json.dumps(tool_input)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def load_cloud_risk_rules():
|
|
92
|
+
try:
|
|
93
|
+
with RULES_PATH.open("r", encoding="utf-8") as file_obj:
|
|
94
|
+
catalog = json.load(file_obj)
|
|
95
|
+
return catalog.get("rules", [])
|
|
96
|
+
except Exception:
|
|
97
|
+
return []
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def condition_matches(condition, text):
|
|
101
|
+
return re.search(condition.get("regex", r"a^"), text, re.I | re.M | re.S) is not None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def rule_matches(rule, text):
|
|
105
|
+
match = rule.get("match") or {}
|
|
106
|
+
all_conditions = match.get("all")
|
|
107
|
+
any_conditions = match.get("any")
|
|
108
|
+
none_conditions = match.get("none")
|
|
109
|
+
|
|
110
|
+
if isinstance(all_conditions, list):
|
|
111
|
+
for condition in all_conditions:
|
|
112
|
+
if not condition_matches(condition, text):
|
|
113
|
+
return False
|
|
114
|
+
if isinstance(any_conditions, list):
|
|
115
|
+
if not any(condition_matches(condition, text) for condition in any_conditions):
|
|
116
|
+
return False
|
|
117
|
+
if isinstance(none_conditions, list):
|
|
118
|
+
if any(condition_matches(condition, text) for condition in none_conditions):
|
|
119
|
+
return False
|
|
120
|
+
return isinstance(all_conditions, list) or isinstance(any_conditions, list)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def first_denied_command_rule(text):
|
|
124
|
+
for rule in load_cloud_risk_rules():
|
|
125
|
+
if "command" not in rule.get("stages", []):
|
|
126
|
+
continue
|
|
127
|
+
if rule.get("severity") != "deny":
|
|
128
|
+
continue
|
|
129
|
+
if rule_matches(rule, text):
|
|
130
|
+
return rule
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def main():
|
|
135
|
+
try:
|
|
136
|
+
data = json.load(sys.stdin)
|
|
137
|
+
except Exception:
|
|
138
|
+
allow()
|
|
139
|
+
|
|
140
|
+
tool_name = data.get("tool_name", "")
|
|
141
|
+
text = command_text(data.get("tool_input", {}))
|
|
142
|
+
|
|
143
|
+
if CONFIG_FILE_RE and CONFIG_FILE_RE.search(text):
|
|
144
|
+
deny("reading Huawei Cloud credential/profile files can expose AK/SK or tokens. Use redacted toolkit tools.")
|
|
145
|
+
if ENV_DUMP_RE.search(text):
|
|
146
|
+
deny("dumping cloud credential environment variables is not allowed.")
|
|
147
|
+
if SECRET_READ_RE and SECRET_READ_RE.search(text):
|
|
148
|
+
deny("direct secret value retrieval would put plaintext secrets into the agent context.")
|
|
149
|
+
denied_rule = first_denied_command_rule(text)
|
|
150
|
+
if denied_rule:
|
|
151
|
+
deny(f"{denied_rule.get('message')} Remediation: {denied_rule.get('remediation')}")
|
|
152
|
+
if tool_name == "Bash" and HCLOUD_RE.search(text) and WRITE_OPERATION_RE.search(text) and not READ_OPERATION_RE.search(text):
|
|
153
|
+
deny("unapproved Huawei Cloud write operations must be planned first and explicitly approved by the user.")
|
|
154
|
+
|
|
155
|
+
allow()
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
if __name__ == "__main__":
|
|
159
|
+
main()
|